Compare commits

...

12 Commits

Author SHA1 Message Date
lzh
016a1e18b7 Merge remote-tracking branch 'origin/cleaning' into cleaning
# Conflicts:
#	viewshanghai-module-iot/viewshanghai-module-iot-biz/src/main/java/com/viewshanghai/module/iot/service/device/message/IotDeviceMessageServiceImpl.java
#	viewshanghai-module-iot/viewshanghai-module-iot-gateway/src/main/java/com/viewshanghai/module/iot/gateway/codec/jt808/IotJt808DeviceMessageCodec.java
#	viewshanghai-module-iot/viewshanghai-module-iot-gateway/src/main/java/com/viewshanghai/module/iot/gateway/protocol/tcp/handler/Jt808ProtocolHandler.java
2025-12-30 13:36:19 +08:00
lzh
7a81d9e478 fix: JT808事件消息eventId改为identifier
Some checks failed
aiot-platform CI/CD / build-and-deploy (push) Has been cancelled
2025-12-28 00:47:42 +08:00
lzh
ea55347651 fix: 业务层跳过 JT808 协议的回复消息生成
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 6m50s
2025-12-28 00:07:10 +08:00
lzh
7561ddf9e9 fix: JT808直接回复通用消息-处理数据上报 2025-12-28 00:06:59 +08:00
lzh
bb8f76d531 fix: 修复TCP上报空Json数据解析失败bug
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 6m23s
2025-12-27 23:05:19 +08:00
lzh
69b0767fd7 fix: JT808修改-若NONE跳过鉴权
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 7m22s
2025-12-26 18:40:00 +08:00
lzh
1737566245 fix: 新增只依据deviceName查询设备信息(暂时使用,后续调整)
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 7m4s
2025-12-26 18:25:44 +08:00
lzh
8d52e9e413 fix: 修复java.lang.RuntimeException: JT808 消息编码失败: 消息参数格式错误,params 必须是 Map 类型
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 7m41s
at com.viewshanghai.module.iot.gateway.codec.jt808.IotJt808DeviceMessageCodec.encode(IotJt808DeviceMessageCodec.java:77) ~[!/:na]
2025-12-26 17:58:36 +08:00
lzh
a5c2b7aabf fix: 修改了 IotJt808DeviceMessageCodec.java:82-111 的 decode() 方法
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 7m33s
2025-12-26 17:42:06 +08:00
lzh
6d159a02fe fix: 修复bug-Caused by: java.lang.RuntimeException: JT808 消息解码失败: null
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 7m28s
2025-12-26 17:07:35 +08:00
lzh
97fef34098 fix: docker部署打开8091端口
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 7m20s
2025-12-26 16:19:46 +08:00
lzh
a2a9ef0c30 cleaning-客流计数器、蓝牙工牌对接 (#1)
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 8m21s
完善了http上报数据、修改了tcp连接协议解析

Reviewed-on: http://124.221.55.225:3000/XW-AIOT/aiot-platform/pulls/1
2025-12-26 14:48:23 +08:00
4 changed files with 81 additions and 12 deletions

View File

@@ -47,8 +47,22 @@ public class IoTDeviceApiImpl implements IotDeviceCommonApi {
@PostMapping(RpcConstants.RPC_API_PREFIX + "/iot/device/get") // 特殊:方便调用,暂时使用 POST实际更推荐 GET
@PermitAll
public CommonResult<IotDeviceRespDTO> getDevice(@RequestBody IotDeviceGetReqDTO getReqDTO) {
IotDeviceDO device = getReqDTO.getId() != null ? deviceService.getDeviceFromCache(getReqDTO.getId())
: deviceService.getDeviceFromCache(getReqDTO.getProductKey(), getReqDTO.getDeviceName());
IotDeviceDO device;
// 查询优先级id > (productKey + deviceName) > deviceName
if (getReqDTO.getId() != null) {
// 通过设备 ID 查询
device = deviceService.getDeviceFromCache(getReqDTO.getId());
} else if (getReqDTO.getProductKey() != null && getReqDTO.getDeviceName() != null) {
// 通过 productKey + deviceName 查询
device = deviceService.getDeviceFromCache(getReqDTO.getProductKey(), getReqDTO.getDeviceName());
} else if (getReqDTO.getDeviceName() != null) {
// 仅通过 deviceName 查询(用于 JT808 等协议,终端手机号应该是全局唯一的)
device = deviceService.getDeviceFromCacheByDeviceName(getReqDTO.getDeviceName());
} else {
device = null;
}
return success(BeanUtils.toBean(device, IotDeviceRespDTO.class, deviceDTO -> {
IotProductDO product = productService.getProductFromCache(deviceDTO.getProductId());
if (product != null) {

View File

@@ -131,6 +131,19 @@ public interface IotDeviceService {
*/
IotDeviceDO getDeviceFromCache(String productKey, String deviceName);
/**
* 【缓存】根据设备名称获得设备信息(仅通过设备名称查询)
* <p>
* 注意:该方法会忽略租户信息,所以调用时,需要确认会不会有跨租户访问的风险!!!
* <p>
* 此方法主要用于 JT808 等协议设备在注册时只知道终端手机号deviceName
* 不知道 productKey。对于 JT808 协议,终端手机号应该是全局唯一的。
*
* @param deviceName 设备名称(如 JT808 的终端手机号)
* @return 设备信息,未找到返回 null
*/
IotDeviceDO getDeviceFromCacheByDeviceName(String deviceName);
/**
* 获得设备分页
*

View File

@@ -259,6 +259,13 @@ public class IotDeviceServiceImpl implements IotDeviceService {
return deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName);
}
@Override
@Cacheable(value = RedisKeyConstants.DEVICE, key = "'deviceName_' + #deviceName", unless = "#result == null")
@TenantIgnore // 忽略租户信息,用于 JT808 等协议,终端手机号应该是全局唯一的
public IotDeviceDO getDeviceFromCacheByDeviceName(String deviceName) {
return deviceMapper.selectByDeviceName(deviceName);
}
@Override
public PageResult<IotDeviceDO> getDevicePage(IotDevicePageReqVO pageReqVO) {
return deviceMapper.selectPage(pageReqVO);

View File

@@ -95,16 +95,51 @@ public class IotTcpJsonDeviceMessageCodec implements IotDeviceMessageCodec {
@SuppressWarnings("DataFlowIssue")
public IotDeviceMessage decode(byte[] bytes) {
String jsonStr = StrUtil.utf8Str(bytes).trim();
TcpJsonMessage tcpJsonMessage = JsonUtils.parseObject(jsonStr, TcpJsonMessage.class);
Assert.notNull(tcpJsonMessage, "消息不能为空");
Assert.notBlank(tcpJsonMessage.getMethod(), "消息方法不能为空");
return IotDeviceMessage.of(
tcpJsonMessage.getId(),
tcpJsonMessage.getMethod(),
tcpJsonMessage.getParams(),
tcpJsonMessage.getData(),
tcpJsonMessage.getCode(),
tcpJsonMessage.getMsg());
// 快速验证是否为 JSON 格式(必须以 { 或 [ 开头)
if (StrUtil.isBlank(jsonStr)) {
throw new IllegalArgumentException("JSON 数据为空");
}
String trimmedJson = jsonStr.trim();
if (!trimmedJson.startsWith("{") && !trimmedJson.startsWith("[")) {
throw new IllegalArgumentException(
String.format("不是有效的 JSON 格式,数据开头: %s",
jsonStr.length() > 20 ? jsonStr.substring(0, 20) : jsonStr));
}
try {
TcpJsonMessage tcpJsonMessage = JsonUtils.parseObject(jsonStr, TcpJsonMessage.class);
// 检查解析结果
if (tcpJsonMessage == null) {
throw new IllegalArgumentException(
String.format("JSON 解析返回 null可能是空对象或格式错误数据: %s",
jsonStr.length() > 100 ? jsonStr.substring(0, 100) + "..." : jsonStr));
}
// 检查必要字段
if (StrUtil.isBlank(tcpJsonMessage.getMethod())) {
throw new IllegalArgumentException(
String.format("JSON 消息缺少 method 字段,数据: %s",
jsonStr.length() > 100 ? jsonStr.substring(0, 100) + "..." : jsonStr));
}
return IotDeviceMessage.of(
tcpJsonMessage.getId(),
tcpJsonMessage.getMethod(),
tcpJsonMessage.getParams(),
tcpJsonMessage.getData(),
tcpJsonMessage.getCode(),
tcpJsonMessage.getMsg());
} catch (IllegalArgumentException e) {
// 重新抛出 IllegalArgumentException已经是我们自己的错误信息
throw e;
} catch (Exception e) {
throw new IllegalArgumentException(
String.format("JSON 解析失败,数据开头: %s错误: %s",
jsonStr.length() > 50 ? jsonStr.substring(0, 50) : jsonStr, e.getMessage()), e);
}
}
}