From 0acb949254769f466c48d3b4dc17ad73ae955d86 Mon Sep 17 00:00:00 2001 From: shenzhouyu Date: Thu, 26 Mar 2026 15:01:02 +0800 Subject: [PATCH] =?UTF-8?q?3in1=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devicecollector/runner/DeviceRunner.java | 213 +++++++++++------- 1 file changed, 129 insertions(+), 84 deletions(-) diff --git a/glue-modbus-collector/src/main/java/com/xujie/devicecollector/runner/DeviceRunner.java b/glue-modbus-collector/src/main/java/com/xujie/devicecollector/runner/DeviceRunner.java index 0102b8b..8f9ceb6 100644 --- a/glue-modbus-collector/src/main/java/com/xujie/devicecollector/runner/DeviceRunner.java +++ b/glue-modbus-collector/src/main/java/com/xujie/devicecollector/runner/DeviceRunner.java @@ -171,63 +171,47 @@ public class DeviceRunner implements CommandLineRunner { buffer.order(ByteOrder.BIG_ENDIAN); // 确保是高位在前(大端模式) return buffer.getFloat(); } - // 处理数据 - public void handleOffData(DeviceInfo deviceInfo, String rollNo) { + public void handleOffData1(DeviceInfo deviceInfo, String rollNo) { // 小卷分切信号获取方式调整:0x502,读取到信号后需要回写 0 String ip = deviceInfo.getIp(); int port = deviceInfo.getPort(); - int smallCutSignalAddr = 504; + int smallCutSignalAddr = 504; // 十六进制地址,十进制1282 Integer smallCutSignal = collectUtil.readHoldingRegister(ip, port, smallCutSignalAddr); logger.info("小卷分切信号:{}", smallCutSignal); - // 如果获取到小卷分切信号为 1,则读取寄存器地址 199 和 200 的值(32位浮点数,低字在前) - Integer lowWord = null; // 寄存器199:低16位 - Integer highWord = null; // 寄存器200:高16位 - Float f = null; - if (smallCutSignal != null && smallCutSignal == 1) { - // 读取199和200两个寄存器,组合成32位浮点数(低字在前) - lowWord = collectUtil.readHoldingRegister(ip, port, 199); - highWord = collectUtil.readHoldingRegister(ip, port, 200); - - if (lowWord != null && highWord != null) { - // 低字在前:低16位放在int的低位,高16位左移16位放在高位 - int bits = (lowWord & 0xFFFF) | ((highWord & 0xFFFF) << 16); - f = Float.intBitsToFloat(bits); - logger.info("小卷分切信号=1时,寄存器199(低字): {}, 寄存器200(高字): {}, 组合后的32位浮点数: {}", - lowWord, highWord, f); - } else { - logger.warn("读取寄存器199或200失败,lowWord: {}, highWord: {}", lowWord, highWord); - } - getTestData(); - } - List list = getConnectData(deviceInfo); // 总数 Integer totalQtyAddress = deviceInfo.getTotalQtyAddress(); - //Integer totalQty = subAddressValue(totalQtyAddress, 1, list).get(0); - logger.info("总数: {}", f); - // 小卷分切不良数量 - Integer multipleRollsAddress = deviceInfo.getMultipleRollsAddress(); - Integer multipleRollsQty = deviceInfo.getMultipleRollsQty(); - List multipleRollsList = subAddressValue(multipleRollsAddress, multipleRollsQty, list).stream().map(BigDecimal::new).collect(Collectors.toList()); - logger.info("小卷分切不良数量:{}", multipleRollsList); + Integer totalQty = subAddressValue(totalQtyAddress, 1, list).get(0); + logger.info("总数: {}", totalQty); + + List addressValue = subAddressValue(totalQtyAddress, 1, list); + logger.info("按卷数获取: {}", addressValue); + // 获取上次数量 小卷分切不良数量 // 上次的总数 - //Integer preQty = (Integer) redisTemplate.opsForValue().get("deviceQty:" + deviceInfo.getIp()); - // 上次的不良总数 + Integer preQty = (Integer) redisTemplate.opsForValue().get("deviceQty:" + deviceInfo.getIp()); + // 上次的总数 @SuppressWarnings("unchecked") List preMultipleRollsList = Optional .ofNullable((List) redisTemplate.opsForValue() .get("deviceMultipleRolls:" + deviceInfo.getIp())) .orElse(new ArrayList<>()); - /*int preTotalQty = 0; + // 上次的不良总数 + int preTotalQty = 0; if (Objects.nonNull(preQty)) { preTotalQty = preQty; - }*/ + } // 小卷分切:优先使用信号触发(0x502),并在处理后回写清零。 // 为兼容历史逻辑,仍保留“总数归零”判断作为兜底。 boolean bySignal = Objects.nonNull(smallCutSignal) && smallCutSignal == 1; if (bySignal) { + // 小卷分切不良数量 + Integer multipleRollsAddress = deviceInfo.getMultipleRollsAddress(); + Integer multipleRollsQty = deviceInfo.getMultipleRollsQty(); + List multipleRollsList = subAddressValue(multipleRollsAddress, multipleRollsQty, list).stream().map(BigDecimal::new).collect(Collectors.toList()); + logger.info("小卷分切不良数量:{}", multipleRollsList); + if (Objects.isNull(preMultipleRollsList) || preMultipleRollsList.isEmpty()) { preMultipleRollsList = new ArrayList<>(Collections.nCopies(multipleRollsList.size(), BigDecimal.ZERO)); } @@ -246,12 +230,11 @@ public class DeviceRunner implements CommandLineRunner { logger.info("设备Site:{}", site); // 小卷分切:信号触发时,优先使用“上次总数”作为分切前总数(若没有则用当前总数兜底) - //int qtyForMinCut = preTotalQty > 0 ? preTotalQty : totalQty; - Integer qtyForMinCut = null; + int qtyForMinCut = preTotalQty > 0 ? preTotalQty : totalQty; + /*Integer qtyForMinCut = null; if (smallCutSignal != null && smallCutSignal == 1) { - qtyForMinCut = Integer.parseInt(String.valueOf(f)); - - } + qtyForMinCut = preTotalQty; + }*/ deviceGatherService.handleMinData(deviceInfo.getIp(), rollNo, site, seqNo, qtyForMinCut, preMultipleRollsList); @@ -259,58 +242,120 @@ public class DeviceRunner implements CommandLineRunner { if (bySignal) { collectUtil.writeHoldingRegister(ip, port, smallCutSignalAddr, 0); } + // 不良数量 + redisTemplate.opsForValue().set("deviceMultipleRolls:" + deviceInfo.getIp(), multipleRollsList); } // 总数 - //redisTemplate.opsForValue().set("deviceQty:" + deviceInfo.getIp(), totalQty); - // 不良数量 - redisTemplate.opsForValue().set("deviceMultipleRolls:" + deviceInfo.getIp(), multipleRollsList); + redisTemplate.opsForValue().set("deviceQty:" + deviceInfo.getIp(), totalQty); + } + // 处理数据 + public void handleOffData(DeviceInfo deviceInfo, String rollNo) { + // 小卷分切信号获取方式调整:0x502,读取到信号后需要回写 0 + String ip = deviceInfo.getIp(); + int port = deviceInfo.getPort(); + int smallCutSignalAddr = 504; // 十六进制地址,十进制1282 + Integer smallCutSignal = collectUtil.readHoldingRegister(ip, port, smallCutSignalAddr); + logger.info("小卷分切信号:{}", smallCutSignal); + + // 如果获取到小卷分切信号为 1,则读取寄存器地址 199 和 200 的值(32位浮点数,低字在前) + Integer lowWord = null; // 寄存器201:低16位 + Integer highWord = null; // 寄存器200:高16位 + Float f = null; + if (smallCutSignal != null && smallCutSignal == 1) { + // 小卷总数:modbus地址300,32位浮点数,占寄存器300和301 + /*highWord = collectUtil.readHoldingRegister(ip, port, 300); + lowWord = collectUtil.readHoldingRegister(ip, port, 301); + + if (highWord != null && lowWord != null) { + int bits1 = ((highWord & 0xFFFF) << 16) | (lowWord & 0xFFFF); + float f1 = Float.intBitsToFloat(bits1); + int bits2 = ((lowWord & 0xFFFF) << 16) | (highWord & 0xFFFF); + float f2 = Float.intBitsToFloat(bits2); + float f3 = highWord.floatValue(); + float f4 = lowWord.floatValue(); + logger.info("寄存器200原始值:{}, 寄存器201原始值:{}", highWord, lowWord); + logger.info("方式1(大端 200高字|201低字):{}, 方式2(小端 201高字|200低字):{}, 方式3(200直接):{}, 方式4(201直接):{}", + f1, f2, f3, f4); + f = f3; + if(f<2000){ + f = 2080.0f; + } + } else { + logger.warn("读取小卷总数寄存器失败,reg200:{}, reg201:{}", highWord, lowWord); + }*/ + List list = getConnectData(deviceInfo); + Integer addressValue = subAddressValue(deviceInfo.getMultipleRollsAddress()-1, 1, list).get(0); + f = Float.parseFloat(addressValue.toString()); + logger.info("1111按卷数获取: {}", addressValue); + } + List list = getConnectData(deviceInfo); + Integer totalQtyAddress = deviceInfo.getTotalQtyAddress(); + + logger.info("总数: {}", f); + + + + // 小卷分切:优先使用信号触发(0x502),并在处理后回写清零。 + boolean bySignal = Objects.nonNull(smallCutSignal) && smallCutSignal == 1; + if (bySignal) { + collectUtil.writeHoldingRegister(ip, port, smallCutSignalAddr, 0); + + // 获取到分切信号后等待2秒,确保不良卷数已更新 + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + logger.warn("等待不良卷数更新时被中断", e); + } + // 重新读取连接数据(等待后刷新) + list = getConnectData(deviceInfo); + // 小卷分切不良数量 + Integer multipleRollsAddress = deviceInfo.getMultipleRollsAddress(); + Integer multipleRollsQty = deviceInfo.getMultipleRollsQty(); + List multipleRollsList = subAddressValue(multipleRollsAddress, multipleRollsQty, list).stream().map(BigDecimal::new).collect(Collectors.toList()); + logger.info("小卷分切不良数量:{}", multipleRollsList); + // 不良数量 + redisTemplate.opsForValue().set("deviceMultipleRolls:" + deviceInfo.getIp(), multipleRollsList); + // 上次的不良总数 + @SuppressWarnings("unchecked") + List preMultipleRollsList = Optional + .ofNullable((List) redisTemplate.opsForValue() + .get("deviceMultipleRolls:" + deviceInfo.getIp())) + .orElse(new ArrayList<>()); + if (Objects.isNull(preMultipleRollsList) || preMultipleRollsList.isEmpty()) { + preMultipleRollsList = new ArrayList<>(Collections.nCopies(multipleRollsList.size(), BigDecimal.ZERO)); + } + String site = ""; + String seqNo = ""; + String value = deviceInfoService.queryDeviceSiteByIp(deviceInfo.getIp()); + if (StringUtils.isEmpty(value)) { + value = "2"; + } + String[] strings = value.split(";"); + if (strings.length > 1) { + seqNo = strings[1]; + } + site = strings[0]; + logger.info("设备Site:{}", site); - private void getTestData() { - try { - // Modbus设备IP地址和端口 - String ipAddress = "172.26.59.53"; // 替换为实际的Modbus设备IP - int port = 502; // 默认Modbus TCP端口为502 - - // 创建TCP连接 - TCPMasterConnection connection = new TCPMasterConnection(InetAddress.getByName(ipAddress)); - connection.setPort(port); - connection.connect(); - - // 创建事务 - ModbusTCPTransaction transaction = new ModbusTCPTransaction(connection); - - // 创建读取输入寄存器的请求,假设地址200是寄存器地址偏移,这里读取2个寄存器(浮点数占2个16位寄存器) - int ref = 200; // 寄存器地址偏移 - int count = 2; // 读取的寄存器数量 - ReadInputRegistersRequest request = new ReadInputRegistersRequest(ref, count); - - // 设置事务的请求 - transaction.setRequest(request); - - // 执行事务 - transaction.execute(); - - // 获取响应 - ReadInputRegistersResponse response = (ReadInputRegistersResponse) transaction.getResponse(); - - // 处理响应数据,将两个寄存器组合成浮点数 - if (response != null) { - InputRegister[] registers = response.getRegisters(); - if (registers.length >= 2) { - // 将两个16位寄存器组合成一个32位浮点数 - int intValue = (registers[0].getValue() << 16) | registers[1].getValue(); - float floatValue = Float.intBitsToFloat(intValue); - System.out.println("读取到的浮点数: " + floatValue); + Integer qtyForMinCut = null; + if (f != null) { + qtyForMinCut = f.intValue(); } + + deviceGatherService.handleMinData(deviceInfo.getIp(), rollNo, site, seqNo, qtyForMinCut, preMultipleRollsList); + + multipleRollsAddress = deviceInfo.getMultipleRollsAddress(); + multipleRollsQty = deviceInfo.getMultipleRollsQty(); + List newMultipleRollsList = subAddressValue(multipleRollsAddress, multipleRollsQty, list).stream().map(BigDecimal::new).collect(Collectors.toList()); + logger.info("最新小卷分切不良数量:{}", multipleRollsList); } - // 关闭连接 - connection.close(); - } catch (Exception e) { - e.printStackTrace(); + // 总数 + //redisTemplate.opsForValue().set("deviceQty:" + deviceInfo.getIp(), totalQty); } - } + private List getConnectData(DeviceInfo deviceInfo) { String ip = deviceInfo.getIp();