浏览代码

【功能新增】IoT:OTA 升级的下行消息的实现

YunaiV 6 月之前
父节点
当前提交
4919439b96
共有 12 个文件被更改,包括 311 次插入31 次删除
  1. 66 0
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDeviceOtaUpgradeReqDTO.java
  2. 35 0
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceOtaProgressReqDTO.java
  3. 21 0
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceOtaPullReqDTO.java
  4. 21 0
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceOtaReportReqDTO.java
  5. 6 1
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageIdentifierEnum.java
  6. 2 1
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageTypeEnum.java
  7. 21 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.http
  8. 61 17
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamServiceImpl.java
  9. 9 4
      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
  10. 3 4
      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
  11. 60 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/IotDeviceOtaUpgradeVertxHandler.java
  12. 6 4
      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

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

@@ -0,0 +1,66 @@
+package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
+
+import cn.hutool.core.map.MapUtil;
+import lombok.Data;
+
+import java.util.Map;
+
+/**
+ * IoT 设备【OTA】升级下发 Request DTO(更新固件消息)
+ *
+ * @author 芋道源码
+ */
+@Data
+public class IotDeviceOtaUpgradeReqDTO extends IotDeviceDownstreamAbstractReqDTO {
+
+    /**
+     * 固件编号
+     */
+    private Long firmwareId;
+    /**
+     * 固件版本
+     */
+    private String version;
+
+    /**
+     * 签名方式
+     *
+     * 例如说:MD5、SHA256
+     */
+    private String signMethod;
+    /**
+     * 固件文件签名
+     */
+    private String fileSign;
+    /**
+     * 固件文件大小
+     */
+    private Long fileSize;
+    /**
+     * 固件文件 URL
+     */
+    private String fileUrl;
+
+    /**
+     * 自定义信息,建议使用 JSON 格式
+     */
+    private String information;
+
+    public static IotDeviceOtaUpgradeReqDTO build(Map<?, ?> map) {
+        return new IotDeviceOtaUpgradeReqDTO()
+                .setFirmwareId(MapUtil.getLong(map, "firmwareId")).setVersion((String) map.get("version"))
+                .setSignMethod((String) map.get("signMethod")).setFileSign((String) map.get("fileSign"))
+                .setFileSize(MapUtil.getLong(map, "fileSize")).setFileUrl((String) map.get("fileUrl"))
+                .setInformation((String) map.get("information"));
+    }
+
+    public static Map<?, ?> build(IotDeviceOtaUpgradeReqDTO dto) {
+        return MapUtil.builder()
+                .put("firmwareId", dto.getFirmwareId()).put("version", dto.getVersion())
+                .put("signMethod", dto.getSignMethod()).put("fileSign", dto.getFileSign())
+                .put("fileSize", dto.getFileSize()).put("fileUrl", dto.getFileUrl())
+                .put("information", dto.getInformation())
+                .build();
+    }
+
+}

+ 35 - 0
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceOtaProgressReqDTO.java

@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
+
+import lombok.Data;
+
+// TODO @芋艿:待实现:/ota/${productKey}/${deviceName}/progress
+/**
+ * IoT 设备【OTA】升级进度 Request DTO(上报更新固件进度)
+ *
+ * @author 芋道源码
+ */
+@Data
+public class IotDeviceOtaProgressReqDTO extends IotDeviceUpstreamAbstractReqDTO {
+
+    /**
+     * 固件编号
+     */
+    private Long firmwareId;
+
+    /**
+     * 升级状态
+     *
+     * 枚举 {@link cn.iocoder.yudao.module.iot.enums.ota.IotOtaUpgradeRecordStatusEnum}
+     */
+    private Integer status;
+    /**
+     * 升级进度,百分比
+     */
+    private Integer progress;
+
+    /**
+     * 升级进度描述
+     */
+    private String description;
+
+}

+ 21 - 0
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceOtaPullReqDTO.java

@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
+
+// TODO @芋艿:待实现:/ota/${productKey}/${deviceName}/pull
+/**
+ * IoT 设备【OTA】升级下拉 Request DTO(拉取固件更新)
+ *
+ * @author 芋道源码
+ */
+public class IotDeviceOtaPullReqDTO {
+
+    /**
+     * 固件编号
+     */
+    private Long firmwareId;
+
+    /**
+     * 固件版本
+     */
+    private String version;
+
+}

+ 21 - 0
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceOtaReportReqDTO.java

@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
+
+// TODO @芋艿:待实现:/ota/${productKey}/${deviceName}/report
+/**
+ * IoT 设备【OTA】上报 Request DTO(上报固件版本)
+ *
+ * @author 芋道源码
+ */
+public class IotDeviceOtaReportReqDTO {
+
+    /**
+     * 固件编号
+     */
+    private Long firmwareId;
+
+    /**
+     * 固件版本
+     */
+    private String version;
+
+}

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

@@ -21,7 +21,12 @@ public enum IotDeviceMessageIdentifierEnum {
     CONFIG_SET("set"), // 下行
 
     SERVICE_INVOKE("${identifier}"), // 下行
-    SERVICE_REPLY_SUFFIX("_reply"); // 芋艿:TODO 芋艿:【讨论】上行 or 下行
+    SERVICE_REPLY_SUFFIX("_reply"), // 芋艿:TODO 芋艿:【讨论】上行 or 下行
+
+    OTA_UPGRADE("upgrade"), // 下行
+    OTA_PULL("pull"), // 上行
+    OTA_PROGRESS("progress"), // 上行
+    OTA_REPORT("report"),; // 上行
 
     /**
      * 标志符

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

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

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

@@ -51,4 +51,25 @@ Authorization: Bearer {{token}}
   "id": 25,
   "type": "config",
   "identifier": "set"
+}
+
+### 请求 /iot/device/downstream 接口(OTA 升级) => 成功
+POST {{baseUrl}}/iot/device/downstream
+Content-Type: application/json
+tenant-id: {{adminTenentId}}
+Authorization: Bearer {{token}}
+
+{
+  "id": 25,
+  "type": "ota",
+  "identifier": "upgrade",
+  "data": {
+    "firmwareId": 1,
+    "version": "1.0.0",
+    "signMethod": "MD5",
+    "fileSign": "d41d8cd98f00b204e9800998ecf8427e",
+    "fileSize": 1024,
+    "fileUrl": "http://example.com/firmware.bin",
+    "information": "{\"desc\":\"升级到最新版本\"}"
+  }
 }

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

@@ -80,11 +80,15 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
         }
         // 配置下发
         if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.CONFIG.getType())
-            && Objects.equals(downstreamReqVO.getIdentifier(), IotDeviceMessageIdentifierEnum.CONFIG_SET.getIdentifier())) {
+                && Objects.equals(downstreamReqVO.getIdentifier(),
+                        IotDeviceMessageIdentifierEnum.CONFIG_SET.getIdentifier())) {
             return setDeviceConfig(downstreamReqVO, device, parentDevice);
         }
-        // TODO 芋艿:ota 升级
-        return null;
+        // OTA 升级
+        if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.OTA.getType())) {
+            return otaUpgrade(downstreamReqVO, device, parentDevice);
+        }
+        throw new IllegalArgumentException("不支持的下行消息类型:" + downstreamReqVO);
     }
 
     /**
@@ -97,7 +101,7 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
      */
     @SuppressWarnings("unchecked")
     private IotDeviceMessage invokeDeviceService(IotDeviceDownstreamReqVO downstreamReqVO,
-                                     IotDeviceDO device, IotDeviceDO parentDevice) {
+                                                 IotDeviceDO device, IotDeviceDO parentDevice) {
         // 1. 参数校验
         if (!(downstreamReqVO.getData() instanceof Map<?, ?>)) {
             throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 Map 类型");
@@ -105,9 +109,10 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
         // TODO @super:【可优化】过滤掉不合法的服务
 
         // 2. 发送请求
-        String url = String.format( "sys/%s/%s/thing/service/%s",
-                getProductKey(device, parentDevice), getDeviceName(device, parentDevice), downstreamReqVO.getIdentifier());
-         IotDeviceServiceInvokeReqDTO reqDTO = new IotDeviceServiceInvokeReqDTO()
+        String url = String.format("sys/%s/%s/thing/service/%s",
+                getProductKey(device, parentDevice), getDeviceName(device, parentDevice),
+                downstreamReqVO.getIdentifier());
+        IotDeviceServiceInvokeReqDTO reqDTO = new IotDeviceServiceInvokeReqDTO()
                 .setParams((Map<String, Object>) downstreamReqVO.getData());
         CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);
 
@@ -144,7 +149,7 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
         // TODO @super:【可优化】过滤掉不合法的属性
 
         // 2. 发送请求
-        String url = String.format( "sys/%s/%s/thing/service/property/set",
+        String url = String.format("sys/%s/%s/thing/service/property/set",
                 getProductKey(device, parentDevice), getDeviceName(device, parentDevice));
         IotDevicePropertySetReqDTO reqDTO = new IotDevicePropertySetReqDTO()
                 .setProperties((Map<String, Object>) downstreamReqVO.getData());
@@ -184,7 +189,7 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
         // TODO @super:【可优化】过滤掉不合法的属性
 
         // 2. 发送请求
-        String url = String.format( "sys/%s/%s/thing/service/property/get",
+        String url = String.format("sys/%s/%s/thing/service/property/get",
                 getProductKey(device, parentDevice), getDeviceName(device, parentDevice));
         IotDevicePropertyGetReqDTO reqDTO = new IotDevicePropertyGetReqDTO()
                 .setIdentifiers((List<String>) downstreamReqVO.getData());
@@ -214,14 +219,14 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
      * @param parentDevice    父设备
      * @return 下发消息
      */
-    @SuppressWarnings({"unchecked", "unused"})
+    @SuppressWarnings({ "unchecked", "unused" })
     private IotDeviceMessage 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",
+        String url = String.format("sys/%s/%s/thing/service/config/set",
                 getProductKey(device, parentDevice), getDeviceName(device, parentDevice));
         IotDeviceConfigSetReqDTO reqDTO = new IotDeviceConfigSetReqDTO()
                 .setConfig(config);
@@ -243,16 +248,54 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
         return message;
     }
 
+    /**
+     * 设备 OTA 升级
+     *
+     * @param downstreamReqVO 下行请求
+     * @param device          设备
+     * @param parentDevice    父设备
+     * @return 下发消息
+     */
+    private IotDeviceMessage otaUpgrade(IotDeviceDownstreamReqVO downstreamReqVO,
+                                        IotDeviceDO device, IotDeviceDO parentDevice) {
+        // 1. 参数校验
+        if (!(downstreamReqVO.getData() instanceof Map<?, ?> data)) {
+            throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 Map 类型");
+        }
+
+        // 2. 发送请求
+        String url = String.format("ota/%s/%s/upgrade",
+                getProductKey(device, parentDevice), getDeviceName(device, parentDevice));
+        IotDeviceOtaUpgradeReqDTO reqDTO = IotDeviceOtaUpgradeReqDTO.build(data);
+        CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);
+
+        // 3. 发送设备消息
+        IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())
+                .setType(IotDeviceMessageTypeEnum.OTA.getType())
+                .setIdentifier(IotDeviceMessageIdentifierEnum.OTA_UPGRADE.getIdentifier())
+                .setData(downstreamReqVO.getData());
+        sendDeviceMessage(message, device, result.getCode());
+
+        // 4. 如果不成功,抛出异常,提示用户
+        if (result.isError()) {
+            log.error("[otaUpgrade][设备({}) OTA 升级失败,请求参数:({}),响应结果:({})]",
+                    device.getDeviceKey(), reqDTO, result);
+            throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());
+        }
+        return message;
+    }
+
     /**
      * 请求插件
      *
-     * @param url     URL
-     * @param reqDTO  请求参数,只需要设置子类的参数!
-     * @param device  设备
+     * @param url    URL
+     * @param reqDTO 请求参数,只需要设置子类的参数!
+     * @param device 设备
      * @return 响应结果
      */
-    @SuppressWarnings({"unchecked", "HttpUrlsUsage"})
-    private CommonResult<Boolean> requestPlugin(String url, IotDeviceDownstreamAbstractReqDTO reqDTO, IotDeviceDO device) {
+    @SuppressWarnings({ "unchecked", "HttpUrlsUsage" })
+    private CommonResult<Boolean> requestPlugin(String url, IotDeviceDownstreamAbstractReqDTO reqDTO,
+            IotDeviceDO device) {
         // 获得设备对应的插件实例
         IotPluginInstanceDO pluginInstance = pluginInstanceService.getPluginInstanceByDeviceKey(device.getDeviceKey());
         if (pluginInstance == null) {
@@ -266,7 +309,8 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
         ResponseEntity<CommonResult<Boolean>> responseEntity;
         try {
             responseEntity = restTemplate.postForEntity(
-                    String.format("http://%s:%d/%s", pluginInstance.getHostIp(), pluginInstance.getDownstreamPort(), url),
+                    String.format("http://%s:%d/%s", pluginInstance.getHostIp(), pluginInstance.getDownstreamPort(),
+                            url),
                     reqDTO, (Class<CommonResult<Boolean>>) (Class<?>) CommonResult.class);
             Assert.isTrue(responseEntity.getStatusCode().is2xxSuccessful(),
                     "HTTP 状态码不是 2xx,而是" + responseEntity.getStatusCode());

+ 9 - 4
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,10 +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;
+import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.*;
 
 /**
  * IoT 设备下行处理器
@@ -47,4 +44,12 @@ public interface IotDeviceDownstreamHandler {
      */
     CommonResult<Boolean> setDeviceConfig(IotDeviceConfigSetReqDTO setReqDTO);
 
+    /**
+     * 升级设备 OTA
+     *
+     * @param upgradeReqDTO 升级设备 OTA 的请求
+     * @return 是否成功
+     */
+    CommonResult<Boolean> upgradeDeviceOta(IotDeviceOtaUpgradeReqDTO upgradeReqDTO);
+
 }

+ 3 - 4
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,10 +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;
+import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.*;
 import io.vertx.core.Vertx;
 import io.vertx.core.http.HttpServer;
 import io.vertx.ext.web.Router;
@@ -39,6 +36,8 @@ public class IotDeviceDownstreamServer {
                 .handler(new IotDevicePropertyGetVertxHandler(deviceDownstreamHandler));
         router.post(IotDeviceConfigSetVertxHandler.PATH)
                 .handler(new IotDeviceConfigSetVertxHandler(deviceDownstreamHandler));
+        router.post(IotDeviceOtaUpgradeVertxHandler.PATH)
+                .handler(new IotDeviceOtaUpgradeVertxHandler(deviceDownstreamHandler));
         // 创建 HttpServer 实例
         this.server = vertx.createHttpServer().requestHandler(router);
     }

+ 60 - 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/IotDeviceOtaUpgradeVertxHandler.java

@@ -0,0 +1,60 @@
+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.util.IotPluginCommonUtils;
+import io.vertx.core.Handler;
+import io.vertx.ext.web.RoutingContext;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import io.vertx.core.json.JsonObject;
+
+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;
+
+@Slf4j
+@RequiredArgsConstructor
+public class IotDeviceOtaUpgradeVertxHandler implements Handler<RoutingContext> {
+
+    public static final String PATH = "/ota/:productKey/:deviceName/upgrade";
+
+    private final IotDeviceDownstreamHandler deviceDownstreamHandler;
+
+    @Override
+    public void handle(RoutingContext routingContext) {
+        // 1. 解析参数
+        IotDeviceOtaUpgradeReqDTO reqDTO;
+        try {
+            String productKey = routingContext.pathParam("productKey");
+            String deviceName = routingContext.pathParam("deviceName");
+            JsonObject body = routingContext.body().asJsonObject();
+            String requestId = body.getString("requestId");
+            Long firmwareId = body.getLong("firmwareId");
+            String version = body.getString("version");
+            String signMethod = body.getString("signMethod");
+            String fileSign = body.getString("fileSign");
+            Long fileSize = body.getLong("fileSize");
+            String fileUrl = body.getString("fileUrl");
+            String information = body.getString("information");
+            reqDTO = ((IotDeviceOtaUpgradeReqDTO) new IotDeviceOtaUpgradeReqDTO()
+                    .setRequestId(requestId).setProductKey(productKey).setDeviceName(deviceName))
+                    .setFirmwareId(firmwareId).setVersion(version)
+                    .setSignMethod(signMethod).setFileSign(fileSign).setFileSize(fileSize).setFileUrl(fileUrl)
+                    .setInformation(information);
+        } catch (Exception e) {
+            log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
+            IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST));
+            return;
+        }
+
+        // 2. 调用处理器
+        try {
+            CommonResult<Boolean> result = deviceDownstreamHandler.upgradeDeviceOta(reqDTO);
+            IotPluginCommonUtils.writeJson(routingContext, result);
+        } catch (Exception e) {
+            log.error("[handle][请求参数({}) OTA 升级异常]", reqDTO, e);
+            IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR));
+        }
+    }
+}

+ 6 - 4
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,10 +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;
+import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.*;
 import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
 
 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED;
@@ -39,4 +36,9 @@ public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandle
         return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
     }
 
+    @Override
+    public CommonResult<Boolean> upgradeDeviceOta(IotDeviceOtaUpgradeReqDTO upgradeReqDTO) {
+        return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
+    }
+
 }