diff --git a/pom.xml b/pom.xml
index 8d79423..945d5a6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.njzscloud
- gps
+ localizer
0.0.1
jar
@@ -18,6 +18,11 @@
fastjson2
2.0.51
+
+ org.eclipse.paho
+ org.eclipse.paho.client.mqttv3
+ 1.2.5
+
com.fasterxml.jackson.core
diff --git a/src/main/java/com/njzscloud/App.java b/src/main/java/com/njzscloud/App.java
index cf3f85c..0caace6 100644
--- a/src/main/java/com/njzscloud/App.java
+++ b/src/main/java/com/njzscloud/App.java
@@ -1,21 +1,14 @@
package com.njzscloud;
-import com.njzscloud.server.TcpServer;
-import com.njzscloud.tuqiang.Tuqiang;
+import com.njzscloud.common.mqtt.Mqtt;
+import com.njzscloud.common.tuqiang.Tuqiang;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class App {
- static Tuqiang tuqiang;
-
public static void main(String[] args) {
- tuqiang = new Tuqiang();
- TcpServer tcpServer = new TcpServer(18888, 1, 2);
- try {
- tcpServer.start();
- log.info("TCP服务器已停止");
- } catch (Exception e) {
- log.error("TCP服务器启动失败", e);
- }
+ Mqtt.run("tcp://localhost:1883", "tuqiang", "admin", "123456");
+ Mqtt.addListener(new MqttMsgHandlers());
+ Tuqiang.run(18888, 1, 2);
}
}
diff --git a/src/main/java/com/njzscloud/MqttMsgHandlers.java b/src/main/java/com/njzscloud/MqttMsgHandlers.java
new file mode 100644
index 0000000..2df8a39
--- /dev/null
+++ b/src/main/java/com/njzscloud/MqttMsgHandlers.java
@@ -0,0 +1,71 @@
+package com.njzscloud;
+
+import com.njzscloud.common.mqtt.support.MqttListener;
+import com.njzscloud.common.mqtt.support.MqttMsg;
+import com.njzscloud.common.tuqiang.Tuqiang;
+import com.njzscloud.param.*;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class MqttMsgHandlers {
+
+ /**
+ * 开启追踪
+ */
+ @MqttListener(topic = "location/track")
+ public void onMessage(MqttMsg msg) {
+ LocationTrackParam locationTrackParam = msg.getMsg(LocationTrackParam.class);
+ Tuqiang.track(locationTrackParam.getTerminalId(), locationTrackParam.getInterval());
+ }
+
+ /**
+ * 获取当前位置
+ */
+ @MqttListener(topic = "location/current")
+ public void currentLocation(MqttMsg msg) {
+ LocationCurrentParam locationCurrentParam = msg.getMsg(LocationCurrentParam.class);
+ Tuqiang.currentLocation(locationCurrentParam.getTerminalId());
+ }
+
+ /**
+ * 启用报警
+ */
+ @MqttListener(topic = "location/warn")
+ public void enableWarn(MqttMsg msg) {
+ EnableWarnParam enableWarnParam = msg.getMsg(EnableWarnParam.class);
+ String terminalId = enableWarnParam.getTerminalId();
+ boolean enable = enableWarnParam.isEnable();
+ Tuqiang.enableWarn(terminalId, enable);
+ }
+
+ /**
+ * 设置速度阈值
+ */
+ @MqttListener(topic = "location/speed_threshold")
+ public void speedThreshold(MqttMsg msg) {
+ SpeedThresholdParam speedThresholdParam = msg.getMsg(SpeedThresholdParam.class);
+ String terminalId = speedThresholdParam.getTerminalId();
+ int speed = speedThresholdParam.getSpeed();
+ Tuqiang.speedThreshold(terminalId, speed);
+ }
+
+ /**
+ * 获取设备信息
+ */
+ @MqttListener(topic = "location/device_info")
+ public void obtainDeviceInfo(MqttMsg msg) {
+ ObtainDeviceInfoParam obtainDeviceInfoParam = msg.getMsg(ObtainDeviceInfoParam.class);
+ String terminalId = obtainDeviceInfoParam.getTerminalId();
+ Tuqiang.obtainDeviceInfo(terminalId);
+ }
+
+ /**
+ * 获取设备信息
+ */
+ @MqttListener(topic = "location/heartbeat")
+ public void setHeartbeat(MqttMsg msg) {
+ SetHeartbeatParam setHeartbeatParam = msg.getMsg(SetHeartbeatParam.class);
+ String terminalId = setHeartbeatParam.getTerminalId();
+ Tuqiang.setHeartbeat(terminalId, setHeartbeatParam.getInterval());
+ }
+}
diff --git a/src/main/java/com/njzscloud/TuqiangListeners.java b/src/main/java/com/njzscloud/TuqiangListeners.java
new file mode 100644
index 0000000..94aeba4
--- /dev/null
+++ b/src/main/java/com/njzscloud/TuqiangListeners.java
@@ -0,0 +1,102 @@
+package com.njzscloud;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.map.MapUtil;
+import com.njzscloud.common.jt808.support.MessageBody;
+import com.njzscloud.common.mqtt.Mqtt;
+import com.njzscloud.common.tuqiang.msg.DeviceInfo;
+import com.njzscloud.common.tuqiang.msg.LocationReportMsg;
+import com.njzscloud.common.tuqiang.msg.SearchLocationResponseMsg;
+import com.njzscloud.common.tuqiang.msg.TerminalTxtReportMsg;
+import com.njzscloud.common.tuqiang.support.TuqiangListener;
+import com.njzscloud.result.RealtimeLocationResult;
+import io.netty.buffer.ByteBuf;
+import lombok.extern.slf4j.Slf4j;
+
+import static com.njzscloud.common.jt808.support.JT808MessageResolver.*;
+
+@Slf4j
+public class TuqiangListeners {
+ /**
+ * 终端心跳消息
+ */
+ @TuqiangListener(messageId = Heartbeat)
+ public void onHeartbeat(MessageBody message) {
+ String terminalId = message.getTerminalId();
+ Mqtt.publish(terminalId + "/online", MapUtil.builder()
+ .put("online", true)
+ .put("terminalId", terminalId)
+ .put("time", DateUtil.now())
+ .build());
+ }
+
+ /**
+ * 终端位置信息汇报消息
+ */
+ @TuqiangListener(messageId = LocationReport)
+ public void onLocationReport(MessageBody message) {
+ ByteBuf byteBuf = message.getBody();
+ LocationReportMsg locationReportMsg = new LocationReportMsg(byteBuf);
+ log.info("终端位置信息汇报消息: {}", locationReportMsg);
+
+ String terminalId = message.getTerminalId();
+ RealtimeLocationResult realtimeLocationResult = BeanUtil.copyProperties(locationReportMsg, RealtimeLocationResult.class)
+ .setTerminalId(terminalId);
+ Mqtt.publish(terminalId + "/track_location", realtimeLocationResult);
+
+ }
+
+ /**
+ * 定位数据批量上传消息
+ */
+ @TuqiangListener(messageId = LocationBatchReport)
+ public void onLocationBatchUpload(MessageBody message) {
+ String terminalId = message.getTerminalId();
+ ByteBuf body = message.getBody();
+ int count = body.readUnsignedShort();
+ int type = body.readByte();
+
+ for (int i = 0; i < count; i++) {
+ int length = body.readUnsignedShort();
+ LocationReportMsg locationReportMsg = new LocationReportMsg(body.slice(body.readerIndex(), length));
+ body.skipBytes(length);
+ BeanUtil.copyProperties(locationReportMsg, RealtimeLocationResult.class);
+ RealtimeLocationResult realtimeLocationResult = BeanUtil.copyProperties(locationReportMsg, RealtimeLocationResult.class)
+ .setTerminalId(terminalId)
+ .setType(type == 0 ? "正常位置汇报" : "盲区补报");
+ Mqtt.publish(terminalId + "/track_location", realtimeLocationResult);
+ }
+ }
+
+ /**
+ * 查询位置响应消息
+ */
+ @TuqiangListener(messageId = LocationSearch)
+ public void onSearchLocationResponse(MessageBody message) {
+ String terminalId = message.getTerminalId();
+ ByteBuf body = message.getBody();
+ SearchLocationResponseMsg searchLocationResponseMsg = new SearchLocationResponseMsg(body);
+ log.info("查询位置响应消息: {}", searchLocationResponseMsg);
+
+ LocationReportMsg locationReportMsg = searchLocationResponseMsg.getLocationReportMsg();
+ RealtimeLocationResult realtimeLocationResult = BeanUtil.copyProperties(locationReportMsg, RealtimeLocationResult.class)
+ .setTerminalId(terminalId);
+ Mqtt.publish(terminalId + "/current_location", realtimeLocationResult);
+ }
+
+ /**
+ * 终端文本信息汇报消息
+ */
+ @TuqiangListener(messageId = TxtReport)
+ public void onTerminalTxtReport(MessageBody message) {
+ TerminalTxtReportMsg terminalTxtReportMsg = new TerminalTxtReportMsg(message.getBody());
+ log.info("终端文本信息汇报消息: {}", terminalTxtReportMsg);
+ String txt = terminalTxtReportMsg.getTxt();
+ DeviceInfo deviceInfo = DeviceInfo.parse(txt);
+ if (deviceInfo != null) {
+ String terminalId = message.getTerminalId();
+ Mqtt.publish(terminalId + "/device_info", deviceInfo);
+ }
+ }
+}
diff --git a/src/main/java/com/njzscloud/common/ex/CliException.java b/src/main/java/com/njzscloud/common/core/ex/CliException.java
similarity index 94%
rename from src/main/java/com/njzscloud/common/ex/CliException.java
rename to src/main/java/com/njzscloud/common/core/ex/CliException.java
index 50d5d49..2a8746e 100644
--- a/src/main/java/com/njzscloud/common/ex/CliException.java
+++ b/src/main/java/com/njzscloud/common/core/ex/CliException.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ex;
+package com.njzscloud.common.core.ex;
import cn.hutool.core.util.StrUtil;
diff --git a/src/main/java/com/njzscloud/common/ex/ExceptionDepthComparator.java b/src/main/java/com/njzscloud/common/core/ex/ExceptionDepthComparator.java
similarity index 98%
rename from src/main/java/com/njzscloud/common/ex/ExceptionDepthComparator.java
rename to src/main/java/com/njzscloud/common/core/ex/ExceptionDepthComparator.java
index 2ef846a..a16a861 100644
--- a/src/main/java/com/njzscloud/common/ex/ExceptionDepthComparator.java
+++ b/src/main/java/com/njzscloud/common/core/ex/ExceptionDepthComparator.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ex;
+package com.njzscloud.common.core.ex;
import cn.hutool.core.lang.Assert;
diff --git a/src/main/java/com/njzscloud/common/ex/ExceptionMsg.java b/src/main/java/com/njzscloud/common/core/ex/ExceptionMsg.java
similarity index 97%
rename from src/main/java/com/njzscloud/common/ex/ExceptionMsg.java
rename to src/main/java/com/njzscloud/common/core/ex/ExceptionMsg.java
index ba516a1..c9cbebc 100644
--- a/src/main/java/com/njzscloud/common/ex/ExceptionMsg.java
+++ b/src/main/java/com/njzscloud/common/core/ex/ExceptionMsg.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ex;
+package com.njzscloud.common.core.ex;
/**
diff --git a/src/main/java/com/njzscloud/common/ex/ExceptionType.java b/src/main/java/com/njzscloud/common/core/ex/ExceptionType.java
similarity index 88%
rename from src/main/java/com/njzscloud/common/ex/ExceptionType.java
rename to src/main/java/com/njzscloud/common/core/ex/ExceptionType.java
index f8c1da9..3615dfb 100644
--- a/src/main/java/com/njzscloud/common/ex/ExceptionType.java
+++ b/src/main/java/com/njzscloud/common/core/ex/ExceptionType.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ex;
+package com.njzscloud.common.core.ex;
import lombok.RequiredArgsConstructor;
diff --git a/src/main/java/com/njzscloud/common/ex/Exceptions.java b/src/main/java/com/njzscloud/common/core/ex/Exceptions.java
similarity index 98%
rename from src/main/java/com/njzscloud/common/ex/Exceptions.java
rename to src/main/java/com/njzscloud/common/core/ex/Exceptions.java
index b90cf41..3643126 100644
--- a/src/main/java/com/njzscloud/common/ex/Exceptions.java
+++ b/src/main/java/com/njzscloud/common/core/ex/Exceptions.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ex;
+package com.njzscloud.common.core.ex;
import cn.hutool.core.util.StrUtil;
diff --git a/src/main/java/com/njzscloud/common/ex/ExpectData.java b/src/main/java/com/njzscloud/common/core/ex/ExpectData.java
similarity index 95%
rename from src/main/java/com/njzscloud/common/ex/ExpectData.java
rename to src/main/java/com/njzscloud/common/core/ex/ExpectData.java
index b1e8d4d..b1f8be2 100644
--- a/src/main/java/com/njzscloud/common/ex/ExpectData.java
+++ b/src/main/java/com/njzscloud/common/core/ex/ExpectData.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ex;
+package com.njzscloud.common.core.ex;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/njzscloud/common/ex/SysError.java b/src/main/java/com/njzscloud/common/core/ex/SysError.java
similarity index 94%
rename from src/main/java/com/njzscloud/common/ex/SysError.java
rename to src/main/java/com/njzscloud/common/core/ex/SysError.java
index 17c541e..ca6b3df 100644
--- a/src/main/java/com/njzscloud/common/ex/SysError.java
+++ b/src/main/java/com/njzscloud/common/core/ex/SysError.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ex;
+package com.njzscloud.common.core.ex;
import cn.hutool.core.util.StrUtil;
diff --git a/src/main/java/com/njzscloud/common/ex/SysException.java b/src/main/java/com/njzscloud/common/core/ex/SysException.java
similarity index 94%
rename from src/main/java/com/njzscloud/common/ex/SysException.java
rename to src/main/java/com/njzscloud/common/core/ex/SysException.java
index 13f45b2..64f1e98 100644
--- a/src/main/java/com/njzscloud/common/ex/SysException.java
+++ b/src/main/java/com/njzscloud/common/core/ex/SysException.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ex;
+package com.njzscloud.common.core.ex;
import cn.hutool.core.util.StrUtil;
diff --git a/src/main/java/com/njzscloud/common/ex/SysThrowable.java b/src/main/java/com/njzscloud/common/core/ex/SysThrowable.java
similarity index 92%
rename from src/main/java/com/njzscloud/common/ex/SysThrowable.java
rename to src/main/java/com/njzscloud/common/core/ex/SysThrowable.java
index 8744760..1e9eb7b 100644
--- a/src/main/java/com/njzscloud/common/ex/SysThrowable.java
+++ b/src/main/java/com/njzscloud/common/core/ex/SysThrowable.java
@@ -1,7 +1,7 @@
-package com.njzscloud.common.ex;
+package com.njzscloud.common.core.ex;
import cn.hutool.core.map.MapUtil;
-import com.njzscloud.common.jackson.Jackson;
+import com.njzscloud.common.core.jackson.Jackson;
/**
* 系统异常
diff --git a/src/main/java/com/njzscloud/common/fastjson/Fastjson.java b/src/main/java/com/njzscloud/common/core/fastjson/Fastjson.java
similarity index 99%
rename from src/main/java/com/njzscloud/common/fastjson/Fastjson.java
rename to src/main/java/com/njzscloud/common/core/fastjson/Fastjson.java
index 4f2fded..59f6e16 100644
--- a/src/main/java/com/njzscloud/common/fastjson/Fastjson.java
+++ b/src/main/java/com/njzscloud/common/core/fastjson/Fastjson.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.fastjson;
+package com.njzscloud.common.core.fastjson;
import cn.hutool.core.date.DatePattern;
import com.alibaba.fastjson2.JSON;
diff --git a/src/main/java/com/njzscloud/common/fastjson/serializer/DictObjectDeserializer.java b/src/main/java/com/njzscloud/common/core/fastjson/serializer/DictObjectDeserializer.java
similarity index 94%
rename from src/main/java/com/njzscloud/common/fastjson/serializer/DictObjectDeserializer.java
rename to src/main/java/com/njzscloud/common/core/fastjson/serializer/DictObjectDeserializer.java
index 9069cdf..548f665 100644
--- a/src/main/java/com/njzscloud/common/fastjson/serializer/DictObjectDeserializer.java
+++ b/src/main/java/com/njzscloud/common/core/fastjson/serializer/DictObjectDeserializer.java
@@ -1,14 +1,14 @@
-package com.njzscloud.common.fastjson.serializer;
+package com.njzscloud.common.core.fastjson.serializer;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import com.alibaba.fastjson2.util.TypeUtils;
-import com.njzscloud.common.ex.Exceptions;
-import com.njzscloud.common.ienum.Dict;
-import com.njzscloud.common.ienum.DictInt;
-import com.njzscloud.common.ienum.DictStr;
-import com.njzscloud.common.ienum.IEnum;
+import com.njzscloud.common.core.ex.Exceptions;
+import com.njzscloud.common.core.ienum.Dict;
+import com.njzscloud.common.core.ienum.DictInt;
+import com.njzscloud.common.core.ienum.DictStr;
+import com.njzscloud.common.core.ienum.IEnum;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Type;
diff --git a/src/main/java/com/njzscloud/common/fastjson/serializer/DictObjectSerializer.java b/src/main/java/com/njzscloud/common/core/fastjson/serializer/DictObjectSerializer.java
similarity index 92%
rename from src/main/java/com/njzscloud/common/fastjson/serializer/DictObjectSerializer.java
rename to src/main/java/com/njzscloud/common/core/fastjson/serializer/DictObjectSerializer.java
index 1d7f668..38f1ce2 100644
--- a/src/main/java/com/njzscloud/common/fastjson/serializer/DictObjectSerializer.java
+++ b/src/main/java/com/njzscloud/common/core/fastjson/serializer/DictObjectSerializer.java
@@ -1,12 +1,12 @@
-package com.njzscloud.common.fastjson.serializer;
+package com.njzscloud.common.core.fastjson.serializer;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.util.TypeUtils;
import com.alibaba.fastjson2.writer.ObjectWriter;
-import com.njzscloud.common.ienum.Dict;
-import com.njzscloud.common.ienum.DictInt;
-import com.njzscloud.common.ienum.DictStr;
-import com.njzscloud.common.ienum.IEnum;
+import com.njzscloud.common.core.ienum.Dict;
+import com.njzscloud.common.core.ienum.DictInt;
+import com.njzscloud.common.core.ienum.DictStr;
+import com.njzscloud.common.core.ienum.IEnum;
import java.lang.reflect.Type;
diff --git a/src/main/java/com/njzscloud/common/ienum/Dict.java b/src/main/java/com/njzscloud/common/core/ienum/Dict.java
similarity index 80%
rename from src/main/java/com/njzscloud/common/ienum/Dict.java
rename to src/main/java/com/njzscloud/common/core/ienum/Dict.java
index c06e017..5b4bfe2 100644
--- a/src/main/java/com/njzscloud/common/ienum/Dict.java
+++ b/src/main/java/com/njzscloud/common/core/ienum/Dict.java
@@ -1,11 +1,11 @@
-package com.njzscloud.common.ienum;
+package com.njzscloud.common.core.ienum;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.njzscloud.common.fastjson.serializer.DictObjectDeserializer;
-import com.njzscloud.common.fastjson.serializer.DictObjectSerializer;
-import com.njzscloud.common.jackson.serializer.DictDeserializer;
-import com.njzscloud.common.jackson.serializer.DictSerializer;
+import com.njzscloud.common.core.fastjson.serializer.DictObjectDeserializer;
+import com.njzscloud.common.core.fastjson.serializer.DictObjectSerializer;
+import com.njzscloud.common.core.jackson.serializer.DictDeserializer;
+import com.njzscloud.common.core.jackson.serializer.DictSerializer;
/**
* 字典枚举
diff --git a/src/main/java/com/njzscloud/common/ienum/DictInt.java b/src/main/java/com/njzscloud/common/core/ienum/DictInt.java
similarity index 77%
rename from src/main/java/com/njzscloud/common/ienum/DictInt.java
rename to src/main/java/com/njzscloud/common/core/ienum/DictInt.java
index 3761461..6e9c5cb 100644
--- a/src/main/java/com/njzscloud/common/ienum/DictInt.java
+++ b/src/main/java/com/njzscloud/common/core/ienum/DictInt.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ienum;
+package com.njzscloud.common.core.ienum;
/**
diff --git a/src/main/java/com/njzscloud/common/ienum/DictStr.java b/src/main/java/com/njzscloud/common/core/ienum/DictStr.java
similarity index 76%
rename from src/main/java/com/njzscloud/common/ienum/DictStr.java
rename to src/main/java/com/njzscloud/common/core/ienum/DictStr.java
index 45c4442..345cfac 100644
--- a/src/main/java/com/njzscloud/common/ienum/DictStr.java
+++ b/src/main/java/com/njzscloud/common/core/ienum/DictStr.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ienum;
+package com.njzscloud.common.core.ienum;
/**
* "值" 类型为 String
diff --git a/src/main/java/com/njzscloud/common/ienum/IEnum.java b/src/main/java/com/njzscloud/common/core/ienum/IEnum.java
similarity index 91%
rename from src/main/java/com/njzscloud/common/ienum/IEnum.java
rename to src/main/java/com/njzscloud/common/core/ienum/IEnum.java
index 865c60b..7bf9bb5 100644
--- a/src/main/java/com/njzscloud/common/ienum/IEnum.java
+++ b/src/main/java/com/njzscloud/common/core/ienum/IEnum.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.ienum;
+package com.njzscloud.common.core.ienum;
/**
* 枚举接口
diff --git a/src/main/java/com/njzscloud/common/jackson/Jackson.java b/src/main/java/com/njzscloud/common/core/jackson/Jackson.java
similarity index 96%
rename from src/main/java/com/njzscloud/common/jackson/Jackson.java
rename to src/main/java/com/njzscloud/common/core/jackson/Jackson.java
index b533645..344be91 100644
--- a/src/main/java/com/njzscloud/common/jackson/Jackson.java
+++ b/src/main/java/com/njzscloud/common/core/jackson/Jackson.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.jackson;
+package com.njzscloud.common.core.jackson;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.annotation.JsonInclude;
@@ -9,10 +9,10 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
-import com.njzscloud.common.ex.Exceptions;
-import com.njzscloud.common.jackson.serializer.BigDecimalModule;
-import com.njzscloud.common.jackson.serializer.LongModule;
-import com.njzscloud.common.jackson.serializer.TimeModule;
+import com.njzscloud.common.core.ex.Exceptions;
+import com.njzscloud.common.core.jackson.serializer.BigDecimalModule;
+import com.njzscloud.common.core.jackson.serializer.LongModule;
+import com.njzscloud.common.core.jackson.serializer.TimeModule;
import lombok.extern.slf4j.Slf4j;
import java.io.InputStream;
diff --git a/src/main/java/com/njzscloud/common/jackson/serializer/BigDecimalModule.java b/src/main/java/com/njzscloud/common/core/jackson/serializer/BigDecimalModule.java
similarity index 88%
rename from src/main/java/com/njzscloud/common/jackson/serializer/BigDecimalModule.java
rename to src/main/java/com/njzscloud/common/core/jackson/serializer/BigDecimalModule.java
index b9990a0..dd4d211 100644
--- a/src/main/java/com/njzscloud/common/jackson/serializer/BigDecimalModule.java
+++ b/src/main/java/com/njzscloud/common/core/jackson/serializer/BigDecimalModule.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.jackson.serializer;
+package com.njzscloud.common.core.jackson.serializer;
import com.fasterxml.jackson.databind.deser.std.NumberDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
diff --git a/src/main/java/com/njzscloud/common/jackson/serializer/BigDecimalSerializer.java b/src/main/java/com/njzscloud/common/core/jackson/serializer/BigDecimalSerializer.java
similarity index 91%
rename from src/main/java/com/njzscloud/common/jackson/serializer/BigDecimalSerializer.java
rename to src/main/java/com/njzscloud/common/core/jackson/serializer/BigDecimalSerializer.java
index 8c68a1a..216e1f2 100644
--- a/src/main/java/com/njzscloud/common/jackson/serializer/BigDecimalSerializer.java
+++ b/src/main/java/com/njzscloud/common/core/jackson/serializer/BigDecimalSerializer.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.jackson.serializer;
+package com.njzscloud.common.core.jackson.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
diff --git a/src/main/java/com/njzscloud/common/jackson/serializer/DictDeserializer.java b/src/main/java/com/njzscloud/common/core/jackson/serializer/DictDeserializer.java
similarity index 93%
rename from src/main/java/com/njzscloud/common/jackson/serializer/DictDeserializer.java
rename to src/main/java/com/njzscloud/common/core/jackson/serializer/DictDeserializer.java
index b84de6a..c7dc002 100644
--- a/src/main/java/com/njzscloud/common/jackson/serializer/DictDeserializer.java
+++ b/src/main/java/com/njzscloud/common/core/jackson/serializer/DictDeserializer.java
@@ -1,15 +1,15 @@
-package com.njzscloud.common.jackson.serializer;
+package com.njzscloud.common.core.jackson.serializer;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.TextNode;
-import com.njzscloud.common.ex.Exceptions;
-import com.njzscloud.common.ienum.Dict;
-import com.njzscloud.common.ienum.DictInt;
-import com.njzscloud.common.ienum.DictStr;
-import com.njzscloud.common.ienum.IEnum;
+import com.njzscloud.common.core.ex.Exceptions;
+import com.njzscloud.common.core.ienum.Dict;
+import com.njzscloud.common.core.ienum.DictInt;
+import com.njzscloud.common.core.ienum.DictStr;
+import com.njzscloud.common.core.ienum.IEnum;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
diff --git a/src/main/java/com/njzscloud/common/jackson/serializer/DictSerializer.java b/src/main/java/com/njzscloud/common/core/jackson/serializer/DictSerializer.java
similarity index 89%
rename from src/main/java/com/njzscloud/common/jackson/serializer/DictSerializer.java
rename to src/main/java/com/njzscloud/common/core/jackson/serializer/DictSerializer.java
index 4dbe41e..cc4b4ed 100644
--- a/src/main/java/com/njzscloud/common/jackson/serializer/DictSerializer.java
+++ b/src/main/java/com/njzscloud/common/core/jackson/serializer/DictSerializer.java
@@ -1,13 +1,13 @@
-package com.njzscloud.common.jackson.serializer;
+package com.njzscloud.common.core.jackson.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
-import com.njzscloud.common.ienum.Dict;
-import com.njzscloud.common.ienum.DictInt;
-import com.njzscloud.common.ienum.DictStr;
-import com.njzscloud.common.ienum.IEnum;
+import com.njzscloud.common.core.ienum.Dict;
+import com.njzscloud.common.core.ienum.DictInt;
+import com.njzscloud.common.core.ienum.DictStr;
+import com.njzscloud.common.core.ienum.IEnum;
import java.io.IOException;
diff --git a/src/main/java/com/njzscloud/common/jackson/serializer/LongModule.java b/src/main/java/com/njzscloud/common/core/jackson/serializer/LongModule.java
similarity index 87%
rename from src/main/java/com/njzscloud/common/jackson/serializer/LongModule.java
rename to src/main/java/com/njzscloud/common/core/jackson/serializer/LongModule.java
index 003223a..e960706 100644
--- a/src/main/java/com/njzscloud/common/jackson/serializer/LongModule.java
+++ b/src/main/java/com/njzscloud/common/core/jackson/serializer/LongModule.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.jackson.serializer;
+package com.njzscloud.common.core.jackson.serializer;
import com.fasterxml.jackson.databind.deser.std.NumberDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
diff --git a/src/main/java/com/njzscloud/common/jackson/serializer/LongSerializer.java b/src/main/java/com/njzscloud/common/core/jackson/serializer/LongSerializer.java
similarity index 91%
rename from src/main/java/com/njzscloud/common/jackson/serializer/LongSerializer.java
rename to src/main/java/com/njzscloud/common/core/jackson/serializer/LongSerializer.java
index e5d60e8..c54a7ad 100644
--- a/src/main/java/com/njzscloud/common/jackson/serializer/LongSerializer.java
+++ b/src/main/java/com/njzscloud/common/core/jackson/serializer/LongSerializer.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.jackson.serializer;
+package com.njzscloud.common.core.jackson.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
diff --git a/src/main/java/com/njzscloud/common/jackson/serializer/TimeModule.java b/src/main/java/com/njzscloud/common/core/jackson/serializer/TimeModule.java
similarity index 96%
rename from src/main/java/com/njzscloud/common/jackson/serializer/TimeModule.java
rename to src/main/java/com/njzscloud/common/core/jackson/serializer/TimeModule.java
index 57eb081..adb18d4 100644
--- a/src/main/java/com/njzscloud/common/jackson/serializer/TimeModule.java
+++ b/src/main/java/com/njzscloud/common/core/jackson/serializer/TimeModule.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.jackson.serializer;
+package com.njzscloud.common.core.jackson.serializer;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.databind.module.SimpleModule;
diff --git a/src/main/java/com/njzscloud/common/log/AnsiColor.java b/src/main/java/com/njzscloud/common/core/log/AnsiColor.java
similarity index 97%
rename from src/main/java/com/njzscloud/common/log/AnsiColor.java
rename to src/main/java/com/njzscloud/common/core/log/AnsiColor.java
index 545e11c..ead36c2 100644
--- a/src/main/java/com/njzscloud/common/log/AnsiColor.java
+++ b/src/main/java/com/njzscloud/common/core/log/AnsiColor.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.log;
+package com.njzscloud.common.core.log;
import java.util.Arrays;
diff --git a/src/main/java/com/njzscloud/common/log/ColorConverter.java b/src/main/java/com/njzscloud/common/core/log/ColorConverter.java
similarity index 96%
rename from src/main/java/com/njzscloud/common/log/ColorConverter.java
rename to src/main/java/com/njzscloud/common/core/log/ColorConverter.java
index 9e3c986..788eea3 100644
--- a/src/main/java/com/njzscloud/common/log/ColorConverter.java
+++ b/src/main/java/com/njzscloud/common/core/log/ColorConverter.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.log;
+package com.njzscloud.common.core.log;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
diff --git a/src/main/java/com/njzscloud/common/utils/BCD.java b/src/main/java/com/njzscloud/common/core/utils/BCD.java
similarity index 87%
rename from src/main/java/com/njzscloud/common/utils/BCD.java
rename to src/main/java/com/njzscloud/common/core/utils/BCD.java
index 40fadb8..cc7913f 100644
--- a/src/main/java/com/njzscloud/common/utils/BCD.java
+++ b/src/main/java/com/njzscloud/common/core/utils/BCD.java
@@ -1,4 +1,4 @@
-package com.njzscloud.common.utils;
+package com.njzscloud.common.core.utils;
public class BCD {
public static String bcdToStr(byte[] bcd) {
diff --git a/src/main/java/com/njzscloud/common/utils/GroupUtil.java b/src/main/java/com/njzscloud/common/core/utils/GroupUtil.java
similarity index 99%
rename from src/main/java/com/njzscloud/common/utils/GroupUtil.java
rename to src/main/java/com/njzscloud/common/core/utils/GroupUtil.java
index d3410ce..dbf5206 100644
--- a/src/main/java/com/njzscloud/common/utils/GroupUtil.java
+++ b/src/main/java/com/njzscloud/common/core/utils/GroupUtil.java
@@ -1,9 +1,9 @@
-package com.njzscloud.common.utils;
+package com.njzscloud.common.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
-import com.njzscloud.common.ex.Exceptions;
-import com.njzscloud.common.fastjson.Fastjson;
+import com.njzscloud.common.core.ex.Exceptions;
+import com.njzscloud.common.core.fastjson.Fastjson;
import java.util.*;
import java.util.function.BiFunction;
diff --git a/src/main/java/com/njzscloud/common/jt808/JT808.java b/src/main/java/com/njzscloud/common/jt808/JT808.java
new file mode 100644
index 0000000..f279c09
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/jt808/JT808.java
@@ -0,0 +1,148 @@
+package com.njzscloud.common.jt808;
+
+import com.njzscloud.common.jt808.support.JT808Message;
+import com.njzscloud.common.jt808.support.JT808MessageResolver;
+import com.njzscloud.common.jt808.support.MessageBody;
+import com.njzscloud.common.jt808.util.FlowId;
+import com.njzscloud.common.tcp.TcpServer;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFutureListener;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
+
+/**
+ * JT808消息发送工具类
+ * 提供便捷的方法发送各种类型的JT808消息
+ */
+@Slf4j
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class JT808 {
+
+ // 终端手机号与Channel的映射
+ private static final Map terminalChannels = new ConcurrentHashMap<>();
+
+ private static TcpServer tcpServer;
+
+ public static void run(int port, int bossThreads, int workerThreads) {
+ tcpServer = new TcpServer(port, bossThreads, workerThreads);
+ tcpServer.start();
+ }
+
+ public static void stop() {
+ if (tcpServer != null) {
+ tcpServer.stop();
+ tcpServer = null;
+ }
+ }
+
+ /**
+ * 注册消息监听器
+ */
+ public static void addListener(String messageId, Consumer listener) {
+ JT808MessageResolver.addResolver(messageId, listener);
+ }
+
+ /**
+ * 注册终端与通道的映射关系
+ */
+ public static void register(String terminalId, Channel channel) {
+ if (terminalId != null && channel != null) {
+ if (terminalChannels.get(terminalId) != channel) {
+ terminalChannels.put(terminalId, channel);
+ }
+ }
+ }
+
+ /**
+ * 移除终端与通道的映射关系
+ */
+ public static void unregister(Channel channel) {
+ if (channel != null) {
+ terminalChannels.values().removeIf(ch -> ch == channel);
+ }
+ }
+
+ /**
+ * 发送通用应答消息 (0x8001)
+ */
+ public static void sendGeneralResponse(JT808Message message) {
+ String terminalPhone = message.getTerminalPhone();
+ int flowId = message.getFlowId();
+ int messageId = message.getMessageId();
+
+ ByteBuf body = Unpooled.buffer();
+ ByteBufUtil.writeShortBE(body, flowId);
+ ByteBufUtil.writeShortBE(body, messageId);
+ body.writeByte(0);
+
+ // 构建消息
+ byte[] bytes = ByteBufUtil.getBytes(body);
+ body.release();
+ message = JT808.createBaseMessage(terminalPhone, 0x8001, bytes);
+ sendMessage(message);
+ }
+
+ /**
+ * 向指定终端发送消息
+ */
+ public static void sendMessage(JT808Message message) {
+ String terminalPhone = message.getTerminalPhone();
+
+ Channel channel = terminalChannels.get(terminalPhone);
+ if (channel != null && channel.isActive()) {
+ channel.writeAndFlush(message)
+ .addListener((ChannelFutureListener) future -> {
+ if (future.isSuccess()) {
+ log.info("消息发送成功, 终端: {}, 消息ID: 0x{}, 流水号: {}", terminalPhone, Integer.toHexString(message.getMessageId()), message.getFlowId());
+ } else {
+ log.error("消息发送失败, 终端: {}, 消息ID: 0x{}, 流水号: {}", terminalPhone, Integer.toHexString(message.getMessageId()), message.getFlowId(), future.cause());
+ }
+ });
+ } else {
+ unregister(channel);
+ // 终端不在线或通道已关闭
+ log.warn("终端不在线: {}", terminalPhone);
+ }
+ }
+
+ /**
+ * 创建基础消息对象
+ */
+ public static JT808Message createBaseMessage(String terminalId, int messageId) {
+ return createBaseMessage(terminalId, messageId, null);
+ }
+
+ public static JT808Message createBaseMessage(String terminalId, int messageId, byte[] body) {
+ JT808Message message = new JT808Message()
+ .setFlowId(FlowId.next(terminalId, messageId));
+
+ // 设置消息ID
+ message.setMessageId(messageId);
+
+ // 设置消息体属性
+ // 其他属性默认:不分包,不加密
+ if (body != null) {
+ message.setMessageBodyProps(body.length);
+ } else {
+ message.setMessageBodyProps(0);
+ }
+
+ // 设置终端手机号
+ message.setTerminalPhone(terminalId);
+
+ // 设置消息体
+ message.setMessageBody(body);
+
+ return message;
+ }
+
+
+}
diff --git a/src/main/java/com/njzscloud/jt808/protocol/JT808Decoder.java b/src/main/java/com/njzscloud/common/jt808/support/JT808Decoder.java
similarity index 99%
rename from src/main/java/com/njzscloud/jt808/protocol/JT808Decoder.java
rename to src/main/java/com/njzscloud/common/jt808/support/JT808Decoder.java
index ee3922c..da74f55 100644
--- a/src/main/java/com/njzscloud/jt808/protocol/JT808Decoder.java
+++ b/src/main/java/com/njzscloud/common/jt808/support/JT808Decoder.java
@@ -1,4 +1,4 @@
-package com.njzscloud.jt808.protocol;
+package com.njzscloud.common.jt808.support;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
diff --git a/src/main/java/com/njzscloud/jt808/protocol/JT808Encoder.java b/src/main/java/com/njzscloud/common/jt808/support/JT808Encoder.java
similarity index 98%
rename from src/main/java/com/njzscloud/jt808/protocol/JT808Encoder.java
rename to src/main/java/com/njzscloud/common/jt808/support/JT808Encoder.java
index 07cc339..3b23134 100644
--- a/src/main/java/com/njzscloud/jt808/protocol/JT808Encoder.java
+++ b/src/main/java/com/njzscloud/common/jt808/support/JT808Encoder.java
@@ -1,4 +1,4 @@
-package com.njzscloud.jt808.protocol;
+package com.njzscloud.common.jt808.support;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
diff --git a/src/main/java/com/njzscloud/jt808/protocol/JT808Message.java b/src/main/java/com/njzscloud/common/jt808/support/JT808Message.java
similarity index 93%
rename from src/main/java/com/njzscloud/jt808/protocol/JT808Message.java
rename to src/main/java/com/njzscloud/common/jt808/support/JT808Message.java
index 825778b..2e64498 100644
--- a/src/main/java/com/njzscloud/jt808/protocol/JT808Message.java
+++ b/src/main/java/com/njzscloud/common/jt808/support/JT808Message.java
@@ -1,7 +1,7 @@
-package com.njzscloud.jt808.protocol;
+package com.njzscloud.common.jt808.support;
import cn.hutool.core.util.ReflectUtil;
-import com.njzscloud.common.fastjson.Fastjson;
+import com.njzscloud.common.core.fastjson.Fastjson;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@@ -30,9 +30,6 @@ public class JT808Message {
// 校验码 (1字节)
private byte checkCode;
- public JT808Message() {
- }
-
// 从消息体属性中获取消息体长度
public int getMessageBodyLength() {
return messageBodyProps & 0x3FF;
diff --git a/src/main/java/com/njzscloud/jt808/protocol/JT808MessageHandler.java b/src/main/java/com/njzscloud/common/jt808/support/JT808MessageHandler.java
similarity index 67%
rename from src/main/java/com/njzscloud/jt808/protocol/JT808MessageHandler.java
rename to src/main/java/com/njzscloud/common/jt808/support/JT808MessageHandler.java
index 5405c6b..8f90cff 100644
--- a/src/main/java/com/njzscloud/jt808/protocol/JT808MessageHandler.java
+++ b/src/main/java/com/njzscloud/common/jt808/support/JT808MessageHandler.java
@@ -1,6 +1,6 @@
-package com.njzscloud.jt808.protocol;
+package com.njzscloud.common.jt808.support;
-import com.njzscloud.jt808.util.JT808;
+import com.njzscloud.common.jt808.JT808;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
@@ -25,26 +25,17 @@ public class JT808MessageHandler extends ChannelInboundHandlerAdapter {
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof JT808Message) {
JT808Message message = (JT808Message) msg;
- log.info("收到消息, 终端: {}, 消息ID: 0x{}, 流水号: {}", message.getTerminalPhone(), Integer.toHexString(message.getMessageId()), message.getFlowId());
- // 根据消息类型处理
- handleMessageByType(ctx, message);
+ int messageId = message.getMessageId();
+ log.info("收到消息, 设备号: {},消息ID: 0x{}, 流水号: {}", message.getTerminalPhone(), Integer.toHexString(messageId), message.getFlowId());
+ if (messageId == 0x0100) {
+ JT808.register(message.getTerminalPhone(), ctx.channel());
+ }
+ JT808MessageResolver.dispatchMsg(messageId, message);
} else {
super.channelRead(ctx, msg);
}
}
- /**
- * 根据消息ID处理不同类型的消息
- */
- private void handleMessageByType(ChannelHandlerContext ctx, JT808Message message) {
- int messageId = message.getMessageId();
- if (messageId == 0x0100) {
- JT808.register(message.getTerminalPhone(), ctx.channel());
- }
-
- JT808.triggerListener(messageId, message);
- }
-
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.info("客户端断开连接: {}", ctx.channel().remoteAddress());
diff --git a/src/main/java/com/njzscloud/common/jt808/support/JT808MessageResolver.java b/src/main/java/com/njzscloud/common/jt808/support/JT808MessageResolver.java
new file mode 100644
index 0000000..6a632ea
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/jt808/support/JT808MessageResolver.java
@@ -0,0 +1,147 @@
+package com.njzscloud.common.jt808.support;
+
+import cn.hutool.core.map.MapUtil;
+import com.njzscloud.common.jt808.JT808;
+import com.njzscloud.common.tuqiang.msg.TerminalAuthMsg;
+import com.njzscloud.common.tuqiang.msg.TerminalGeneralResponseMsg;
+import com.njzscloud.common.tuqiang.msg.TerminalRegisterMsg;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
+
+@Slf4j
+public class JT808MessageResolver {
+ public static final String Heartbeat = "Heartbeat";
+ public static final String LocationReport = "LocationReport";
+ public static final String LocationBatchReport = "LocationBatchReport";
+ public static final String LocationSearch = "LocationSearch";
+ public static final String TxtReport = "TxtReport";
+
+ private static Map> resolvers = new ConcurrentHashMap<>();
+
+ private static Map> stdResolvers = MapUtil.>builder()
+ .put(0x0100, JT808MessageResolver::onTerminalRegister)
+ .put(0x0102, JT808MessageResolver::onTerminalAuth)
+ .put(0x0002, JT808MessageResolver::onHeartbeat)
+ .put(0x0200, JT808MessageResolver::onLocationReport)
+ .put(0x704, JT808MessageResolver::onLocationBatchUpload)
+ .put(0x0201, JT808MessageResolver::onSearchLocationResponse)
+ .put(0x0001, JT808MessageResolver::onTerminalGeneralResponse)
+ .put(0x6006, JT808MessageResolver::onTerminalTxtReport)
+ .build();
+
+ public static void addResolver(String messageId, Consumer resolver) {
+ JT808MessageResolver.resolvers.put(messageId, resolver);
+ }
+
+ public static void dispatchMsg(String messageId, JT808Message message) {
+ Consumer heartbeat = resolvers.get(messageId);
+ if (heartbeat != null) {
+ String terminalPhone = message.getTerminalPhone();
+ byte[] messageBody = message.getMessageBody();
+ ByteBuf byteBuf = Unpooled.wrappedBuffer(messageBody);
+ try {
+ heartbeat.accept(new MessageBody()
+ .setTerminalId(terminalPhone)
+ .setBody(byteBuf));
+ } catch (Exception e) {
+ log.error("处理消息时发生异常,消息 Id:{},设备号:{} ", messageId, terminalPhone, e);
+ } finally {
+ byteBuf.release();
+ }
+ }
+ }
+
+ public static void dispatchMsg(Integer messageId, JT808Message message) {
+ Consumer stdResolver = stdResolvers.get(messageId);
+ if (stdResolver != null) {
+ stdResolver.accept(message);
+ }
+ }
+
+ /**
+ * 终端注册消息
+ */
+ public static void onTerminalRegister(JT808Message message) {
+ String terminalPhone = message.getTerminalPhone();
+ ByteBuf body = Unpooled.buffer();
+ ByteBufUtil.writeShortBE(body, message.getFlowId());
+ body.writeByte(0);
+ ByteBufUtil.writeUtf8(body, terminalPhone);
+
+ // 构建消息
+ byte[] bytes = ByteBufUtil.getBytes(body);
+ body.release();
+ JT808.sendMessage(JT808.createBaseMessage(terminalPhone, 0x8100, bytes));
+
+ TerminalRegisterMsg terminalRegisterMsg = message.getMessageBody(TerminalRegisterMsg.class);
+
+ log.info("终端注册消息: {}", terminalRegisterMsg);
+ }
+
+ /**
+ * 终端鉴权消息
+ */
+ public static void onTerminalAuth(JT808Message message) {
+ JT808.sendGeneralResponse(message);
+ TerminalAuthMsg authMsg = message.getMessageBody(TerminalAuthMsg.class);
+ log.info("终端鉴权消息: {}", authMsg);
+ }
+
+ /**
+ * 终端通用应答消息
+ */
+ public static void onTerminalGeneralResponse(JT808Message message) {
+ TerminalGeneralResponseMsg terminalGeneralResponseMsg = message.getMessageBody(TerminalGeneralResponseMsg.class);
+ int messageId = message.getMessageId();
+ String terminalPhone = message.getTerminalPhone();
+ int result = terminalGeneralResponseMsg.getResult();
+ log.info("设备通用响应,设备号:{},消息 Id:{},结果:{}", terminalPhone, Integer.toHexString(messageId), result);
+ }
+
+ /**
+ * 终端心跳消息
+ */
+ public static void onHeartbeat(JT808Message message) {
+ JT808.sendGeneralResponse(message);
+ dispatchMsg(Heartbeat, message);
+ }
+
+ /**
+ * 终端位置信息汇报消息
+ */
+ public static void onLocationReport(JT808Message message) {
+ dispatchMsg(LocationReport, message);
+ }
+
+ /**
+ * 定位数据批量上传消息
+ */
+ public static void onLocationBatchUpload(JT808Message message) {
+ dispatchMsg(LocationBatchReport, message);
+ }
+
+ /**
+ * 查询位置响应消息
+ */
+ public static void onSearchLocationResponse(JT808Message message) {
+ JT808.sendGeneralResponse(message);
+ dispatchMsg(LocationSearch, message);
+ }
+
+ /**
+ * 终端文本信息汇报消息
+ */
+ public static void onTerminalTxtReport(JT808Message message) {
+ JT808.sendGeneralResponse(message);
+ int messageId = message.getMessageId();
+ String terminalPhone = message.getTerminalPhone();
+ dispatchMsg(TxtReport, message);
+ }
+
+}
diff --git a/src/main/java/com/njzscloud/common/jt808/support/MessageBody.java b/src/main/java/com/njzscloud/common/jt808/support/MessageBody.java
new file mode 100644
index 0000000..c342ae7
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/jt808/support/MessageBody.java
@@ -0,0 +1,16 @@
+package com.njzscloud.common.jt808.support;
+
+import io.netty.buffer.ByteBuf;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class MessageBody {
+ private String terminalId;
+ private ByteBuf body;
+}
diff --git a/src/main/java/com/njzscloud/common/jt808/util/FlowId.java b/src/main/java/com/njzscloud/common/jt808/util/FlowId.java
new file mode 100644
index 0000000..e56c2ee
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/jt808/util/FlowId.java
@@ -0,0 +1,19 @@
+package com.njzscloud.common.jt808.util;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class FlowId {
+ private static final Map flowId = new ConcurrentHashMap<>();
+
+ public static synchronized int next(String terminalId, int messageId) {
+ String key = terminalId + "_" + messageId;
+ Integer i = flowId.get(key);
+ if (i == null || i >= 0xFFFF) {
+ i = 0;
+ }
+ i++;
+ flowId.put(key, i);
+ return i;
+ }
+}
diff --git a/src/main/java/com/njzscloud/common/mqtt/Mqtt.java b/src/main/java/com/njzscloud/common/mqtt/Mqtt.java
new file mode 100644
index 0000000..0b6ac23
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/mqtt/Mqtt.java
@@ -0,0 +1,129 @@
+package com.njzscloud.common.mqtt;
+
+import cn.hutool.core.util.StrUtil;
+import com.njzscloud.common.core.jackson.Jackson;
+import com.njzscloud.common.mqtt.support.MqttListener;
+import com.njzscloud.common.mqtt.support.MqttMsg;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.paho.client.mqttv3.*;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
+
+@Slf4j
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class Mqtt {
+ private static final Map> listeners = new ConcurrentHashMap<>();
+ private static MqttClient client;
+
+ public static void run(String broker, String clientId, String username, String password) {
+ try {
+ client = new MqttClient(broker, clientId);
+ MqttConnectOptions options = new MqttConnectOptions();
+ if (StrUtil.isNotBlank(username) && StrUtil.isNotBlank(password)) {
+ options.setUserName(username);
+ options.setPassword(password.toCharArray());
+ }
+
+ client.connect(options);
+ client.setCallback(new MsgHandler());
+ log.info("mqtt连接成功:{} {}", broker, clientId);
+ } catch (Exception e) {
+ log.error("mqtt连接失败", e);
+ shutdown();
+ }
+ }
+
+ public static void shutdown() {
+ try {
+ if (client != null) {
+ client.disconnect();
+ client = null;
+ }
+ } catch (Exception e) {
+ log.error("mqtt关闭失败", e);
+ }
+ }
+
+ public static void subscribe(String topic, int qos) {
+ try {
+ client.subscribe(topic, qos);
+ log.info("mqtt 订阅成功:{} {}", topic, qos);
+ } catch (Exception e) {
+ log.error("mqtt 订阅失败:{} {}", topic, qos, e);
+ }
+ }
+
+ public static void subscribe(String topic) {
+ subscribe(topic, 0);
+ }
+
+ public static void subscribe(String topic, int qos, Consumer handler) {
+ listeners.put(topic, handler);
+ subscribe(topic, qos);
+ }
+
+ public static void subscribe(String topic, Consumer handler) {
+ subscribe(topic, 0, handler);
+ }
+
+ public static void publish(String topic, int qos, Object msg) {
+ String jsonStr = null;
+ try {
+ jsonStr = Jackson.toJsonStr(msg);
+ log.info("mqtt 发布消息:{} {} {}", topic, qos, jsonStr);
+ MqttMessage message = new MqttMessage(jsonStr.getBytes());
+ message.setQos(qos);
+ client.publish(topic, message);
+ } catch (Exception e) {
+ log.error("mqtt 发布消息失败:{} {} {}", topic, qos, jsonStr, e);
+ }
+ }
+
+ public static void publish(String topic, Object msg) {
+ publish(topic, 0, msg);
+ }
+
+ public static void addListener(Object obj) {
+ Class> clazz = obj.getClass();
+ for (Method method : clazz.getDeclaredMethods()) {
+ MqttListener mqttListener = method.getAnnotation(MqttListener.class);
+ if (mqttListener == null) continue;
+ String topic = mqttListener.topic();
+ int qos = mqttListener.qos();
+ subscribe(topic, qos);
+ Consumer handler = (msg) -> {
+ try {
+ method.invoke(obj, msg);
+ } catch (Exception e) {
+ log.error("mqtt 消息处理失败:{}", topic, e);
+ }
+ };
+ listeners.put(topic, handler);
+ }
+ }
+
+ public static class MsgHandler implements MqttCallback {
+ public void messageArrived(String topic, MqttMessage message) throws Exception {
+ Consumer handler = listeners.get(topic);
+ if (handler == null) return;
+ try {
+ handler.accept(new MqttMsg(message.getPayload()));
+ } catch (Exception e) {
+ log.error("mqtt 消息处理失败:{} {}", topic, new String(message.getPayload()), e);
+ }
+ }
+
+ public void connectionLost(Throwable cause) {
+ log.error("mqtt 连接已断开", cause);
+ }
+
+ public void deliveryComplete(IMqttDeliveryToken token) {
+ log.info("消息投递结果:{}", token.isComplete());
+ }
+ }
+}
diff --git a/src/main/java/com/njzscloud/common/mqtt/config/MqttProperties.java b/src/main/java/com/njzscloud/common/mqtt/config/MqttProperties.java
new file mode 100644
index 0000000..7c9fada
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/mqtt/config/MqttProperties.java
@@ -0,0 +1,14 @@
+package com.njzscloud.common.mqtt.config;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class MqttProperties {
+ private boolean enabled;
+ private String broker;
+ private String clientId;
+ private String username;
+ private String password;
+}
diff --git a/src/main/java/com/njzscloud/common/mqtt/support/MqttListener.java b/src/main/java/com/njzscloud/common/mqtt/support/MqttListener.java
new file mode 100644
index 0000000..1a2c58a
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/mqtt/support/MqttListener.java
@@ -0,0 +1,14 @@
+package com.njzscloud.common.mqtt.support;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface MqttListener {
+ String topic();
+
+ int qos() default 0;
+}
diff --git a/src/main/java/com/njzscloud/common/mqtt/support/MqttMsg.java b/src/main/java/com/njzscloud/common/mqtt/support/MqttMsg.java
new file mode 100644
index 0000000..e9b9732
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/mqtt/support/MqttMsg.java
@@ -0,0 +1,15 @@
+package com.njzscloud.common.mqtt.support;
+
+import com.njzscloud.common.core.jackson.Jackson;
+
+public class MqttMsg {
+ private final byte[] msg;
+
+ public MqttMsg(byte[] msg) {
+ this.msg = msg;
+ }
+
+ public T getMsg(Class clazz) {
+ return Jackson.toBean(msg, clazz);
+ }
+}
diff --git a/src/main/java/com/njzscloud/server/TcpServer.java b/src/main/java/com/njzscloud/common/tcp/TcpServer.java
similarity index 55%
rename from src/main/java/com/njzscloud/server/TcpServer.java
rename to src/main/java/com/njzscloud/common/tcp/TcpServer.java
index 8661fa0..76f1f36 100644
--- a/src/main/java/com/njzscloud/server/TcpServer.java
+++ b/src/main/java/com/njzscloud/common/tcp/TcpServer.java
@@ -1,8 +1,9 @@
-package com.njzscloud.server;
+package com.njzscloud.common.tcp;
-import com.njzscloud.jt808.protocol.JT808Decoder;
-import com.njzscloud.jt808.protocol.JT808Encoder;
-import com.njzscloud.jt808.protocol.JT808MessageHandler;
+import com.njzscloud.common.core.ex.Exceptions;
+import com.njzscloud.common.jt808.support.JT808Decoder;
+import com.njzscloud.common.jt808.support.JT808Encoder;
+import com.njzscloud.common.jt808.support.JT808MessageHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioIoHandler;
@@ -13,30 +14,23 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TcpServer {
private final int port;
- private final int bossThreads;
- private final int workerThreads;
+ private EventLoopGroup bossGroup;
+ private EventLoopGroup workerGroup;
+ private ServerBootstrap bootstrap;
public TcpServer(int port, int bossThreads, int workerThreads) {
this.port = port;
- this.bossThreads = bossThreads;
- this.workerThreads = workerThreads;
- }
-
- public TcpServer() {
- this.port = 18888;
- this.bossThreads = 5;
- this.workerThreads = 200;
+ buildServer(bossThreads, workerThreads);
}
- public void start() throws Exception {
- // 创建两个EventLoopGroup,bossGroup用于接收客户端连接,workerGroup用于处理连接后的IO操作
- EventLoopGroup bossGroup = new MultiThreadIoEventLoopGroup(bossThreads, NioIoHandler.newFactory());
- EventLoopGroup workerGroup = new MultiThreadIoEventLoopGroup(workerThreads, NioIoHandler.newFactory());
-
+ public void buildServer(int bossThreads, int workerThreads) {
try {
+ // 创建两个EventLoopGroup,bossGroup用于接收客户端连接,workerGroup用于处理连接后的IO操作
+ bossGroup = new MultiThreadIoEventLoopGroup(bossThreads, NioIoHandler.newFactory());
+ workerGroup = new MultiThreadIoEventLoopGroup(workerThreads, NioIoHandler.newFactory());
// 服务器启动辅助类
- ServerBootstrap bootstrap = new ServerBootstrap();
+ bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
// 指定使用NIO的服务器通道
.channel(NioServerSocketChannel.class)
@@ -55,17 +49,34 @@ public class TcpServer {
.addLast(new JT808MessageHandler()); // 消息处理器
}
});
-
- // 绑定端口并开始接收连接
- ChannelFuture future = bootstrap.bind(port).sync();
- log.info("服务器已启动,监听端口: {}", port);
- // 等待服务器 socket 关闭
- future.channel().closeFuture().sync();
- } finally {
- // 关闭事件循环组
- workerGroup.shutdownGracefully();
- bossGroup.shutdownGracefully();
- log.info("服务器已停止");
+ } catch (Exception e) {
+ log.error("服务器启动失败", e);
+ this.stop();
+ throw Exceptions.error(e, "服务器构建失败");
}
}
+
+ public void start() {
+ try {
+ ChannelFuture future = bootstrap.bind(port).sync();
+ log.info("服务器已启动,监听端口: {}", port);
+ future.channel().closeFuture().sync();
+ } catch (Exception e) {
+ log.error("服务器启动失败,端口: {}", port, e);
+ stop();
+ throw Exceptions.error(e, "服务器启动失败");
+ }
+ }
+
+ public void stop() {
+ if (bossGroup != null) {
+ bossGroup.shutdownGracefully();
+ bossGroup = null;
+ }
+ if (workerGroup != null) {
+ workerGroup.shutdownGracefully();
+ workerGroup = null;
+ }
+ log.info("服务器已停止");
+ }
}
diff --git a/src/main/java/com/njzscloud/common/tuqiang/Tuqiang.java b/src/main/java/com/njzscloud/common/tuqiang/Tuqiang.java
new file mode 100644
index 0000000..1a453d6
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/tuqiang/Tuqiang.java
@@ -0,0 +1,109 @@
+package com.njzscloud.common.tuqiang;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import com.njzscloud.TuqiangListeners;
+import com.njzscloud.common.jt808.JT808;
+import com.njzscloud.common.jt808.support.JT808Message;
+import com.njzscloud.common.tuqiang.msg.PublishTxtMsg;
+import com.njzscloud.common.tuqiang.support.TuqiangListener;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.reflect.Method;
+
+@Slf4j
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class Tuqiang {
+ public static void run(int port, int bossThreads, int workerThreads) {
+ addListener(new TuqiangListeners());
+ JT808.run(port, bossThreads, workerThreads);
+ }
+
+ private static void addListener(Object object) {
+ Method[] methods = object.getClass().getDeclaredMethods();
+ for (Method method : methods) {
+ if (method.isAnnotationPresent(TuqiangListener.class)) {
+ TuqiangListener tuqiangListener = method.getAnnotation(TuqiangListener.class);
+ String messageId = tuqiangListener.messageId();
+ JT808.addListener(messageId, (msg) -> {
+ try {
+ method.invoke(object, msg);
+ } catch (Exception e) {
+ log.error("途强处理消息 {} 时出错", messageId, e);
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * 开启追踪
+ *
+ * @param terminalId 终端ID
+ * @param interval 上报间隔,单位秒,0-3600秒,0表示不追踪
+ */
+ public static void track(String terminalId, int interval) {
+ Assert.isTrue(interval >= 0 && interval <= 3600, "上报间隔必须为0-3600秒");
+ JT808.sendMessage(JT808.createBaseMessage(terminalId, 0x8300, new PublishTxtMsg(StrUtil.format("", interval)).toBytes()));
+ }
+
+ /**
+ * 获取设备信息
+ *
+ * @param terminalId 终端ID
+ */
+ public static void obtainDeviceInfo(String terminalId) {
+ JT808.sendMessage(JT808.createBaseMessage(terminalId, 0x8300, new PublishTxtMsg("").toBytes()));
+ }
+
+ /**
+ * 设置心跳
+ *
+ * @param terminalId 终端ID
+ */
+ public static void setHeartbeat(String terminalId, int interval) {
+ ByteBuf body = Unpooled.buffer();
+ body.writeByte(1);
+ body.writeByte(1);
+ body.writeInt(0x0001);
+ // body.writeByte(1);
+ body.writeByte(interval);
+ byte[] bytes = ByteBufUtil.getBytes(body);
+ body.release();
+ JT808.sendMessage(JT808.createBaseMessage(terminalId, 0x8103, bytes));
+ }
+
+ /**
+ * 启用报警
+ *
+ * @param terminalId 终端ID
+ */
+ public static void enableWarn(String terminalId, boolean enable) {
+ JT808.sendMessage(JT808.createBaseMessage(terminalId, 0x8300, new PublishTxtMsg(StrUtil.format("", enable ? 1 : 0)).toBytes()));
+ }
+
+ /**
+ * 设置速度报警
+ *
+ * @param terminalId 终端ID
+ * @param speed 速度,单位km/h
+ */
+ public static void speedThreshold(String terminalId, int speed) {
+ JT808.sendMessage(JT808.createBaseMessage(terminalId, 0x8300, new PublishTxtMsg(StrUtil.format("", speed)).toBytes()));
+ }
+
+ /**
+ * 获取当前位置
+ *
+ * @param terminalId 终端ID
+ */
+ public static void currentLocation(String terminalId) {
+ JT808Message baseMessage = JT808.createBaseMessage(terminalId, 0x8201);
+ JT808.sendMessage(baseMessage);
+ }
+}
diff --git a/src/main/java/com/njzscloud/tuqiang/DeviceInfo.java b/src/main/java/com/njzscloud/common/tuqiang/msg/DeviceInfo.java
similarity index 59%
rename from src/main/java/com/njzscloud/tuqiang/DeviceInfo.java
rename to src/main/java/com/njzscloud/common/tuqiang/msg/DeviceInfo.java
index e94432c..2c3935f 100644
--- a/src/main/java/com/njzscloud/tuqiang/DeviceInfo.java
+++ b/src/main/java/com/njzscloud/common/tuqiang/msg/DeviceInfo.java
@@ -1,4 +1,4 @@
-package com.njzscloud.tuqiang;
+package com.njzscloud.common.tuqiang.msg;
import lombok.Getter;
import lombok.Setter;
@@ -10,34 +10,90 @@ import lombok.experimental.Accessors;
@ToString
@Accessors(chain = true)
public class DeviceInfo {
- // GPS定位状态
+ // region GPS定位状态
+ /**
+ * 这是 GPS 定位的核心状态,三个参数分别代表:
+ * 1. 定位有效性:V = Valid(有效定位),若为N则表示 No Valid(无效定位,如无卫星信号);
+ * 2. 卫星数量:0 = 当前参与定位的卫星数量(此处为 0,可能是瞬时值或信号弱导致,正常定位时通常≥4);
+ * 3. 定位精度 / 备用参数:0 = 部分设备此处代表定位精度(单位:米),或备用状态码(具体需结合设备型号,途强部分设备此参数为 “定位类型”,0 = 未知,1=GPS,2 = 北斗)。
+ */
private String gpsValid; // 定位有效性(V/N)
private int satelliteCount; // 卫星数量
private int gpsAccuracy; // 定位精度或备用参数
+ /**
+ * GPS 模块硬件状态:OK = GPS 模块正常工作(供电、硬件无故障);若为ERR则表示 GPS 模块故障(如硬件损坏、供电异常)。
+ */
private String gpsModuleStatus; // GPS模块状态(OK/ERR)
+ // endregion
- // 网络与信号状态
+ // region 网络与信号状态
private String serverIp; // 服务器IP
private int serverPort; // 服务器端口
+ /**
+ * 2G/4G 网络注册状态(CGREG 是 GSM/UMTS 网络的 “小区注册状态” 指令):
+ * 1 = 设备已成功注册到本地移动网络(可正常联网);
+ * 其他常见值:0= 未注册,2= 正在注册,3= 注册被拒绝(如 SIM 卡欠费、无信号)
+ */
private int cgregStatus; // 网络注册状态
+ /**
+ * 网络信号强度(CSQ = Carrier Signal Quality,载波信号质量):
+ * 取值范围0-31,22属于良好信号(12-20 为中等,21-31 为良好,0 为无信号);
+ * 对应信号强度约为 -78dBm(CSQ 与 dBm 换算公式:dBm = -113 + (CSQ×2),22 时即 - 113+44=-69dBm,数值越接近 0 信号越强)。
+ */
private int csq; // 信号强度
+ // endregion
- // 硬件与电源状态
+ // region 硬件与电源状态
+ /**
+ * 设备内置电池电压:单位为 “V(伏特)”,3.5V 属于正常电压范围(途强设备电池电压通常在 3.3V-4.2V 之间,低于 3.3V 可能触发低电报警)。
+ */
private double batteryVoltage; // 电池电压(V)
+ /**
+ * 供电模式 / 电池状态:
+ * 常见含义(途强设备自定义):1= 外接电源供电(如车充、市电),2= 电池供电,0= 供电异常;
+ * 部分设备此参数代表 “电池健康度”,2= 良好(需结合具体型号确认)。
+ */
private int powerMode; // 供电模式(1=外接电源,2=电池)
+ /**
+ * 北斗定位模块状态(BD = BeiDou):
+ * 0 = 北斗模块未启用 / 未定位(若设备支持北斗,此值为1表示北斗已参与定位);0不代表故障,仅表示当前未使用北斗信号。
+ */
private int beidouStatus; // 北斗模块状态(0=未启用,1=启用)
+ // endregion
- // 功能与附加状态
+ // region 功能与附加状态
+ /**
+ * 报警状态:* = 无当前报警(途强设备常用 “*” 表示无报警,若有报警会显示具体报警码,如A:1= 低电报警,A:2= 位移报警)
+ */
private String alarmStatus; // 报警状态(*)
+ /**
+ * 计数器 / 里程相关:常见为 “累计里程计数状态” 或 “指令执行计数”,0通常表示 “无异常” 或 “初始值”(部分设备此为 “充电次数”,需结合型号)。
+ */
private int counter; // 计数器/里程相关
+ /**
+ * 定位上报间隔:单位为 “秒”,300 = 设备每 5 分钟自动上报一次定位数据(途强设备支持远程配置此间隔,如 10 秒、60 秒、300 秒等)
+ */
private int reportInterval; // 定位上报间隔(秒)
- private int powerSavingMode; // 省电模式(0=关闭,1=开启)
- private int backupPower; // 备用电源状态
- private int vibrationStatus; // 震动传感器状态
+ /**
+ * 超速阈值
+ */
+ private int speedThreshold; // 超速阈值(km/h)
+ /**
+ * 关闭日志
+ */
+ private int logOff; // 关闭日志(0=关闭,1=开启)
+ /**
+ * 关闭拐点
+ */
+ private int inflectionPointOff; // 拐点关闭状态(0=关闭,1=开启)
private int heartbeatInterval; // 心跳包间隔(秒)
- private int accStatus; // ACC点火状态(1=通电,0=断电)
+ /**
+ * 关闭基站
+ */
+ private int baseStationOff; // 基站关闭状态(1=关闭,0=开启)
private int chargingStatus; // 充电状态(0=未充电,1=充电中)
private int bluetoothStatus; // 蓝牙状态(1=开启,0=关闭)
+ private int enableWarn; // 蓝牙状态(1=开启,0=关闭)
private String extendStatus; // 扩展状态码(十六进制)
private String temperature; // 温度传感器状态
private String deviceTime; // 设备本地时间
@@ -48,16 +104,19 @@ public class DeviceInfo {
private int lowBatteryThreshold; // 低电阈值状态
private int accelerometerStatus; // 加速度传感器状态
private int flightMode; // 飞行模式(0=关闭,1=开启)
+ // endregion
-
- public static DeviceInfo parse(String gpsString) {
+ public static DeviceInfo parse(String str) {
DeviceInfo data = new DeviceInfo();
- if (gpsString == null || gpsString.isEmpty()) {
- return data;
+ if (str == null || str.isEmpty()) {
+ return null;
+ }
+ if (!str.startsWith("<") || !str.endsWith(">")) {
+ return null;
}
// 去除首尾的<和>
- String content = gpsString.replaceAll("[<>]", "");
+ String content = str.replaceAll("[<>]", "");
// 按*分割字段
String[] fields = content.split("\\*");
@@ -111,19 +170,19 @@ public class DeviceInfo {
data.reportInterval = parseInt(value);
break;
case "CS":
- data.powerSavingMode = parseInt(value);
+ data.speedThreshold = parseInt(value);
break;
case "3U":
- data.backupPower = parseInt(value);
+ data.logOff = parseInt(value);
break;
case "3Z":
- data.vibrationStatus = parseInt(value);
+ data.inflectionPointOff = parseInt(value);
break;
case "H":
data.heartbeatInterval = parseInt(value);
break;
case "2A":
- data.accStatus = parseInt(value);
+ data.baseStationOff = parseInt(value);
break;
case "5C":
data.chargingStatus = parseInt(value);
@@ -131,6 +190,9 @@ public class DeviceInfo {
case "60":
data.bluetoothStatus = parseInt(value);
break;
+ case "6W":
+ data.enableWarn = parseInt(value);
+ break;
case "3E":
data.extendStatus = value;
break;
@@ -202,6 +264,4 @@ public class DeviceInfo {
return -1; // 用-1表示解析失败
}
}
-
-
}
diff --git a/src/main/java/com/njzscloud/tuqiang/msg/LocationReportMsg.java b/src/main/java/com/njzscloud/common/tuqiang/msg/LocationReportMsg.java
similarity index 53%
rename from src/main/java/com/njzscloud/tuqiang/msg/LocationReportMsg.java
rename to src/main/java/com/njzscloud/common/tuqiang/msg/LocationReportMsg.java
index 8b11c61..7e7a4ed 100644
--- a/src/main/java/com/njzscloud/tuqiang/msg/LocationReportMsg.java
+++ b/src/main/java/com/njzscloud/common/tuqiang/msg/LocationReportMsg.java
@@ -1,8 +1,8 @@
-package com.njzscloud.tuqiang.msg;
+package com.njzscloud.common.tuqiang.msg;
-import com.njzscloud.common.utils.BCD;
+import cn.hutool.core.date.DateUtil;
+import com.njzscloud.common.core.utils.BCD;
import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@@ -33,50 +33,33 @@ public class LocationReportMsg {
private int direction;
private String time;
- public LocationReportMsg(byte[] bytes) {
- ByteBuf body = Unpooled.wrappedBuffer(bytes);
+ private boolean overspeed;
+ private boolean powerUnderVoltage;
+ private boolean soundAlarm;
+ private boolean accOn;
+ private boolean position;
+ private boolean south;
+ private boolean west;
+
+ public LocationReportMsg(ByteBuf body) {
this.alarmFlag = body.readUnsignedInt();
this.status = body.readUnsignedInt();
- double longitude = body.readUnsignedInt() * 1.0 / 1000000;
- this.longitude = isWest() ? -longitude : longitude;
double latitude = body.readUnsignedInt() * 1.0 / 1000000;
- this.latitude = isSouth() ? -latitude : latitude;
+ this.latitude = isWest() ? -latitude : latitude;
+ double longitude = body.readUnsignedInt() * 1.0 / 1000000;
+ this.longitude = isSouth() ? -longitude : longitude;
this.altitude = body.readUnsignedShort();
this.speed = body.readUnsignedShort() * 1.0 / 10;
this.direction = body.readUnsignedShort();
- byte[] terminalIdBytes = new byte[7];
+ byte[] terminalIdBytes = new byte[6];
body.readBytes(terminalIdBytes);
- this.time = BCD.bcdToStr(terminalIdBytes);
-
-
- body.release();
- }
-
- public boolean isOverspeed() {
- return (alarmFlag & 0x02) == 0x02;
- }
-
- public boolean isPowerUnderVoltage() {
- return (alarmFlag & 0x40) == 0x40;
- }
-
- public boolean isSoundAlarm() {
- return (alarmFlag & 0x80) == 0x80;
- }
-
- public boolean isAccOn() {
- return (status & 0x01) == 0x01;
- }
-
- public boolean isPosition() {
- return (status & 0x02) == 0x02;
- }
-
- public boolean isSouth() {
- return (status & 0x04) == 0x04;
- }
-
- public boolean isWest() {
- return (status & 0x08) == 0x08;
+ this.time = DateUtil.format(DateUtil.parse(BCD.bcdToStr(terminalIdBytes), "yyMMddHHmmss"), "yyyy-MM-dd HH:mm:ss");
+ this.overspeed = (alarmFlag & 0x02) == 0x02;
+ this.powerUnderVoltage = (alarmFlag & 0x40) == 0x40;
+ this.soundAlarm = (alarmFlag & 0x80) == 0x80;
+ this.accOn = (status & 0x01) == 0x01;
+ this.position = (status & 0x02) == 0x02;
+ this.south = (status & 0x04) == 0x04;
+ this.west = (status & 0x08) == 0x08;
}
}
diff --git a/src/main/java/com/njzscloud/common/tuqiang/msg/PublishTxtMsg.java b/src/main/java/com/njzscloud/common/tuqiang/msg/PublishTxtMsg.java
new file mode 100644
index 0000000..d3b8f6b
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/tuqiang/msg/PublishTxtMsg.java
@@ -0,0 +1,36 @@
+package com.njzscloud.common.tuqiang.msg;
+
+import cn.hutool.core.util.CharsetUtil;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.UnsupportedEncodingException;
+
+@Getter
+@Setter
+@ToString
+@Slf4j
+@Accessors(chain = true)
+public class PublishTxtMsg {
+ private byte flag;
+ private String txt;
+
+ public PublishTxtMsg(String txt) {
+ this.flag = 0x01;
+ this.txt = txt;
+ }
+
+ public byte[] toBytes() {
+ byte[] messageBody = new byte[txt.length() + 1];
+ messageBody[0] = flag;
+ try {
+ System.arraycopy(txt.getBytes(CharsetUtil.GBK), 0, messageBody, 1, txt.length());
+ } catch (UnsupportedEncodingException e) {
+ log.error("文本消息构建失败,原文本:{}", txt, e);
+ }
+ return messageBody;
+ }
+}
diff --git a/src/main/java/com/njzscloud/tuqiang/msg/SearchLocationResponseMsg.java b/src/main/java/com/njzscloud/common/tuqiang/msg/SearchLocationResponseMsg.java
similarity index 60%
rename from src/main/java/com/njzscloud/tuqiang/msg/SearchLocationResponseMsg.java
rename to src/main/java/com/njzscloud/common/tuqiang/msg/SearchLocationResponseMsg.java
index 2643d5d..83c94e0 100644
--- a/src/main/java/com/njzscloud/tuqiang/msg/SearchLocationResponseMsg.java
+++ b/src/main/java/com/njzscloud/common/tuqiang/msg/SearchLocationResponseMsg.java
@@ -1,8 +1,6 @@
-package com.njzscloud.tuqiang.msg;
+package com.njzscloud.common.tuqiang.msg;
import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufUtil;
-import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@@ -17,10 +15,9 @@ public class SearchLocationResponseMsg {
private int flowId;
private LocationReportMsg locationReportMsg;
- public SearchLocationResponseMsg(byte[] bytes) {
- ByteBuf body = Unpooled.wrappedBuffer(bytes);
+ public SearchLocationResponseMsg(ByteBuf body) {
this.flowId = body.readUnsignedShort();
- byte[] locationReportMsgBytes = ByteBufUtil.getBytes(body);
- this.locationReportMsg = new LocationReportMsg(locationReportMsgBytes);
+ ByteBuf locationReportMsgBody = body.slice(body.readerIndex(), body.readableBytes());
+ this.locationReportMsg = new LocationReportMsg(locationReportMsgBody);
}
}
diff --git a/src/main/java/com/njzscloud/tuqiang/msg/TerminalAuthMsg.java b/src/main/java/com/njzscloud/common/tuqiang/msg/TerminalAuthMsg.java
similarity index 90%
rename from src/main/java/com/njzscloud/tuqiang/msg/TerminalAuthMsg.java
rename to src/main/java/com/njzscloud/common/tuqiang/msg/TerminalAuthMsg.java
index 6064046..945f65a 100644
--- a/src/main/java/com/njzscloud/tuqiang/msg/TerminalAuthMsg.java
+++ b/src/main/java/com/njzscloud/common/tuqiang/msg/TerminalAuthMsg.java
@@ -1,4 +1,4 @@
-package com.njzscloud.tuqiang.msg;
+package com.njzscloud.common.tuqiang.msg;
import cn.hutool.core.util.CharsetUtil;
import io.netty.buffer.ByteBuf;
@@ -20,5 +20,6 @@ public class TerminalAuthMsg {
byte[] authCodeBytes = new byte[body.readableBytes()];
body.readBytes(authCodeBytes);
this.authCode = new String(authCodeBytes, CharsetUtil.CHARSET_GBK);
+ body.release();
}
}
diff --git a/src/main/java/com/njzscloud/tuqiang/msg/TerminalGeneralResponseMsg.java b/src/main/java/com/njzscloud/common/tuqiang/msg/TerminalGeneralResponseMsg.java
similarity index 88%
rename from src/main/java/com/njzscloud/tuqiang/msg/TerminalGeneralResponseMsg.java
rename to src/main/java/com/njzscloud/common/tuqiang/msg/TerminalGeneralResponseMsg.java
index a4ba5a9..4e4f00b 100644
--- a/src/main/java/com/njzscloud/tuqiang/msg/TerminalGeneralResponseMsg.java
+++ b/src/main/java/com/njzscloud/common/tuqiang/msg/TerminalGeneralResponseMsg.java
@@ -1,4 +1,4 @@
-package com.njzscloud.tuqiang.msg;
+package com.njzscloud.common.tuqiang.msg;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@@ -14,6 +14,9 @@ import lombok.experimental.Accessors;
public class TerminalGeneralResponseMsg {
private int flowId;
private int messageId;
+ /**
+ * 0:成功/确认;1:失败;2:消息有误;3:不支持
+ */
private int result;
public TerminalGeneralResponseMsg(byte[] bytes) {
diff --git a/src/main/java/com/njzscloud/tuqiang/msg/TerminalRegisterMsg.java b/src/main/java/com/njzscloud/common/tuqiang/msg/TerminalRegisterMsg.java
similarity index 98%
rename from src/main/java/com/njzscloud/tuqiang/msg/TerminalRegisterMsg.java
rename to src/main/java/com/njzscloud/common/tuqiang/msg/TerminalRegisterMsg.java
index 4a8c052..3ceedaa 100644
--- a/src/main/java/com/njzscloud/tuqiang/msg/TerminalRegisterMsg.java
+++ b/src/main/java/com/njzscloud/common/tuqiang/msg/TerminalRegisterMsg.java
@@ -1,4 +1,4 @@
-package com.njzscloud.tuqiang.msg;
+package com.njzscloud.common.tuqiang.msg;
import cn.hutool.core.util.CharsetUtil;
import io.netty.buffer.ByteBuf;
diff --git a/src/main/java/com/njzscloud/tuqiang/msg/TerminalTxtReportMsg.java b/src/main/java/com/njzscloud/common/tuqiang/msg/TerminalTxtReportMsg.java
similarity index 65%
rename from src/main/java/com/njzscloud/tuqiang/msg/TerminalTxtReportMsg.java
rename to src/main/java/com/njzscloud/common/tuqiang/msg/TerminalTxtReportMsg.java
index 156a604..e46f94a 100644
--- a/src/main/java/com/njzscloud/tuqiang/msg/TerminalTxtReportMsg.java
+++ b/src/main/java/com/njzscloud/common/tuqiang/msg/TerminalTxtReportMsg.java
@@ -1,8 +1,7 @@
-package com.njzscloud.tuqiang.msg;
+package com.njzscloud.common.tuqiang.msg;
import cn.hutool.core.util.CharsetUtil;
import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@@ -17,12 +16,11 @@ public class TerminalTxtReportMsg {
/**
* 文本信息
*/
- private String text;
+ private String txt;
- public TerminalTxtReportMsg(byte[] bytes) {
- ByteBuf body = Unpooled.wrappedBuffer(bytes);
+ public TerminalTxtReportMsg(ByteBuf body) {
this.type = body.readByte();
- this.text = body.toString(body.readerIndex(), body.readableBytes(),
+ this.txt = body.toString(body.readerIndex(), body.readableBytes(),
this.type == 0x00 ?
CharsetUtil.CHARSET_GBK :
CharsetUtil.CHARSET_UTF_8);
diff --git a/src/main/java/com/njzscloud/common/tuqiang/support/Directive.java b/src/main/java/com/njzscloud/common/tuqiang/support/Directive.java
new file mode 100644
index 0000000..5691407
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/tuqiang/support/Directive.java
@@ -0,0 +1,93 @@
+package com.njzscloud.common.tuqiang.support;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public enum Directive {
+ /**
+ * 设置位置信息传输间隔
+ */
+ _C("C"),
+ /**
+ * 设置心跳间隔
+ */
+ _H("H"),
+ /**
+ * 设置IP、端口
+ */
+ _T("T"),
+ /**
+ * 设置速度阈值
+ */
+ _CS("CS"),
+ /**
+ * 关闭日志
+ */
+ _3U("3U"),
+ /**
+ * 关闭位拐点
+ */
+ _3Z("3Z"),
+ /**
+ * 关闭基站
+ */
+ _2A("2A"),
+ /**
+ * 低电压阈值
+ */
+ _5Y("5Y"),
+ /**
+ * 设置时区,8:00 东8区
+ */
+ _9E("9E"),
+ /**
+ * 设置防震动阈值
+ */
+ _3D("3D"),
+ /**
+ * 设置允许报警
+ */
+ _6W("6W"),
+ /**
+ * 设置录音灵敏度,【5-100】
+ */
+ _3E("3E"),
+ /**
+ * 设置设备ID
+ */
+ _N("N"),
+ /**
+ * 2G/4G 网络注册状态
+ */
+ _CGREG("CGREG"),
+ /**
+ * 信号质量,取值范围0-31,22属于良好信号(12-20 为中等,21-31 为良好,0 为无信号)
+ */
+ _CSQ("CSQ"),
+ /**
+ * GPS 状态,V-->有效,N-->无效定位,值:(V,0,0)
+ */
+ _GPS("GPS"),
+ /**
+ * GPS 模块硬件状态,OK-->正常,ERR-->故障
+ */
+ _GP("GP"),
+ /**
+ * 充电状态:0 = 未充电;1 = 正在充电
+ */
+ _5C("5C"),
+ /**
+ * 1= 外接电源供电(,2= 电池供电,0= 供电异常
+ */
+ _B("B"),
+
+
+ ;
+
+ private final String value;
+
+ {
+ String[] strings = {"N:61000602070", "T:139.224.54.144,30100", "CGREG:1", "CSQ:23", "GPS:(V,0,0)", "A:", "C:0", "O:300", "CS:0", "3U:0", "3Z:0", "H:300", "2A:1", "GP:OK", "5C:0", "60:1", "5Y:3.5", "6W:0", "3E:000300", "5T:2,2", "9E:08:00", "1H:1", "3D:000000", "2S:0", "I:0000000", "B:2", "LT:0", "AG:1", "BD:0", "FLY:0"};
+ }
+
+}
diff --git a/src/main/java/com/njzscloud/common/tuqiang/support/TuqiangDirectiveMsg.java b/src/main/java/com/njzscloud/common/tuqiang/support/TuqiangDirectiveMsg.java
new file mode 100644
index 0000000..7ad810e
--- /dev/null
+++ b/src/main/java/com/njzscloud/common/tuqiang/support/TuqiangDirectiveMsg.java
@@ -0,0 +1,14 @@
+package com.njzscloud.common.tuqiang.support;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class TuqiangDirectiveMsg {
+
+}
diff --git a/src/main/java/com/njzscloud/tuqiang/Listener.java b/src/main/java/com/njzscloud/common/tuqiang/support/TuqiangListener.java
similarity index 51%
rename from src/main/java/com/njzscloud/tuqiang/Listener.java
rename to src/main/java/com/njzscloud/common/tuqiang/support/TuqiangListener.java
index fd3355d..f86b37a 100644
--- a/src/main/java/com/njzscloud/tuqiang/Listener.java
+++ b/src/main/java/com/njzscloud/common/tuqiang/support/TuqiangListener.java
@@ -1,10 +1,10 @@
-package com.njzscloud.tuqiang;
+package com.njzscloud.common.tuqiang.support;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
-public @interface Listener {
- int messageId();
+public @interface TuqiangListener {
+ String messageId();
}
diff --git a/src/main/java/com/njzscloud/jt808/util/FlowId.java b/src/main/java/com/njzscloud/jt808/util/FlowId.java
deleted file mode 100644
index 4538471..0000000
--- a/src/main/java/com/njzscloud/jt808/util/FlowId.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.njzscloud.jt808.util;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class FlowId {
- private static final Map flowId = new ConcurrentHashMap<>();
-
- public static synchronized int next(int messageId) {
- Integer i = flowId.get(messageId);
- if (i == null || i >= 0xFFFF) {
- i = 0;
- }
- flowId.put(messageId, i++);
- return i;
- }
-}
diff --git a/src/main/java/com/njzscloud/jt808/util/JT808.java b/src/main/java/com/njzscloud/jt808/util/JT808.java
deleted file mode 100644
index 20c3fc1..0000000
--- a/src/main/java/com/njzscloud/jt808/util/JT808.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package com.njzscloud.jt808.util;
-
-import com.njzscloud.jt808.protocol.JT808Message;
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufUtil;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFutureListener;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Consumer;
-
-/**
- * JT808消息发送工具类
- * 提供便捷的方法发送各种类型的JT808消息
- */
-@Slf4j
-public class JT808 {
- // 终端手机号与Channel的映射
- private static final Map terminalChannels = new ConcurrentHashMap<>();
-
- private static final Map>> listeners = new ConcurrentHashMap<>();
-
- /**
- * 注册消息监听器
- */
- public static void addListener(Integer messageId, Consumer listener) {
- if (messageId != null && listener != null) {
- listeners.computeIfAbsent(messageId, k -> new java.util.ArrayList<>()).add(listener);
- }
- }
-
- /**
- * 触发消息监听器
- */
- public static void triggerListener(Integer messageId, JT808Message message) {
- if (messageId != null && message != null) {
- List> consumers = listeners.get(messageId);
- if (consumers != null) {
- consumers.forEach(m -> m.accept(message));
- } else {
-
- log.warn("当前消息无处理函数: 0x{}、消息内容: {}", Integer.toHexString(messageId), message);
- }
- }
- }
-
- /**
- * 移除消息监听器
- */
- public static void unregisterListener(String messageId) {
- if (messageId != null) {
- listeners.remove(messageId);
- }
- }
-
- /**
- * 注册终端与通道的映射关系
- */
- public static void register(String terminalId, Channel channel) {
- if (terminalId != null && channel != null) {
- if (terminalChannels.get(terminalId) != channel) {
- terminalChannels.put(terminalId, channel);
- }
- }
- }
-
- /**
- * 移除终端与通道的映射关系
- */
- public static void unregister(Channel channel) {
- if (channel != null) {
- terminalChannels.values().removeIf(ch -> ch == channel);
- }
- }
-
-
- /**
- * 发送通用应答消息 (0x8001)
- */
- public static void sendGeneralResponse(JT808Message message) {
- sendMessage(message.getTerminalPhone(), createGeneralMessage(message));
- }
-
- /**
- * 发送终端注册应答消息 (0x8100)
- */
- public static void sendTerminalRegisterResponse(String terminalPhone, int flowId, String authCode, int result) {
- // 构建消息体
- ByteBuf body = Unpooled.buffer();
- body.writeByte(result); // 结果
- if (result == 0) { // 成功才需要后面的字段
- writeString(body, authCode); // 鉴权码
- }
-
- // 构建消息
- byte[] bytes = ByteBufUtil.getBytes(body);
- body.release();
- JT808Message message = createBaseMessage(terminalPhone, 0x8100, bytes);
- message.setFlowId(flowId);
-
- // 发送消息
- sendMessage(terminalPhone, message);
- }
-
- /**
- * 发送文本信息下发消息 (0x8300)
- */
- public static void sendTextMessage(String terminalPhone, String content, int messageType) {
- // 构建消息体
- ByteBuf body = Unpooled.buffer();
- body.writeByte(messageType); // 消息类型
- writeString(body, content); // 消息内容
- byte[] bytes = ByteBufUtil.getBytes(body);
- body.release();
- // 构建消息
- JT808Message message = createBaseMessage(terminalPhone, 0x8300, bytes);
-
- // 发送消息
- sendMessage(terminalPhone, message);
- }
-
-
- /**
- * 向指定终端发送消息
- */
- public static void sendMessage(String terminalId, JT808Message message) {
- if (terminalId == null || message == null) {
- return;
- }
-
- Channel channel = terminalChannels.get(terminalId);
- if (channel != null && channel.isActive()) {
- channel.writeAndFlush(message)
- .addListener((ChannelFutureListener) future -> {
- if (future.isSuccess()) {
- log.info("消息发送成功, 终端: {}, 消息ID: 0x{}, 流水号: {}", terminalId, Integer.toHexString(message.getMessageId()), message.getFlowId());
- } else {
- log.error("消息发送失败, 终端: {}", terminalId, future.cause());
- }
- });
- } else {
- unregister(channel);
- // 终端不在线或通道已关闭
- log.warn("终端不在线: {}", terminalId);
- }
- }
-
- /**
- * 创建基础消息对象
- */
- public static JT808Message createBaseMessage(String terminalId, int messageId) {
- return createBaseMessage(terminalId, messageId, null);
- }
-
- public static JT808Message createBaseMessage(String terminalId, int messageId, byte[] body) {
- JT808Message message = new JT808Message()
- .setFlowId(FlowId.next(messageId));
-
- // 设置消息ID
- message.setMessageId(messageId);
-
- // 设置消息体属性
- // 其他属性默认:不分包,不加密
- if (body != null) {
- message.setMessageBodyProps(body.length);
- } else {
- message.setMessageBodyProps(0);
- }
-
- // 设置终端手机号
- message.setTerminalPhone(terminalId);
-
- // 设置消息体
- message.setMessageBody(body);
-
- return message;
- }
-
- public static JT808Message createGeneralMessage(JT808Message message) {
- String terminalPhone = message.getTerminalPhone();
- int flowId = message.getFlowId();
- int messageId = message.getMessageId();
-
- ByteBuf body = Unpooled.buffer();
- ByteBufUtil.writeShortBE(body, flowId);
- ByteBufUtil.writeShortBE(body, messageId);
- body.writeByte(0);
-
- // 构建消息
- byte[] bytes = ByteBufUtil.getBytes(body);
- body.release();
- return JT808.createBaseMessage(terminalPhone, 0x8001, bytes);
- }
-
- /**
- * 写入字符串(JT808协议格式:1字节长度 + 内容)
- */
- private static void writeString(ByteBuf buf, String str) {
- if (str == null || str.isEmpty()) {
- buf.writeByte(0);
- return;
- }
-
- byte[] bytes = str.getBytes();
- // 字符串长度(1字节) + 字符串内容
- buf.writeByte(bytes.length);
- buf.writeBytes(bytes);
- }
-}
diff --git a/src/main/java/com/njzscloud/param/EnableWarnParam.java b/src/main/java/com/njzscloud/param/EnableWarnParam.java
new file mode 100644
index 0000000..d741fd7
--- /dev/null
+++ b/src/main/java/com/njzscloud/param/EnableWarnParam.java
@@ -0,0 +1,15 @@
+package com.njzscloud.param;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class EnableWarnParam {
+ private String terminalId;
+ private boolean enable;
+}
diff --git a/src/main/java/com/njzscloud/param/LocationCurrentParam.java b/src/main/java/com/njzscloud/param/LocationCurrentParam.java
new file mode 100644
index 0000000..23694ad
--- /dev/null
+++ b/src/main/java/com/njzscloud/param/LocationCurrentParam.java
@@ -0,0 +1,14 @@
+package com.njzscloud.param;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class LocationCurrentParam {
+ private String terminalId;
+}
diff --git a/src/main/java/com/njzscloud/param/LocationTrackParam.java b/src/main/java/com/njzscloud/param/LocationTrackParam.java
new file mode 100644
index 0000000..1e0bf74
--- /dev/null
+++ b/src/main/java/com/njzscloud/param/LocationTrackParam.java
@@ -0,0 +1,15 @@
+package com.njzscloud.param;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class LocationTrackParam {
+ private String terminalId;
+ private int interval;
+}
diff --git a/src/main/java/com/njzscloud/param/ObtainDeviceInfoParam.java b/src/main/java/com/njzscloud/param/ObtainDeviceInfoParam.java
new file mode 100644
index 0000000..140dfae
--- /dev/null
+++ b/src/main/java/com/njzscloud/param/ObtainDeviceInfoParam.java
@@ -0,0 +1,14 @@
+package com.njzscloud.param;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class ObtainDeviceInfoParam {
+ private String terminalId;
+}
diff --git a/src/main/java/com/njzscloud/param/SetHeartbeatParam.java b/src/main/java/com/njzscloud/param/SetHeartbeatParam.java
new file mode 100644
index 0000000..80c711a
--- /dev/null
+++ b/src/main/java/com/njzscloud/param/SetHeartbeatParam.java
@@ -0,0 +1,16 @@
+package com.njzscloud.param;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class SetHeartbeatParam {
+ private String terminalId;
+
+ private int interval;
+}
diff --git a/src/main/java/com/njzscloud/param/SpeedThresholdParam.java b/src/main/java/com/njzscloud/param/SpeedThresholdParam.java
new file mode 100644
index 0000000..ce338ba
--- /dev/null
+++ b/src/main/java/com/njzscloud/param/SpeedThresholdParam.java
@@ -0,0 +1,15 @@
+package com.njzscloud.param;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class SpeedThresholdParam {
+ private String terminalId;
+ private int speed;
+}
diff --git a/src/main/java/com/njzscloud/result/RealtimeLocationResult.java b/src/main/java/com/njzscloud/result/RealtimeLocationResult.java
new file mode 100644
index 0000000..3698e70
--- /dev/null
+++ b/src/main/java/com/njzscloud/result/RealtimeLocationResult.java
@@ -0,0 +1,42 @@
+package com.njzscloud.result;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class RealtimeLocationResult {
+ private String terminalId;
+ private String type;
+
+ /**
+ * 1 1:超速报警 标志维持至报警条件解除
+ * 7 1:终端主电源欠压 标志维持至报警条件解除
+ * 8 1:声控录音报警
+ */
+ private long alarmFlag;
+ /**
+ * 0 0:ACC 关 1:ACC 开
+ * 1 0:未定位 1:定位
+ * 2 0:北纬 1:南纬
+ * 3 0:东经 1:西经
+ */
+ private long status;
+ private double longitude;
+ private double latitude;
+ private int altitude;
+ private double speed;
+ private int direction;
+ private String time;
+ private boolean overspeed;
+ private boolean powerUnderVoltage;
+ private boolean soundAlarm;
+ private boolean accOn;
+ private boolean position;
+ private boolean south;
+ private boolean west;
+}
diff --git a/src/main/java/com/njzscloud/tuqiang/Listeners.java b/src/main/java/com/njzscloud/tuqiang/Listeners.java
deleted file mode 100644
index a287f38..0000000
--- a/src/main/java/com/njzscloud/tuqiang/Listeners.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.njzscloud.tuqiang;
-
-import com.njzscloud.jt808.protocol.JT808Message;
-import com.njzscloud.jt808.util.JT808;
-import com.njzscloud.tuqiang.msg.*;
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufUtil;
-import io.netty.buffer.Unpooled;
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-public class Listeners {
-
- @Listener(messageId = 0x0100)
- public void onTerminalRegister(JT808Message message) {
- String terminalPhone = message.getTerminalPhone();
- ByteBuf body = Unpooled.buffer();
- ByteBufUtil.writeShortBE(body, message.getFlowId());
- body.writeByte(0);
- ByteBufUtil.writeUtf8(body, terminalPhone);
-
- // 构建消息
- byte[] bytes = ByteBufUtil.getBytes(body);
- body.release();
- JT808.sendMessage(terminalPhone, JT808.createBaseMessage(terminalPhone, 0x8100, bytes));
-
- TerminalRegisterMsg terminalRegisterMsg = message.getMessageBody(TerminalRegisterMsg.class);
-
- log.info("终端注册消息: {}", terminalRegisterMsg);
- }
-
- @Listener(messageId = 0x0102)
- public void onTerminalAuth(JT808Message message) {
- JT808.sendGeneralResponse(message);
- TerminalAuthMsg authMsg = message.getMessageBody(TerminalAuthMsg.class);
- log.info("终端鉴权消息: {}", authMsg);
-
- // ThreadUtil.sleep(10000);
- // log.info("发送指令: {}", "");
- // JT808.sendMessage("61000602070", JT808.createBaseMessage("61000602070", 0x8300, new PublishDirectiveMsg("").toBytes()));
- // ThreadUtil.sleep(10000);
- // JT808.sendMessage("61000602070", JT808.createBaseMessage("61000602070", 0x8300, new PublishDirectiveMsg("").toBytes()));
-
- }
-
- @Listener(messageId = 0x0002)
- public void onHeartbeat(JT808Message message) {
- log.info("终端心跳消息: {}", message.getTerminalPhone());
- JT808.sendGeneralResponse(message);
- }
-
- @Listener(messageId = 0x0200)
- public void onLocationReport(JT808Message message) {
- LocationReportMsg locationReportMsg = message.getMessageBody(LocationReportMsg.class);
- log.info("终端位置信息汇报消息: {}", locationReportMsg);
- JT808.sendGeneralResponse(message);
- }
-
- @Listener(messageId = 0x0001)
- public void onTerminalGeneralResponse(JT808Message message) {
- TerminalGeneralResponseMsg terminalGeneralResponseMsg = message.getMessageBody(TerminalGeneralResponseMsg.class);
- log.info("终端通用应答消息: {}", terminalGeneralResponseMsg);
- JT808.sendGeneralResponse(message);
- }
-
- @Listener(messageId = 0x6006)
- public void onTerminalTxtReport(JT808Message message) {
- TerminalTxtReportMsg terminalTxtReportMsg = message.getMessageBody(TerminalTxtReportMsg.class);
- log.info("终端文本信息汇报消息: {}", terminalTxtReportMsg);
- JT808.sendGeneralResponse(message);
- }
-
- @Listener(messageId = 0x0201)
- public void onSearchLocationResponse(JT808Message message) {
- SearchLocationResponseMsg searchLocationResponseMsg = message.getMessageBody(SearchLocationResponseMsg.class);
- log.info("查询位置响应消息: {}", searchLocationResponseMsg);
- JT808.sendGeneralResponse(message);
- }
-}
diff --git a/src/main/java/com/njzscloud/tuqiang/Tuqiang.java b/src/main/java/com/njzscloud/tuqiang/Tuqiang.java
deleted file mode 100644
index ec25445..0000000
--- a/src/main/java/com/njzscloud/tuqiang/Tuqiang.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.njzscloud.tuqiang;
-
-import com.njzscloud.jt808.util.JT808;
-import lombok.extern.slf4j.Slf4j;
-
-import java.lang.reflect.Method;
-
-@Slf4j
-public class Tuqiang {
-
- public Tuqiang() {
- addListeners(new Listeners());
- }
-
- private void addListeners(Object object) {
- Method[] methods = object.getClass().getMethods();
- for (Method method : methods) {
- if (method.isAnnotationPresent(Listener.class)) {
- Listener listener = method.getAnnotation(Listener.class);
- JT808.addListener(listener.messageId(), (msg) -> {
- try {
- method.invoke(object, msg);
- } catch (Exception e) {
- log.error("处理消息 {} 时出错", listener.messageId(), e);
- }
- });
- }
- }
- }
-
-}
diff --git a/src/main/java/com/njzscloud/tuqiang/msg/PublishDirectiveMsg.java b/src/main/java/com/njzscloud/tuqiang/msg/PublishDirectiveMsg.java
deleted file mode 100644
index 9f3e201..0000000
--- a/src/main/java/com/njzscloud/tuqiang/msg/PublishDirectiveMsg.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.njzscloud.tuqiang.msg;
-
-import lombok.Getter;
-import lombok.Setter;
-import lombok.ToString;
-import lombok.experimental.Accessors;
-
-@Getter
-@Setter
-@ToString
-@Accessors(chain = true)
-public class PublishDirectiveMsg {
- private byte flag;
- private String directive;
-
- public PublishDirectiveMsg(String directive) {
- this.flag = 0x01;
- this.directive = directive;
- }
-
- public byte[] toBytes() {
- byte[] messageBody = new byte[directive.length() + 1];
- messageBody[0] = flag;
- System.arraycopy(directive.getBytes(), 0, messageBody, 1, directive.length());
- return messageBody;
- }
-}
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
index fe4903e..8dd1276 100644
--- a/src/main/resources/logback.xml
+++ b/src/main/resources/logback.xml
@@ -1,6 +1,6 @@
-
+