Commit 348c138749cbdc3a6dd874098ec1a1a46b2216e9

Authored by 安浩浩
1 parent 34453a3f

【功能完善】IoT:引入 IotStandardResponse 实体类,统一处理器的响应格式,优化错误处理逻辑

Showing 12 changed files with 412 additions and 88 deletions
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDeviceConfigSetVertxHandler.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.downstream.router; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.downstream.router;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceConfigSetReqDTO; 4 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceConfigSetReqDTO;
5 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; 5 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
  6 +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
6 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; 7 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
7 import io.vertx.core.Handler; 8 import io.vertx.core.Handler;
8 import io.vertx.core.json.JsonObject; 9 import io.vertx.core.json.JsonObject;
@@ -25,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @@ -25,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
25 public class IotDeviceConfigSetVertxHandler implements Handler<RoutingContext> { 26 public class IotDeviceConfigSetVertxHandler implements Handler<RoutingContext> {
26 27
27 public static final String PATH = "/sys/:productKey/:deviceName/thing/service/config/set"; 28 public static final String PATH = "/sys/:productKey/:deviceName/thing/service/config/set";
  29 + public static final String METHOD = "thing.service.config.set";
28 30
29 private final IotDeviceDownstreamHandler deviceDownstreamHandler; 31 private final IotDeviceDownstreamHandler deviceDownstreamHandler;
30 32
@@ -44,17 +46,32 @@ public class IotDeviceConfigSetVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -44,17 +46,32 @@ public class IotDeviceConfigSetVertxHandler implements Handler&lt;RoutingContext&gt; {
44 .setConfig(config); 46 .setConfig(config);
45 } catch (Exception e) { 47 } catch (Exception e) {
46 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); 48 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
47 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); 49 + // 使用IotStandardResponse实体类返回错误
  50 + IotStandardResponse errorResponse = IotStandardResponse.error(
  51 + null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
  52 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
48 return; 53 return;
49 } 54 }
50 55
51 // 2. 调用处理器 56 // 2. 调用处理器
52 try { 57 try {
53 CommonResult<Boolean> result = deviceDownstreamHandler.setDeviceConfig(reqDTO); 58 CommonResult<Boolean> result = deviceDownstreamHandler.setDeviceConfig(reqDTO);
54 - IotPluginCommonUtils.writeJson(routingContext, result); 59 +
  60 + // 使用IotStandardResponse实体类返回结果
  61 + IotStandardResponse response;
  62 + if (result.isSuccess()) {
  63 + response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData());
  64 + } else {
  65 + response = IotStandardResponse.error(
  66 + reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
  67 + }
  68 + IotPluginCommonUtils.writeJsonResponse(routingContext, response);
55 } catch (Exception e) { 69 } catch (Exception e) {
56 log.error("[handle][请求参数({}) 配置设置异常]", reqDTO, e); 70 log.error("[handle][请求参数({}) 配置设置异常]", reqDTO, e);
57 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); 71 + // 使用IotStandardResponse实体类返回错误
  72 + IotStandardResponse errorResponse = IotStandardResponse.error(
  73 + reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
  74 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
58 } 75 }
59 } 76 }
60 77
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDeviceOtaUpgradeVertxHandler.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.downstream.router; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.downstream.router;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceOtaUpgradeReqDTO; 4 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceOtaUpgradeReqDTO;
5 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; 5 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
  6 +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
6 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; 7 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
7 import io.vertx.core.Handler; 8 import io.vertx.core.Handler;
8 import io.vertx.core.json.JsonObject; 9 import io.vertx.core.json.JsonObject;
@@ -23,6 +24,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @@ -23,6 +24,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
23 public class IotDeviceOtaUpgradeVertxHandler implements Handler<RoutingContext> { 24 public class IotDeviceOtaUpgradeVertxHandler implements Handler<RoutingContext> {
24 25
25 public static final String PATH = "/ota/:productKey/:deviceName/upgrade"; 26 public static final String PATH = "/ota/:productKey/:deviceName/upgrade";
  27 + public static final String METHOD = "ota.device.upgrade";
26 28
27 private final IotDeviceDownstreamHandler deviceDownstreamHandler; 29 private final IotDeviceDownstreamHandler deviceDownstreamHandler;
28 30
@@ -49,17 +51,32 @@ public class IotDeviceOtaUpgradeVertxHandler implements Handler&lt;RoutingContext&gt; @@ -49,17 +51,32 @@ public class IotDeviceOtaUpgradeVertxHandler implements Handler&lt;RoutingContext&gt;
49 .setInformation(information); 51 .setInformation(information);
50 } catch (Exception e) { 52 } catch (Exception e) {
51 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); 53 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
52 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); 54 + // 使用IotStandardResponse实体类返回错误
  55 + IotStandardResponse errorResponse = IotStandardResponse.error(
  56 + null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
  57 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
53 return; 58 return;
54 } 59 }
55 60
56 // 2. 调用处理器 61 // 2. 调用处理器
57 try { 62 try {
58 CommonResult<Boolean> result = deviceDownstreamHandler.upgradeDeviceOta(reqDTO); 63 CommonResult<Boolean> result = deviceDownstreamHandler.upgradeDeviceOta(reqDTO);
59 - IotPluginCommonUtils.writeJson(routingContext, result); 64 +
  65 + // 使用IotStandardResponse实体类返回结果
  66 + IotStandardResponse response;
  67 + if (result.isSuccess()) {
  68 + response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData());
  69 + } else {
  70 + response = IotStandardResponse.error(
  71 + reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
  72 + }
  73 + IotPluginCommonUtils.writeJsonResponse(routingContext, response);
60 } catch (Exception e) { 74 } catch (Exception e) {
61 log.error("[handle][请求参数({}) OTA 升级异常]", reqDTO, e); 75 log.error("[handle][请求参数({}) OTA 升级异常]", reqDTO, e);
62 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); 76 + // 使用IotStandardResponse实体类返回错误
  77 + IotStandardResponse errorResponse = IotStandardResponse.error(
  78 + reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
  79 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
63 } 80 }
64 } 81 }
65 } 82 }
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDevicePropertyGetVertxHandler.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.downstream.router; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.downstream.router;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO; 4 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;
5 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; 5 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
  6 +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
6 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; 7 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
7 import io.vertx.core.Handler; 8 import io.vertx.core.Handler;
8 import io.vertx.core.json.JsonObject; 9 import io.vertx.core.json.JsonObject;
@@ -25,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @@ -25,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
25 public class IotDevicePropertyGetVertxHandler implements Handler<RoutingContext> { 26 public class IotDevicePropertyGetVertxHandler implements Handler<RoutingContext> {
26 27
27 public static final String PATH = "/sys/:productKey/:deviceName/thing/service/property/get"; 28 public static final String PATH = "/sys/:productKey/:deviceName/thing/service/property/get";
  29 + public static final String METHOD = "thing.service.property.get";
28 30
29 private final IotDeviceDownstreamHandler deviceDownstreamHandler; 31 private final IotDeviceDownstreamHandler deviceDownstreamHandler;
30 32
@@ -44,17 +46,32 @@ public class IotDevicePropertyGetVertxHandler implements Handler&lt;RoutingContext&gt; @@ -44,17 +46,32 @@ public class IotDevicePropertyGetVertxHandler implements Handler&lt;RoutingContext&gt;
44 .setIdentifiers(identifiers); 46 .setIdentifiers(identifiers);
45 } catch (Exception e) { 47 } catch (Exception e) {
46 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); 48 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
47 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); 49 + // 使用IotStandardResponse实体类返回错误
  50 + IotStandardResponse errorResponse = IotStandardResponse.error(
  51 + null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
  52 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
48 return; 53 return;
49 } 54 }
50 55
51 // 2. 调用处理器 56 // 2. 调用处理器
52 try { 57 try {
53 CommonResult<Boolean> result = deviceDownstreamHandler.getDeviceProperty(reqDTO); 58 CommonResult<Boolean> result = deviceDownstreamHandler.getDeviceProperty(reqDTO);
54 - IotPluginCommonUtils.writeJson(routingContext, result); 59 +
  60 + // 使用IotStandardResponse实体类返回结果
  61 + IotStandardResponse response;
  62 + if (result.isSuccess()) {
  63 + response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData());
  64 + } else {
  65 + response = IotStandardResponse.error(
  66 + reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
  67 + }
  68 + IotPluginCommonUtils.writeJsonResponse(routingContext, response);
55 } catch (Exception e) { 69 } catch (Exception e) {
56 log.error("[handle][请求参数({}) 属性获取异常]", reqDTO, e); 70 log.error("[handle][请求参数({}) 属性获取异常]", reqDTO, e);
57 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); 71 + // 使用IotStandardResponse实体类返回错误
  72 + IotStandardResponse errorResponse = IotStandardResponse.error(
  73 + reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
  74 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
58 } 75 }
59 } 76 }
60 77
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDevicePropertySetVertxHandler.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.downstream.router; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.downstream.router;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO; 4 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO;
5 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; 5 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
  6 +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
6 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; 7 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
7 import io.vertx.core.Handler; 8 import io.vertx.core.Handler;
8 import io.vertx.core.json.JsonObject; 9 import io.vertx.core.json.JsonObject;
@@ -25,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @@ -25,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
25 public class IotDevicePropertySetVertxHandler implements Handler<RoutingContext> { 26 public class IotDevicePropertySetVertxHandler implements Handler<RoutingContext> {
26 27
27 public static final String PATH = "/sys/:productKey/:deviceName/thing/service/property/set"; 28 public static final String PATH = "/sys/:productKey/:deviceName/thing/service/property/set";
  29 + public static final String METHOD = "thing.service.property.set";
28 30
29 private final IotDeviceDownstreamHandler deviceDownstreamHandler; 31 private final IotDeviceDownstreamHandler deviceDownstreamHandler;
30 32
@@ -44,17 +46,32 @@ public class IotDevicePropertySetVertxHandler implements Handler&lt;RoutingContext&gt; @@ -44,17 +46,32 @@ public class IotDevicePropertySetVertxHandler implements Handler&lt;RoutingContext&gt;
44 .setProperties(properties); 46 .setProperties(properties);
45 } catch (Exception e) { 47 } catch (Exception e) {
46 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); 48 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
47 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); 49 + // 使用IotStandardResponse实体类返回错误
  50 + IotStandardResponse errorResponse = IotStandardResponse.error(
  51 + null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
  52 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
48 return; 53 return;
49 } 54 }
50 55
51 // 2. 调用处理器 56 // 2. 调用处理器
52 try { 57 try {
53 CommonResult<Boolean> result = deviceDownstreamHandler.setDeviceProperty(reqDTO); 58 CommonResult<Boolean> result = deviceDownstreamHandler.setDeviceProperty(reqDTO);
54 - IotPluginCommonUtils.writeJson(routingContext, result); 59 +
  60 + // 使用IotStandardResponse实体类返回结果
  61 + IotStandardResponse response;
  62 + if (result.isSuccess()) {
  63 + response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData());
  64 + } else {
  65 + response = IotStandardResponse.error(
  66 + reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
  67 + }
  68 + IotPluginCommonUtils.writeJsonResponse(routingContext, response);
55 } catch (Exception e) { 69 } catch (Exception e) {
56 log.error("[handle][请求参数({}) 属性设置异常]", reqDTO, e); 70 log.error("[handle][请求参数({}) 属性设置异常]", reqDTO, e);
57 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); 71 + // 使用IotStandardResponse实体类返回错误
  72 + IotStandardResponse errorResponse = IotStandardResponse.error(
  73 + reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
  74 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
58 } 75 }
59 } 76 }
60 77
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDeviceServiceInvokeVertxHandler.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.downstream.router; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.downstream.router;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO; 4 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
5 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; 5 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
  6 +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
6 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; 7 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
7 import io.vertx.core.Handler; 8 import io.vertx.core.Handler;
8 import io.vertx.core.json.JsonObject; 9 import io.vertx.core.json.JsonObject;
@@ -25,6 +26,8 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @@ -25,6 +26,8 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
25 public class IotDeviceServiceInvokeVertxHandler implements Handler<RoutingContext> { 26 public class IotDeviceServiceInvokeVertxHandler implements Handler<RoutingContext> {
26 27
27 public static final String PATH = "/sys/:productKey/:deviceName/thing/service/:identifier"; 28 public static final String PATH = "/sys/:productKey/:deviceName/thing/service/:identifier";
  29 + public static final String METHOD_PREFIX = "thing.service.";
  30 + public static final String METHOD_SUFFIX = "";
28 31
29 private final IotDeviceDownstreamHandler deviceDownstreamHandler; 32 private final IotDeviceDownstreamHandler deviceDownstreamHandler;
30 33
@@ -45,17 +48,35 @@ public class IotDeviceServiceInvokeVertxHandler implements Handler&lt;RoutingContex @@ -45,17 +48,35 @@ public class IotDeviceServiceInvokeVertxHandler implements Handler&lt;RoutingContex
45 .setIdentifier(identifier).setParams(params); 48 .setIdentifier(identifier).setParams(params);
46 } catch (Exception e) { 49 } catch (Exception e) {
47 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); 50 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
48 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); 51 + // 使用IotStandardResponse实体类返回错误
  52 + String method = METHOD_PREFIX + routingContext.pathParam("identifier") + METHOD_SUFFIX;
  53 + IotStandardResponse errorResponse = IotStandardResponse.error(
  54 + null, method, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
  55 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
49 return; 56 return;
50 } 57 }
51 58
52 // 2. 调用处理器 59 // 2. 调用处理器
53 try { 60 try {
54 CommonResult<Boolean> result = deviceDownstreamHandler.invokeDeviceService(reqDTO); 61 CommonResult<Boolean> result = deviceDownstreamHandler.invokeDeviceService(reqDTO);
55 - IotPluginCommonUtils.writeJson(routingContext, result); 62 +
  63 + // 使用IotStandardResponse实体类返回结果
  64 + String method = METHOD_PREFIX + reqDTO.getIdentifier() + METHOD_SUFFIX;
  65 + IotStandardResponse response;
  66 + if (result.isSuccess()) {
  67 + response = IotStandardResponse.success(reqDTO.getRequestId(), method, result.getData());
  68 + } else {
  69 + response = IotStandardResponse.error(
  70 + reqDTO.getRequestId(), method, result.getCode(), result.getMsg());
  71 + }
  72 + IotPluginCommonUtils.writeJsonResponse(routingContext, response);
56 } catch (Exception e) { 73 } catch (Exception e) {
57 log.error("[handle][请求参数({}) 服务调用异常]", reqDTO, e); 74 log.error("[handle][请求参数({}) 服务调用异常]", reqDTO, e);
58 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); 75 + // 使用IotStandardResponse实体类返回错误
  76 + String method = METHOD_PREFIX + reqDTO.getIdentifier() + METHOD_SUFFIX;
  77 + IotStandardResponse errorResponse = IotStandardResponse.error(
  78 + reqDTO.getRequestId(), method, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
  79 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
59 } 80 }
60 } 81 }
61 82
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/pojo/IotStandardResponse.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.plugin.common.pojo;
  2 +
  3 +import lombok.Data;
  4 +import lombok.experimental.Accessors;
  5 +
  6 +/**
  7 + * IoT 标准协议响应实体类
  8 + * <p>
  9 + * 用于统一 MQTT 和 HTTP 的响应格式
  10 + *
  11 + * @author haohao
  12 + */
  13 +@Data
  14 +@Accessors(chain = true)
  15 +public class IotStandardResponse {
  16 +
  17 + /**
  18 + * 消息ID
  19 + */
  20 + private String id;
  21 +
  22 + /**
  23 + * 状态码
  24 + */
  25 + private Integer code;
  26 +
  27 + /**
  28 + * 响应数据
  29 + */
  30 + private Object data;
  31 +
  32 + /**
  33 + * 响应消息
  34 + */
  35 + private String message;
  36 +
  37 + /**
  38 + * 方法名
  39 + */
  40 + private String method;
  41 +
  42 + /**
  43 + * 协议版本
  44 + */
  45 + private String version;
  46 +
  47 + /**
  48 + * 创建成功响应
  49 + *
  50 + * @param id 消息ID
  51 + * @param method 方法名
  52 + * @return 成功响应
  53 + */
  54 + public static IotStandardResponse success(String id, String method) {
  55 + return success(id, method, null);
  56 + }
  57 +
  58 + /**
  59 + * 创建成功响应
  60 + *
  61 + * @param id 消息ID
  62 + * @param method 方法名
  63 + * @param data 响应数据
  64 + * @return 成功响应
  65 + */
  66 + public static IotStandardResponse success(String id, String method, Object data) {
  67 + return new IotStandardResponse()
  68 + .setId(id)
  69 + .setCode(200)
  70 + .setData(data)
  71 + .setMessage("success")
  72 + .setMethod(method)
  73 + .setVersion("1.0");
  74 + }
  75 +
  76 + /**
  77 + * 创建错误响应
  78 + *
  79 + * @param id 消息ID
  80 + * @param method 方法名
  81 + * @param code 错误码
  82 + * @param message 错误消息
  83 + * @return 错误响应
  84 + */
  85 + public static IotStandardResponse error(String id, String method, Integer code, String message) {
  86 + return new IotStandardResponse()
  87 + .setId(id)
  88 + .setCode(code)
  89 + .setData(null)
  90 + .setMessage(message)
  91 + .setMethod(method)
  92 + .setVersion("1.0");
  93 + }
  94 +}
0 \ No newline at end of file 95 \ No newline at end of file
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/util/IotPluginCommonUtils.java
@@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.plugin.common.util; @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.plugin.common.util;
3 import cn.hutool.core.util.IdUtil; 3 import cn.hutool.core.util.IdUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 import cn.hutool.system.SystemUtil; 5 import cn.hutool.system.SystemUtil;
6 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  7 +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
8 import io.vertx.core.http.HttpHeaders; 8 import io.vertx.core.http.HttpHeaders;
9 import io.vertx.ext.web.RoutingContext; 9 import io.vertx.ext.web.RoutingContext;
10 import org.springframework.http.MediaType; 10 import org.springframework.http.MediaType;
@@ -12,7 +12,7 @@ import org.springframework.http.MediaType; @@ -12,7 +12,7 @@ import org.springframework.http.MediaType;
12 /** 12 /**
13 * IoT 插件的通用工具类 13 * IoT 插件的通用工具类
14 * 14 *
15 - * 芋道源码 15 + * @author 芋道源码
16 */ 16 */
17 public class IotPluginCommonUtils { 17 public class IotPluginCommonUtils {
18 18
@@ -33,34 +33,43 @@ public class IotPluginCommonUtils { @@ -33,34 +33,43 @@ public class IotPluginCommonUtils {
33 SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID(), IdUtil.fastSimpleUUID()); 33 SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID(), IdUtil.fastSimpleUUID());
34 } 34 }
35 35
  36 + /**
  37 + * 将对象转换为JSON字符串后写入HTTP响应
  38 + *
  39 + * @param routingContext 路由上下文
  40 + * @param data 数据对象
  41 + */
36 @SuppressWarnings("deprecation") 42 @SuppressWarnings("deprecation")
37 - public static void writeJson(RoutingContext routingContext, CommonResult<?> result) {  
38 - routingContext.response()  
39 - .setStatusCode(200)  
40 - .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)  
41 - .end(JsonUtils.toJsonString(result));  
42 - }  
43 -  
44 - @SuppressWarnings("deprecation")  
45 - public static void writeJson(RoutingContext routingContext, String result) { 43 + public static void writeJsonResponse(RoutingContext routingContext, Object data) {
46 routingContext.response() 44 routingContext.response()
47 .setStatusCode(200) 45 .setStatusCode(200)
48 .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) 46 .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
49 - .end(result); 47 + .end(JsonUtils.toJsonString(data));
50 } 48 }
51 49
52 /** 50 /**
53 - * 将对象转换为 JSON 字符串后写入响应 51 + * 生成标准JSON格式的响应并写入HTTP响应(基于IotStandardResponse)
  52 + * <p>
  53 + * 推荐使用此方法,统一MQTT和HTTP的响应格式。使用方式:
  54 + *
  55 + * <pre>
  56 + * // 成功响应
  57 + * IotStandardResponse response = IotStandardResponse.success(requestId, method, data);
  58 + * IotPluginCommonUtils.writeJsonResponse(routingContext, response);
  59 + *
  60 + * // 错误响应
  61 + * IotStandardResponse errorResponse = IotStandardResponse.error(requestId, method, code, message);
  62 + * IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
  63 + * </pre>
54 * 64 *
55 * @param routingContext 路由上下文 65 * @param routingContext 路由上下文
56 - * @param data 数据对象 66 + * @param response IotStandardResponse响应对象
57 */ 67 */
58 @SuppressWarnings("deprecation") 68 @SuppressWarnings("deprecation")
59 - public static void writeJson(RoutingContext routingContext, Object data) { 69 + public static void writeJsonResponse(RoutingContext routingContext, IotStandardResponse response) {
60 routingContext.response() 70 routingContext.response()
61 .setStatusCode(200) 71 .setStatusCode(200)
62 .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) 72 .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
63 - .end(JsonUtils.toJsonString(data)); 73 + .end(JsonUtils.toJsonString(response));
64 } 74 }
65 -  
66 } 75 }
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceAuthVertxHandler.java
@@ -14,7 +14,12 @@ import java.util.Collections; @@ -14,7 +14,12 @@ import java.util.Collections;
14 14
15 /** 15 /**
16 * IoT Emqx 连接认证的 Vert.x Handler 16 * IoT Emqx 连接认证的 Vert.x Handler
17 - * <a href="https://docs.emqx.com/zh/emqx/latest/access-control/authn/http.html">MQTT HTTP</a> 17 + * <a href=
  18 + * "https://docs.emqx.com/zh/emqx/latest/access-control/authn/http.html">MQTT
  19 + * HTTP</a>
  20 + *
  21 + * 注意:该处理器需要返回特定格式:{"result": "allow"} 或 {"result": "deny"},
  22 + * 以符合 EMQX 认证插件的要求,因此不使用 IotStandardResponse 实体类。
18 * 23 *
19 * @author haohao 24 * @author haohao
20 */ 25 */
@@ -43,15 +48,18 @@ public class IotDeviceAuthVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -43,15 +48,18 @@ public class IotDeviceAuthVertxHandler implements Handler&lt;RoutingContext&gt; {
43 // 调用认证 API 48 // 调用认证 API
44 CommonResult<Boolean> authResult = deviceUpstreamApi.authenticateEmqxConnection(authReqDTO); 49 CommonResult<Boolean> authResult = deviceUpstreamApi.authenticateEmqxConnection(authReqDTO);
45 if (authResult.getCode() != 0 || !authResult.getData()) { 50 if (authResult.getCode() != 0 || !authResult.getData()) {
46 - IotPluginCommonUtils.writeJson(routingContext, Collections.singletonMap("result", "deny")); 51 + // 注意:这里必须返回 {"result": "deny"} 格式,以符合 EMQX 认证插件的要求
  52 + IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "deny"));
47 return; 53 return;
48 } 54 }
49 55
50 // 响应结果 56 // 响应结果
51 - IotPluginCommonUtils.writeJson(routingContext, Collections.singletonMap("result", "allow")); 57 + // 注意:这里必须返回 {"result": "allow"} 格式,以符合 EMQX 认证插件的要求
  58 + IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "allow"));
52 } catch (Exception e) { 59 } catch (Exception e) {
53 log.error("[handle][EMQX 认证异常]", e); 60 log.error("[handle][EMQX 认证异常]", e);
54 - IotPluginCommonUtils.writeJson(routingContext, Collections.singletonMap("result", "deny")); 61 + // 注意:这里必须返回 {"result": "deny"} 格式,以符合 EMQX 认证插件的要求
  62 + IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "deny"));
55 } 63 }
56 } 64 }
57 65
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceMqttMessageHandler.java
@@ -2,9 +2,11 @@ package cn.iocoder.yudao.module.iot.plugin.emqx.upstream.router; @@ -2,9 +2,11 @@ package cn.iocoder.yudao.module.iot.plugin.emqx.upstream.router;
2 2
3 import cn.hutool.json.JSONObject; 3 import cn.hutool.json.JSONObject;
4 import cn.hutool.json.JSONUtil; 4 import cn.hutool.json.JSONUtil;
  5 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; 6 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
6 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO; 7 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO;
7 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO; 8 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO;
  9 +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
8 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; 10 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
9 import io.netty.handler.codec.mqtt.MqttQoS; 11 import io.netty.handler.codec.mqtt.MqttQoS;
10 import io.vertx.core.buffer.Buffer; 12 import io.vertx.core.buffer.Buffer;
@@ -14,6 +16,8 @@ import lombok.extern.slf4j.Slf4j; @@ -14,6 +16,8 @@ import lombok.extern.slf4j.Slf4j;
14 16
15 import java.time.LocalDateTime; 17 import java.time.LocalDateTime;
16 import java.util.Arrays; 18 import java.util.Arrays;
  19 +import java.util.HashMap;
  20 +import java.util.Map;
17 21
18 /** 22 /**
19 * IoT 设备 MQTT 消息处理器 23 * IoT 设备 MQTT 消息处理器
@@ -32,16 +36,16 @@ public class IotDeviceMqttMessageHandler { @@ -32,16 +36,16 @@ public class IotDeviceMqttMessageHandler {
32 // 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply 36 // 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply
33 37
34 // 设备上报事件 标准 JSON 38 // 设备上报事件 标准 JSON
35 - // 请求 Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post  
36 - // 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post_reply 39 + // 请求
  40 + // Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post
  41 + // 响应
  42 + // Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post_reply
37 43
38 private static final String SYS_TOPIC_PREFIX = "/sys/"; 44 private static final String SYS_TOPIC_PREFIX = "/sys/";
39 private static final String PROPERTY_POST_TOPIC = "/thing/event/property/post"; 45 private static final String PROPERTY_POST_TOPIC = "/thing/event/property/post";
40 private static final String EVENT_POST_TOPIC_PREFIX = "/thing/event/"; 46 private static final String EVENT_POST_TOPIC_PREFIX = "/thing/event/";
41 private static final String EVENT_POST_TOPIC_SUFFIX = "/post"; 47 private static final String EVENT_POST_TOPIC_SUFFIX = "/post";
42 private static final String REPLY_SUFFIX = "_reply"; 48 private static final String REPLY_SUFFIX = "_reply";
43 - private static final int SUCCESS_CODE = 200;  
44 - private static final String SUCCESS_MESSAGE = "success";  
45 private static final String PROPERTY_METHOD = "thing.event.property.post"; 49 private static final String PROPERTY_METHOD = "thing.event.property.post";
46 private static final String EVENT_METHOD_PREFIX = "thing.event."; 50 private static final String EVENT_METHOD_PREFIX = "thing.event.";
47 private static final String EVENT_METHOD_SUFFIX = ".post"; 51 private static final String EVENT_METHOD_SUFFIX = ".post";
@@ -211,27 +215,25 @@ public class IotDeviceMqttMessageHandler { @@ -211,27 +215,25 @@ public class IotDeviceMqttMessageHandler {
211 * @param method 响应方法 215 * @param method 响应方法
212 * @param customData 自定义数据,可为null 216 * @param customData 自定义数据,可为null
213 */ 217 */
214 - private void sendResponse(String topic, JSONObject jsonObject, String method, JSONObject customData) { 218 + private void sendResponse(String topic, JSONObject jsonObject, String method, Object customData) {
215 String replyTopic = topic + REPLY_SUFFIX; 219 String replyTopic = topic + REPLY_SUFFIX;
216 - JSONObject data = customData != null ? customData : new JSONObject();  
217 220
218 - JSONObject response = new JSONObject()  
219 - .set("id", jsonObject.getStr("id"))  
220 - .set("code", SUCCESS_CODE)  
221 - .set("data", data)  
222 - .set("message", SUCCESS_MESSAGE)  
223 - .set("method", method); 221 + // 使用IotStandardResponse实体类构建响应
  222 + IotStandardResponse response = IotStandardResponse.success(
  223 + jsonObject.getStr("id"),
  224 + method,
  225 + customData);
224 226
225 try { 227 try {
226 mqttClient.publish(replyTopic, 228 mqttClient.publish(replyTopic,
227 - Buffer.buffer(response.toString()), 229 + Buffer.buffer(JsonUtils.toJsonString(response)),
228 MqttQoS.AT_LEAST_ONCE, 230 MqttQoS.AT_LEAST_ONCE,
229 false, 231 false,
230 false); 232 false);
231 log.info("[sendResponse][发送响应消息成功][topic: {}]", replyTopic); 233 log.info("[sendResponse][发送响应消息成功][topic: {}]", replyTopic);
232 } catch (Exception e) { 234 } catch (Exception e) {
233 log.error("[sendResponse][发送响应消息失败][topic: {}][response: {}]", 235 log.error("[sendResponse][发送响应消息失败][topic: {}][response: {}]",
234 - replyTopic, response.toString(), e); 236 + replyTopic, response, e);
235 } 237 }
236 } 238 }
237 239
@@ -249,7 +251,29 @@ public class IotDeviceMqttMessageHandler { @@ -249,7 +251,29 @@ public class IotDeviceMqttMessageHandler {
249 reportReqDTO.setReportTime(LocalDateTime.now()); 251 reportReqDTO.setReportTime(LocalDateTime.now());
250 reportReqDTO.setProductKey(topicParts[2]); 252 reportReqDTO.setProductKey(topicParts[2]);
251 reportReqDTO.setDeviceName(topicParts[3]); 253 reportReqDTO.setDeviceName(topicParts[3]);
252 - reportReqDTO.setProperties(jsonObject.getJSONObject("params")); 254 +
  255 + // 只使用标准JSON格式处理属性数据
  256 + JSONObject params = jsonObject.getJSONObject("params");
  257 + if (params == null) {
  258 + log.warn("[buildPropertyReportDTO][消息格式不正确,缺少params字段][jsonObject: {}]", jsonObject);
  259 + params = new JSONObject();
  260 + }
  261 +
  262 + // 将标准格式的params转换为平台需要的properties格式
  263 + Map<String, Object> properties = new HashMap<>();
  264 + for (Map.Entry<String, Object> entry : params.entrySet()) {
  265 + String key = entry.getKey();
  266 + Object valueObj = entry.getValue();
  267 +
  268 + // 如果是复杂结构(包含value和time)
  269 + if (valueObj instanceof JSONObject valueJson) {
  270 + properties.put(key, valueJson.getOrDefault("value", valueObj));
  271 + } else {
  272 + properties.put(key, valueObj);
  273 + }
  274 + }
  275 + reportReqDTO.setProperties(properties);
  276 +
253 return reportReqDTO; 277 return reportReqDTO;
254 } 278 }
255 279
@@ -268,7 +292,15 @@ public class IotDeviceMqttMessageHandler { @@ -268,7 +292,15 @@ public class IotDeviceMqttMessageHandler {
268 reportReqDTO.setProductKey(topicParts[2]); 292 reportReqDTO.setProductKey(topicParts[2]);
269 reportReqDTO.setDeviceName(topicParts[3]); 293 reportReqDTO.setDeviceName(topicParts[3]);
270 reportReqDTO.setIdentifier(topicParts[6]); 294 reportReqDTO.setIdentifier(topicParts[6]);
271 - reportReqDTO.setParams(jsonObject.getJSONObject("params")); 295 +
  296 + // 只使用标准JSON格式处理事件参数
  297 + JSONObject params = jsonObject.getJSONObject("params");
  298 + if (params == null) {
  299 + log.warn("[buildEventReportDTO][消息格式不正确,缺少params字段][jsonObject: {}]", jsonObject);
  300 + params = new JSONObject();
  301 + }
  302 + reportReqDTO.setParams(params);
  303 +
272 return reportReqDTO; 304 return reportReqDTO;
273 } 305 }
274 } 306 }
275 \ No newline at end of file 307 \ No newline at end of file
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceWebhookVertxHandler.java
@@ -18,7 +18,11 @@ import java.util.Collections; @@ -18,7 +18,11 @@ import java.util.Collections;
18 /** 18 /**
19 * IoT Emqx Webhook 事件处理的 Vert.x Handler 19 * IoT Emqx Webhook 事件处理的 Vert.x Handler
20 * 20 *
21 - * <a href="https://docs.emqx.com/zh/emqx/latest/data-integration/webhook.html">EMQXWebhook</a> 21 + * <a href=
  22 + * "https://docs.emqx.com/zh/emqx/latest/data-integration/webhook.html">EMQXWebhook</a>
  23 + *
  24 + * 注意:该处理器需要返回特定格式:{"result": "success"} 或 {"result": "error"},
  25 + * 以符合 EMQX Webhook 插件的要求,因此不使用 IotStandardResponse 实体类。
22 * 26 *
23 * @author haohao 27 * @author haohao
24 */ 28 */
@@ -54,10 +58,12 @@ public class IotDeviceWebhookVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -54,10 +58,12 @@ public class IotDeviceWebhookVertxHandler implements Handler&lt;RoutingContext&gt; {
54 } 58 }
55 59
56 // 返回成功响应 60 // 返回成功响应
57 - IotPluginCommonUtils.writeJson(routingContext, Collections.singletonMap("result", "success")); 61 + // 注意:这里必须返回 {"result": "success"} 格式,以符合 EMQX Webhook 插件的要求
  62 + IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "success"));
58 } catch (Exception e) { 63 } catch (Exception e) {
59 log.error("[handle][处理 Webhook 事件异常]", e); 64 log.error("[handle][处理 Webhook 事件异常]", e);
60 - IotPluginCommonUtils.writeJson(routingContext, Collections.singletonMap("result", "error")); 65 + // 注意:这里必须返回 {"result": "error"} 格式,以符合 EMQX Webhook 插件的要求
  66 + IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "error"));
61 } 67 }
62 } 68 }
63 69
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDeviceEventReportVertxHandler.java
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
7 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO; 7 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO;
8 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO; 8 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO;
9 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; 9 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;
  10 +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
10 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; 11 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
11 import io.vertx.core.Handler; 12 import io.vertx.core.Handler;
12 import io.vertx.core.json.JsonObject; 13 import io.vertx.core.json.JsonObject;
@@ -15,6 +16,7 @@ import lombok.RequiredArgsConstructor; @@ -15,6 +16,7 @@ import lombok.RequiredArgsConstructor;
15 import lombok.extern.slf4j.Slf4j; 16 import lombok.extern.slf4j.Slf4j;
16 17
17 import java.time.LocalDateTime; 18 import java.time.LocalDateTime;
  19 +import java.util.HashMap;
18 import java.util.Map; 20 import java.util.Map;
19 21
20 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; 22 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
@@ -28,6 +30,9 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @@ -28,6 +30,9 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
28 public class IotDeviceEventReportVertxHandler implements Handler<RoutingContext> { 30 public class IotDeviceEventReportVertxHandler implements Handler<RoutingContext> {
29 31
30 public static final String PATH = "/sys/:productKey/:deviceName/thing/event/:identifier/post"; 32 public static final String PATH = "/sys/:productKey/:deviceName/thing/event/:identifier/post";
  33 + private static final String VERSION = "1.0";
  34 + private static final String EVENT_METHOD_PREFIX = "thing.event.";
  35 + private static final String EVENT_METHOD_SUFFIX = ".post";
31 36
32 private final IotDeviceUpstreamApi deviceUpstreamApi; 37 private final IotDeviceUpstreamApi deviceUpstreamApi;
33 38
@@ -36,40 +41,71 @@ public class IotDeviceEventReportVertxHandler implements Handler&lt;RoutingContext&gt; @@ -36,40 +41,71 @@ public class IotDeviceEventReportVertxHandler implements Handler&lt;RoutingContext&gt;
36 public void handle(RoutingContext routingContext) { 41 public void handle(RoutingContext routingContext) {
37 // 1. 解析参数 42 // 1. 解析参数
38 IotDeviceEventReportReqDTO reportReqDTO; 43 IotDeviceEventReportReqDTO reportReqDTO;
  44 + String identifier = null;
  45 + String requestId = IdUtil.fastSimpleUUID();
39 try { 46 try {
40 String productKey = routingContext.pathParam("productKey"); 47 String productKey = routingContext.pathParam("productKey");
41 String deviceName = routingContext.pathParam("deviceName"); 48 String deviceName = routingContext.pathParam("deviceName");
42 - String identifier = routingContext.pathParam("identifier"); 49 + identifier = routingContext.pathParam("identifier");
43 JsonObject body = routingContext.body().asJsonObject(); 50 JsonObject body = routingContext.body().asJsonObject();
44 - String id = ObjUtil.defaultIfBlank(body.getString("id"), IdUtil.fastSimpleUUID());  
45 - Map<String, Object> params = (Map<String, Object>) body.getMap().get("params");  
46 - reportReqDTO = ((IotDeviceEventReportReqDTO)  
47 - new IotDeviceEventReportReqDTO().setRequestId(id)  
48 - .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())  
49 - .setProductKey(productKey).setDeviceName(deviceName)) 51 + requestId = ObjUtil.defaultIfBlank(body.getString("id"), requestId);
  52 +
  53 + // 按照标准JSON格式处理事件参数
  54 + Map<String, Object> params;
  55 +
  56 + // 优先使用params字段,符合标准
  57 + if (body.getJsonObject("params") != null) {
  58 + params = body.getJsonObject("params").getMap();
  59 + } else {
  60 + // 兼容旧格式
  61 + params = new HashMap<>();
  62 + }
  63 +
  64 + reportReqDTO = ((IotDeviceEventReportReqDTO) new IotDeviceEventReportReqDTO().setRequestId(requestId)
  65 + .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
  66 + .setProductKey(productKey).setDeviceName(deviceName))
50 .setIdentifier(identifier).setParams(params); 67 .setIdentifier(identifier).setParams(params);
51 } catch (Exception e) { 68 } catch (Exception e) {
52 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); 69 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
53 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); 70 + // 使用IotStandardResponse实体类返回错误
  71 + String method = identifier != null ? EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX
  72 + : "thing.event.unknown.post";
  73 + IotStandardResponse errorResponse = IotStandardResponse.error(
  74 + requestId, method, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
  75 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
54 return; 76 return;
55 } 77 }
56 78
57 try { 79 try {
58 // 2. 设备上线 80 // 2. 设备上线
59 - deviceUpstreamApi.updateDeviceState(((IotDeviceStateUpdateReqDTO)  
60 - new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()) 81 + deviceUpstreamApi.updateDeviceState(
  82 + ((IotDeviceStateUpdateReqDTO) new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID())
61 .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) 83 .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
62 .setProductKey(reportReqDTO.getProductKey()).setDeviceName(reportReqDTO.getDeviceName())) 84 .setProductKey(reportReqDTO.getProductKey()).setDeviceName(reportReqDTO.getDeviceName()))
63 - .setState(IotDeviceStateEnum.ONLINE.getState())); 85 + .setState(IotDeviceStateEnum.ONLINE.getState()));
64 86
65 - // 3.1 属性上报 87 + // 3.1 事件上报
66 CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO); 88 CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO);
67 - // 3.2 返回结果  
68 - IotPluginCommonUtils.writeJson(routingContext, result); 89 +
  90 + // 3.2 返回结果 - 使用IotStandardResponse实体类
  91 + String method = EVENT_METHOD_PREFIX + reportReqDTO.getIdentifier() + EVENT_METHOD_SUFFIX;
  92 + IotStandardResponse response;
  93 + if (result.isSuccess()) {
  94 + response = IotStandardResponse.success(reportReqDTO.getRequestId(), method, result.getData());
  95 + } else {
  96 + response = IotStandardResponse.error(
  97 + reportReqDTO.getRequestId(), method, result.getCode(), result.getMsg());
  98 + }
  99 + IotPluginCommonUtils.writeJsonResponse(routingContext, response);
69 } catch (Exception e) { 100 } catch (Exception e) {
70 - log.error("[handle][请求参数({}) 时间上报异常]", reportReqDTO, e);  
71 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); 101 + log.error("[handle][请求参数({}) 事件上报异常]", reportReqDTO, e);
  102 +
  103 + // 构建错误响应 - 使用IotStandardResponse实体类
  104 + String method = EVENT_METHOD_PREFIX + reportReqDTO.getIdentifier() + EVENT_METHOD_SUFFIX;
  105 + IotStandardResponse errorResponse = IotStandardResponse.error(
  106 + reportReqDTO.getRequestId(), method,
  107 + INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
  108 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
72 } 109 }
73 } 110 }
74 -  
75 } 111 }
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDevicePropertyReportVertxHandler.java
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
7 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO; 7 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO;
8 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO; 8 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO;
9 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; 9 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;
  10 +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
10 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; 11 import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
11 import io.vertx.core.Handler; 12 import io.vertx.core.Handler;
12 import io.vertx.core.json.JsonObject; 13 import io.vertx.core.json.JsonObject;
@@ -15,6 +16,7 @@ import lombok.RequiredArgsConstructor; @@ -15,6 +16,7 @@ import lombok.RequiredArgsConstructor;
15 import lombok.extern.slf4j.Slf4j; 16 import lombok.extern.slf4j.Slf4j;
16 17
17 import java.time.LocalDateTime; 18 import java.time.LocalDateTime;
  19 +import java.util.HashMap;
18 import java.util.Map; 20 import java.util.Map;
19 21
20 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; 22 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
@@ -31,6 +33,8 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @@ -31,6 +33,8 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
31 public class IotDevicePropertyReportVertxHandler implements Handler<RoutingContext> { 33 public class IotDevicePropertyReportVertxHandler implements Handler<RoutingContext> {
32 34
33 public static final String PATH = "/sys/:productKey/:deviceName/thing/event/property/post"; 35 public static final String PATH = "/sys/:productKey/:deviceName/thing/event/property/post";
  36 + private static final String VERSION = "1.0";
  37 + private static final String METHOD = "thing.event.property.post";
34 38
35 private final IotDeviceUpstreamApi deviceUpstreamApi; 39 private final IotDeviceUpstreamApi deviceUpstreamApi;
36 40
@@ -39,43 +43,89 @@ public class IotDevicePropertyReportVertxHandler implements Handler&lt;RoutingConte @@ -39,43 +43,89 @@ public class IotDevicePropertyReportVertxHandler implements Handler&lt;RoutingConte
39 public void handle(RoutingContext routingContext) { 43 public void handle(RoutingContext routingContext) {
40 // 1. 解析参数 44 // 1. 解析参数
41 IotDevicePropertyReportReqDTO reportReqDTO; 45 IotDevicePropertyReportReqDTO reportReqDTO;
  46 + String requestId = IdUtil.fastSimpleUUID();
42 try { 47 try {
43 String productKey = routingContext.pathParam("productKey"); 48 String productKey = routingContext.pathParam("productKey");
44 String deviceName = routingContext.pathParam("deviceName"); 49 String deviceName = routingContext.pathParam("deviceName");
45 JsonObject body = routingContext.body().asJsonObject(); 50 JsonObject body = routingContext.body().asJsonObject();
46 - String id = ObjUtil.defaultIfBlank(body.getString("id"), IdUtil.fastSimpleUUID());  
47 - Map<String, Object> properties = (Map<String, Object>) body.getMap().get("properties");  
48 - reportReqDTO = ((IotDevicePropertyReportReqDTO)  
49 - new IotDevicePropertyReportReqDTO().setRequestId(id)  
50 - .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())  
51 - .setProductKey(productKey).setDeviceName(deviceName)) 51 + requestId = ObjUtil.defaultIfBlank(body.getString("id"), requestId);
  52 +
  53 + // 按照标准JSON格式处理属性数据
  54 + Map<String, Object> properties = new HashMap<>();
  55 +
  56 + // 优先使用params字段,符合标准
  57 + Map<String, Object> params = body.getJsonObject("params") != null ? body.getJsonObject("params").getMap()
  58 + : null;
  59 +
  60 + if (params != null) {
  61 + // 将标准格式的params转换为平台需要的properties格式
  62 + for (Map.Entry<String, Object> entry : params.entrySet()) {
  63 + String key = entry.getKey();
  64 + Object valueObj = entry.getValue();
  65 +
  66 + // 如果是复杂结构(包含value和time)
  67 + if (valueObj instanceof Map) {
  68 + Map<String, Object> valueMap = (Map<String, Object>) valueObj;
  69 + if (valueMap.containsKey("value")) {
  70 + properties.put(key, valueMap.get("value"));
  71 + } else {
  72 + properties.put(key, valueObj);
  73 + }
  74 + } else {
  75 + properties.put(key, valueObj);
  76 + }
  77 + }
  78 + } else {
  79 + // 兼容旧格式,直接使用properties字段
  80 + properties = body.getJsonObject("properties") != null ? body.getJsonObject("properties").getMap()
  81 + : new HashMap<>();
  82 + }
  83 +
  84 + reportReqDTO = ((IotDevicePropertyReportReqDTO) new IotDevicePropertyReportReqDTO().setRequestId(requestId)
  85 + .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
  86 + .setProductKey(productKey).setDeviceName(deviceName))
52 .setProperties(properties); 87 .setProperties(properties);
53 } catch (Exception e) { 88 } catch (Exception e) {
54 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); 89 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
55 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); 90 + // 使用IotStandardResponse实体类返回错误
  91 + IotStandardResponse errorResponse = IotStandardResponse.error(
  92 + requestId, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
  93 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
56 return; 94 return;
57 } 95 }
58 96
59 // TODO @芋艿:secret 校验。目前的想法: 97 // TODO @芋艿:secret 校验。目前的想法:
60 - // 方案一:请求的时候,带上 secret 参数,然后进行校验,减少请求的频次。不过可能要看下 mqtt 能不能复用!  
61 - // 方案二:本地有设备信息的缓存,异步刷新。这样可能 mqtt 的校验,和 http 校验都容易适配。 98 + // 方案一:请求的时候,带上 secret 参数,然后进行校验,减少请求的频次。不过可能要看下 mqtt 能不能复用!
  99 + // 方案二:本地有设备信息的缓存,异步刷新。这样可能 mqtt 的校验,和 http 校验都容易适配。
62 100
63 try { 101 try {
64 // 2. 设备上线 102 // 2. 设备上线
65 - deviceUpstreamApi.updateDeviceState(((IotDeviceStateUpdateReqDTO)  
66 - new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()) 103 + deviceUpstreamApi.updateDeviceState(
  104 + ((IotDeviceStateUpdateReqDTO) new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID())
67 .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) 105 .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
68 .setProductKey(reportReqDTO.getProductKey()).setDeviceName(reportReqDTO.getDeviceName())) 106 .setProductKey(reportReqDTO.getProductKey()).setDeviceName(reportReqDTO.getDeviceName()))
69 - .setState(IotDeviceStateEnum.ONLINE.getState())); 107 + .setState(IotDeviceStateEnum.ONLINE.getState()));
70 108
71 // 3.1 属性上报 109 // 3.1 属性上报
72 CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceProperty(reportReqDTO); 110 CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceProperty(reportReqDTO);
73 - // 3.2 返回结果  
74 - IotPluginCommonUtils.writeJson(routingContext, result); 111 +
  112 + // 3.2 返回结果 - 使用IotStandardResponse实体类
  113 + IotStandardResponse response;
  114 + if (result.isSuccess()) {
  115 + response = IotStandardResponse.success(reportReqDTO.getRequestId(), METHOD, result.getData());
  116 + } else {
  117 + response = IotStandardResponse.error(
  118 + reportReqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
  119 + }
  120 + IotPluginCommonUtils.writeJsonResponse(routingContext, response);
75 } catch (Exception e) { 121 } catch (Exception e) {
76 log.error("[handle][请求参数({}) 属性上报异常]", reportReqDTO, e); 122 log.error("[handle][请求参数({}) 属性上报异常]", reportReqDTO, e);
77 - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); 123 +
  124 + // 构建错误响应 - 使用IotStandardResponse实体类
  125 + IotStandardResponse errorResponse = IotStandardResponse.error(
  126 + reportReqDTO.getRequestId(), METHOD,
  127 + INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
  128 + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
78 } 129 }
79 } 130 }
80 -  
81 } 131 }