| New file |
| | |
| | | package com.zy.core.constant; |
| | | |
| | | |
| | | /** |
| | | * 设备字段枚举(对应 §2.2) |
| | | */ |
| | | public enum DeviceField { |
| | | // 扫码器:每站点16字节,String[14] |
| | | BARCODE("DB101", 0, 16), |
| | | // 称重:每站点4字节,Float |
| | | WEIGHT("DB102", 0, 4), |
| | | // 尺寸异常:每站点2字节,Bit数组 |
| | | DIMENSION_WORD("DB103", 0, 2); |
| | | |
| | | private final String addressPattern; |
| | | private final int offset; |
| | | private final int byteLength; |
| | | |
| | | DeviceField(String addressPattern, int offset, int byteLength) { |
| | | this.addressPattern = addressPattern; |
| | | this.offset = offset; |
| | | this.byteLength = byteLength; |
| | | } |
| | | |
| | | public String getAddressPattern() { |
| | | return addressPattern; |
| | | } |
| | | |
| | | public int getOffset() { |
| | | return offset; |
| | | } |
| | | |
| | | public int getByteLength() { |
| | | return byteLength; |
| | | } |
| | | |
| | | /** |
| | | * 根据 DB 块编号和站点偏移生成具体地址 |
| | | * |
| | | * @return PLC4X 地址字符串,如 "DB100.DBD0" |
| | | */ |
| | | public String buildAddress() { |
| | | return addressPattern + PlcConstant.ADDRESS_CONCATENATION + offset; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.core.constant; |
| | | |
| | | /** |
| | | * PLC 报警定义(对应 §2.3) |
| | | */ |
| | | public enum PlcAlarmDefinition { |
| | | ALL("DB25", 0, 4, "所有报警"), |
| | | EMERGENCY_STOP("DB25", 1, 4, "急停"), |
| | | LOWER_BREAKER_TRIP("DB25", 2, 4, "低位断路器断开"), |
| | | LOWER_INVERTER_FAULT("DB25", 3, 4, "低位变频器故障"), |
| | | CONVEYOR_TIMEOUT("DB25", 4, 4, "输送运行超时"), |
| | | LIFT_TIMEOUT("DB25", 5, 4, "顶升运行超时"), |
| | | TASK_REQUEST_TIMEOUT("DB25", 6, 4, "申请任务超时"), |
| | | PALLET_PROTRUSION("DB25", 7, 4, "托盘突出报警"), |
| | | TASK_DUPLICATE("DB25", 8, 4, "任务重复报警"), |
| | | PRECONDITION_ERROR("DB25", 9, 4, "入站过程中前置条件异常"); |
| | | |
| | | private final String addressPattern; |
| | | private final int index; // 报警序号(1-based) |
| | | private final int byteLength; |
| | | private final String description; |
| | | |
| | | PlcAlarmDefinition(String addressPattern, int index, int byteLength, String description) { |
| | | this.addressPattern = addressPattern; |
| | | this.index = index; |
| | | this.byteLength = byteLength; |
| | | this.description = description; |
| | | } |
| | | |
| | | |
| | | public String buildAddress() { |
| | | return addressPattern + PlcConstant.ADDRESS_CONCATENATION + index; |
| | | } |
| | | |
| | | public String getAddressPattern() { |
| | | return addressPattern; |
| | | } |
| | | |
| | | public int getIndex() { |
| | | return index; |
| | | } |
| | | |
| | | public int getByteLength() { |
| | | return byteLength; |
| | | } |
| | | |
| | | public String getDescription() { |
| | | return description; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.core.constant; |
| | | |
| | | |
| | | public interface PlcConstant { |
| | | |
| | | |
| | | public static final String ADDRESS_CONCATENATION = "."; |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.core.constant; |
| | | |
| | | |
| | | /** |
| | | * 站点状态字段枚举(对应 §2.1) |
| | | */ |
| | | public enum StationStatusField { |
| | | ALL("DB100", 0, 12), |
| | | TASK_NUMBER("DB100", 0, 4), // 任务号,偏移0,4字节 |
| | | FINAL_TARGET("DB100", 4, 2), // 最终目标站,偏移4,2字节 |
| | | STATUS_WORD("DB100", 6, 2), // 状态字,偏移6,2字节 |
| | | TASK_WRITABLE("DB100", 8, 2); // 任务可写区,偏移8,2字节 |
| | | |
| | | private final String addressPattern; |
| | | private final int offset; |
| | | private final int byteLength; |
| | | |
| | | StationStatusField(String addressPattern, int offset, int byteLength) { |
| | | this.addressPattern = addressPattern; |
| | | this.offset = offset; |
| | | this.byteLength = byteLength; |
| | | } |
| | | |
| | | /** |
| | | * 根据 DB 块编号和站点偏移生成具体地址 |
| | | * |
| | | * @return PLC4X 地址字符串,如 "DB100.D0" |
| | | */ |
| | | public String buildAddress() { |
| | | return addressPattern + PlcConstant.ADDRESS_CONCATENATION + offset; |
| | | } |
| | | |
| | | |
| | | public String getAddressPattern() { |
| | | return addressPattern; |
| | | } |
| | | |
| | | public int getOffset() { |
| | | return offset; |
| | | } |
| | | |
| | | public int getByteLength() { |
| | | return byteLength; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.core.constant; |
| | | |
| | | |
| | | /** |
| | | * 任务下发字段枚举(对应 §2.4) |
| | | */ |
| | | public enum TaskField { |
| | | ALL("DB13", 0, 12), |
| | | TASK_NUMBER("DB13", 0, 4), |
| | | START_STATION("DB13", 4, 2), |
| | | DEST_STATION("DB13", 6, 2), |
| | | DIRECTION("DB13", 8, 2), |
| | | ROUTE_NUMBER("DB13", 10, 2); |
| | | |
| | | private final String addressPattern; |
| | | private final int offset; |
| | | private final int byteLength; |
| | | |
| | | TaskField(String addressPattern, int offset, int byteLength) { |
| | | this.addressPattern = addressPattern; |
| | | this.offset = offset; |
| | | this.byteLength = byteLength; |
| | | } |
| | | |
| | | public String getAddressPattern() { |
| | | return addressPattern; |
| | | } |
| | | |
| | | public int getOffset() { |
| | | return offset; |
| | | } |
| | | |
| | | public int getByteLength() { |
| | | return byteLength; |
| | | } |
| | | |
| | | /** |
| | | * 根据 DB 块编号和站点偏移生成具体地址 |
| | | * |
| | | * @return PLC4X 地址字符串,如 "DB100.DBD0" |
| | | */ |
| | | public String buildAddress() { |
| | | return addressPattern + PlcConstant.ADDRESS_CONCATENATION + offset; |
| | | } |
| | | } |
| | |
| | | |
| | | private List<Integer> staNos = new ArrayList<>(); |
| | | |
| | | private List<Integer> staNosError = new ArrayList<>(); |
| | | |
| | | @Data |
| | | public static class Sta { |
| | | |
| | |
| | | import com.zy.core.cache.MessageQueue; |
| | | import com.zy.core.cache.OutputQueue; |
| | | import com.zy.core.cache.SlaveConnection; |
| | | import com.zy.core.constant.*; |
| | | import com.zy.core.enums.SlaveType; |
| | | import com.zy.core.enums.TaskType; |
| | | import com.zy.core.model.DevpSlave; |
| | |
| | | private void read() throws InterruptedException { |
| | | List<Integer> staNos = slave.getStaNos(); |
| | | int staNoSize = staNos.size(); |
| | | OperateResultExOne<byte[]> result = siemensS7Net.Read("DB100.0", (short) (staNoSize * 10)); |
| | | OperateResultExOne<byte[]> result = siemensS7Net.Read(StationStatusField.ALL.buildAddress(), (short) (staNoSize * StationStatusField.ALL.getByteLength())); |
| | | if (result.IsSuccess) { |
| | | for (int i = 0; i < staNoSize; i++) { |
| | | Integer siteId = staNos.get(i); // 站点编号 |
| | |
| | | staProtocol.setSiteId(siteId); |
| | | station.put(siteId, staProtocol); |
| | | } |
| | | staProtocol.setWorkNo((int) siemensS7Net.getByteTransform().TransUInt32(result.Content, i * 10)); |
| | | staProtocol.setStaNo((int) siemensS7Net.getByteTransform().TransInt16(result.Content, i * 10 + 4)); |
| | | boolean[] status = siemensS7Net.getByteTransform().TransBool(result.Content, i * 10 + 6, 2); |
| | | staProtocol.setWorkNo((int) siemensS7Net.getByteTransform().TransUInt32(result.Content, i * StationStatusField.ALL.getByteLength())); |
| | | staProtocol.setStaNo((int) siemensS7Net.getByteTransform().TransInt16(result.Content, i * StationStatusField.ALL.getByteLength() + 4)); |
| | | boolean[] status = siemensS7Net.getByteTransform().TransBool(result.Content, i * StationStatusField.ALL.getByteLength() + 6, 2); |
| | | staProtocol.setAutoing(status[0]); // 自动 |
| | | staProtocol.setLoading(status[1]); // 有物 |
| | | staProtocol.setInEnable(status[2]); // 可入 |
| | |
| | | |
| | | //条码扫描器 |
| | | List<Integer> barcodeArr = slave.getBarcodeArr(); |
| | | OperateResultExOne<byte[]> result5 = siemensS7Net.Read("DB101.0", (short) (barcodeArr.size() * 8)); |
| | | OperateResultExOne<byte[]> result5 = siemensS7Net.Read(DeviceField.BARCODE.buildAddress(), (short) (barcodeArr.size() * DeviceField.BARCODE.getByteLength())); |
| | | if (result5.IsSuccess) { |
| | | for (int i = 0; i < barcodeArr.size(); i++) { |
| | | String barcode = siemensS7Net.getByteTransform().TransString(result5.Content, i * 8, 8, "UTF-8"); |
| | | String barcode = siemensS7Net.getByteTransform().TransString(result5.Content, i * DeviceField.BARCODE.getByteLength(), DeviceField.BARCODE.getByteLength(), "UTF-8"); |
| | | BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, barcodeArr.get(i)); |
| | | if (Cools.isEmpty(barcode)) { |
| | | barcodeThread.clearBarcode(); |
| | |
| | | } |
| | | } |
| | | |
| | | OperateResultExOne<byte[]> resultError = siemensS7Net.Read("DB103.0", (short) (staNoSize * 2)); |
| | | List<Integer> staNosError = slave.getStaNosError(); |
| | | OperateResultExOne<byte[]> resultError = siemensS7Net.Read(DeviceField.DIMENSION_WORD.buildAddress(), (short) (staNoSize * DeviceField.DIMENSION_WORD.getByteLength())); |
| | | if (resultError.IsSuccess) { |
| | | ArrayList<Integer> staNoError = new ArrayList<Integer>() {{ |
| | | add(102); |
| | | add(201); |
| | | add(211); |
| | | }}; |
| | | for (int i = 0; i < staNoError.size(); i++) { |
| | | Integer siteId = staNoError.get(i); // 站点编号 |
| | | for (int i = 0; i < staNosError.size(); i++) { |
| | | Integer siteId = staNosError.get(i); // 站点编号 |
| | | StaProtocol staProtocol = station.get(siteId); |
| | | if (null == staProtocol) { |
| | | staProtocol = new StaProtocol(); |
| | | staProtocol.setSiteId(siteId); |
| | | station.put(siteId, staProtocol); |
| | | } |
| | | boolean[] status = siemensS7Net.getByteTransform().TransBool(resultError.Content, i * 2, 1); |
| | | boolean[] status = siemensS7Net.getByteTransform().TransBool(resultError.Content, i * DeviceField.DIMENSION_WORD.getByteLength(), DeviceField.DIMENSION_WORD.getByteLength()); |
| | | staProtocol.setFrontErr(status[0]);// 前超限 |
| | | staProtocol.setBackErr(status[1]);// 后超限 |
| | | staProtocol.setHighErr(status[2]);// 高超限 |
| | |
| | | } |
| | | |
| | | //plc故障 |
| | | OperateResultExOne<byte[]> resultErr2 = siemensS7Net.Read("DB25.0", (short) (staNoSize * 4)); |
| | | OperateResultExOne<byte[]> resultErr2 = siemensS7Net.Read(PlcAlarmDefinition.ALL.buildAddress(), (short) (staNoSize * PlcAlarmDefinition.ALL.getByteLength())); |
| | | if (resultErr2.IsSuccess) { |
| | | for (int i = 0; i < staNoSize; i++) { |
| | | Integer siteId = staNos.get(i); // 站点编号 |
| | | boolean[] status = siemensS7Net.getByteTransform().TransBool(resultErr2.Content, i * 4, 2); |
| | | boolean[] status = siemensS7Net.getByteTransform().TransBool(resultErr2.Content, i * PlcAlarmDefinition.ALL.getByteLength(), PlcAlarmDefinition.ALL.getByteLength()); |
| | | StaProtocol staProtocol = station.get(siteId); |
| | | if (staProtocol != null) { |
| | | staProtocol.setBreakerErr(status[0]); |
| | |
| | | //任务下发次数 |
| | | int writeCount = 0; |
| | | do { |
| | | write = siemensS7Net.Write("DB13." + index * 12, staProtocol.getWorkNo().shortValue()); // 工作号 |
| | | write = siemensS7Net.Write(TaskField.TASK_NUMBER.getAddressPattern() + PlcConstant.ADDRESS_CONCATENATION + (index * TaskField.ALL.getByteLength() + TaskField.TASK_NUMBER.getOffset()), staProtocol.getWorkNo().shortValue()); // 工作号 |
| | | Thread.sleep(200); |
| | | write1 = siemensS7Net.Write("DB13." + (index * 12 + 6), staProtocol.getStaNo().shortValue()); // 目标站 |
| | | write1 = siemensS7Net.Write(TaskField.DEST_STATION.getAddressPattern() + PlcConstant.ADDRESS_CONCATENATION + (index * TaskField.ALL.getByteLength() + TaskField.DEST_STATION.getOffset()), staProtocol.getStaNo().shortValue()); // 目标站 |
| | | if (write.IsSuccess && write1.IsSuccess) { |
| | | log.info("写入输送线命令成功。输送线plc编号={},站点数据={},写入次数={}", slave.getId(), JSON.toJSON(staProtocol), writeCount); |
| | | break; |
| | |
| | | port: 102 |
| | | rack: 0 |
| | | slot: 0 |
| | | staNos: 1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013 |
| | | staNos: |
| | | - 1001 |
| | | - 1002 |
| | | - 1003 |
| | | - 1004 |
| | | - 1005 |
| | | - 1006 |
| | | - 1007 |
| | | - 1008 |
| | | - 1009 |
| | | - 1010 |
| | | - 1011 |
| | | - 1012 |
| | | - 1013 |
| | | staNosError: |
| | | - 1006 |
| | | barcodeArr: 1 |
| | | # ctu放货站点 |
| | | releaseSta[0]: |