Prechádzať zdrojové kódy

【代码优化】IoT:优化 http 插件 IotDevicePropertyReportVertxHandler 的代码

YunaiV 6 mesiacov pred
rodič
commit
2512f2dde8

+ 1 - 0
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDevicePropertyGetReqDTO.java

@@ -5,6 +5,7 @@ import lombok.Data;
 
 import java.util.List;
 
+// TODO @芋艿:从 server => plugin => device 是否有必要?从阿里云 iot 来看,没有这个功能?!
 /**
  * IoT 设备【属性】获取 Request DTO
  *

+ 17 - 25
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/upstream/IotDeviceUpstreamClient.java

@@ -6,10 +6,11 @@ import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEven
 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.api.device.dto.control.upstream.IotPluginInstanceHeartbeatReqDTO;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.client.RestTemplate;
 
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
 
 /**
  * 设备数据 Upstream 上行客户端
@@ -18,60 +19,51 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  *
  * @author haohao
  */
+@RequiredArgsConstructor
 @Slf4j
 public class IotDeviceUpstreamClient implements IotDeviceUpstreamApi {
 
     public static final String URL_PREFIX = "/rpc-api/iot/device/upstream";
 
     private final RestTemplate restTemplate;
-    private final String deviceDataUrl;
 
-    // 可以通过构造器把 RestTemplate 和 baseUrl 注入进来
-    // TODO @haohao:可以用 lombok 简化
-    public IotDeviceUpstreamClient(RestTemplate restTemplate, String deviceDataUrl) {
-        this.restTemplate = restTemplate;
-        this.deviceDataUrl = deviceDataUrl;
-    }
+    // TODO @芋艿:改个名字
+    private final String deviceDataUrl;
 
-    // TODO @haohao:返回结果,不用 CommonResult 哈。
     @Override
     public CommonResult<Boolean> updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {
         String url = deviceDataUrl + URL_PREFIX + "/update-state";
-        return doPost(url, updateReqDTO, "updateDeviceState");
+        return doPost(url, updateReqDTO);
     }
 
     @Override
     public CommonResult<Boolean> reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) {
         String url = deviceDataUrl + URL_PREFIX + "/report-event";
-        return doPost(url, reportReqDTO, "reportDeviceEventData");
+        return doPost(url, reportReqDTO);
     }
 
     @Override
     public CommonResult<Boolean> reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) {
         String url = deviceDataUrl + URL_PREFIX + "/report-property";
-        return doPost(url, reportReqDTO, "reportDevicePropertyData");
+        return doPost(url, reportReqDTO);
     }
 
     @Override
     public CommonResult<Boolean> heartbeatPluginInstance(IotPluginInstanceHeartbeatReqDTO heartbeatReqDTO) {
         String url = deviceDataUrl + URL_PREFIX + "/heartbeat-plugin-instance";
-        return doPost(url, heartbeatReqDTO, "heartbeatPluginInstance");
+        return doPost(url, heartbeatReqDTO);
     }
 
-    // TODO @haohao:未来可能有 get 类型哈
-    /**
-     * 将与远程服务交互的通用逻辑抽取成一个私有方法
-     */
-    private <T> CommonResult<Boolean> doPost(String url, T requestBody, String actionName) {
-        log.info("[{}] Sending request to URL: {}", actionName, url);
+    @SuppressWarnings("unchecked")
+    private <T> CommonResult<Boolean> doPost(String url, T requestBody) {
         try {
-            // 这里指定返回类型为 CommonResult<?>,根据后台服务返回的实际结构做调整
-            restTemplate.postForObject(url, requestBody, CommonResult.class);
-            // TODO @haohao:check 结果,是否成功
-            return success(true);
+            CommonResult<Boolean> result = restTemplate.postForObject(url, requestBody,
+                    (Class<CommonResult<Boolean>>) (Class<?>) CommonResult.class);
+            log.info("[doPost][url({}) requestBody({}) result({})]", url, requestBody, result);
+            return result;
         } catch (Exception e) {
-            log.error("[{}] Error sending request to URL: {}", actionName, url, e);
-            return CommonResult.error(400, "Request error: " + e.getMessage());
+            log.error("[doPost][url({}) requestBody({}) 发生异常]", url, requestBody, e);
+            return CommonResult.error(INTERNAL_SERVER_ERROR);
         }
     }
 

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

@@ -31,7 +31,7 @@ public class IotDeviceUpstreamServer {
         Router router = Router.router(vertx);
         router.route().handler(BodyHandler.create()); // 处理 Body
         router.post(IotDevicePropertyReportVertxHandler.PATH)
-                .handler(new IotDevicePropertyReportVertxHandler(deviceUpstreamApi)); // 处理设备属性上报
+                .handler(new IotDevicePropertyReportVertxHandler(deviceUpstreamApi));
         // 创建 HttpServer 实例
         this.server = vertx.createHttpServer().requestHandler(router);
     }

+ 32 - 53
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,15 +1,15 @@
 package cn.iocoder.yudao.module.iot.plugin.http.upstream.router;
 
 import cn.hutool.core.util.IdUtil;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
+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.util.IotPluginCommonUtils;
 import io.vertx.core.Handler;
-import io.vertx.ext.web.RequestBody;
+import io.vertx.core.json.JsonObject;
 import io.vertx.ext.web.RoutingContext;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -17,8 +17,13 @@ import lombok.extern.slf4j.Slf4j;
 import java.time.LocalDateTime;
 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
+ *
+ * @author haohao
  */
 @RequiredArgsConstructor
 @Slf4j
@@ -29,69 +34,43 @@ public class IotDevicePropertyReportVertxHandler implements Handler<RoutingConte
     private final IotDeviceUpstreamApi deviceUpstreamApi;
 
     @Override
-    public void handle(RoutingContext ctx) {
-        String productKey = ctx.pathParam("productKey");
-        String deviceName = ctx.pathParam("deviceName");
-
-        // TODO @haohao:requestBody.asJsonObject() 貌似天然就是 json 对象哈?
-        RequestBody requestBody = ctx.body();
-        JSONObject jsonData;
+    @SuppressWarnings("unchecked")
+    public void handle(RoutingContext routingContext) {
+        // 1. 解析参数
+        IotDevicePropertyReportReqDTO reportReqDTO;
         try {
-            jsonData = JSONUtil.parseObj(requestBody.asJsonObject());
+            String productKey = routingContext.pathParam("productKey");
+            String deviceName = routingContext.pathParam("deviceName");
+            JsonObject body = routingContext.body().asJsonObject();
+            String id = ObjUtil.defaultIfBlank(body.getString("id"), IdUtil.fastSimpleUUID());
+            Map<String, Object> properties = (Map<String, Object>) body.getMap().get("properties");
+            reportReqDTO = ((IotDevicePropertyReportReqDTO)
+                    new IotDevicePropertyReportReqDTO().setRequestId(id)
+                            .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
+                            .setProductKey(productKey).setDeviceName(deviceName))
+                    .setProperties(properties);
         } catch (Exception e) {
-            log.error("[HttpVertxHandler] 请求数据解析失败", e);
-            ctx.response().setStatusCode(400)
-                    .putHeader("Content-Type", "application/json; charset=UTF-8")
-                    .end(createResponseJson(400, null, null,
-                            "请求数据不是合法的 JSON 格式: " + e.getMessage(),
-                            "thing.event.property.post", "1.0").toString());
+            log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
+            IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST));
             return;
         }
 
-        String id = jsonData.getStr("id");
-
         try {
-            // 设备上线
+            // 2. 设备上线
             deviceUpstreamApi.updateDeviceState(((IotDeviceStateUpdateReqDTO)
                     new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID())
                             .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
-                            .setProductKey(productKey).setDeviceName(deviceName))
+                            .setProductKey(reportReqDTO.getProductKey()).setDeviceName(reportReqDTO.getDeviceName()))
                     .setState(IotDeviceStateEnum.ONLINE.getState()));
 
-            // 属性上报
-            deviceUpstreamApi.reportDeviceProperty(((IotDevicePropertyReportReqDTO)
-                    new IotDevicePropertyReportReqDTO().setRequestId(IdUtil.fastSimpleUUID())
-                            .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
-                            .setProductKey(productKey).setDeviceName(deviceName))
-                    .setProperties((Map<String, Object>) requestBody.asJsonObject().getMap().get("properties")));
-
-            ctx.response()
-                    .setStatusCode(200)
-                    .putHeader("Content-Type", "application/json; charset=UTF-8")
-                    .end(createResponseJson(200, new JSONObject(), id, "success",
-                            "thing.event.property.post", "1.0").toString());
+            // 3.1 属性上报
+            CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceProperty(reportReqDTO);
+            // 3.2 返回结果
+            IotPluginCommonUtils.writeJson(routingContext, result);
         } catch (Exception e) {
-            log.error("[HttpVertxHandler] 上报属性数据失败", e);
-            ctx.response()
-                    .setStatusCode(500)
-                    .putHeader("Content-Type", "application/json; charset=UTF-8")
-                    .end(createResponseJson(500, new JSONObject(), id,
-                            "The format of result is error!",
-                            "thing.event.property.post", "1.0").toString());
+            log.error("[handle][请求参数({}) 属性获取异常]", reportReqDTO, e);
+            IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR));
         }
     }
 
-    // TODO @芋艿:抽一个 IotPluginCommonResult 出来?等 mqtt、websocket 出来后,再考虑优化!
-    private JSONObject createResponseJson(int code, JSONObject data, String id,
-                                          String message, String method, String version) {
-        JSONObject res = new JSONObject();
-        res.set("code", code);
-        res.set("data", data != null ? data : new JSONObject());
-        res.set("id", id);
-        res.set("message", message);
-        res.set("method", method);
-        res.set("version", version);
-        return res;
-    }
-
 }