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 @@ - +