|
@@ -4,17 +4,19 @@ package com.ruoyi.common.server;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import com.ruoyi.common.utils.ModBusUtils;
|
|
|
import io.netty.buffer.ByteBuf;
|
|
|
+import io.netty.buffer.ByteBufUtil;
|
|
|
import io.netty.buffer.Unpooled;
|
|
|
-import io.netty.channel.Channel;
|
|
|
-import io.netty.channel.ChannelHandler;
|
|
|
-import io.netty.channel.ChannelHandlerContext;
|
|
|
-import io.netty.channel.ChannelInboundHandlerAdapter;
|
|
|
+import io.netty.channel.*;
|
|
|
+import io.netty.util.CharsetUtil;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
+import java.nio.ByteBuffer;
|
|
|
+import java.nio.ByteOrder;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.LocalTime;
|
|
|
import java.time.ZoneId;
|
|
@@ -23,6 +25,8 @@ import java.util.Map;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
+import static ch.qos.logback.core.encoder.ByteArrayUtil.hexStringToByteArray;
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @Project : huimv.shiwan
|
|
@@ -64,15 +68,73 @@ public class EnvInputServerHandler extends ChannelInboundHandlerAdapter {
|
|
|
}
|
|
|
askTextSb.append(text);
|
|
|
}
|
|
|
- @Override
|
|
|
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
|
|
|
|
|
- System.out.println("收到的数据:"+msg);
|
|
|
+@Override
|
|
|
+public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
|
|
+ System.out.println("收到的数据:" + msg);
|
|
|
+
|
|
|
+ if (msg instanceof ByteBuf) {
|
|
|
+ ByteBuf byteBuf = (ByteBuf) msg;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 1. 打印原始十六进制数据(用于调试)
|
|
|
+ String hexData = ByteBufUtil.hexDump(byteBuf);
|
|
|
+ System.out.println("十六进制数据: " + hexData);
|
|
|
+
|
|
|
+ // 2. 检查数据长度是否足够(假设每个参数占4字节,状态码占2字节)
|
|
|
+ if (byteBuf.readableBytes() < 22) { // 5个浮点数(4*5=20) + 1个状态码(2) = 22字节
|
|
|
+ System.err.println("数据长度不足!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 读取数据到字节数组(方便解析)
|
|
|
+
|
|
|
+ byte[] bytes = hexStringToByteArray(hexData.substring(14));
|
|
|
+
|
|
|
+ // 4. 解析浮点数参数(IEEE 754,大端序)
|
|
|
+ float cod = bytesToFloat(bytes, 0); // 寄存器 0-1
|
|
|
+ float ph = bytesToFloat(bytes, 4); // 寄存器 2-3
|
|
|
+ float flow = bytesToFloat(bytes, 8); // 寄存器 4-5
|
|
|
+ float ammonia = bytesToFloat(bytes, 12); // 寄存器 6-7
|
|
|
+ float phosphorus = bytesToFloat(bytes, 16);// 寄存器 8-9
|
|
|
+
|
|
|
+ // 5. 解析状态码(16位有符号整数)
|
|
|
+ int status = bytesToInt16(bytes, 20); // 寄存器 10
|
|
|
+
|
|
|
+ // 6. 打印解析结果
|
|
|
+ System.out.println("解析结果:");
|
|
|
+ System.out.println("COD: " + cod + " mg/L");
|
|
|
+ System.out.println("pH: " + ph);
|
|
|
+ System.out.println("流量: " + flow + " m³/h");
|
|
|
+ System.out.println("氨氮: " + ammonia + " mg/L");
|
|
|
+ System.out.println("总磷: " + phosphorus + " mg/L");
|
|
|
+
|
|
|
+ } finally {
|
|
|
+ // 7. 释放 ByteBuf
|
|
|
+ byteBuf.release();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
- super.channelRead(ctx, msg);
|
|
|
+
|
|
|
+ // 解析 IEEE 754 浮点数(4字节)
|
|
|
+ private float bytesToFloat(byte[] bytes, int offset) {
|
|
|
+ return ByteBuffer.wrap(bytes, offset, 4)
|
|
|
+ .order(ByteOrder.BIG_ENDIAN)
|
|
|
+ .getFloat();
|
|
|
}
|
|
|
|
|
|
- public static boolean isStartOfToday(Date date) {
|
|
|
+ // 解析 16位有符号整数(2字节)
|
|
|
+ private int bytesToInt16(byte[] bytes, int offset) {
|
|
|
+ return ByteBuffer.wrap(bytes, offset, 2)
|
|
|
+ .order(ByteOrder.BIG_ENDIAN)
|
|
|
+ .getShort();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public boolean isStartOfToday(Date date) {
|
|
|
// 创建一个示例的LocalDateTime对象
|
|
|
LocalDateTime exampleTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
|
|
// 获取今天的开始时间
|
|
@@ -87,27 +149,7 @@ public class EnvInputServerHandler extends ChannelInboundHandlerAdapter {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
- public boolean isTimeBetween(LocalTime startTime, LocalTime endTime) {
|
|
|
- LocalDateTime now = LocalDateTime.now();
|
|
|
-
|
|
|
- // 获取当前日期的00:00和23:59:59
|
|
|
- LocalDateTime startOfDay = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
|
|
|
- LocalDateTime endOfDay = startOfDay.plusDays(1).minusSeconds(1);
|
|
|
-
|
|
|
- // 创建表示时间段的开始和结束时间的LocalDateTime对象
|
|
|
- LocalDateTime startDateTime = LocalDateTime.of(now.toLocalDate(), startTime);
|
|
|
- LocalDateTime endDateTime = LocalDateTime.of(now.toLocalDate(), endTime);
|
|
|
-
|
|
|
- // 判断当前时间是否在两个时间段之一内
|
|
|
- if (endDateTime.isBefore(startDateTime)) {
|
|
|
- // 时间段跨越午夜,分两部分判断
|
|
|
- return (now.isAfter(startDateTime) && now.isBefore(endOfDay)) ||
|
|
|
- (now.isAfter(startOfDay) && now.isBefore(endDateTime));
|
|
|
- } else {
|
|
|
- // 时间段在同一天内,直接判断
|
|
|
- return now.isAfter(startDateTime) && now.isBefore(endDateTime);
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
@Override
|
|
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
|
|
Channel channel = ctx.channel();
|
|
@@ -155,6 +197,7 @@ public class EnvInputServerHandler extends ChannelInboundHandlerAdapter {
|
|
|
|
|
|
@Override
|
|
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
|
|
+ System.err.println("发生异常: " + cause.getMessage());
|
|
|
if (cause.getMessage().indexOf("Connection reset") != -1) {
|
|
|
log.info("相关采集器设备正在重启:" + cause.toString());
|
|
|
}
|