From fb2913c9aa28a91f6427c53db26a1cee0df331f3 Mon Sep 17 00:00:00 2001 From: gengby <858962040@qq.com> Date: Wed, 22 May 2024 09:50:50 +0800 Subject: [PATCH] =?UTF-8?q?add=EF=BC=9Amodbus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shangdianke/ItemProtocol.java | 38 +++++++ .../PhotoelectricDetectionDeviceDriver.java | 64 +++--------- ...otoelectricDetectionStationDefinition.java | 5 - .../java/org/nl/acs/modbus/TCPClient.java | 99 +++++++++++++++++++ .../java/org/nl/acs/modbus/TCPClient2.java | 96 ++++++++++++++++++ .../java/org/nl/acs/opc/DeviceManageDto.java | 2 +- .../resources/config/application-dev2.yml | 1 + .../photoelectric_detection_station.vue | 42 +++++++- .../device/driver/standard_ordinary_site.vue | 35 ++++++- 9 files changed, 325 insertions(+), 57 deletions(-) create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/ItemProtocol.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/modbus/TCPClient.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/modbus/TCPClient2.java diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/ItemProtocol.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/ItemProtocol.java new file mode 100644 index 0000000..7398f8d --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/ItemProtocol.java @@ -0,0 +1,38 @@ +package org.nl.acs.device_driver.shangdianke; + +import cn.hutool.core.util.StrUtil; +import lombok.Getter; +import lombok.Setter; +import org.nl.acs.modbus.TCPClient; +import org.nl.acs.modbus.TCPClient2; + +import java.util.Optional; + +/** + * @author zhangjiangwei + */ +@Getter +@Setter +public class ItemProtocol { + + /** + * 光电信号 + */ + public static final String ITEM_MOVE = "move"; + + private final PhotoelectricDetectionDeviceDriver driver; + + public ItemProtocol(PhotoelectricDetectionDeviceDriver driver) { + this.driver = driver; + } + + public int getMove() { + String ip = Optional.ofNullable(this.getDriver().getDevice().getExtraValue().get("ipAddress")).map(Object::toString).orElse(null); + String index = Optional.ofNullable(this.getDriver().getDevice().getExtraValue().get("index")).map(Object::toString).orElse("-1"); + if (StrUtil.isNotEmpty(ip) && !StrUtil.equals(index, "-1")) { + return TCPClient.startConnection(ip, 502, Integer.parseInt(index)); + } + return 0; + } + +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/PhotoelectricDetectionDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/PhotoelectricDetectionDeviceDriver.java index b355ff3..1c66bac 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/PhotoelectricDetectionDeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/PhotoelectricDetectionDeviceDriver.java @@ -1,6 +1,7 @@ package org.nl.acs.device_driver.shangdianke; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.Getter; @@ -15,6 +16,7 @@ import org.nl.acs.ext.wms.data.BaseRequest; import org.nl.acs.ext.wms.data.BaseResponse; import org.nl.acs.ext.wms.service.AcsToWmsService; import org.nl.acs.log.service.DeviceExecuteLogService; +import org.nl.acs.modbus.TCPClient; import org.nl.acs.monitor.DeviceStageMonitor; import org.nl.acs.opc.DeviceAppService; import org.nl.acs.task.service.TaskService; @@ -25,6 +27,7 @@ import org.nl.modules.wql.util.SpringContextHolder; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; +import java.util.Optional; /** * @author zhangjiangwei @@ -35,47 +38,15 @@ import java.util.Map; @RequiredArgsConstructor public class PhotoelectricDetectionDeviceDriver extends AbstractOpcDeviceDriver implements DeviceDriver, ExecutableDeviceDriver, RouteableDeviceDriver, DeviceStageMonitor, StandardRequestMethod, HeartbeatableDeviceDriver { - /** - * 心跳 - */ - private int heartbeat = 0; - private int lastHeartbeat = this.heartbeat; - - /** - * 工作模式 - */ - private int mode = 0; - private int lastMode = this.mode; - /** * 光电信号 */ private int move = 0; private int lastMove = this.move; - /** - * 动作信号 - */ - private int action = 0; - private int lastAction = this.action; - - /** - * 报警信号 - */ - private int error = 0; - private int lastError = this.error; - - /** - * 下发命令 - */ - private int toCommand = 0; - private int lastToCommand = this.toCommand; - private static final int MODE = 3; private String currentDeviceCode = null; - private boolean isOnline = false; - private boolean isError = false; private String message = ""; private final ItemProtocol itemProtocol = new ItemProtocol(this); @@ -84,7 +55,7 @@ public class PhotoelectricDetectionDeviceDriver extends AbstractOpcDeviceDriver private long requireTime = System.currentTimeMillis(); private long requireTimeOut = 10000L; - private final DeviceExecuteLogService deviceExecuteLogService = SpringContextHolder.getBean(DeviceExecuteLogService.class); + //private final DeviceExecuteLogService deviceExecuteLogService = SpringContextHolder.getBean(DeviceExecuteLogService.class); private final DeviceAppService deviceAppService = SpringContextHolder.getBean(DeviceAppService.class); private final TaskService taskService = SpringContextHolder.getBean(TaskService.class); private final DeviceService deviceService = SpringContextHolder.getBean(DeviceService.class); @@ -97,20 +68,19 @@ public class PhotoelectricDetectionDeviceDriver extends AbstractOpcDeviceDriver try { this.currentDeviceCode = this.getDeviceCode(); - this.heartbeat = this.itemProtocol.getHeartbeat(); - this.mode = this.itemProtocol.getMode(); this.move = this.itemProtocol.getMove(); - this.action = this.itemProtocol.getAction(); - this.error = this.itemProtocol.getError(); - this.toCommand = this.itemProtocol.getToCommand(); if (this.move != this.lastMove) { + this.lucene.deviceExecuteLog(new LuceneLogDto(this.currentDeviceCode, "信号, move发生变化, 由" + lastMove + " ->" + move)); if (move == 0) { requireSuccess = false; } } - if (mode > 0 && !requireSuccess) { + String applyFlag = Optional.ofNullable(this.getDevice().getExtraValue().get("applyFlag")).map(Object::toString).orElse("false"); + + + if (StrUtil.equals(applyFlag, "true") && !requireSuccess) { Object methodName = this.device.getExtraValue().get(String.valueOf(MODE)); if (ObjectUtil.isNotEmpty(methodName)) { try { @@ -120,13 +90,13 @@ public class PhotoelectricDetectionDeviceDriver extends AbstractOpcDeviceDriver log.error(e.getMessage(), e); String message = "执行工作模式对应方法 " + methodName + " 错误!错误信息:" + e.getMessage(); this.message = message; - this.deviceExecuteLogService.deviceExecuteLog(this.currentDeviceCode, "", "", message); - this.isError = true; + this.lucene.deviceExecuteLog(new LuceneLogDto(this.currentDeviceCode, message)); } } else { String message = "未知工作模式,驱动未配置对应方法。"; this.message = message; - this.deviceExecuteLogService.deviceExecuteLog(this.currentDeviceCode, "", "", message); + this.lucene.deviceExecuteLog(new LuceneLogDto(this.currentDeviceCode, message)); + // this.deviceExecuteLogService.deviceExecuteLog(this.currentDeviceCode, "", "", message); } } @@ -135,12 +105,8 @@ public class PhotoelectricDetectionDeviceDriver extends AbstractOpcDeviceDriver log.error(e.getMessage(), e); return; } - this.lastHeartbeat = this.heartbeat; - this.lastMode = this.mode; + this.lastMove = this.move; - this.lastAction = this.action; - this.lastError = this.error; - this.lastToCommand = this.toCommand; } private void executionMethodByMode(String methodName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { @@ -160,14 +126,14 @@ public class PhotoelectricDetectionDeviceDriver extends AbstractOpcDeviceDriver */ @Override public boolean apply_put_empty_vehicle() { - if (move == 0) { + if (this.move == 0) { BaseRequest request = new BaseRequest(); request.setDevice_code(this.currentDeviceCode); request.setRequest_medthod_code(Thread.currentThread().getStackTrace()[1].getMethodName()); request.setRequest_medthod_name(RequestMethodEnum.getName(Thread.currentThread().getStackTrace()[1].getMethodName())); BaseResponse resp = JSON.toJavaObject(JSONObject.parseObject(acsToWmsService.applyTask(request)), BaseResponse.class); message = RequestMethodEnum.getName("apply_put_empty_vehicle") + "apply_put_empty_vehicle 接口请求LMS..."; - lucene.deviceExecuteLog(new LuceneLogDto(this.currentDeviceCode, message + "参数:" + JSON.toJSONString(request))); + this.lucene.deviceExecuteLog(new LuceneLogDto(this.currentDeviceCode, message + "参数:" + JSON.toJSONString(request))); if (resp.isOk()) { this.requireSuccess = true; } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/PhotoelectricDetectionStationDefinition.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/PhotoelectricDetectionStationDefinition.java index f62d55d..9d1712a 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/PhotoelectricDetectionStationDefinition.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/shangdianke/PhotoelectricDetectionStationDefinition.java @@ -52,18 +52,13 @@ public class PhotoelectricDetectionStationDefinition implements OpcDeviceDriverD @Override public List getReadableItemDTOs() { ArrayList itemDTOs = new ArrayList<>(); - itemDTOs.add(new ItemDTO(ItemProtocol.ITEM_HEARTBEAT, "心跳", "")); - itemDTOs.add(new ItemDTO(ItemProtocol.ITEM_MODE, "工作模式", "")); itemDTOs.add(new ItemDTO(ItemProtocol.ITEM_MOVE, "光电信号", "")); - itemDTOs.add(new ItemDTO(ItemProtocol.ITEM_ACTION, "动作信号", "")); - itemDTOs.add(new ItemDTO(ItemProtocol.ITEM_ERROR, "报警信号", "")); return itemDTOs; } @Override public List getWriteableItemDTOs() { ArrayList itemDTOs = new ArrayList<>(); - itemDTOs.add(new ItemDTO(ItemProtocol.ITEM_TO_COMMAND, "下发命令", "")); return itemDTOs; } } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/modbus/TCPClient.java b/acs/nladmin-system/src/main/java/org/nl/acs/modbus/TCPClient.java new file mode 100644 index 0000000..0c060d7 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/modbus/TCPClient.java @@ -0,0 +1,99 @@ +package org.nl.acs.modbus; + +import java.io.*; +import java.net.Socket; +import java.net.SocketTimeoutException; + +public class TCPClient { + + public static synchronized int startConnection(String ip, int port, int index) { + String hexMessage = "000600000006010200000008"; + try (Socket socket = new Socket(ip, port); + DataOutputStream outToServer = new DataOutputStream(socket.getOutputStream()); + BufferedReader inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()))) { + socket.setSoTimeout(10000); + sendMessage(outToServer, hexMessage); + String message = receiveMessage(socket); + int[] binary = binary(message); +// for (int bit : binary) { +// System.out.println(bit); +// } + return binary[index - 1]; + } catch (IOException e) { + e.printStackTrace(); + } + return -1; + } + + + private static void sendMessage(DataOutputStream out, String hexMessage) throws IOException { + byte[] messageBytes = hexStringToByteArray(hexMessage); + out.write(messageBytes); + } + + private static String receiveMessage(Socket socket) throws IOException { + try (InputStream inputStream = socket.getInputStream(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { + byte[] data = new byte[1024]; + int nRead; + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + if (nRead < 1024) { + break; + } + } + buffer.flush(); + return byteArrayToHexString(buffer.toByteArray()); + } catch (SocketTimeoutException e) { + e.printStackTrace(); + return null; + } + } + + private static byte[] hexStringToByteArray(String s) { + int length = s.length(); + byte[] data = new byte[length / 2]; + for (int i = 0; i < length; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + + Character.digit(s.charAt(i + 1), 16)); + } + return data; + } + + private static String byteArrayToHexString(byte[] bytes) { + StringBuilder sb = new StringBuilder(); + for (byte b : bytes) { + sb.append(String.format("%02X", b)); + } + return sb.toString(); + } + + public static int[] binary(String hexString) { + String lastFourHex = hexString.substring(hexString.length() - 4); + int decimal = Integer.parseInt(lastFourHex, 16); + String binaryString = Integer.toBinaryString(decimal); + System.out.println("length:" + binaryString.length()); + int[] binaryArray = new int[binaryString.length()]; + for (int i = 0; i < binaryString.length(); i++) { + binaryArray[i] = Character.getNumericValue(binaryString.charAt(i)); + } + reverseArray(binaryArray); + return binaryArray; + } + + public static void reverseArray(int[] array) { + int temp; + int n = array.length; + for (int i = 0; i < n / 2; i++) { + temp = array[i]; + array[i] = array[n - i - 1]; + array[n - i - 1] = temp; + } + } + + public static void main(String[] args) { + int move = startConnection("192.168.1.12", 502, 2); + System.out.println(move); + } + +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/modbus/TCPClient2.java b/acs/nladmin-system/src/main/java/org/nl/acs/modbus/TCPClient2.java new file mode 100644 index 0000000..0d204c5 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/modbus/TCPClient2.java @@ -0,0 +1,96 @@ +package org.nl.acs.modbus; + +import lombok.SneakyThrows; + +import java.io.*; +import java.net.Socket; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantLock; + +import static oshi.util.ParseUtil.byteArrayToHexString; +import static oshi.util.ParseUtil.hexStringToByteArray; + +public class TCPClient2 { + + private static final ConcurrentHashMap connectionPools = new ConcurrentHashMap<>(); + private static final ReentrantLock lock = new ReentrantLock(); + private static final String hexMessage = "000600000006010200000008"; + + @SneakyThrows + public static int startConnection(String ip, int port, int index) { + String key = ip + ":" + port; + Socket socket = getSocketFromPool(key, ip, port); + if (socket == null) return -1; + DataOutputStream outToServer = new DataOutputStream(socket.getOutputStream()); + sendMessage(outToServer, hexMessage); + String message = receiveMessage(socket); + int[] binary = binary(message); + return binary[index - 1]; + } + + //@SneakyThrows + private static Socket getSocketFromPool(String key, String ip, int port) { + lock.lock(); + try { + if (connectionPools.keySet().contains(key) && connectionPools.get(key).isConnected()) { + return connectionPools.get(key); + } else { + connectionPools.remove(key); + Socket socket = new Socket(ip, port); + socket.setKeepAlive(true); + socket.setSoTimeout(10000); + connectionPools.put(key, socket); + return socket; + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + return null; + } + + + private static void sendMessage(DataOutputStream out, String hexMessage) throws IOException { + byte[] messageBytes = hexStringToByteArray(hexMessage); + out.write(messageBytes); + } + + private static String receiveMessage(Socket socket) throws IOException { + InputStream inputStream = socket.getInputStream(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + byte[] data = new byte[1024]; + int nRead; + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + if (nRead < 1024) { + break; + } + } + buffer.flush(); + return byteArrayToHexString(buffer.toByteArray()); + } + + private static int[] binary(String hexString) { + if (hexString == null) { + hexString = "00060000000401020100"; + } + String lastFourHex = hexString.substring(hexString.length() - 4); + int decimal = Integer.parseInt(lastFourHex, 16); + String binaryString = Integer.toBinaryString(decimal); + int[] binaryArray = new int[binaryString.length()]; + for (int i = 0; i < binaryString.length(); i++) { + binaryArray[i] = Character.getNumericValue(binaryString.charAt(i)); + } + reverseArray(binaryArray); + return binaryArray; + } + + private static void reverseArray(int[] array) { + for (int i = 0, j = array.length - 1; i < j; i++, j--) { + int temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + } +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/opc/DeviceManageDto.java b/acs/nladmin-system/src/main/java/org/nl/acs/opc/DeviceManageDto.java index bbcd560..128528b 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/opc/DeviceManageDto.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/opc/DeviceManageDto.java @@ -73,7 +73,7 @@ public class DeviceManageDto { DeviceExtraManageDto dto = (DeviceExtraManageDto) var2.next(); // result.put(dto.getExtra_code(), dto.parseName()); if(ObjectUtil.isEmpty( dto.getExtra_value())){ - result.put(dto.getExtra_code(), dto.getExtra_name()); + result.put(dto.getExtra_code(), dto.parseName()); } else { result.put(dto.getExtra_code(), dto.parseName()); } diff --git a/acs/nladmin-system/src/main/resources/config/application-dev2.yml b/acs/nladmin-system/src/main/resources/config/application-dev2.yml index 04eaae3..847dc94 100644 --- a/acs/nladmin-system/src/main/resources/config/application-dev2.yml +++ b/acs/nladmin-system/src/main/resources/config/application-dev2.yml @@ -1,5 +1,6 @@ server: port: 8010 + max-http-header-size: 65536 #配置数据源 spring: datasource: diff --git a/acs/nladmin-ui/src/views/acs/device/driver/shangdianke/photoelectric_detection_station.vue b/acs/nladmin-ui/src/views/acs/device/driver/shangdianke/photoelectric_detection_station.vue index 09f1948..675849d 100644 --- a/acs/nladmin-ui/src/views/acs/device/driver/shangdianke/photoelectric_detection_station.vue +++ b/acs/nladmin-ui/src/views/acs/device/driver/shangdianke/photoelectric_detection_station.vue @@ -49,6 +49,28 @@ + + + + + + + + + + + + + + + + + @@ -98,6 +120,13 @@ + + + + + + + @@ -332,7 +361,10 @@ export default { manual_create_task: true, is_pickup: true, is_release: true, - link_device_code: [] + link_device_code: [], + ipAddress: '', + index: '', + applyFlag: '' }, rules: {} } @@ -541,6 +573,14 @@ export default { item.code = this.opc_code + '.' + this.plc_code + '.' + this.device_code + '.' + item.code } }) + }, + validateInput(value) { + const num = parseInt(value, 10) + if (num < 1 || num > 8) { + this.form.index = 1 + } else { + this.form.index = num + } } } } diff --git a/acs/nladmin-ui/src/views/acs/device/driver/standard_ordinary_site.vue b/acs/nladmin-ui/src/views/acs/device/driver/standard_ordinary_site.vue index 1dfd00e..696e306 100644 --- a/acs/nladmin-ui/src/views/acs/device/driver/standard_ordinary_site.vue +++ b/acs/nladmin-ui/src/views/acs/device/driver/standard_ordinary_site.vue @@ -7,8 +7,31 @@ + + + + + + + + + + + + + + + + + + @@ -168,7 +191,9 @@ export default { is_release: true, station_manager: true, auto_clean_task: true, - input_material: true + input_material: true, + ipAddress: '', + index: '' }, rules: {} } @@ -210,6 +235,14 @@ export default { }) } }) + }, + validateInput(value) { + const num = parseInt(value, 10) + if (num < 1 || num > 8) { + this.form.index = 1 + } else { + this.form.index = num + } } } }