Forráskód Böngészése

【代码新增】IoT:增加 device 配置下发(设置)实现

YunaiV 6 hónapja
szülő
commit
f46a2fb011
9 módosított fájl, 175 hozzáadás és 20 törlés
  1. 22 0
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDeviceConfigSetReqDTO.java
  2. 5 3
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageIdentifierEnum.java
  3. 2 1
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageTypeEnum.java
  4. 18 6
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.http
  5. 49 10
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamServiceImpl.java
  6. 9 0
      yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/IotDeviceDownstreamHandler.java
  7. 3 0
      yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/IotDeviceDownstreamServer.java
  8. 61 0
      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
  9. 6 0
      yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/downstream/IotDeviceDownstreamHandlerImpl.java

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

@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.util.Map;
+
+/**
+ * IoT 设备【配置】设置 Request DTO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class IotDeviceConfigSetReqDTO extends IotDeviceDownstreamAbstractReqDTO {
+
+    /**
+     * 配置
+     */
+    @NotNull(message = "配置不能为空")
+    private Map<String, Object> config;
+
+}

+ 5 - 3
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageIdentifierEnum.java

@@ -10,19 +10,21 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public enum IotDeviceMessageIdentifierEnum {
 
-    PROPERTY_GET("get"), // 下行
+    PROPERTY_GET("get"), // 下行 TODO 芋艿:【讨论】貌似这个“上行”更合理?device 主动拉取配置。和 IotDevicePropertyGetReqDTO 一样的配置
     PROPERTY_SET("set"), // 下行
     PROPERTY_REPORT("report"), // 上行
 
     STATE_ONLINE("online"), // 上行
     STATE_OFFLINE("offline"), // 上行
 
-    SERVICE_REPLY_SUFFIX("_reply"); // TODO 上行 or 下行
+    CONFIG_GET("get"), // 上行 TODO 芋艿:【讨论】暂时没有上行的场景
+    CONFIG_SET("set"), // 下行
 
+    SERVICE_REPLY_SUFFIX("_reply"); // 芋艿:TODO 芋艿:【讨论】上行 or 下行
 
     /**
      * 标志符
      */
     private final String identifier;
 
-}
+}

+ 2 - 1
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageTypeEnum.java

@@ -16,7 +16,8 @@ public enum IotDeviceMessageTypeEnum implements ArrayValuable<String> {
     STATE("state"), // 设备状态
     PROPERTY("property"), // 设备属性
     EVENT("event"), // 设备事件
-    SERVICE("service"); // 设备服务
+    SERVICE("service"), // 设备服务
+    CONFIG("config"); // 设备配置
 
     public static final String[] ARRAYS = Arrays.stream(values()).map(IotDeviceMessageTypeEnum::getType).toArray(String[]::new);
 

+ 18 - 6
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.http

@@ -1,5 +1,5 @@
-### 请求 /iot/device/simulation-downstream 接口(服务调用) => 成功
-POST {{baseUrl}}/iot/device/simulation-downstream
+### 请求 /iot/device/downstream 接口(服务调用) => 成功
+POST {{baseUrl}}/iot/device/downstream
 Content-Type: application/json
 tenant-id: {{adminTenentId}}
 Authorization: Bearer {{token}}
@@ -13,8 +13,8 @@ Authorization: Bearer {{token}}
   }
 }
 
-### 请求 /iot/device/simulation-downstream 接口(属性设置) => 成功
-POST {{baseUrl}}/iot/device/simulation-downstream
+### 请求 /iot/device/downstream 接口(属性设置) => 成功
+POST {{baseUrl}}/iot/device/downstream
 Content-Type: application/json
 tenant-id: {{adminTenentId}}
 Authorization: Bearer {{token}}
@@ -28,8 +28,8 @@ Authorization: Bearer {{token}}
   }
 }
 
-### 请求 /iot/device/simulation-downstream 接口(属性获取) => 成功
-POST {{baseUrl}}/iot/device/simulation-downstream
+### 请求 /iot/device/downstream 接口(属性获取) => 成功
+POST {{baseUrl}}/iot/device/downstream
 Content-Type: application/json
 tenant-id: {{adminTenentId}}
 Authorization: Bearer {{token}}
@@ -39,4 +39,16 @@ Authorization: Bearer {{token}}
   "type": "property",
   "identifier": "get",
   "data": ["xx", "yy"]
+}
+
+### 请求 /iot/device/downstream 接口(配置设置) => 成功
+POST {{baseUrl}}/iot/device/downstream
+Content-Type: application/json
+tenant-id: {{adminTenentId}}
+Authorization: Bearer {{token}}
+
+{
+  "id": 25,
+  "type": "config",
+  "identifier": "set"
 }

+ 49 - 10
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamServiceImpl.java

@@ -5,10 +5,8 @@ import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.IdUtil;
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceDownstreamAbstractReqDTO;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.*;
 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInstanceDO;
@@ -68,21 +66,27 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
             return;
         }
         // 属性相关
-        if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType()))
+        if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType())) {
             // 属性设置
             if (Objects.equals(downstreamReqVO.getIdentifier(),
                     IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier())) {
                 setDeviceProperty(downstreamReqVO, device, parentDevice);
                 return;
             }
-        // 属性设置
-        if (Objects.equals(downstreamReqVO.getIdentifier(),
-                IotDeviceMessageIdentifierEnum.PROPERTY_GET.getIdentifier())) {
-            getDeviceProperty(downstreamReqVO, device, parentDevice);
+            // 属性设置
+            if (Objects.equals(downstreamReqVO.getIdentifier(),
+                    IotDeviceMessageIdentifierEnum.PROPERTY_GET.getIdentifier())) {
+                getDeviceProperty(downstreamReqVO, device, parentDevice);
+                return;
+            }
+        }
+        // 配置下发
+        if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.CONFIG.getType())
+            && Objects.equals(downstreamReqVO.getIdentifier(), IotDeviceMessageIdentifierEnum.CONFIG_SET.getIdentifier())) {
+            setDeviceConfig(downstreamReqVO, device, parentDevice);
             return;
         }
         // TODO 芋艿:ota 升级
-        // TODO 芋艿:配置下发
     }
 
     /**
@@ -198,6 +202,41 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
         }
     }
 
+    /**
+     * 设置设备配置
+     *
+     * @param downstreamReqVO 下行请求
+     * @param device          设备
+     * @param parentDevice    父设备
+     */
+    @SuppressWarnings({"unchecked", "unused"})
+    private void setDeviceConfig(IotDeviceDownstreamReqVO downstreamReqVO,
+                                 IotDeviceDO device, IotDeviceDO parentDevice) {
+        // 1. 参数转换,无需校验
+        Map<String, Object> config = JsonUtils.parseObject(device.getConfig(), Map.class);
+
+        // 2. 发送请求
+        String url = String.format( "sys/%s/%s/thing/service/config/set",
+                getProductKey(device, parentDevice), getDeviceName(device, parentDevice));
+        IotDeviceConfigSetReqDTO reqDTO = new IotDeviceConfigSetReqDTO()
+                .setConfig(config);
+        CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);
+
+        // 3. 发送设备消息
+        IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())
+                .setType(IotDeviceMessageTypeEnum.CONFIG.getType())
+                .setIdentifier(IotDeviceMessageIdentifierEnum.CONFIG_SET.getIdentifier())
+                .setData(reqDTO.getConfig());
+        sendDeviceMessage(message, device, result.getCode());
+
+        // 4. 如果不成功,抛出异常,提示用户
+        if (result.isError()) {
+            log.error("[setDeviceConfig][设备({})配置下发失败,请求参数:({}),响应结果:({})]",
+                    device.getDeviceKey(), reqDTO, result);
+            throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());
+        }
+    }
+
     /**
      * 请求插件
      *

+ 9 - 0
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/IotDeviceDownstreamHandler.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.iot.plugin.common.downstream;
 
 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.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;
 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO;
 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
@@ -38,4 +39,12 @@ public interface IotDeviceDownstreamHandler {
      */
     CommonResult<Boolean> setDeviceProperty(IotDevicePropertySetReqDTO setReqDTO);
 
+    /**
+     * 设置设备配置
+     *
+     * @param setReqDTO 设置设备配置的请求
+     * @return 是否成功
+     */
+    CommonResult<Boolean> setDeviceConfig(IotDeviceConfigSetReqDTO setReqDTO);
+
 }

+ 3 - 0
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/IotDeviceDownstreamServer.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.iot.plugin.common.downstream;
 
 import cn.iocoder.yudao.module.iot.plugin.common.config.IotPluginCommonProperties;
+import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDeviceConfigSetVertxHandler;
 import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDevicePropertyGetVertxHandler;
 import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDevicePropertySetVertxHandler;
 import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDeviceServiceInvokeVertxHandler;
@@ -36,6 +37,8 @@ public class IotDeviceDownstreamServer {
                 .handler(new IotDevicePropertySetVertxHandler(deviceDownstreamHandler));
         router.post(IotDevicePropertyGetVertxHandler.PATH)
                 .handler(new IotDevicePropertyGetVertxHandler(deviceDownstreamHandler));
+        router.post(IotDeviceConfigSetVertxHandler.PATH)
+                .handler(new IotDeviceConfigSetVertxHandler(deviceDownstreamHandler));
         // 创建 HttpServer 实例
         this.server = vertx.createHttpServer().requestHandler(router);
     }

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

@@ -0,0 +1,61 @@
+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.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.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 设备配置设置 Vertx Handler
+ *
+ * 芋道源码
+ */
+@Slf4j
+@RequiredArgsConstructor
+public class IotDeviceConfigSetVertxHandler implements Handler<RoutingContext> {
+
+    public static final String PATH = "/sys/:productKey/:deviceName/thing/service/config/set";
+
+    private final IotDeviceDownstreamHandler deviceDownstreamHandler;
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void handle(RoutingContext routingContext) {
+        // 1. 解析参数
+        IotDeviceConfigSetReqDTO reqDTO;
+        try {
+            String productKey = routingContext.pathParam("productKey");
+            String deviceName = routingContext.pathParam("deviceName");
+            JsonObject body = routingContext.body().asJsonObject();
+            String requestId = body.getString("requestId");
+            Map<String, Object> config = (Map<String, Object>) body.getMap().get("config");
+            reqDTO = ((IotDeviceConfigSetReqDTO) new IotDeviceConfigSetReqDTO()
+                    .setRequestId(requestId).setProductKey(productKey).setDeviceName(deviceName))
+                    .setConfig(config);
+        } catch (Exception e) {
+            log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
+            IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST));
+            return;
+        }
+
+        // 2. 调用处理器
+        try {
+            CommonResult<Boolean> result = deviceDownstreamHandler.setDeviceConfig(reqDTO);
+            IotPluginCommonUtils.writeJson(routingContext, result);
+        } catch (Exception e) {
+            log.error("[handle][请求参数({}) 配置设置异常]", reqDTO, e);
+            IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR));
+        }
+    }
+
+}

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

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.iot.plugin.http.downstream;
 
 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.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;
 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO;
 import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
@@ -33,4 +34,9 @@ public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandle
         return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
     }
 
+    @Override
+    public CommonResult<Boolean> setDeviceConfig(IotDeviceConfigSetReqDTO setReqDTO) {
+        return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
+    }
+
 }