Browse Source

【功能优化】IoT:重构上行请求处理逻辑,合并属性和事件上报处理,简化代码结构,删除冗余处理器

安浩浩 5 months ago
parent
commit
81739186c9
9 changed files with 201 additions and 264 deletions
  1. 0 11
      yudao-module-iot/yudao-module-iot-biz/pom.xml
  2. 1 2
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotKafkaMQDataBridgeExecute.java
  3. 6 3
      yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotEmqxPlugin.java
  4. 1 0
      yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/downstream/IotDeviceDownstreamHandlerImpl.java
  5. 1 0
      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
  6. 7 6
      yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/IotDeviceUpstreamServer.java
  7. 0 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/IotDeviceEventReportVertxHandler.java
  8. 0 131
      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
  9. 185 0
      yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDeviceUpstreamVertxHandler.java

+ 0 - 11
yudao-module-iot/yudao-module-iot-biz/pom.xml

@@ -64,17 +64,6 @@
             <artifactId>yudao-spring-boot-starter-excel</artifactId>
         </dependency>
 
-        <!-- TODO @haohao:貌似不需要这个? -->
-<!--        <dependency>-->
-<!--            <groupId>io.vertx</groupId>-->
-<!--            <artifactId>vertx-web</artifactId>-->
-<!--        </dependency>-->
-
-        <!-- TODO @haohao:貌似 biz 模块,不需要 MQTT? -->
-<!--        <dependency>-->
-<!--            <groupId>org.eclipse.paho</groupId> &lt;!&ndash; MQTT &ndash;&gt;-->
-<!--            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>-->
-<!--        </dependency>-->
         <!-- 消息队列相关 -->
         <dependency>
             <groupId>org.apache.rocketmq</groupId>

+ 1 - 2
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotKafkaMQDataBridgeExecute.java

@@ -10,7 +10,6 @@ import org.apache.kafka.common.serialization.StringSerializer;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
 import org.springframework.kafka.core.DefaultKafkaProducerFactory;
 import org.springframework.kafka.core.KafkaTemplate;
-import org.springframework.stereotype.Component;
 
 import java.time.Duration;
 import java.time.LocalDateTime;
@@ -24,7 +23,7 @@ import java.util.concurrent.TimeUnit;
  * @author HUIHUI
  */
 @ConditionalOnClass(name = "org.springframework.kafka.core.KafkaTemplate")
-@Component
+//@Component
 @Slf4j
 public class IotKafkaMQDataBridgeExecute extends
         AbstractCacheableDataBridgeExecute<IotDataBridgeKafkaMQConfig, KafkaTemplate<String, String>> {

+ 6 - 3
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotEmqxPlugin.java

@@ -7,10 +7,13 @@ import org.pf4j.spring.SpringPlugin;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
-// TODO @芋艿:完善注释
-
 /**
- * 负责插件的启动和停止
+ * EMQX 插件实现类
+ *
+ * 基于 PF4J 插件框架,实现 EMQX 消息中间件的集成
+ * 负责插件的生命周期管理,包括启动、停止和应用上下文的创建
+ *
+ * @author 芋道源码
  */
 @Slf4j
 public class IotEmqxPlugin extends SpringPlugin {

+ 1 - 0
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/downstream/IotDeviceDownstreamHandlerImpl.java

@@ -27,6 +27,7 @@ public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandle
     private static final String SYS_TOPIC_PREFIX = "/sys/";
 
     // TODO @haohao:讨论,感觉 mqtt 和 http,可以做个相对统一的格式哈。
+    // 回复 都使用 Alink 格式,方便后续扩展。
     // 设备服务调用 标准 JSON
     // 请求Topic:/sys/${productKey}/${deviceName}/thing/service/${tsl.service.identifier}
     // 响应Topic:/sys/${productKey}/${deviceName}/thing/service/${tsl.service.identifier}_reply

+ 1 - 0
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

@@ -31,6 +31,7 @@ import java.util.Map;
 public class IotDeviceMqttMessageHandler {
 
     // TODO @haohao:讨论,感觉 mqtt 和 http,可以做个相对统一的格式哈。
+    // 回复 都使用 Alink 格式,方便后续扩展。
     // 设备上报属性 标准 JSON
     // 请求 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post
     // 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply

+ 7 - 6
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/IotDeviceUpstreamServer.java

@@ -2,8 +2,7 @@ package cn.iocoder.yudao.module.iot.plugin.http.upstream;
 
 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
 import cn.iocoder.yudao.module.iot.plugin.http.config.IotPluginHttpProperties;
-import cn.iocoder.yudao.module.iot.plugin.http.upstream.router.IotDeviceEventReportVertxHandler;
-import cn.iocoder.yudao.module.iot.plugin.http.upstream.router.IotDevicePropertyReportVertxHandler;
+import cn.iocoder.yudao.module.iot.plugin.http.upstream.router.IotDeviceUpstreamVertxHandler;
 import io.vertx.core.Vertx;
 import io.vertx.core.http.HttpServer;
 import io.vertx.ext.web.Router;
@@ -32,10 +31,12 @@ public class IotDeviceUpstreamServer {
         // 创建 Router 实例
         Router router = Router.router(vertx);
         router.route().handler(BodyHandler.create()); // 处理 Body
-        router.post(IotDevicePropertyReportVertxHandler.PATH)
-                .handler(new IotDevicePropertyReportVertxHandler(deviceUpstreamApi));
-        router.post(IotDeviceEventReportVertxHandler.PATH)
-                .handler(new IotDeviceEventReportVertxHandler(deviceUpstreamApi));
+
+        // 使用统一的 Handler 处理所有上行请求
+        IotDeviceUpstreamVertxHandler upstreamHandler = new IotDeviceUpstreamVertxHandler(deviceUpstreamApi);
+        router.post(IotDeviceUpstreamVertxHandler.PROPERTY_PATH).handler(upstreamHandler);
+        router.post(IotDeviceUpstreamVertxHandler.EVENT_PATH).handler(upstreamHandler);
+
         // 创建 HttpServer 实例
         this.server = vertx.createHttpServer().requestHandler(router);
     }

+ 0 - 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/IotDeviceEventReportVertxHandler.java

@@ -1,111 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.http.upstream.router;
-
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.core.util.ObjUtil;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-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;
-import io.vertx.ext.web.RoutingContext;
-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;
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
-
-/**
- * IoT 设备事件上报的 Vert.x Handler
- */
-@RequiredArgsConstructor
-@Slf4j
-public class IotDeviceEventReportVertxHandler implements Handler<RoutingContext> {
-
-    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;
-
-    @Override
-    @SuppressWarnings("unchecked")
-    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");
-            identifier = routingContext.pathParam("identifier");
-            JsonObject body = routingContext.body().asJsonObject();
-            requestId = ObjUtil.defaultIfBlank(body.getString("id"), requestId);
-
-            // 按照标准JSON格式处理事件参数
-            Map<String, Object> 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);
-            // 使用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())
-                            .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
-                            .setProductKey(reportReqDTO.getProductKey()).setDeviceName(reportReqDTO.getDeviceName()))
-                            .setState(IotDeviceStateEnum.ONLINE.getState()));
-
-            // 3.1 事件上报
-            CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO);
-
-            // 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);
-
-            // 构建错误响应 - 使用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);
-        }
-    }
-}

+ 0 - 131
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

@@ -1,131 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.http.upstream.router;
-
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.core.util.ObjUtil;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-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;
-import io.vertx.ext.web.RoutingContext;
-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;
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
-
-// TODO @芋艿:【待定 005】要不要简化成,解析后,统一处理?只有一个 Handler!!!
-/**
- * IoT 设备属性上报的 Vert.x Handler
- *
- * @author haohao
- */
-@RequiredArgsConstructor
-@Slf4j
-public class IotDevicePropertyReportVertxHandler implements Handler<RoutingContext> {
-
-    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;
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public void handle(RoutingContext routingContext) {
-        // 1. 解析参数
-        IotDevicePropertyReportReqDTO reportReqDTO;
-        String requestId = IdUtil.fastSimpleUUID();
-        try {
-            String productKey = routingContext.pathParam("productKey");
-            String deviceName = routingContext.pathParam("deviceName");
-            JsonObject body = routingContext.body().asJsonObject();
-            requestId = ObjUtil.defaultIfBlank(body.getString("id"), requestId);
-
-            // 按照标准JSON格式处理属性数据
-            Map<String, Object> properties = new HashMap<>();
-
-            // 优先使用params字段,符合标准
-            Map<String, Object> params = body.getJsonObject("params") != null ? body.getJsonObject("params").getMap()
-                    : null;
-
-            if (params != null) {
-                // 将标准格式的params转换为平台需要的properties格式
-                for (Map.Entry<String, Object> entry : params.entrySet()) {
-                    String key = entry.getKey();
-                    Object valueObj = entry.getValue();
-
-                    // 如果是复杂结构(包含value和time)
-                    if (valueObj instanceof Map) {
-                        Map<String, Object> valueMap = (Map<String, Object>) 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);
-            // 使用IotStandardResponse实体类返回错误
-            IotStandardResponse errorResponse = IotStandardResponse.error(
-                    requestId, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
-            IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
-            return;
-        }
-
-        // TODO @芋艿:secret 校验。目前的想法:
-        // 方案一:请求的时候,带上 secret 参数,然后进行校验,减少请求的频次。不过可能要看下 mqtt 能不能复用!
-        // 方案二:本地有设备信息的缓存,异步刷新。这样可能 mqtt 的校验,和 http 校验都容易适配。
-
-        try {
-            // 2. 设备上线
-            deviceUpstreamApi.updateDeviceState(
-                    ((IotDeviceStateUpdateReqDTO) new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID())
-                            .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
-                            .setProductKey(reportReqDTO.getProductKey()).setDeviceName(reportReqDTO.getDeviceName()))
-                            .setState(IotDeviceStateEnum.ONLINE.getState()));
-
-            // 3.1 属性上报
-            CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceProperty(reportReqDTO);
-
-            // 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);
-
-            // 构建错误响应 - 使用IotStandardResponse实体类
-            IotStandardResponse errorResponse = IotStandardResponse.error(
-                    reportReqDTO.getRequestId(), METHOD,
-                    INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
-            IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
-        }
-    }
-}

+ 185 - 0
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDeviceUpstreamVertxHandler.java

@@ -0,0 +1,185 @@
+package cn.iocoder.yudao.module.iot.plugin.http.upstream.router;
+
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+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.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;
+import io.vertx.ext.web.RoutingContext;
+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;
+import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
+
+/**
+ * IoT 设备上行统一处理的 Vert.x Handler
+ * <p>
+ * 统一处理设备属性上报和事件上报的请求
+ *
+ * @author haohao
+ */
+@RequiredArgsConstructor
+@Slf4j
+public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> {
+
+    // 属性上报路径
+    public static final String PROPERTY_PATH = "/sys/:productKey/:deviceName/thing/event/property/post";
+    // 事件上报路径
+    public static final String EVENT_PATH = "/sys/:productKey/:deviceName/thing/event/:identifier/post";
+
+    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";
+
+    private final IotDeviceUpstreamApi deviceUpstreamApi;
+
+    @Override
+    public void handle(RoutingContext routingContext) {
+        String path = routingContext.request().path();
+        String requestId = IdUtil.fastSimpleUUID();
+
+        try {
+            // 1. 解析通用参数
+            String productKey = routingContext.pathParam("productKey");
+            String deviceName = routingContext.pathParam("deviceName");
+            JsonObject body = routingContext.body().asJsonObject();
+            requestId = ObjUtil.defaultIfBlank(body.getString("id"), requestId);
+
+            // 2. 根据路径模式处理不同类型的请求
+            CommonResult<Boolean> result;
+            String method;
+
+            if (path.matches(".*/thing/event/property/post")) {
+                // 处理属性上报
+                IotDevicePropertyReportReqDTO reportReqDTO = parsePropertyReportRequest(productKey, deviceName, requestId, body);
+
+                // 设备上线
+                updateDeviceState(reportReqDTO.getProductKey(), reportReqDTO.getDeviceName());
+
+                // 属性上报
+                result = deviceUpstreamApi.reportDeviceProperty(reportReqDTO);
+                method = PROPERTY_METHOD;
+            } else if (path.matches(".*/thing/event/.+/post")) {
+                // 处理事件上报
+                String identifier = routingContext.pathParam("identifier");
+                IotDeviceEventReportReqDTO reportReqDTO = parseEventReportRequest(productKey, deviceName, identifier, requestId, body);
+
+                // 设备上线
+                updateDeviceState(reportReqDTO.getProductKey(), reportReqDTO.getDeviceName());
+
+                // 事件上报
+                result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO);
+                method = EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX;
+            } else {
+                // 不支持的请求路径
+                IotStandardResponse errorResponse = IotStandardResponse.error(requestId, "unknown", BAD_REQUEST.getCode(), "不支持的请求路径");
+                IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
+                return;
+            }
+
+            // 3. 返回标准响应
+            IotStandardResponse response;
+            if (result.isSuccess()) {
+                response = IotStandardResponse.success(requestId, method, result.getData());
+            } else {
+                response = IotStandardResponse.error(requestId, method, result.getCode(), result.getMsg());
+            }
+            IotPluginCommonUtils.writeJsonResponse(routingContext, response);
+
+        } catch (Exception e) {
+            log.error("[handle][处理上行请求异常] path={}", path, e);
+
+            // 构建错误响应
+            String method = path.contains("/property/") ? PROPERTY_METHOD : EVENT_METHOD_PREFIX + (routingContext.pathParams().containsKey("identifier") ? routingContext.pathParam("identifier") : "unknown") + EVENT_METHOD_SUFFIX;
+
+            IotStandardResponse errorResponse = IotStandardResponse.error(requestId, method, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
+            IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
+        }
+    }
+
+    /**
+     * 更新设备状态
+     *
+     * @param productKey 产品Key
+     * @param deviceName 设备名称
+     */
+    private void updateDeviceState(String productKey, String deviceName) {
+        deviceUpstreamApi.updateDeviceState(((IotDeviceStateUpdateReqDTO) new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()).setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()).setProductKey(productKey).setDeviceName(deviceName)).setState(IotDeviceStateEnum.ONLINE.getState()));
+    }
+
+    /**
+     * 解析属性上报请求
+     *
+     * @param productKey 产品Key
+     * @param deviceName 设备名称
+     * @param requestId  请求ID
+     * @param body       请求体
+     * @return 属性上报请求DTO
+     */
+    @SuppressWarnings("unchecked")
+    private IotDevicePropertyReportReqDTO parsePropertyReportRequest(String productKey, String deviceName, String requestId, JsonObject body) {
+
+        // 按照标准JSON格式处理属性数据
+        Map<String, Object> properties = new HashMap<>();
+
+        // 优先使用params字段,符合标准
+        Map<String, Object> params = body.getJsonObject("params") != null ? body.getJsonObject("params").getMap() : null;
+
+        if (params != null) {
+            // 将标准格式的params转换为平台需要的properties格式
+            for (Map.Entry<String, Object> entry : params.entrySet()) {
+                String key = entry.getKey();
+                Object valueObj = entry.getValue();
+
+                // 如果是复杂结构(包含value和time)
+                if (valueObj instanceof Map) {
+                    Map<String, Object> valueMap = (Map<String, Object>) valueObj;
+                    properties.put(key, valueMap.getOrDefault("value", valueObj));
+                } else {
+                    properties.put(key, valueObj);
+                }
+            }
+        }
+
+        return ((IotDevicePropertyReportReqDTO) new IotDevicePropertyReportReqDTO().setRequestId(requestId).setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()).setProductKey(productKey).setDeviceName(deviceName)).setProperties(properties);
+    }
+
+    /**
+     * 解析事件上报请求
+     *
+     * @param productKey 产品Key
+     * @param deviceName 设备名称
+     * @param identifier 事件标识符
+     * @param requestId  请求ID
+     * @param body       请求体
+     * @return 事件上报请求DTO
+     */
+    @SuppressWarnings("unchecked")
+    private IotDeviceEventReportReqDTO parseEventReportRequest(String productKey, String deviceName, String identifier, String requestId, JsonObject body) {
+
+        // 按照标准JSON格式处理事件参数
+        Map<String, Object> params;
+
+        // 优先使用params字段,符合标准
+        if (body.getJsonObject("params") != null) {
+            params = body.getJsonObject("params").getMap();
+        } else {
+            // 兼容旧格式
+            params = new HashMap<>();
+        }
+
+        return ((IotDeviceEventReportReqDTO) new IotDeviceEventReportReqDTO().setRequestId(requestId).setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()).setProductKey(productKey).setDeviceName(deviceName)).setIdentifier(identifier).setParams(params);
+    }
+}