From 348c138749cbdc3a6dd874098ec1a1a46b2216e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sat, 15 Mar 2025 00:26:44 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E3=80=91IoT=EF=BC=9A=E5=BC=95=E5=85=A5=20IotStandardResponse?= =?UTF-8?q?=20=E5=AE=9E=E4=BD=93=E7=B1=BB=EF=BC=8C=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=99=A8=E7=9A=84=E5=93=8D=E5=BA=94=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E4=BC=98=E5=8C=96=E9=94=99=E8=AF=AF=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IotDeviceConfigSetVertxHandler.java | 23 ++++- .../IotDeviceOtaUpgradeVertxHandler.java | 23 ++++- .../IotDevicePropertyGetVertxHandler.java | 23 ++++- .../IotDevicePropertySetVertxHandler.java | 23 ++++- .../IotDeviceServiceInvokeVertxHandler.java | 27 +++++- .../common/pojo/IotStandardResponse.java | 94 +++++++++++++++++++ .../common/util/IotPluginCommonUtils.java | 49 ++++++---- .../router/IotDeviceAuthVertxHandler.java | 16 +++- .../router/IotDeviceMqttMessageHandler.java | 64 +++++++++---- .../router/IotDeviceWebhookVertxHandler.java | 12 ++- .../IotDeviceEventReportVertxHandler.java | 70 ++++++++++---- .../IotDevicePropertyReportVertxHandler.java | 82 ++++++++++++---- 12 files changed, 415 insertions(+), 91 deletions(-) create mode 100644 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 diff --git a/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 b/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 index 5051965b2f..6d2b3b5bae 100644 --- a/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 +++ b/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; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceConfigSetReqDTO; import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse; import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; import io.vertx.core.Handler; import io.vertx.core.json.JsonObject; @@ -25,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC public class IotDeviceConfigSetVertxHandler implements Handler { public static final String PATH = "/sys/:productKey/:deviceName/thing/service/config/set"; + public static final String METHOD = "thing.service.config.set"; private final IotDeviceDownstreamHandler deviceDownstreamHandler; @@ -44,17 +46,32 @@ public class IotDeviceConfigSetVertxHandler implements Handler { .setConfig(config); } catch (Exception e) { log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); + // 使用IotStandardResponse实体类返回错误 + IotStandardResponse errorResponse = IotStandardResponse.error( + null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); return; } // 2. 调用处理器 try { CommonResult result = deviceDownstreamHandler.setDeviceConfig(reqDTO); - IotPluginCommonUtils.writeJson(routingContext, result); + + // 使用IotStandardResponse实体类返回结果 + IotStandardResponse response; + if (result.isSuccess()) { + response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData()); + } else { + response = IotStandardResponse.error( + reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg()); + } + IotPluginCommonUtils.writeJsonResponse(routingContext, response); } catch (Exception e) { log.error("[handle][请求参数({}) 配置设置异常]", reqDTO, e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); + // 使用IotStandardResponse实体类返回错误 + IotStandardResponse errorResponse = IotStandardResponse.error( + reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); } } diff --git a/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 b/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 index 0d52dad498..888677d8b2 100644 --- a/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 +++ b/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; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceOtaUpgradeReqDTO; import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse; import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; import io.vertx.core.Handler; import io.vertx.core.json.JsonObject; @@ -23,6 +24,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC public class IotDeviceOtaUpgradeVertxHandler implements Handler { public static final String PATH = "/ota/:productKey/:deviceName/upgrade"; + public static final String METHOD = "ota.device.upgrade"; private final IotDeviceDownstreamHandler deviceDownstreamHandler; @@ -49,17 +51,32 @@ public class IotDeviceOtaUpgradeVertxHandler implements Handler .setInformation(information); } catch (Exception e) { log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); + // 使用IotStandardResponse实体类返回错误 + IotStandardResponse errorResponse = IotStandardResponse.error( + null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); return; } // 2. 调用处理器 try { CommonResult result = deviceDownstreamHandler.upgradeDeviceOta(reqDTO); - IotPluginCommonUtils.writeJson(routingContext, result); + + // 使用IotStandardResponse实体类返回结果 + IotStandardResponse response; + if (result.isSuccess()) { + response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData()); + } else { + response = IotStandardResponse.error( + reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg()); + } + IotPluginCommonUtils.writeJsonResponse(routingContext, response); } catch (Exception e) { log.error("[handle][请求参数({}) OTA 升级异常]", reqDTO, e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); + // 使用IotStandardResponse实体类返回错误 + IotStandardResponse errorResponse = IotStandardResponse.error( + reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); } } } diff --git a/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 b/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 index 2e99a1b626..dc2a8acfef 100644 --- a/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 +++ b/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; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO; import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse; import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; import io.vertx.core.Handler; import io.vertx.core.json.JsonObject; @@ -25,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC public class IotDevicePropertyGetVertxHandler implements Handler { public static final String PATH = "/sys/:productKey/:deviceName/thing/service/property/get"; + public static final String METHOD = "thing.service.property.get"; private final IotDeviceDownstreamHandler deviceDownstreamHandler; @@ -44,17 +46,32 @@ public class IotDevicePropertyGetVertxHandler implements Handler .setIdentifiers(identifiers); } catch (Exception e) { log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); + // 使用IotStandardResponse实体类返回错误 + IotStandardResponse errorResponse = IotStandardResponse.error( + null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); return; } // 2. 调用处理器 try { CommonResult result = deviceDownstreamHandler.getDeviceProperty(reqDTO); - IotPluginCommonUtils.writeJson(routingContext, result); + + // 使用IotStandardResponse实体类返回结果 + IotStandardResponse response; + if (result.isSuccess()) { + response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData()); + } else { + response = IotStandardResponse.error( + reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg()); + } + IotPluginCommonUtils.writeJsonResponse(routingContext, response); } catch (Exception e) { log.error("[handle][请求参数({}) 属性获取异常]", reqDTO, e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); + // 使用IotStandardResponse实体类返回错误 + IotStandardResponse errorResponse = IotStandardResponse.error( + reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); } } diff --git a/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 b/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 index ddcebccffb..4f0afdccf2 100644 --- a/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 +++ b/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; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO; import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse; import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; import io.vertx.core.Handler; import io.vertx.core.json.JsonObject; @@ -25,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC public class IotDevicePropertySetVertxHandler implements Handler { public static final String PATH = "/sys/:productKey/:deviceName/thing/service/property/set"; + public static final String METHOD = "thing.service.property.set"; private final IotDeviceDownstreamHandler deviceDownstreamHandler; @@ -44,17 +46,32 @@ public class IotDevicePropertySetVertxHandler implements Handler .setProperties(properties); } catch (Exception e) { log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); + // 使用IotStandardResponse实体类返回错误 + IotStandardResponse errorResponse = IotStandardResponse.error( + null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); return; } // 2. 调用处理器 try { CommonResult result = deviceDownstreamHandler.setDeviceProperty(reqDTO); - IotPluginCommonUtils.writeJson(routingContext, result); + + // 使用IotStandardResponse实体类返回结果 + IotStandardResponse response; + if (result.isSuccess()) { + response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData()); + } else { + response = IotStandardResponse.error( + reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg()); + } + IotPluginCommonUtils.writeJsonResponse(routingContext, response); } catch (Exception e) { log.error("[handle][请求参数({}) 属性设置异常]", reqDTO, e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); + // 使用IotStandardResponse实体类返回错误 + IotStandardResponse errorResponse = IotStandardResponse.error( + reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); } } diff --git a/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 b/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 index c4fd2e5044..3a52f212c2 100644 --- a/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 +++ b/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; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO; import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse; import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; import io.vertx.core.Handler; import io.vertx.core.json.JsonObject; @@ -25,6 +26,8 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC public class IotDeviceServiceInvokeVertxHandler implements Handler { public static final String PATH = "/sys/:productKey/:deviceName/thing/service/:identifier"; + public static final String METHOD_PREFIX = "thing.service."; + public static final String METHOD_SUFFIX = ""; private final IotDeviceDownstreamHandler deviceDownstreamHandler; @@ -45,17 +48,35 @@ public class IotDeviceServiceInvokeVertxHandler implements Handler result = deviceDownstreamHandler.invokeDeviceService(reqDTO); - IotPluginCommonUtils.writeJson(routingContext, result); + + // 使用IotStandardResponse实体类返回结果 + String method = METHOD_PREFIX + reqDTO.getIdentifier() + METHOD_SUFFIX; + IotStandardResponse response; + if (result.isSuccess()) { + response = IotStandardResponse.success(reqDTO.getRequestId(), method, result.getData()); + } else { + response = IotStandardResponse.error( + reqDTO.getRequestId(), method, result.getCode(), result.getMsg()); + } + IotPluginCommonUtils.writeJsonResponse(routingContext, response); } catch (Exception e) { log.error("[handle][请求参数({}) 服务调用异常]", reqDTO, e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); + // 使用IotStandardResponse实体类返回错误 + String method = METHOD_PREFIX + reqDTO.getIdentifier() + METHOD_SUFFIX; + IotStandardResponse errorResponse = IotStandardResponse.error( + reqDTO.getRequestId(), method, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); } } diff --git a/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 b/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 new file mode 100644 index 0000000000..a006f3a6ad --- /dev/null +++ b/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,0 +1,94 @@ +package cn.iocoder.yudao.module.iot.plugin.common.pojo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * IoT 标准协议响应实体类 + *

+ * 用于统一 MQTT 和 HTTP 的响应格式 + * + * @author haohao + */ +@Data +@Accessors(chain = true) +public class IotStandardResponse { + + /** + * 消息ID + */ + private String id; + + /** + * 状态码 + */ + private Integer code; + + /** + * 响应数据 + */ + private Object data; + + /** + * 响应消息 + */ + private String message; + + /** + * 方法名 + */ + private String method; + + /** + * 协议版本 + */ + private String version; + + /** + * 创建成功响应 + * + * @param id 消息ID + * @param method 方法名 + * @return 成功响应 + */ + public static IotStandardResponse success(String id, String method) { + return success(id, method, null); + } + + /** + * 创建成功响应 + * + * @param id 消息ID + * @param method 方法名 + * @param data 响应数据 + * @return 成功响应 + */ + public static IotStandardResponse success(String id, String method, Object data) { + return new IotStandardResponse() + .setId(id) + .setCode(200) + .setData(data) + .setMessage("success") + .setMethod(method) + .setVersion("1.0"); + } + + /** + * 创建错误响应 + * + * @param id 消息ID + * @param method 方法名 + * @param code 错误码 + * @param message 错误消息 + * @return 错误响应 + */ + public static IotStandardResponse error(String id, String method, Integer code, String message) { + return new IotStandardResponse() + .setId(id) + .setCode(code) + .setData(null) + .setMessage(message) + .setMethod(method) + .setVersion("1.0"); + } +} \ No newline at end of file diff --git a/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 b/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 index d60df9cc0d..2e09c3c5c3 100644 --- a/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 +++ b/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; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.system.SystemUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse; import io.vertx.core.http.HttpHeaders; import io.vertx.ext.web.RoutingContext; import org.springframework.http.MediaType; @@ -12,7 +12,7 @@ import org.springframework.http.MediaType; /** * IoT 插件的通用工具类 * - * 芋道源码 + * @author 芋道源码 */ public class IotPluginCommonUtils { @@ -33,34 +33,43 @@ public class IotPluginCommonUtils { SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID(), IdUtil.fastSimpleUUID()); } - @SuppressWarnings("deprecation") - public static void writeJson(RoutingContext routingContext, CommonResult result) { - routingContext.response() - .setStatusCode(200) - .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) - .end(JsonUtils.toJsonString(result)); - } - - @SuppressWarnings("deprecation") - public static void writeJson(RoutingContext routingContext, String result) { - routingContext.response() - .setStatusCode(200) - .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) - .end(result); - } - /** - * 将对象转换为 JSON 字符串后写入响应 + * 将对象转换为JSON字符串后写入HTTP响应 * * @param routingContext 路由上下文 * @param data 数据对象 */ @SuppressWarnings("deprecation") - public static void writeJson(RoutingContext routingContext, Object data) { + public static void writeJsonResponse(RoutingContext routingContext, Object data) { routingContext.response() .setStatusCode(200) .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) .end(JsonUtils.toJsonString(data)); } + /** + * 生成标准JSON格式的响应并写入HTTP响应(基于IotStandardResponse) + *

+ * 推荐使用此方法,统一MQTT和HTTP的响应格式。使用方式: + * + *

+     * // 成功响应
+     * IotStandardResponse response = IotStandardResponse.success(requestId, method, data);
+     * IotPluginCommonUtils.writeJsonResponse(routingContext, response);
+     *
+     * // 错误响应
+     * IotStandardResponse errorResponse = IotStandardResponse.error(requestId, method, code, message);
+     * IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
+     * 
+ * + * @param routingContext 路由上下文 + * @param response IotStandardResponse响应对象 + */ + @SuppressWarnings("deprecation") + public static void writeJsonResponse(RoutingContext routingContext, IotStandardResponse response) { + routingContext.response() + .setStatusCode(200) + .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) + .end(JsonUtils.toJsonString(response)); + } } diff --git a/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 b/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 index 3f3cf94e9a..472eb83f7f 100644 --- a/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 +++ b/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; /** * IoT Emqx 连接认证的 Vert.x Handler - * MQTT HTTP + * MQTT + * HTTP + * + * 注意:该处理器需要返回特定格式:{"result": "allow"} 或 {"result": "deny"}, + * 以符合 EMQX 认证插件的要求,因此不使用 IotStandardResponse 实体类。 * * @author haohao */ @@ -43,15 +48,18 @@ public class IotDeviceAuthVertxHandler implements Handler { // 调用认证 API CommonResult authResult = deviceUpstreamApi.authenticateEmqxConnection(authReqDTO); if (authResult.getCode() != 0 || !authResult.getData()) { - IotPluginCommonUtils.writeJson(routingContext, Collections.singletonMap("result", "deny")); + // 注意:这里必须返回 {"result": "deny"} 格式,以符合 EMQX 认证插件的要求 + IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "deny")); return; } // 响应结果 - IotPluginCommonUtils.writeJson(routingContext, Collections.singletonMap("result", "allow")); + // 注意:这里必须返回 {"result": "allow"} 格式,以符合 EMQX 认证插件的要求 + IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "allow")); } catch (Exception e) { log.error("[handle][EMQX 认证异常]", e); - IotPluginCommonUtils.writeJson(routingContext, Collections.singletonMap("result", "deny")); + // 注意:这里必须返回 {"result": "deny"} 格式,以符合 EMQX 认证插件的要求 + IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "deny")); } } diff --git a/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 b/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 index 9851d1747f..4af6877bfd 100644 --- a/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 +++ b/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; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO; import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO; +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse; import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; import io.netty.handler.codec.mqtt.MqttQoS; import io.vertx.core.buffer.Buffer; @@ -14,6 +16,8 @@ import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; /** * IoT 设备 MQTT 消息处理器 @@ -32,16 +36,16 @@ public class IotDeviceMqttMessageHandler { // 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply // 设备上报事件 标准 JSON - // 请求 Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post - // 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post_reply + // 请求 + // Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post + // 响应 + // Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post_reply private static final String SYS_TOPIC_PREFIX = "/sys/"; private static final String PROPERTY_POST_TOPIC = "/thing/event/property/post"; private static final String EVENT_POST_TOPIC_PREFIX = "/thing/event/"; private static final String EVENT_POST_TOPIC_SUFFIX = "/post"; private static final String REPLY_SUFFIX = "_reply"; - private static final int SUCCESS_CODE = 200; - private static final String SUCCESS_MESSAGE = "success"; private static final String PROPERTY_METHOD = "thing.event.property.post"; private static final String EVENT_METHOD_PREFIX = "thing.event."; private static final String EVENT_METHOD_SUFFIX = ".post"; @@ -211,27 +215,25 @@ public class IotDeviceMqttMessageHandler { * @param method 响应方法 * @param customData 自定义数据,可为null */ - private void sendResponse(String topic, JSONObject jsonObject, String method, JSONObject customData) { + private void sendResponse(String topic, JSONObject jsonObject, String method, Object customData) { String replyTopic = topic + REPLY_SUFFIX; - JSONObject data = customData != null ? customData : new JSONObject(); - JSONObject response = new JSONObject() - .set("id", jsonObject.getStr("id")) - .set("code", SUCCESS_CODE) - .set("data", data) - .set("message", SUCCESS_MESSAGE) - .set("method", method); + // 使用IotStandardResponse实体类构建响应 + IotStandardResponse response = IotStandardResponse.success( + jsonObject.getStr("id"), + method, + customData); try { mqttClient.publish(replyTopic, - Buffer.buffer(response.toString()), + Buffer.buffer(JsonUtils.toJsonString(response)), MqttQoS.AT_LEAST_ONCE, false, false); log.info("[sendResponse][发送响应消息成功][topic: {}]", replyTopic); } catch (Exception e) { log.error("[sendResponse][发送响应消息失败][topic: {}][response: {}]", - replyTopic, response.toString(), e); + replyTopic, response, e); } } @@ -249,7 +251,29 @@ public class IotDeviceMqttMessageHandler { reportReqDTO.setReportTime(LocalDateTime.now()); reportReqDTO.setProductKey(topicParts[2]); reportReqDTO.setDeviceName(topicParts[3]); - reportReqDTO.setProperties(jsonObject.getJSONObject("params")); + + // 只使用标准JSON格式处理属性数据 + JSONObject params = jsonObject.getJSONObject("params"); + if (params == null) { + log.warn("[buildPropertyReportDTO][消息格式不正确,缺少params字段][jsonObject: {}]", jsonObject); + params = new JSONObject(); + } + + // 将标准格式的params转换为平台需要的properties格式 + Map properties = new HashMap<>(); + for (Map.Entry entry : params.entrySet()) { + String key = entry.getKey(); + Object valueObj = entry.getValue(); + + // 如果是复杂结构(包含value和time) + if (valueObj instanceof JSONObject valueJson) { + properties.put(key, valueJson.getOrDefault("value", valueObj)); + } else { + properties.put(key, valueObj); + } + } + reportReqDTO.setProperties(properties); + return reportReqDTO; } @@ -268,7 +292,15 @@ public class IotDeviceMqttMessageHandler { reportReqDTO.setProductKey(topicParts[2]); reportReqDTO.setDeviceName(topicParts[3]); reportReqDTO.setIdentifier(topicParts[6]); - reportReqDTO.setParams(jsonObject.getJSONObject("params")); + + // 只使用标准JSON格式处理事件参数 + JSONObject params = jsonObject.getJSONObject("params"); + if (params == null) { + log.warn("[buildEventReportDTO][消息格式不正确,缺少params字段][jsonObject: {}]", jsonObject); + params = new JSONObject(); + } + reportReqDTO.setParams(params); + return reportReqDTO; } } \ No newline at end of file diff --git a/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 b/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 index 31679fe056..6f1e8a11b8 100644 --- a/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 +++ b/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; /** * IoT Emqx Webhook 事件处理的 Vert.x Handler * - * EMQXWebhook + * EMQXWebhook + * + * 注意:该处理器需要返回特定格式:{"result": "success"} 或 {"result": "error"}, + * 以符合 EMQX Webhook 插件的要求,因此不使用 IotStandardResponse 实体类。 * * @author haohao */ @@ -54,10 +58,12 @@ public class IotDeviceWebhookVertxHandler implements Handler { } // 返回成功响应 - IotPluginCommonUtils.writeJson(routingContext, Collections.singletonMap("result", "success")); + // 注意:这里必须返回 {"result": "success"} 格式,以符合 EMQX Webhook 插件的要求 + IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "success")); } catch (Exception e) { log.error("[handle][处理 Webhook 事件异常]", e); - IotPluginCommonUtils.writeJson(routingContext, Collections.singletonMap("result", "error")); + // 注意:这里必须返回 {"result": "error"} 格式,以符合 EMQX Webhook 插件的要求 + IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "error")); } } diff --git a/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 b/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 index bdb92b6ee7..e4d1a73814 100644 --- a/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 +++ b/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; import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO; import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse; import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; import io.vertx.core.Handler; import io.vertx.core.json.JsonObject; @@ -15,6 +16,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; +import java.util.HashMap; import java.util.Map; 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 public class IotDeviceEventReportVertxHandler implements Handler { public static final String PATH = "/sys/:productKey/:deviceName/thing/event/:identifier/post"; + private static final String VERSION = "1.0"; + private static final String EVENT_METHOD_PREFIX = "thing.event."; + private static final String EVENT_METHOD_SUFFIX = ".post"; private final IotDeviceUpstreamApi deviceUpstreamApi; @@ -36,40 +41,71 @@ public class IotDeviceEventReportVertxHandler implements Handler public void handle(RoutingContext routingContext) { // 1. 解析参数 IotDeviceEventReportReqDTO reportReqDTO; + String identifier = null; + String requestId = IdUtil.fastSimpleUUID(); try { String productKey = routingContext.pathParam("productKey"); String deviceName = routingContext.pathParam("deviceName"); - String identifier = routingContext.pathParam("identifier"); + identifier = routingContext.pathParam("identifier"); JsonObject body = routingContext.body().asJsonObject(); - String id = ObjUtil.defaultIfBlank(body.getString("id"), IdUtil.fastSimpleUUID()); - Map params = (Map) body.getMap().get("params"); - reportReqDTO = ((IotDeviceEventReportReqDTO) - new IotDeviceEventReportReqDTO().setRequestId(id) - .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) - .setProductKey(productKey).setDeviceName(deviceName)) + requestId = ObjUtil.defaultIfBlank(body.getString("id"), requestId); + + // 按照标准JSON格式处理事件参数 + Map params; + + // 优先使用params字段,符合标准 + if (body.getJsonObject("params") != null) { + params = body.getJsonObject("params").getMap(); + } else { + // 兼容旧格式 + params = new HashMap<>(); + } + + reportReqDTO = ((IotDeviceEventReportReqDTO) new IotDeviceEventReportReqDTO().setRequestId(requestId) + .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) + .setProductKey(productKey).setDeviceName(deviceName)) .setIdentifier(identifier).setParams(params); } catch (Exception e) { log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); + // 使用IotStandardResponse实体类返回错误 + String method = identifier != null ? EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX + : "thing.event.unknown.post"; + IotStandardResponse errorResponse = IotStandardResponse.error( + requestId, method, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); return; } try { // 2. 设备上线 - deviceUpstreamApi.updateDeviceState(((IotDeviceStateUpdateReqDTO) - new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()) + deviceUpstreamApi.updateDeviceState( + ((IotDeviceStateUpdateReqDTO) new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()) .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) .setProductKey(reportReqDTO.getProductKey()).setDeviceName(reportReqDTO.getDeviceName())) - .setState(IotDeviceStateEnum.ONLINE.getState())); + .setState(IotDeviceStateEnum.ONLINE.getState())); - // 3.1 属性上报 + // 3.1 事件上报 CommonResult result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO); - // 3.2 返回结果 - IotPluginCommonUtils.writeJson(routingContext, result); + + // 3.2 返回结果 - 使用IotStandardResponse实体类 + String method = EVENT_METHOD_PREFIX + reportReqDTO.getIdentifier() + EVENT_METHOD_SUFFIX; + IotStandardResponse response; + if (result.isSuccess()) { + response = IotStandardResponse.success(reportReqDTO.getRequestId(), method, result.getData()); + } else { + response = IotStandardResponse.error( + reportReqDTO.getRequestId(), method, result.getCode(), result.getMsg()); + } + IotPluginCommonUtils.writeJsonResponse(routingContext, response); } catch (Exception e) { - log.error("[handle][请求参数({}) 时间上报异常]", reportReqDTO, e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); + log.error("[handle][请求参数({}) 事件上报异常]", reportReqDTO, e); + + // 构建错误响应 - 使用IotStandardResponse实体类 + String method = EVENT_METHOD_PREFIX + reportReqDTO.getIdentifier() + EVENT_METHOD_SUFFIX; + IotStandardResponse errorResponse = IotStandardResponse.error( + reportReqDTO.getRequestId(), method, + INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); } } - } diff --git a/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 b/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 index 22fb1be821..be3e0017ad 100644 --- a/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 +++ b/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; import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO; import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; +import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse; import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils; import io.vertx.core.Handler; import io.vertx.core.json.JsonObject; @@ -15,6 +16,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; +import java.util.HashMap; import java.util.Map; 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 public class IotDevicePropertyReportVertxHandler implements Handler { public static final String PATH = "/sys/:productKey/:deviceName/thing/event/property/post"; + private static final String VERSION = "1.0"; + private static final String METHOD = "thing.event.property.post"; private final IotDeviceUpstreamApi deviceUpstreamApi; @@ -39,43 +43,89 @@ public class IotDevicePropertyReportVertxHandler implements Handler properties = (Map) body.getMap().get("properties"); - reportReqDTO = ((IotDevicePropertyReportReqDTO) - new IotDevicePropertyReportReqDTO().setRequestId(id) - .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) - .setProductKey(productKey).setDeviceName(deviceName)) + requestId = ObjUtil.defaultIfBlank(body.getString("id"), requestId); + + // 按照标准JSON格式处理属性数据 + Map properties = new HashMap<>(); + + // 优先使用params字段,符合标准 + Map params = body.getJsonObject("params") != null ? body.getJsonObject("params").getMap() + : null; + + if (params != null) { + // 将标准格式的params转换为平台需要的properties格式 + for (Map.Entry entry : params.entrySet()) { + String key = entry.getKey(); + Object valueObj = entry.getValue(); + + // 如果是复杂结构(包含value和time) + if (valueObj instanceof Map) { + Map valueMap = (Map) valueObj; + if (valueMap.containsKey("value")) { + properties.put(key, valueMap.get("value")); + } else { + properties.put(key, valueObj); + } + } else { + properties.put(key, valueObj); + } + } + } else { + // 兼容旧格式,直接使用properties字段 + properties = body.getJsonObject("properties") != null ? body.getJsonObject("properties").getMap() + : new HashMap<>(); + } + + reportReqDTO = ((IotDevicePropertyReportReqDTO) new IotDevicePropertyReportReqDTO().setRequestId(requestId) + .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) + .setProductKey(productKey).setDeviceName(deviceName)) .setProperties(properties); } catch (Exception e) { log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); + // 使用IotStandardResponse实体类返回错误 + IotStandardResponse errorResponse = IotStandardResponse.error( + requestId, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); return; } // TODO @芋艿:secret 校验。目前的想法: - // 方案一:请求的时候,带上 secret 参数,然后进行校验,减少请求的频次。不过可能要看下 mqtt 能不能复用! - // 方案二:本地有设备信息的缓存,异步刷新。这样可能 mqtt 的校验,和 http 校验都容易适配。 + // 方案一:请求的时候,带上 secret 参数,然后进行校验,减少请求的频次。不过可能要看下 mqtt 能不能复用! + // 方案二:本地有设备信息的缓存,异步刷新。这样可能 mqtt 的校验,和 http 校验都容易适配。 try { // 2. 设备上线 - deviceUpstreamApi.updateDeviceState(((IotDeviceStateUpdateReqDTO) - new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()) + deviceUpstreamApi.updateDeviceState( + ((IotDeviceStateUpdateReqDTO) new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()) .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) .setProductKey(reportReqDTO.getProductKey()).setDeviceName(reportReqDTO.getDeviceName())) - .setState(IotDeviceStateEnum.ONLINE.getState())); + .setState(IotDeviceStateEnum.ONLINE.getState())); // 3.1 属性上报 CommonResult result = deviceUpstreamApi.reportDeviceProperty(reportReqDTO); - // 3.2 返回结果 - IotPluginCommonUtils.writeJson(routingContext, result); + + // 3.2 返回结果 - 使用IotStandardResponse实体类 + IotStandardResponse response; + if (result.isSuccess()) { + response = IotStandardResponse.success(reportReqDTO.getRequestId(), METHOD, result.getData()); + } else { + response = IotStandardResponse.error( + reportReqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg()); + } + IotPluginCommonUtils.writeJsonResponse(routingContext, response); } catch (Exception e) { log.error("[handle][请求参数({}) 属性上报异常]", reportReqDTO, e); - IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); + + // 构建错误响应 - 使用IotStandardResponse实体类 + IotStandardResponse errorResponse = IotStandardResponse.error( + reportReqDTO.getRequestId(), METHOD, + INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); + IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse); } } - }