mirror of
https://gitee.com/NexIoT/Universal-IoT-Java.git
synced 2026-10-29 20:21:29 +08:00
fix:重要!子设备无法添加bug
This commit is contained in:
+118
-20
@@ -34,7 +34,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* HTTP协议转换器 将UnifiedDownlinkCommand转换为HttpDownRequest
|
||||
* HTTP协议转换器
|
||||
* 将UnifiedDownlinkCommand转换为HttpDownRequest
|
||||
*
|
||||
* @version 1.0
|
||||
* @since 2025/10/25
|
||||
@@ -71,15 +72,27 @@ public class HttpDownRequestConverter extends AbstratIoTService
|
||||
}
|
||||
}
|
||||
|
||||
/** 转换网关子设备请求 */
|
||||
/**
|
||||
* 转换网关子设备请求
|
||||
*/
|
||||
private HttpDownRequest convertGatewaySubDevice(
|
||||
UnifiedDownlinkCommand command, IoTProduct subProduct, DownlinkContext<?> context) {
|
||||
log.info(
|
||||
"[HTTP转换器] 检测到网关子设备, productKey={}, deviceId={}",
|
||||
"[HTTP转换器] 检测到网关子设备, productKey={}, deviceId={}, cmd={}",
|
||||
command.getProductKey(),
|
||||
command.getDeviceId());
|
||||
command.getDeviceId(),
|
||||
command.getCmd());
|
||||
|
||||
// 1. 加载子设备信息
|
||||
// 1. 判断是否需要网关代理
|
||||
boolean needGatewayProxy = isNeedGatewayProxy(command.getCmd());
|
||||
|
||||
if (!needGatewayProxy) {
|
||||
// 对于不需要网关代理的命令(如DEV_ADD等设备管理命令),直接使用子设备信息
|
||||
log.info("[HTTP转换器] 命令{}不需要网关代理,直接使用子设备信息", command.getCmd());
|
||||
return convertSubDeviceDirectly(command, subProduct, context);
|
||||
}
|
||||
|
||||
// 2. 加载子设备信息(需要网关代理时必须存在)
|
||||
IoTDeviceDTO subDevice =
|
||||
getIoTDeviceDTO(
|
||||
IoTDeviceQuery.builder()
|
||||
@@ -88,26 +101,29 @@ public class HttpDownRequestConverter extends AbstratIoTService
|
||||
.iotId(command.getIotId())
|
||||
.build());
|
||||
|
||||
if (subDevice == null && command.getCmd() != DownCmd.DEV_ADD) {
|
||||
if (subDevice == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"子设备不存在: productKey=" + command.getProductKey() + ", deviceId=" + command.getDeviceId());
|
||||
}
|
||||
|
||||
// 2. 查询网关设备信息
|
||||
// 3. 验证网关绑定信息
|
||||
if (StrUtil.isBlank(subDevice.getGwProductKey())
|
||||
|| StrUtil.isBlank(subDevice.getExtDeviceId())) {
|
||||
throw new IllegalArgumentException(
|
||||
"网关子设备缺少网关信息: gwProductKey="
|
||||
"网关子设备缺少网关绑定信息: gwProductKey="
|
||||
+ subDevice.getGwProductKey()
|
||||
+ ", extDeviceId="
|
||||
+ subDevice.getExtDeviceId());
|
||||
+ subDevice.getExtDeviceId()
|
||||
+ ", 请先完成子设备与网关的绑定");
|
||||
}
|
||||
|
||||
// 4. 查询网关产品信息
|
||||
IoTProduct gatewayProduct = getProduct(subDevice.getGwProductKey());
|
||||
if (gatewayProduct == null) {
|
||||
throw new IllegalArgumentException("网关产品不存在: " + subDevice.getGwProductKey());
|
||||
}
|
||||
|
||||
// 5. 查询网关设备信息
|
||||
IoTDeviceDTO gatewayDevice =
|
||||
getIoTDeviceDTO(
|
||||
IoTDeviceQuery.builder()
|
||||
@@ -123,7 +139,7 @@ public class HttpDownRequestConverter extends AbstratIoTService
|
||||
+ subDevice.getExtDeviceId());
|
||||
}
|
||||
|
||||
// 3. 构建请求对象
|
||||
// 6. 构建请求对象(通过网关代理)
|
||||
HttpDownRequest request = new HttpDownRequest();
|
||||
BeanUtil.copyProperties(command, request, "extensions", "metadata");
|
||||
|
||||
@@ -136,13 +152,13 @@ public class HttpDownRequestConverter extends AbstratIoTService
|
||||
request.setSubProductKey(command.getProductKey());
|
||||
request.setIsGatewayProxy(true);
|
||||
|
||||
// 4. 获取网关产品配置
|
||||
// 7. 获取网关产品配置
|
||||
JSONObject config = JSONUtil.parseObj(gatewayProduct.getConfiguration());
|
||||
String down = config.getStr("down");
|
||||
|
||||
// 5. 处理功能下发场景:使用子设备ProductKey编解码
|
||||
// 8. 处理功能下发场景:使用子设备ProductKey编解码
|
||||
if ((StrUtil.isNotBlank(down)
|
||||
&& ListUtil.of(down.split(",")).contains(command.getCmd().getValue()))
|
||||
&& ListUtil.of(down.split(",")).contains(command.getCmd().getValue()))
|
||||
|| CollectionUtil.isNotEmpty(command.getFunction())) {
|
||||
String payload = encodeFunction(command);
|
||||
request.setDownResult(payload);
|
||||
@@ -151,12 +167,12 @@ public class HttpDownRequestConverter extends AbstratIoTService
|
||||
log.debug("[HTTP转换器] 子设备编解码完成, deviceId={}, payload={}", command.getDeviceId(), payload);
|
||||
}
|
||||
|
||||
// 6. 处理扩展字段
|
||||
// 9. 处理扩展字段
|
||||
if (command.getExtensions() != null && !command.getExtensions().isEmpty()) {
|
||||
request.setData(JSONUtil.parseObj(command.getExtensions()));
|
||||
}
|
||||
|
||||
// 7. 设置消息ID
|
||||
// 10. 设置消息ID
|
||||
if (StrUtil.isBlank(request.getMsgId())) {
|
||||
request.setMsgId(generateMsgId());
|
||||
}
|
||||
@@ -169,7 +185,86 @@ public class HttpDownRequestConverter extends AbstratIoTService
|
||||
return request;
|
||||
}
|
||||
|
||||
/** 转换普通设备请求 */
|
||||
/**
|
||||
* 判断命令是否需要网关代理
|
||||
* @param cmd 下行命令
|
||||
* @return true-需要网关代理, false-直接使用子设备信息
|
||||
*/
|
||||
private boolean isNeedGatewayProxy(DownCmd cmd) {
|
||||
if (cmd == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设备管理类命令不需要网关代理,直接操作子设备
|
||||
return switch (cmd) {
|
||||
case DEV_ADD, DEV_ADDS, // 设备新增
|
||||
DEV_DEL, DEVICE_DELETE, // 设备删除
|
||||
DEV_UPDATE, DEVICE_UPDATE // 设备更新
|
||||
-> false;
|
||||
// 其他命令(功能调用、状态查询等)需要通过网关代理
|
||||
default -> true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接使用子设备信息转换(不需要网关代理的场景)
|
||||
* @param command 下行命令
|
||||
* @param subProduct 子设备产品信息
|
||||
* @param context 下行上下文
|
||||
* @return HTTP下行请求
|
||||
*/
|
||||
private HttpDownRequest convertSubDeviceDirectly(
|
||||
UnifiedDownlinkCommand command, IoTProduct subProduct, DownlinkContext<?> context) {
|
||||
|
||||
// 1. 创建请求对象
|
||||
HttpDownRequest request = new HttpDownRequest();
|
||||
BeanUtil.copyProperties(command, request, "extensions", "metadata");
|
||||
|
||||
// 2. 设置子设备产品信息
|
||||
request.setIoTProduct(subProduct);
|
||||
|
||||
// 3. 尝试加载子设备信息(DEV_ADD时可能不存在)
|
||||
IoTDeviceDTO subDevice = null;
|
||||
if (command.getCmd() != DownCmd.DEV_ADD && command.getCmd() != DownCmd.DEV_ADDS) {
|
||||
subDevice = getIoTDeviceDTO(
|
||||
IoTDeviceQuery.builder()
|
||||
.productKey(command.getProductKey())
|
||||
.deviceId(command.getDeviceId())
|
||||
.iotId(command.getIotId())
|
||||
.build());
|
||||
|
||||
if (subDevice == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"子设备不存在: productKey=" + command.getProductKey() + ", deviceId=" + command.getDeviceId());
|
||||
}
|
||||
}
|
||||
request.setIoTDeviceDTO(subDevice);
|
||||
|
||||
// 4. 处理扩展字段
|
||||
if (command.getExtensions() != null && !command.getExtensions().isEmpty()) {
|
||||
request.setData(JSONUtil.parseObj(command.getExtensions()));
|
||||
}
|
||||
|
||||
// 5. 设置消息ID
|
||||
if (StrUtil.isBlank(request.getMsgId())) {
|
||||
request.setMsgId(generateMsgId());
|
||||
}
|
||||
|
||||
// 6. 标记为子设备(但不通过网关代理)
|
||||
request.setIsGatewayProxy(false);
|
||||
|
||||
log.info(
|
||||
"[HTTP转换器] 子设备直接转换完成(无需网关代理): productKey={}, deviceId={}, cmd={}",
|
||||
command.getProductKey(),
|
||||
command.getDeviceId(),
|
||||
command.getCmd());
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换普通设备请求
|
||||
*/
|
||||
private HttpDownRequest convertNormalDevice(
|
||||
UnifiedDownlinkCommand command, IoTProduct ioTProduct, DownlinkContext<?> context) {
|
||||
// 1. 创建请求对象
|
||||
@@ -202,12 +297,13 @@ public class HttpDownRequestConverter extends AbstratIoTService
|
||||
|
||||
// 6. 处理功能下发场景:编解码
|
||||
if ((StrUtil.isNotBlank(down)
|
||||
&& ListUtil.of(down.split(",")).contains(command.getCmd().getValue()))
|
||||
&& ListUtil.of(down.split(",")).contains(command.getCmd().getValue()))
|
||||
|| CollectionUtil.isNotEmpty(command.getFunction())) {
|
||||
String payload = encodeFunction(command);
|
||||
request.setDownResult(payload);
|
||||
request.setPayload(payload);
|
||||
log.debug("[HTTP转换器] 功能下发编解码完成, deviceId={}, payload={}", command.getDeviceId(), payload);
|
||||
log.debug(
|
||||
"[HTTP转换器] 功能下发编解码完成, deviceId={}, payload={}", command.getDeviceId(), payload);
|
||||
}
|
||||
|
||||
// 7. 处理扩展字段
|
||||
@@ -229,7 +325,9 @@ public class HttpDownRequestConverter extends AbstratIoTService
|
||||
return request;
|
||||
}
|
||||
|
||||
/** 判断是否为网关子设备 */
|
||||
/**
|
||||
* 判断是否为网关子设备
|
||||
*/
|
||||
private boolean isGatewaySubDevice(IoTProduct product) {
|
||||
return DeviceNode.GATEWAY_SUB_DEVICE.getValue().equalsIgnoreCase(product.getDeviceNode());
|
||||
}
|
||||
@@ -294,7 +392,7 @@ public class HttpDownRequestConverter extends AbstratIoTService
|
||||
// 保存设备信息到上下文(供后续拦截器使用)
|
||||
if (request.getIoTDeviceDTO() != null) {
|
||||
context.setAttribute("deviceName", request.getIoTDeviceDTO().getDeviceName());
|
||||
context.setAttribute("deviceStatus", request.getIoTDeviceDTO().getState()); // 使用getState()
|
||||
context.setAttribute("deviceStatus", request.getIoTDeviceDTO().getState()); // 使用getState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+114
-19
@@ -74,11 +74,21 @@ public class MQTTDownRequestConverter extends AbstratIoTService
|
||||
private MQTTDownRequest convertGatewaySubDevice(
|
||||
UnifiedDownlinkCommand command, IoTProduct subProduct, DownlinkContext<?> context) {
|
||||
log.info(
|
||||
"[MQTT转换器] 检测到网关子设备, productKey={}, deviceId={}",
|
||||
"[MQTT转换器] 检测到网关子设备, productKey={}, deviceId={}, cmd={}",
|
||||
command.getProductKey(),
|
||||
command.getDeviceId());
|
||||
command.getDeviceId(),
|
||||
command.getCmd());
|
||||
|
||||
// 1. 加载子设备信息
|
||||
// 1. 判断是否需要网关代理
|
||||
boolean needGatewayProxy = isNeedGatewayProxy(command.getCmd());
|
||||
|
||||
if (!needGatewayProxy) {
|
||||
// 对于不需要网关代理的命令(如DEV_ADD等设备管理命令),直接使用子设备信息
|
||||
log.info("[MQTT转换器] 命令{}不需要网关代理,直接使用子设备信息", command.getCmd());
|
||||
return convertSubDeviceDirectly(command, subProduct, context);
|
||||
}
|
||||
|
||||
// 2. 加载子设备信息(需要网关代理时必须存在)
|
||||
IoTDeviceDTO subDevice =
|
||||
getIoTDeviceDTO(
|
||||
IoTDeviceQuery.builder()
|
||||
@@ -87,12 +97,23 @@ public class MQTTDownRequestConverter extends AbstratIoTService
|
||||
.iotId(command.getIotId())
|
||||
.build());
|
||||
|
||||
if (subDevice == null && command.getCmd() != DownCmd.DEV_ADD) {
|
||||
if (subDevice == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"子设备不存在: productKey=" + command.getProductKey() + ", deviceId=" + command.getDeviceId());
|
||||
}
|
||||
|
||||
// 2. 使用子设备的ProductKey执行编解码
|
||||
// 3. 验证网关绑定信息
|
||||
if (StrUtil.isBlank(subDevice.getGwProductKey())
|
||||
|| StrUtil.isBlank(subDevice.getExtDeviceId())) {
|
||||
throw new IllegalArgumentException(
|
||||
"网关子设备缺少网关绑定信息: gwProductKey="
|
||||
+ subDevice.getGwProductKey()
|
||||
+ ", extDeviceId="
|
||||
+ subDevice.getExtDeviceId()
|
||||
+ ", 请先完成子设备与网关的绑定");
|
||||
}
|
||||
|
||||
// 4. 使用子设备的ProductKey执行编解码
|
||||
String payload = null;
|
||||
if (DownCmd.DEV_FUNCTION.equals(command.getCmd())
|
||||
&& CollectionUtil.isNotEmpty(command.getFunction())) {
|
||||
@@ -107,21 +128,13 @@ public class MQTTDownRequestConverter extends AbstratIoTService
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 查询网关设备信息
|
||||
if (StrUtil.isBlank(subDevice.getGwProductKey())
|
||||
|| StrUtil.isBlank(subDevice.getExtDeviceId())) {
|
||||
throw new IllegalArgumentException(
|
||||
"网关子设备缺少网关信息: gwProductKey="
|
||||
+ subDevice.getGwProductKey()
|
||||
+ ", extDeviceId="
|
||||
+ subDevice.getExtDeviceId());
|
||||
}
|
||||
|
||||
// 5. 查询网关产品信息
|
||||
IoTProduct gatewayProduct = getProduct(subDevice.getGwProductKey());
|
||||
if (gatewayProduct == null) {
|
||||
throw new IllegalArgumentException("网关产品不存在: " + subDevice.getGwProductKey());
|
||||
}
|
||||
|
||||
// 6. 查询网关设备信息
|
||||
IoTDeviceDTO gatewayDevice =
|
||||
getIoTDeviceDTO(
|
||||
IoTDeviceQuery.builder()
|
||||
@@ -137,7 +150,7 @@ public class MQTTDownRequestConverter extends AbstratIoTService
|
||||
+ subDevice.getExtDeviceId());
|
||||
}
|
||||
|
||||
// 4. 构建请求对象(使用网关设备的配置)
|
||||
// 7. 构建请求对象(通过网关代理)
|
||||
MQTTDownRequest request = new MQTTDownRequest();
|
||||
BeanUtil.copyProperties(command, request, "extensions", "metadata");
|
||||
|
||||
@@ -156,17 +169,17 @@ public class MQTTDownRequestConverter extends AbstratIoTService
|
||||
request.setSubProductKey(command.getProductKey());
|
||||
request.setIsGatewayProxy(true);
|
||||
|
||||
// 5. 设置网关的配置信息
|
||||
// 8. 设置网关的配置信息
|
||||
DownCommonData downCommonData = new DownCommonData();
|
||||
downCommonData.setConfiguration(parseProductConfigurationSafely(gatewayProduct));
|
||||
request.setDownCommonData(downCommonData);
|
||||
|
||||
// 6. 处理扩展字段
|
||||
// 9. 处理扩展字段
|
||||
if (command.getExtensions() != null && !command.getExtensions().isEmpty()) {
|
||||
request.setData(JSONUtil.parseObj(command.getExtensions()));
|
||||
}
|
||||
|
||||
// 7. 设置消息ID
|
||||
// 10. 设置消息ID
|
||||
if (StrUtil.isBlank(request.getMsgId())) {
|
||||
request.setMsgId(generateMsgId());
|
||||
}
|
||||
@@ -179,6 +192,88 @@ public class MQTTDownRequestConverter extends AbstratIoTService
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断命令是否需要网关代理
|
||||
* @param cmd 下行命令
|
||||
* @return true-需要网关代理, false-直接使用子设备信息
|
||||
*/
|
||||
private boolean isNeedGatewayProxy(DownCmd cmd) {
|
||||
if (cmd == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设备管理类命令不需要网关代理,直接操作子设备
|
||||
return switch (cmd) {
|
||||
case DEV_ADD, DEV_ADDS, // 设备新增
|
||||
DEV_DEL, DEVICE_DELETE, // 设备删除
|
||||
DEV_UPDATE, DEVICE_UPDATE // 设备更新
|
||||
-> false;
|
||||
// 其他命令(功能调用、状态查询等)需要通过网关代理
|
||||
default -> true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接使用子设备信息转换(不需要网关代理的场景)
|
||||
* @param command 下行命令
|
||||
* @param subProduct 子设备产品信息
|
||||
* @param context 下行上下文
|
||||
* @return MQTT下行请求
|
||||
*/
|
||||
private MQTTDownRequest convertSubDeviceDirectly(
|
||||
UnifiedDownlinkCommand command, IoTProduct subProduct, DownlinkContext<?> context) {
|
||||
|
||||
// 1. 创建请求对象
|
||||
MQTTDownRequest request = new MQTTDownRequest();
|
||||
BeanUtil.copyProperties(command, request, "extensions", "metadata");
|
||||
|
||||
// 2. 设置子设备产品信息
|
||||
request.setIoTProduct(subProduct);
|
||||
|
||||
// 3. 尝试加载子设备信息(DEV_ADD时可能不存在)
|
||||
IoTDeviceDTO subDevice = null;
|
||||
if (command.getCmd() != DownCmd.DEV_ADD && command.getCmd() != DownCmd.DEV_ADDS) {
|
||||
subDevice = getIoTDeviceDTO(
|
||||
IoTDeviceQuery.builder()
|
||||
.productKey(command.getProductKey())
|
||||
.deviceId(command.getDeviceId())
|
||||
.iotId(command.getIotId())
|
||||
.build());
|
||||
|
||||
if (subDevice == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"子设备不存在: productKey=" + command.getProductKey() + ", deviceId=" + command.getDeviceId());
|
||||
}
|
||||
}
|
||||
request.setIoTDeviceDTO(subDevice);
|
||||
|
||||
// 4. 设置子设备的配置信息
|
||||
DownCommonData downCommonData = new DownCommonData();
|
||||
downCommonData.setConfiguration(parseProductConfigurationSafely(subProduct));
|
||||
request.setDownCommonData(downCommonData);
|
||||
|
||||
// 5. 处理扩展字段
|
||||
if (command.getExtensions() != null && !command.getExtensions().isEmpty()) {
|
||||
request.setData(JSONUtil.parseObj(command.getExtensions()));
|
||||
}
|
||||
|
||||
// 6. 设置消息ID
|
||||
if (StrUtil.isBlank(request.getMsgId())) {
|
||||
request.setMsgId(generateMsgId());
|
||||
}
|
||||
|
||||
// 7. 标记为子设备(但不通过网关代理)
|
||||
request.setIsGatewayProxy(false);
|
||||
|
||||
log.info(
|
||||
"[MQTT转换器] 子设备直接转换完成(无需网关代理): productKey={}, deviceId={}, cmd={}",
|
||||
command.getProductKey(),
|
||||
command.getDeviceId(),
|
||||
command.getCmd());
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
/** 转换普通设备请求 */
|
||||
private MQTTDownRequest convertNormalDevice(
|
||||
UnifiedDownlinkCommand command, IoTProduct ioTProduct, DownlinkContext<?> context) {
|
||||
|
||||
Reference in New Issue
Block a user