|
|
@ -171,63 +171,47 @@ public class DeviceRunner implements CommandLineRunner { |
|
|
buffer.order(ByteOrder.BIG_ENDIAN); // 确保是高位在前(大端模式) |
|
|
buffer.order(ByteOrder.BIG_ENDIAN); // 确保是高位在前(大端模式) |
|
|
return buffer.getFloat(); |
|
|
return buffer.getFloat(); |
|
|
} |
|
|
} |
|
|
// 处理数据 |
|
|
|
|
|
public void handleOffData(DeviceInfo deviceInfo, String rollNo) { |
|
|
|
|
|
|
|
|
public void handleOffData1(DeviceInfo deviceInfo, String rollNo) { |
|
|
// 小卷分切信号获取方式调整:0x502,读取到信号后需要回写 0 |
|
|
// 小卷分切信号获取方式调整:0x502,读取到信号后需要回写 0 |
|
|
String ip = deviceInfo.getIp(); |
|
|
String ip = deviceInfo.getIp(); |
|
|
int port = deviceInfo.getPort(); |
|
|
int port = deviceInfo.getPort(); |
|
|
int smallCutSignalAddr = 504; |
|
|
|
|
|
|
|
|
int smallCutSignalAddr = 504; // 十六进制地址,十进制1282 |
|
|
Integer smallCutSignal = collectUtil.readHoldingRegister(ip, port, smallCutSignalAddr); |
|
|
Integer smallCutSignal = collectUtil.readHoldingRegister(ip, port, smallCutSignalAddr); |
|
|
logger.info("小卷分切信号:{}", smallCutSignal); |
|
|
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<Integer> list = getConnectData(deviceInfo); |
|
|
List<Integer> list = getConnectData(deviceInfo); |
|
|
// 总数 |
|
|
// 总数 |
|
|
Integer totalQtyAddress = deviceInfo.getTotalQtyAddress(); |
|
|
Integer totalQtyAddress = deviceInfo.getTotalQtyAddress(); |
|
|
//Integer totalQty = subAddressValue(totalQtyAddress, 1, list).get(0); |
|
|
|
|
|
logger.info("总数: {}", f); |
|
|
|
|
|
// 小卷分切不良数量 |
|
|
|
|
|
Integer multipleRollsAddress = deviceInfo.getMultipleRollsAddress(); |
|
|
|
|
|
Integer multipleRollsQty = deviceInfo.getMultipleRollsQty(); |
|
|
|
|
|
List<BigDecimal> 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<Integer> 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") |
|
|
@SuppressWarnings("unchecked") |
|
|
List<BigDecimal> preMultipleRollsList = Optional |
|
|
List<BigDecimal> preMultipleRollsList = Optional |
|
|
.ofNullable((List<BigDecimal>) redisTemplate.opsForValue() |
|
|
.ofNullable((List<BigDecimal>) redisTemplate.opsForValue() |
|
|
.get("deviceMultipleRolls:" + deviceInfo.getIp())) |
|
|
.get("deviceMultipleRolls:" + deviceInfo.getIp())) |
|
|
.orElse(new ArrayList<>()); |
|
|
.orElse(new ArrayList<>()); |
|
|
/*int preTotalQty = 0; |
|
|
|
|
|
|
|
|
// 上次的不良总数 |
|
|
|
|
|
int preTotalQty = 0; |
|
|
if (Objects.nonNull(preQty)) { |
|
|
if (Objects.nonNull(preQty)) { |
|
|
preTotalQty = preQty; |
|
|
preTotalQty = preQty; |
|
|
}*/ |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 小卷分切:优先使用信号触发(0x502),并在处理后回写清零。 |
|
|
// 小卷分切:优先使用信号触发(0x502),并在处理后回写清零。 |
|
|
// 为兼容历史逻辑,仍保留“总数归零”判断作为兜底。 |
|
|
// 为兼容历史逻辑,仍保留“总数归零”判断作为兜底。 |
|
|
boolean bySignal = Objects.nonNull(smallCutSignal) && smallCutSignal == 1; |
|
|
boolean bySignal = Objects.nonNull(smallCutSignal) && smallCutSignal == 1; |
|
|
if (bySignal) { |
|
|
if (bySignal) { |
|
|
|
|
|
// 小卷分切不良数量 |
|
|
|
|
|
Integer multipleRollsAddress = deviceInfo.getMultipleRollsAddress(); |
|
|
|
|
|
Integer multipleRollsQty = deviceInfo.getMultipleRollsQty(); |
|
|
|
|
|
List<BigDecimal> multipleRollsList = subAddressValue(multipleRollsAddress, multipleRollsQty, list).stream().map(BigDecimal::new).collect(Collectors.toList()); |
|
|
|
|
|
logger.info("小卷分切不良数量:{}", multipleRollsList); |
|
|
|
|
|
|
|
|
if (Objects.isNull(preMultipleRollsList) || preMultipleRollsList.isEmpty()) { |
|
|
if (Objects.isNull(preMultipleRollsList) || preMultipleRollsList.isEmpty()) { |
|
|
preMultipleRollsList = new ArrayList<>(Collections.nCopies(multipleRollsList.size(), BigDecimal.ZERO)); |
|
|
preMultipleRollsList = new ArrayList<>(Collections.nCopies(multipleRollsList.size(), BigDecimal.ZERO)); |
|
|
} |
|
|
} |
|
|
@ -246,12 +230,11 @@ public class DeviceRunner implements CommandLineRunner { |
|
|
logger.info("设备Site:{}", site); |
|
|
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) { |
|
|
if (smallCutSignal != null && smallCutSignal == 1) { |
|
|
qtyForMinCut = Integer.parseInt(String.valueOf(f)); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
qtyForMinCut = preTotalQty; |
|
|
|
|
|
}*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deviceGatherService.handleMinData(deviceInfo.getIp(), rollNo, site, seqNo, qtyForMinCut, preMultipleRollsList); |
|
|
deviceGatherService.handleMinData(deviceInfo.getIp(), rollNo, site, seqNo, qtyForMinCut, preMultipleRollsList); |
|
|
@ -259,59 +242,121 @@ public class DeviceRunner implements CommandLineRunner { |
|
|
if (bySignal) { |
|
|
if (bySignal) { |
|
|
collectUtil.writeHoldingRegister(ip, port, smallCutSignalAddr, 0); |
|
|
collectUtil.writeHoldingRegister(ip, port, smallCutSignalAddr, 0); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
// 总数 |
|
|
|
|
|
//redisTemplate.opsForValue().set("deviceQty:" + deviceInfo.getIp(), totalQty); |
|
|
|
|
|
// 不良数量 |
|
|
// 不良数量 |
|
|
redisTemplate.opsForValue().set("deviceMultipleRolls:" + deviceInfo.getIp(), multipleRollsList); |
|
|
redisTemplate.opsForValue().set("deviceMultipleRolls:" + deviceInfo.getIp(), multipleRollsList); |
|
|
} |
|
|
} |
|
|
|
|
|
// 总数 |
|
|
|
|
|
redisTemplate.opsForValue().set("deviceQty:" + deviceInfo.getIp(), totalQty); |
|
|
|
|
|
|
|
|
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(); |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
// 处理数据 |
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
// 创建事务 |
|
|
|
|
|
ModbusTCPTransaction transaction = new ModbusTCPTransaction(connection); |
|
|
|
|
|
|
|
|
// 如果获取到小卷分切信号为 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<Integer> list = getConnectData(deviceInfo); |
|
|
|
|
|
Integer addressValue = subAddressValue(deviceInfo.getMultipleRollsAddress()-1, 1, list).get(0); |
|
|
|
|
|
f = Float.parseFloat(addressValue.toString()); |
|
|
|
|
|
logger.info("1111按卷数获取: {}", addressValue); |
|
|
|
|
|
} |
|
|
|
|
|
List<Integer> list = getConnectData(deviceInfo); |
|
|
|
|
|
Integer totalQtyAddress = deviceInfo.getTotalQtyAddress(); |
|
|
|
|
|
|
|
|
// 创建读取输入寄存器的请求,假设地址200是寄存器地址偏移,这里读取2个寄存器(浮点数占2个16位寄存器) |
|
|
|
|
|
int ref = 200; // 寄存器地址偏移 |
|
|
|
|
|
int count = 2; // 读取的寄存器数量 |
|
|
|
|
|
ReadInputRegistersRequest request = new ReadInputRegistersRequest(ref, count); |
|
|
|
|
|
|
|
|
logger.info("总数: {}", f); |
|
|
|
|
|
|
|
|
// 设置事务的请求 |
|
|
|
|
|
transaction.setRequest(request); |
|
|
|
|
|
|
|
|
|
|
|
// 执行事务 |
|
|
|
|
|
transaction.execute(); |
|
|
|
|
|
|
|
|
|
|
|
// 获取响应 |
|
|
|
|
|
ReadInputRegistersResponse response = (ReadInputRegistersResponse) transaction.getResponse(); |
|
|
|
|
|
|
|
|
// 小卷分切:优先使用信号触发(0x502),并在处理后回写清零。 |
|
|
|
|
|
boolean bySignal = Objects.nonNull(smallCutSignal) && smallCutSignal == 1; |
|
|
|
|
|
if (bySignal) { |
|
|
|
|
|
collectUtil.writeHoldingRegister(ip, port, smallCutSignalAddr, 0); |
|
|
|
|
|
|
|
|
// 处理响应数据,将两个寄存器组合成浮点数 |
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
// 获取到分切信号后等待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<BigDecimal> 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<BigDecimal> preMultipleRollsList = Optional |
|
|
|
|
|
.ofNullable((List<BigDecimal>) 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); |
|
|
|
|
|
|
|
|
// 关闭连接 |
|
|
|
|
|
connection.close(); |
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
|
|
|
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<BigDecimal> newMultipleRollsList = subAddressValue(multipleRollsAddress, multipleRollsQty, list).stream().map(BigDecimal::new).collect(Collectors.toList()); |
|
|
|
|
|
logger.info("最新小卷分切不良数量:{}", multipleRollsList); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 总数 |
|
|
|
|
|
//redisTemplate.opsForValue().set("deviceQty:" + deviceInfo.getIp(), totalQty); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<Integer> getConnectData(DeviceInfo deviceInfo) { |
|
|
private List<Integer> getConnectData(DeviceInfo deviceInfo) { |
|
|
String ip = deviceInfo.getIp(); |
|
|
String ip = deviceInfo.getIp(); |
|
|
int port = deviceInfo.getPort(); |
|
|
int port = deviceInfo.getPort(); |
|
|
|