Browse Source

reactor:【IoT 物联网】清理 components 和 protocol,基本已经融合到 gateway

YunaiV 5 tháng trước cách đây
mục cha
commit
800a85f7bc
63 tập tin đã thay đổi với 1 bổ sung5759 xóa
  1. 0 2
      yudao-module-iot/pom.xml
  2. 0 22
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDeviceConfigSetReqDTO.java
  3. 0 30
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDeviceDownstreamAbstractReqDTO.java
  4. 0 66
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDeviceOtaUpgradeReqDTO.java
  5. 0 24
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDevicePropertyGetReqDTO.java
  6. 0 22
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDevicePropertySetReqDTO.java
  7. 0 26
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDeviceServiceInvokeReqDTO.java
  8. 0 35
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceOtaProgressReqDTO.java
  9. 0 21
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceOtaPullReqDTO.java
  10. 0 21
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceOtaReportReqDTO.java
  11. 0 16
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ApiConstants.java
  12. 0 3
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/DictTypeConstants.java
  13. 0 37
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/plugin/IotPluginDeployTypeEnum.java
  14. 0 37
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/plugin/IotPluginStatusEnum.java
  15. 0 37
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/plugin/IotPluginTypeEnum.java
  16. 0 47
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptLanguageEnum.java
  17. 0 54
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptStatusEnum.java
  18. 0 50
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptTypeEnum.java
  19. 1 1
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamServiceImpl.java
  20. 0 1
      yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/package-info.java
  21. 0 25
      yudao-module-iot/yudao-module-iot-net-components/pom.xml
  22. 0 65
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/pom.xml
  23. 0 153
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/message/IotMqttMessage.java
  24. 0 93
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/pojo/IotStandardResponse.java
  25. 0 44
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/pom.xml
  26. 0 83
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/config/IotNetComponentEmqxAutoConfiguration.java
  27. 0 82
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/config/IotNetComponentEmqxProperties.java
  28. 0 121
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/downstream/IotDeviceDownstreamHandlerImpl.java
  29. 0 261
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/IotDeviceUpstreamServer.java
  30. 0 64
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/router/IotDeviceAuthVertxHandler.java
  31. 0 287
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/router/IotDeviceMqttMessageHandler.java
  32. 0 152
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/router/IotDeviceWebhookVertxHandler.java
  33. 0 1
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  34. 0 18
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/resources/application.yml
  35. 0 37
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/pom.xml
  36. 0 52
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/config/IotNetComponentServerConfiguration.java
  37. 0 34
      yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/config/IotNetComponentServerProperties.java
  38. 0 254
      yudao-module-iot/yudao-module-iot-protocol/README.md
  39. 0 71
      yudao-module-iot/yudao-module-iot-protocol/pom.xml
  40. 0 74
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/config/IotProtocolAutoConfiguration.java
  41. 0 166
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/constants/IotHttpConstants.java
  42. 0 91
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/constants/IotLogConstants.java
  43. 0 157
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/constants/IotTopicConstants.java
  44. 0 48
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/convert/IotProtocolConverter.java
  45. 0 132
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/convert/impl/DefaultIotProtocolConverter.java
  46. 0 49
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/enums/IotMessageDirectionEnum.java
  47. 0 140
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/enums/IotMessageTypeEnum.java
  48. 0 79
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/enums/IotProtocolTypeEnum.java
  49. 0 36
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/message/IotMessageParser.java
  50. 0 154
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/message/IotMqttMessage.java
  51. 0 95
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/message/IotStandardResponse.java
  52. 0 348
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/message/impl/IotHttpMessageParser.java
  53. 0 87
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/message/impl/IotMqttMessageParser.java
  54. 0 279
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/util/IotHttpTopicUtils.java
  55. 0 237
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/util/IotTopicParser.java
  56. 0 184
      yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/util/IotTopicUtils.java
  57. 0 1
      yudao-module-iot/yudao-module-iot-protocol/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  58. 0 71
      yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/config/IotProtocolAutoConfigurationTest.java
  59. 0 166
      yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/example/AliyunHttpProtocolExample.java
  60. 0 259
      yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/message/impl/IotHttpMessageParserTest.java
  61. 0 190
      yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/message/impl/IotMqttMessageParserTest.java
  62. 0 186
      yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/util/IotHttpTopicUtilsTest.java
  63. 0 81
      yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/util/IotTopicUtilsTest.java

+ 0 - 2
yudao-module-iot/pom.xml

@@ -9,8 +9,6 @@
     <modules>
         <module>yudao-module-iot-api</module>
         <module>yudao-module-iot-biz</module>
-        <module>yudao-module-iot-net-components</module>
-        <module>yudao-module-iot-protocol</module>
         <module>yudao-module-iot-core</module>
         <module>yudao-module-iot-gateway</module>
     </modules>

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

@@ -1,22 +0,0 @@
-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;
-
-}

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

@@ -1,30 +0,0 @@
-package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
-
-import jakarta.validation.constraints.NotEmpty;
-import lombok.Data;
-
-/**
- * IoT 设备下行的抽象 Request DTO
- *
- * @author 芋道源码
- */
-@Data
-public abstract class IotDeviceDownstreamAbstractReqDTO {
-
-    /**
-     * 请求编号
-     */
-    private String requestId;
-
-    /**
-     * 产品标识
-     */
-    @NotEmpty(message = "产品标识不能为空")
-    private String productKey;
-    /**
-     * 设备名称
-     */
-    @NotEmpty(message = "设备名称不能为空")
-    private String deviceName;
-
-}

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

@@ -1,66 +0,0 @@
-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();
-    }
-
-}

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

@@ -1,24 +0,0 @@
-package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
-
-import jakarta.validation.constraints.NotEmpty;
-import lombok.Data;
-
-import java.util.List;
-
-// TODO @芋艿:从 server => plugin => device 是否有必要?从阿里云 iot 来看,没有这个功能?!
-// TODO @芋艿:是不是改成 read 更好?在看看阿里云的 topic 设计
-/**
- * IoT 设备【属性】获取 Request DTO
- *
- * @author 芋道源码
- */
-@Data
-public class IotDevicePropertyGetReqDTO extends IotDeviceDownstreamAbstractReqDTO {
-
-    /**
-     * 属性标识数组
-     */
-    @NotEmpty(message = "属性标识数组不能为空")
-    private List<String> identifiers;
-
-}

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

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

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

@@ -1,26 +0,0 @@
-package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
-
-import jakarta.validation.constraints.NotEmpty;
-import lombok.Data;
-
-import java.util.Map;
-
-/**
- * IoT 设备【服务】调用 Request DTO
- *
- * @author 芋道源码
- */
-@Data
-public class IotDeviceServiceInvokeReqDTO extends IotDeviceDownstreamAbstractReqDTO {
-
-    /**
-     * 服务标识
-     */
-    @NotEmpty(message = "服务标识不能为空")
-    private String identifier;
-    /**
-     * 调用参数
-     */
-    private Map<String, Object> params;
-
-}

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

@@ -1,35 +0,0 @@
-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;
-
-}

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

@@ -1,21 +0,0 @@
-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;
-
-}

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

@@ -1,21 +0,0 @@
-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;
-
-}

+ 0 - 16
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ApiConstants.java

@@ -1,16 +0,0 @@
-package cn.iocoder.yudao.module.iot.enums;
-
-import cn.iocoder.yudao.framework.common.enums.RpcConstants;
-
-/**
- * API 相关的枚举
- *
- * @author 芋道源码
- */
-public class ApiConstants {
-
-    public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/iot";
-
-    public static final String VERSION = "1.0.0";
-
-}

+ 0 - 3
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/DictTypeConstants.java

@@ -15,8 +15,5 @@ public class DictTypeConstants {
     public static final String VALIDATE_TYPE = "iot_validate_type";
 
     public static final String DEVICE_STATE = "iot_device_state";
-    
-    public static final String IOT_DATA_BRIDGE_DIRECTION_ENUM = "iot_data_bridge_direction_enum";
-    public static final String IOT_DATA_BRIDGE_TYPE_ENUM = "iot_data_bridge_type_enum";
 
 }

+ 0 - 37
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/plugin/IotPluginDeployTypeEnum.java

@@ -1,37 +0,0 @@
-package cn.iocoder.yudao.module.iot.enums.plugin;
-
-import cn.iocoder.yudao.framework.common.core.ArrayValuable;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-import java.util.Arrays;
-
-/**
- * IoT 部署方式枚举
- *
- * @author haohao
- */
-@RequiredArgsConstructor
-@Getter
-public enum IotPluginDeployTypeEnum implements ArrayValuable<Integer> {
-
-    JAR(0, "JAR 部署"),
-    STANDALONE(1, "独立部署");
-
-    public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotPluginDeployTypeEnum::getDeployType).toArray(Integer[]::new);
-
-    /**
-     * 部署方式
-     */
-    private final Integer deployType;
-    /**
-     * 部署方式名
-     */
-    private final String name;
-
-    @Override
-    public Integer[] array() {
-        return ARRAYS;
-    }
-
-}

+ 0 - 37
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/plugin/IotPluginStatusEnum.java

@@ -1,37 +0,0 @@
-package cn.iocoder.yudao.module.iot.enums.plugin;
-
-import cn.iocoder.yudao.framework.common.core.ArrayValuable;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-import java.util.Arrays;
-
-/**
- * IoT 插件状态枚举
- *
- * @author haohao
- */
-@RequiredArgsConstructor
-@Getter
-public enum IotPluginStatusEnum implements ArrayValuable<Integer> {
-
-    STOPPED(0, "停止"),
-    RUNNING(1, "运行");
-
-    public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotPluginStatusEnum::getStatus).toArray(Integer[]::new);
-
-    /**
-     * 状态
-     */
-    private final Integer status;
-    /**
-     * 状态名
-     */
-    private final String name;
-
-    @Override
-    public Integer[] array() {
-        return ARRAYS;
-    }
-
-}

+ 0 - 37
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/plugin/IotPluginTypeEnum.java

@@ -1,37 +0,0 @@
-package cn.iocoder.yudao.module.iot.enums.plugin;
-
-import cn.iocoder.yudao.framework.common.core.ArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-/**
- * IoT 插件类型枚举
- *
- * @author haohao
- */
-@AllArgsConstructor
-@Getter
-public enum IotPluginTypeEnum implements ArrayValuable<Integer> {
-
-    NORMAL(0, "普通插件"),
-    DEVICE(1, "设备插件");
-
-    public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotPluginTypeEnum::getType).toArray(Integer[]::new);
-
-    /**
-     * 类型
-     */
-    private final Integer type;
-    /**
-     * 类型名
-     */
-    private final String name;
-
-    @Override
-    public Integer[] array() {
-        return ARRAYS;
-    }
-
-}

+ 0 - 47
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptLanguageEnum.java

@@ -1,47 +0,0 @@
-package cn.iocoder.yudao.module.iot.enums.product;
-
-import cn.iocoder.yudao.framework.common.core.ArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-/**
- * IoT 产品脚本语言枚举
- *
- * @author 芋道源码
- */
-@Getter
-@AllArgsConstructor
-public enum IotProductScriptLanguageEnum implements ArrayValuable<String> {
-
-    JAVASCRIPT("javascript", "JavaScript"),
-    JAVA("java", "Java"),
-    PYTHON("python", "Python"),
-    ;
-
-    public static final String[] ARRAYS = Arrays.stream(values()).map(IotProductScriptLanguageEnum::getCode)
-            .toArray(String[]::new);
-
-    /**
-     * 编码
-     */
-    private final String code;
-    /**
-     * 名称
-     */
-    private final String name;
-
-    @Override
-    public String[] array() {
-        return ARRAYS;
-    }
-
-    public static IotProductScriptLanguageEnum getByCode(String code) {
-        return Arrays.stream(values())
-                .filter(type -> type.getCode().equals(code))
-                .findFirst()
-                .orElse(null);
-    }
-
-}

+ 0 - 54
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptStatusEnum.java

@@ -1,54 +0,0 @@
-package cn.iocoder.yudao.module.iot.enums.product;
-
-import cn.iocoder.yudao.framework.common.core.ArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-// TODO @haohao:要不复用 commonstatus?
-/**
- * IoT 产品脚本状态枚举
- *
- * @author 芋道源码
- */
-@Getter
-@AllArgsConstructor
-public enum IotProductScriptStatusEnum implements ArrayValuable<Integer> {
-
-    ENABLE(0, "启用"),
-    DISABLE(1, "禁用"),
-    ;
-
-    public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotProductScriptStatusEnum::getStatus)
-            .toArray(Integer[]::new);
-
-    /**
-     * 状态值
-     */
-    private final Integer status;
-    /**
-     * 状态名
-     */
-    private final String name;
-
-    @Override
-    public Integer[] array() {
-        return ARRAYS;
-    }
-
-    public static IotProductScriptStatusEnum getByStatus(Integer status) {
-        return Arrays.stream(values())
-                .filter(type -> type.getStatus().equals(status))
-                .findFirst()
-                .orElse(null);
-    }
-
-    public static boolean isEnable(Integer status) {
-        return ENABLE.getStatus().equals(status);
-    }
-
-    public static boolean isDisable(Integer status) {
-        return DISABLE.getStatus().equals(status);
-    }
-}

+ 0 - 50
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptTypeEnum.java

@@ -1,50 +0,0 @@
-package cn.iocoder.yudao.module.iot.enums.product;
-
-import cn.iocoder.yudao.framework.common.core.ArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-/**
- * IoT 产品脚本类型枚举
- *
- * @author 芋道源码
- */
-@Getter
-@AllArgsConstructor
-public enum IotProductScriptTypeEnum implements ArrayValuable<Integer> {
-
-    PROPERTY_PARSER(1, "property_parser", "属性解析"),
-    EVENT_PARSER(2, "event_parser", "事件解析"),
-    COMMAND_ENCODER(3, "command_encoder", "命令编码"),
-    ;
-
-    public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotProductScriptTypeEnum::getCode)
-            .toArray(Integer[]::new);
-
-    /**
-     * 编码
-     */
-    private final Integer code;
-    /**
-     * 类型
-     */
-    private final String type;
-    /**
-     * 名称
-     */
-    private final String name;
-
-    @Override
-    public Integer[] array() {
-        return ARRAYS;
-    }
-
-    public static IotProductScriptTypeEnum getByCode(Integer code) {
-        return Arrays.stream(values())
-                .filter(type -> type.getCode().equals(code))
-                .findFirst()
-                .orElse(null);
-    }
-}

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

@@ -55,7 +55,7 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
         if (StrUtil.isEmpty(serverId)) {
             throw exception(DEVICE_DOWNSTREAM_FAILED_SERVER_ID_NULL);
         }
-        deviceMessageProducer.sendGatewayDeviceMessage(serverId, message);
+        deviceMessageProducer.sendDeviceMessageToGateway(serverId, message);
 
         // 3.2 发送给服务器(用于设备日志等的记录)
         deviceMessageProducer.sendDeviceMessage(message);

+ 0 - 1
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/package-info.java

@@ -1 +0,0 @@
-package cn.iocoder.yudao.module.iot.gateway.protocol.mqtt;

+ 0 - 25
yudao-module-iot/yudao-module-iot-net-components/pom.xml

@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>yudao-module-iot</artifactId>
-        <groupId>cn.iocoder.boot</groupId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>yudao-module-iot-net-components</artifactId>
-    <packaging>pom</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>
-        物联网网络组件模块,提供与物联网设备通讯、管理的网络组件实现
-    </description>
-
-    <modules>
-        <module>yudao-module-iot-net-component-core</module>
-        <module>yudao-module-iot-net-component-emqx</module>
-        <module>yudao-module-iot-net-component-server</module>
-    </modules>
-
-</project>

+ 0 - 65
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/pom.xml

@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>yudao-module-iot-net-components</artifactId>
-        <groupId>cn.iocoder.boot</groupId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>yudao-module-iot-net-component-core</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>
-        物联网网络组件核心模块
-    </description>
-
-    <dependencies>
-        <dependency>
-            <groupId>cn.iocoder.boot</groupId>
-            <artifactId>yudao-module-iot-api</artifactId>
-            <version>${revision}</version>
-        </dependency>
-
-        <dependency>
-            <groupId>cn.iocoder.boot</groupId>
-            <artifactId>yudao-module-iot-core</artifactId>
-            <version>${revision}</version>
-        </dependency>
-
-        <!-- IoT 协议模块 -->
-        <dependency>
-            <groupId>cn.iocoder.boot</groupId>
-            <artifactId>yudao-module-iot-protocol</artifactId>
-            <version>${revision}</version>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter</artifactId>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-web</artifactId>
-        </dependency>
-
-        <!-- 工具类相关 -->
-        <dependency>
-            <groupId>io.vertx</groupId>
-            <artifactId>vertx-web</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- 参数校验 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-validation</artifactId>
-            <optional>true</optional>
-        </dependency>
-    </dependencies>
-</project>

+ 0 - 153
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/message/IotMqttMessage.java

@@ -1,153 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.core.message;
-
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.json.JSONObject;
-import lombok.Builder;
-import lombok.Data;
-
-import java.util.Map;
-
-/**
- * IoT MQTT 消息模型
- * <p>
- * 基于 MQTT 协议规范实现的标准消息格式,兼容 Alink 协议
- *
- * @author haohao
- */
-@Data
-@Builder
-public class IotMqttMessage {
-
-    /**
-     * 消息 ID
-     */
-    private String id;
-
-    /**
-     * 协议版本
-     */
-    @Builder.Default
-    private String version = "1.0";
-
-    /**
-     * 消息方法
-     */
-    private String method;
-
-    /**
-     * 消息参数
-     */
-    private Map<String, Object> params;
-
-    /**
-     * 转换为 JSONObject
-     *
-     * @return JSONObject 对象
-     */
-    public JSONObject toJsonObject() {
-        JSONObject json = new JSONObject();
-        json.set("id", id);
-        json.set("version", version);
-        json.set("method", method);
-        json.set("params", params != null ? params : new JSONObject());
-        return json;
-    }
-
-    /**
-     * 转换为 JSON 字符串
-     *
-     * @return JSON 字符串
-     */
-    public String toJsonString() {
-        return toJsonObject().toString();
-    }
-
-    /**
-     * 创建设备服务调用消息
-     *
-     * @param requestId         请求 ID,为空时自动生成
-     * @param serviceIdentifier 服务标识符
-     * @param params            服务参数
-     * @return MQTT 消息对象
-     */
-    public static IotMqttMessage createServiceInvokeMessage(String requestId, String serviceIdentifier,
-                                                             Map<String, Object> params) {
-        return IotMqttMessage.builder()
-                .id(requestId != null ? requestId : generateRequestId())
-                .method("thing.service." + serviceIdentifier)
-                .params(params)
-                .build();
-    }
-
-    /**
-     * 创建设备属性设置消息
-     *
-     * @param requestId  请求 ID,为空时自动生成
-     * @param properties 设备属性
-     * @return MQTT 消息对象
-     */
-    public static IotMqttMessage createPropertySetMessage(String requestId, Map<String, Object> properties) {
-        return IotMqttMessage.builder()
-                .id(requestId != null ? requestId : generateRequestId())
-                .method("thing.service.property.set")
-                .params(properties)
-                .build();
-    }
-
-    /**
-     * 创建设备属性获取消息
-     *
-     * @param requestId   请求 ID,为空时自动生成
-     * @param identifiers 要获取的属性标识符列表
-     * @return MQTT 消息对象
-     */
-    public static IotMqttMessage createPropertyGetMessage(String requestId, String[] identifiers) {
-        JSONObject params = new JSONObject();
-        params.set("identifiers", identifiers);
-
-        return IotMqttMessage.builder()
-                .id(requestId != null ? requestId : generateRequestId())
-                .method("thing.service.property.get")
-                .params(params)
-                .build();
-    }
-
-    /**
-     * 创建设备配置设置消息
-     *
-     * @param requestId 请求 ID,为空时自动生成
-     * @param configs   设备配置
-     * @return MQTT 消息对象
-     */
-    public static IotMqttMessage createConfigSetMessage(String requestId, Map<String, Object> configs) {
-        return IotMqttMessage.builder()
-                .id(requestId != null ? requestId : generateRequestId())
-                .method("thing.service.config.set")
-                .params(configs)
-                .build();
-    }
-
-    /**
-     * 创建设备 OTA 升级消息
-     *
-     * @param requestId 请求 ID,为空时自动生成
-     * @param otaInfo   OTA 升级信息
-     * @return MQTT 消息对象
-     */
-    public static IotMqttMessage createOtaUpgradeMessage(String requestId, Map<String, Object> otaInfo) {
-        return IotMqttMessage.builder()
-                .id(requestId != null ? requestId : generateRequestId())
-                .method("thing.service.ota.upgrade")
-                .params(otaInfo)
-                .build();
-    }
-
-    /**
-     * 生成请求 ID
-     *
-     * @return 请求 ID
-     */
-    public static String generateRequestId() {
-        return IdUtil.fastSimpleUUID();
-    }
-}

+ 0 - 93
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/pojo/IotStandardResponse.java

@@ -1,93 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.core.pojo;
-
-import cn.hutool.core.util.StrUtil;
-import lombok.Data;
-
-/**
- * IoT 标准协议响应实体类
- * <p>
- * 用于统一 MQTT 和 HTTP 的响应格式
- *
- * @author haohao
- */
-@Data
-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(StrUtil.blankToDefault(message, "error"))
-                .setMethod(method)
-                .setVersion("1.0");
-    }
-}

+ 0 - 44
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/pom.xml

@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>yudao-module-iot-net-components</artifactId>
-        <groupId>cn.iocoder.boot</groupId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>yudao-module-iot-net-component-emqx</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>
-        物联网网络组件 EMQX 模块
-    </description>
-
-    <dependencies>
-        <dependency>
-            <groupId>cn.iocoder.boot</groupId>
-            <artifactId>yudao-module-iot-net-component-core</artifactId>
-            <version>${revision}</version>
-        </dependency>
-
-        <!-- 工具类相关 -->
-        <dependency>
-            <groupId>io.vertx</groupId>
-            <artifactId>vertx-web</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.vertx</groupId>
-            <artifactId>vertx-mqtt</artifactId>
-        </dependency>
-
-        <!-- 参数校验 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-validation</artifactId>
-            <optional>true</optional>
-        </dependency>
-    </dependencies>
-
-</project>

+ 0 - 83
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/config/IotNetComponentEmqxAutoConfiguration.java

@@ -1,83 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.emqx.config;
-
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.core.util.ObjUtil;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.net.component.emqx.upstream.IotDeviceUpstreamServer;
-import io.vertx.core.Vertx;
-import io.vertx.mqtt.MqttClient;
-import io.vertx.mqtt.MqttClientOptions;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.event.ApplicationStartedEvent;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.event.EventListener;
-
-/**
- * IoT 网络组件 EMQX 的自动配置类
- *
- * @author haohao
- */
-@AutoConfiguration
-@EnableConfigurationProperties(IotNetComponentEmqxProperties.class)
-@ConditionalOnProperty(prefix = "yudao.iot.component.emqx", name = "enabled", havingValue = "true")
-@ComponentScan(basePackages = {
-        "cn.iocoder.yudao.module.iot.net.component.emqx" // 只扫描 EMQX 组件包
-}) // TODO @haohao:自动配置后,不需要这个哈。
-@Slf4j
-public class IotNetComponentEmqxAutoConfiguration {
-
-    /**
-     * 初始化 EMQX 组件
-     *
-     * @param event 应用启动事件
-     */
-    @EventListener(ApplicationStartedEvent.class)
-    public void initialize(ApplicationStartedEvent event) {
-        log.info("[IotNetComponentEmqxAutoConfiguration][开始初始化]");
-
-        // 从应用上下文中获取需要的 Bean
-        // TODO @芋艿:看看要不要监听下
-
-        log.info("[initialize][IoT EMQX 组件初始化完成]");
-    }
-
-    /**
-     * 创建 Vert.x 实例
-     */
-    @Bean(name = "emqxVertx")
-    public Vertx vertx() {
-        return Vertx.vertx();
-    }
-
-    /**
-     * 创建 MQTT 客户端
-     */
-    @Bean
-    public MqttClient mqttClient(@Qualifier("emqxVertx") Vertx vertx, IotNetComponentEmqxProperties emqxProperties) {
-        MqttClientOptions options = new MqttClientOptions()
-                .setClientId("yudao-iot-downstream-" + IdUtil.fastSimpleUUID())
-                .setUsername(emqxProperties.getMqttUsername())
-                .setPassword(emqxProperties.getMqttPassword());
-        // 设置 SSL 选项
-        options.setSsl(ObjUtil.defaultIfNull(emqxProperties.getMqttSsl(), false));
-        return MqttClient.create(vertx, options);
-    }
-
-    /**
-     * 创建设备上行服务器
-     */
-    @Bean(name = "emqxDeviceUpstreamServer", initMethod = "start", destroyMethod = "stop")
-    public IotDeviceUpstreamServer deviceUpstreamServer(
-            IotDeviceUpstreamApi deviceUpstreamApi,
-            IotNetComponentEmqxProperties emqxProperties,
-            @Qualifier("emqxVertx") Vertx vertx,
-            MqttClient mqttClient) {
-        return new IotDeviceUpstreamServer(emqxProperties, deviceUpstreamApi, vertx, mqttClient);
-    }
-
-}

+ 0 - 82
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/config/IotNetComponentEmqxProperties.java

@@ -1,82 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.emqx.config;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-
-/**
- * IoT EMQX 网络组件配置属性
- *
- * @author haohao
- */
-@ConfigurationProperties(prefix = "yudao.iot.component.emqx")
-@Data
-@Validated
-public class IotNetComponentEmqxProperties {
-
-    /**
-     * 是否启用 EMQX 组件
-     */
-    private Boolean enabled;
-
-    /**
-     * MQTT 服务主机
-     */
-    @NotBlank(message = "MQTT 服务器主机不能为空")
-    private String mqttHost;
-
-    /**
-     * MQTT 服务端口
-     */
-    @NotNull(message = "MQTT 服务器端口不能为空")
-    private Integer mqttPort;
-
-    /**
-     * MQTT 服务用户名
-     */
-    @NotBlank(message = "MQTT 服务器用户名不能为空")
-    private String mqttUsername;
-
-    /**
-     * MQTT 服务密码
-     */
-    @NotBlank(message = "MQTT 服务器密码不能为空")
-    private String mqttPassword;
-
-    /**
-     * 是否启用 SSL
-     */
-    @NotNull(message = "MQTT SSL 配置不能为空")
-    private Boolean mqttSsl;
-
-    /**
-     * 订阅的主题列表
-     */
-    @NotEmpty(message = "MQTT 订阅主题不能为空")
-    private String[] mqttTopics;
-
-    /**
-     * 认证端口
-     */
-    @NotNull(message = "认证端口不能为空")
-    private Integer authPort;
-
-    // TODO @haohao:可以使用 Duration 类型,可读性更好
-    /**
-     * 重连延迟时间(毫秒)
-     * <p>
-     * 默认值:5000 毫秒
-     */
-    private Integer reconnectDelayMs = 5000;
-
-    /**
-     * 连接超时时间(毫秒)
-     * <p>
-     * 默认值:10000 毫秒
-     */
-    private Integer connectionTimeoutMs = 10000;
-
-}

+ 0 - 121
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/downstream/IotDeviceDownstreamHandlerImpl.java

@@ -1,121 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.emqx.downstream;
-
-// TODO @芋艿:后续再支持下;@haohao;改成消费者
-///**
-// * EMQX 网络组件的 {@link IotDeviceDownstreamHandler} 实现类
-// *
-// * @author 芋道源码
-// */
-//@Slf4j
-//public class IotDeviceDownstreamHandlerImpl {
-//
-//    /**
-//     * MQTT 客户端
-//     */
-//    private final MqttClient mqttClient;
-//
-//    /**
-//     * 构造函数
-//     *
-//     * @param mqttClient MQTT 客户端
-//     */
-//    public IotDeviceDownstreamHandlerImpl(MqttClient mqttClient) {
-//        this.mqttClient = mqttClient;
-//    }
-//
-//    @Override
-//    public CommonResult<Boolean> invokeDeviceService(IotDeviceServiceInvokeReqDTO reqDTO) {
-//        log.info("[invokeService][开始调用设备服务][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO));
-//
-//        // 验证参数
-//        if (reqDTO.getProductKey() == null || reqDTO.getDeviceName() == null || reqDTO.getIdentifier() == null) {
-//            log.error("[invokeService][参数不完整][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO));
-//            return CommonResult.error(MQTT_TOPIC_ILLEGAL.getCode(), MQTT_TOPIC_ILLEGAL.getMsg());
-//        }
-//
-//        try {
-//            // 构建请求主题
-//            String topic = IotDeviceTopicEnum.buildServiceTopic(reqDTO.getProductKey(), reqDTO.getDeviceName(),
-//                    reqDTO.getIdentifier());
-//
-//            // 构建请求消息
-//            String requestId = StrUtil.isNotEmpty(reqDTO.getRequestId()) ? reqDTO.getRequestId()
-//                    : IotNetComponentCommonUtils.generateRequestId();
-//            IotMqttMessage message = IotMqttMessage.createServiceInvokeMessage(
-//                    requestId, reqDTO.getIdentifier(), reqDTO.getParams());
-//
-//            // 发送消息
-//            publishMessage(topic, message.toJsonObject());
-//
-//            log.info("[invokeService][调用设备服务成功][requestId: {}][topic: {}]", requestId, topic);
-//            return CommonResult.success(true);
-//        } catch (Exception e) {
-//            log.error("[invokeService][调用设备服务异常][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO), e);
-//            return CommonResult.error(MQTT_TOPIC_ILLEGAL.getCode(), MQTT_TOPIC_ILLEGAL.getMsg());
-//        }
-//    }
-//
-//    @Override
-//    public CommonResult<Boolean> getDeviceProperty(IotDevicePropertyGetReqDTO getReqDTO) {
-//        // 暂未实现,返回成功
-//        return CommonResult.success(true);
-//    }
-//
-//    @Override
-//    public CommonResult<Boolean> setDeviceProperty(IotDevicePropertySetReqDTO reqDTO) {
-//        log.info("[setProperty][开始设置设备属性][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO));
-//
-//        // 验证参数
-//        if (reqDTO.getProductKey() == null || reqDTO.getDeviceName() == null) {
-//            log.error("[setProperty][参数不完整][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO));
-//            return CommonResult.error(MQTT_TOPIC_ILLEGAL.getCode(), MQTT_TOPIC_ILLEGAL.getMsg());
-//        }
-//
-//        try {
-//            // 构建请求主题
-//            String topic = IotDeviceTopicEnum.buildPropertySetTopic(reqDTO.getProductKey(), reqDTO.getDeviceName());
-//
-//            // 构建请求消息
-//            String requestId = StrUtil.isNotEmpty(reqDTO.getRequestId()) ? reqDTO.getRequestId()
-//                    : IotNetComponentCommonUtils.generateRequestId();
-//            IotMqttMessage message = IotMqttMessage.createPropertySetMessage(requestId, reqDTO.getProperties());
-//
-//            // 发送消息
-//            publishMessage(topic, message.toJsonObject());
-//
-//            log.info("[setProperty][设置设备属性成功][requestId: {}][topic: {}]", requestId, topic);
-//            return CommonResult.success(true);
-//        } catch (Exception e) {
-//            log.error("[setProperty][设置设备属性异常][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO), e);
-//            return CommonResult.error(MQTT_TOPIC_ILLEGAL.getCode(), MQTT_TOPIC_ILLEGAL.getMsg());
-//        }
-//    }
-//
-//    @Override
-//    public CommonResult<Boolean> setDeviceConfig(IotDeviceConfigSetReqDTO setReqDTO) {
-//        // 暂未实现,返回成功
-//        return CommonResult.success(true);
-//    }
-//
-//    @Override
-//    public CommonResult<Boolean> upgradeDeviceOta(IotDeviceOtaUpgradeReqDTO upgradeReqDTO) {
-//        // 暂未实现,返回成功
-//        return CommonResult.success(true);
-//    }
-//
-//    /**
-//     * 发布 MQTT 消息
-//     *
-//     * @param topic   主题
-//     * @param payload 消息内容
-//     */
-//    private void publishMessage(String topic, JSONObject payload) {
-//        mqttClient.publish(
-//                topic,
-//                Buffer.buffer(payload.toString()),
-//                MqttQoS.AT_LEAST_ONCE,
-//                false,
-//                false);
-//        log.info("[publishMessage][发送消息成功][topic: {}][payload: {}]", topic, payload);
-//    }
-//}

+ 0 - 261
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/IotDeviceUpstreamServer.java

@@ -1,261 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.emqx.upstream;
-
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.net.component.emqx.config.IotNetComponentEmqxProperties;
-import cn.iocoder.yudao.module.iot.net.component.emqx.upstream.router.IotDeviceAuthVertxHandler;
-import cn.iocoder.yudao.module.iot.net.component.emqx.upstream.router.IotDeviceMqttMessageHandler;
-import cn.iocoder.yudao.module.iot.net.component.emqx.upstream.router.IotDeviceWebhookVertxHandler;
-import io.netty.handler.codec.mqtt.MqttQoS;
-import io.vertx.core.Future;
-import io.vertx.core.Vertx;
-import io.vertx.core.http.HttpServer;
-import io.vertx.ext.web.Router;
-import io.vertx.ext.web.handler.BodyHandler;
-import io.vertx.mqtt.MqttClient;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-
-/**
- * IoT 设备上行服务端,接收来自 device 设备的请求,转发给 server 服务器
- * <p>
- * 协议:HTTP、MQTT
- *
- * @author haohao
- */
-@Slf4j
-public class IotDeviceUpstreamServer {
-
-    /**
-     * 默认 QoS 级别
-     */
-    private static final MqttQoS DEFAULT_QOS = MqttQoS.AT_LEAST_ONCE;
-
-    private final Vertx vertx;
-    private final HttpServer server;
-    private final MqttClient client;
-    private final IotNetComponentEmqxProperties emqxProperties;
-    private final IotDeviceMqttMessageHandler mqttMessageHandler;
-
-    /**
-     * 服务运行状态标志
-     */
-    private volatile boolean isRunning = false;
-
-    public IotDeviceUpstreamServer(IotNetComponentEmqxProperties emqxProperties,
-                                   IotDeviceUpstreamApi deviceUpstreamApi,
-                                   Vertx vertx,
-                                   MqttClient client) {
-        this.vertx = vertx;
-        this.emqxProperties = emqxProperties;
-        this.client = client;
-
-        // 创建 Router 实例
-        Router router = Router.router(vertx);
-        router.route().handler(BodyHandler.create()); // 处理 Body
-        router.post(IotDeviceAuthVertxHandler.PATH)
-                // MQTT 认证不必须通过 HTTP 进行,但 HTTP 认证是 EMQX 等 MQTT 服务器支持的一种灵活的认证方式
-                .handler(new IotDeviceAuthVertxHandler(deviceUpstreamApi));
-        // 添加 Webhook 处理器,用于处理设备连接和断开连接事件
-        router.post(IotDeviceWebhookVertxHandler.PATH)
-                .handler(new IotDeviceWebhookVertxHandler(deviceUpstreamApi));
-        // 创建 HttpServer 实例
-        this.server = vertx.createHttpServer().requestHandler(router);
-        this.mqttMessageHandler = new IotDeviceMqttMessageHandler(deviceUpstreamApi, client);
-    }
-
-    /**
-     * 启动 HTTP 服务器、MQTT 客户端
-     */
-    public void start() {
-        if (isRunning) {
-            log.warn("[start][服务已经在运行中,请勿重复启动]");
-            return;
-        }
-        log.info("[start][开始启动服务]");
-
-        // 检查 authPort 是否为 null
-        // TODO @haohao:authPort 里面搞默认值?包括下面,这个类不搞任何默认值,都交给 emqxProperties
-        Integer authPort = emqxProperties.getAuthPort();
-        if (authPort == null) {
-            log.warn("[start][authPort 为 null,使用默认端口 8080]");
-            authPort = 8080; // 默认端口
-        }
-
-        // 获取连接超时时间
-        int connectionTimeoutMs = emqxProperties.getConnectionTimeoutMs() != null
-                ? emqxProperties.getConnectionTimeoutMs()
-                : 10000;
-
-        // 1. 启动 HTTP 服务器
-        final Integer finalAuthPort = authPort; // 为 lambda 表达式创建 final 变量
-        CompletableFuture<Void> httpFuture = server.listen(finalAuthPort)
-                .toCompletionStage()
-                .toCompletableFuture()
-                .thenAccept(v -> log.info("[start][HTTP 服务器启动完成,端口: {}]", server.actualPort()));
-
-        // 2. 连接 MQTT Broker
-        CompletableFuture<Void> mqttFuture = connectMqtt()
-                .toCompletionStage()
-                .toCompletableFuture()
-                .thenAccept(v -> {
-                    // 2.1 添加 MQTT 断开重连监听器
-                    client.closeHandler(closeEvent -> {
-                        log.warn("[closeHandler][MQTT 连接已断开,准备重连]");
-                        reconnectWithDelay();
-                    });
-                    // 2.2 设置 MQTT 消息处理器
-                    setupMessageHandler();
-                });
-
-        // 3. 等待所有服务启动完成
-        CompletableFuture.allOf(httpFuture, mqttFuture)
-                .orTimeout(connectionTimeoutMs, TimeUnit.MILLISECONDS)
-                .whenComplete((result, error) -> {
-                    if (error != null) {
-                        log.error("[start][服务启动失败]", error);
-                    } else {
-                        isRunning = true;
-                        log.info("[start][所有服务启动完成]");
-                    }
-                });
-    }
-
-    /**
-     * 设置 MQTT 消息处理器
-     */
-    private void setupMessageHandler() {
-        client.publishHandler(mqttMessageHandler::handle);
-        log.debug("[setupMessageHandler][MQTT 消息处理器设置完成]");
-    }
-
-    /**
-     * 重连 MQTT 客户端
-     */
-    private void reconnectWithDelay() {
-        if (!isRunning) {
-            log.info("[reconnectWithDelay][服务已停止,不再尝试重连]");
-            return;
-        }
-
-        // 获取重连延迟时间
-        int reconnectDelayMs = emqxProperties.getReconnectDelayMs() != null
-                ? emqxProperties.getReconnectDelayMs()
-                : 5000;
-
-        vertx.setTimer(reconnectDelayMs, id -> {
-            log.info("[reconnectWithDelay][开始重新连接 MQTT]");
-            connectMqtt();
-        });
-    }
-
-    /**
-     * 连接 MQTT Broker 并订阅主题
-     *
-     * @return 连接结果的 Future
-     */
-    private Future<Void> connectMqtt() {
-        // 检查必要的 MQTT 配置
-        String host = emqxProperties.getMqttHost();
-        Integer port = emqxProperties.getMqttPort();
-        if (StrUtil.isBlank(host)) {
-            String msg = "[connectMqtt][MQTT Host 为空,无法连接]";
-            log.error(msg);
-            return Future.failedFuture(new IllegalStateException(msg));
-        }
-        if (port == null) {
-            log.warn("[connectMqtt][MQTT Port 为 null,使用默认端口 1883]");
-            port = 1883; // 默认 MQTT 端口
-        }
-
-        final Integer finalPort = port;
-        return client.connect(finalPort, host)
-                .compose(connAck -> {
-                    log.info("[connectMqtt][MQTT 客户端连接成功]");
-                    return subscribeToTopics();
-                })
-                .recover(error -> {
-                    log.error("[connectMqtt][连接 MQTT Broker 失败:]", error);
-                    reconnectWithDelay();
-                    return Future.failedFuture(error);
-                });
-    }
-
-    /**
-     * 订阅设备上行消息主题
-     *
-     * @return 订阅结果的 Future
-     */
-    private Future<Void> subscribeToTopics() {
-        String[] topics = emqxProperties.getMqttTopics();
-        if (ArrayUtil.isEmpty(topics)) {
-            log.warn("[subscribeToTopics][未配置 MQTT 主题或为 null,使用默认主题]");
-            topics = new String[]{"/device/#"}; // 默认订阅所有设备上下行主题
-        }
-
-        // 使用协调器追踪多个 Future 的完成状态
-        Future<Void> result = Future.succeededFuture();
-        for (String topic : topics) {
-            if (StrUtil.isBlank(topic)) {
-                log.warn("[subscribeToTopics][跳过空主题]");
-                continue;
-            }
-
-            result = result.compose(v -> client.subscribe(topic, DEFAULT_QOS.value())
-                    .<Void>map(ack -> {
-                        log.info("[subscribeToTopics][订阅主题成功: {}]", topic);
-                        return null;
-                    })
-                    .recover(err -> {
-                        log.error("[subscribeToTopics][订阅主题失败: {}]", topic, err);
-                        return Future.failedFuture(err);
-                    }));
-        }
-        return result;
-    }
-
-    /**
-     * 停止服务
-     */
-    public void stop() {
-        if (!isRunning) {
-            log.warn("[stop][服务已经停止,无需再次停止]");
-            return;
-        }
-        log.info("[stop][开始停止服务]");
-
-        // 1. 取消 MQTT 主题订阅
-        if (client.isConnected()) {
-            for (String topic : emqxProperties.getMqttTopics()) {
-                try {
-                    client.unsubscribe(topic);
-                } catch (Exception e) {
-                    log.warn("[stop][取消订阅主题异常: {}]", topic, e);
-                }
-            }
-        }
-
-        // 2. 关闭 MQTT 客户端
-        try {
-            if (client.isConnected()) {
-                client.disconnect();
-            }
-        } catch (Exception e) {
-            log.warn("[stop][关闭 MQTT 客户端异常]", e);
-        }
-
-        // 3. 关闭 HTTP 服务器
-        try {
-            server.close();
-        } catch (Exception e) {
-            log.warn("[stop][关闭 HTTP 服务器异常]", e);
-        }
-
-        // 4. 更新状态
-        isRunning = false;
-        log.info("[stop][服务已停止]");
-    }
-}

+ 0 - 64
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/router/IotDeviceAuthVertxHandler.java

@@ -1,64 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.emqx.upstream.router;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceEmqxAuthReqDTO;
-import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils;
-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.Collections;
-
-/**
- * IoT EMQX 连接认证的 Vert.x Handler
- * <p>
- * 参考:<a href="https://docs.emqx.com/zh/emqx/latest/access-control/authn/http.html">EMQX HTTP</a>
- * <p>
- * 注意:该处理器需要返回特定格式:{"result": "allow"} 或 {"result": "deny"},
- * 以符合 EMQX 认证插件的要求,因此不使用 IotStandardResponse 实体类
- *
- * @author haohao
- */
-@RequiredArgsConstructor
-@Slf4j
-public class IotDeviceAuthVertxHandler implements Handler<RoutingContext> {
-
-    public static final String PATH = "/mqtt/auth";
-
-    private final IotDeviceUpstreamApi deviceUpstreamApi;
-
-    @Override
-    public void handle(RoutingContext routingContext) {
-        try {
-            // 构建认证请求 DTO
-            JsonObject json = routingContext.body().asJsonObject();
-            String clientId = json.getString("clientid");
-            String username = json.getString("username");
-            String password = json.getString("password");
-            IotDeviceEmqxAuthReqDTO authReqDTO = new IotDeviceEmqxAuthReqDTO()
-                    .setClientId(clientId)
-                    .setUsername(username)
-                    .setPassword(password);
-
-            // 调用认证 API
-            CommonResult<Boolean> authResult = deviceUpstreamApi.authenticateEmqxConnection(authReqDTO);
-            if (authResult.getCode() != 0 || !authResult.getData()) {
-                // 注意:这里必须返回 {"result": "deny"} 格式,以符合 EMQX 认证插件的要求
-                IotNetComponentCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "deny"));
-                return;
-            }
-
-            // 响应结果
-            // 注意:这里必须返回 {"result": "allow"} 格式,以符合 EMQX 认证插件的要求
-            IotNetComponentCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "allow"));
-        } catch (Exception e) {
-            log.error("[handle][EMQX 认证异常]", e);
-            // 注意:这里必须返回 {"result": "deny"} 格式,以符合 EMQX 认证插件的要求
-            IotNetComponentCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "deny"));
-        }
-    }
-
-}

+ 0 - 287
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/router/IotDeviceMqttMessageHandler.java

@@ -1,287 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.emqx.upstream.router;
-
-import cn.hutool.core.util.StrUtil;
-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.net.component.core.constants.IotDeviceTopicEnum;
-import cn.iocoder.yudao.module.iot.net.component.core.pojo.IotStandardResponse;
-import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils;
-import io.netty.handler.codec.mqtt.MqttQoS;
-import io.vertx.core.buffer.Buffer;
-import io.vertx.mqtt.MqttClient;
-import io.vertx.mqtt.messages.MqttPublishMessage;
-import lombok.extern.slf4j.Slf4j;
-
-import java.time.LocalDateTime;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * IoT 设备 MQTT 消息处理器
- * <p>
- * 参考:<a href=
- * "https://help.aliyun.com/zh/iot/user-guide/device-properties-events-and-services">设备属性、事件、服务</a>
- */
-@Slf4j
-public class IotDeviceMqttMessageHandler {
-
-    // TODO @haohao:下面的,有办法也抽到 IotDeviceTopicEnum 么?想的是,尽量把这些 method、topic、url 统一化;
-    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;
-    private final MqttClient mqttClient;
-
-    public IotDeviceMqttMessageHandler(IotDeviceUpstreamApi deviceUpstreamApi, MqttClient mqttClient) {
-        this.deviceUpstreamApi = deviceUpstreamApi;
-        this.mqttClient = mqttClient;
-    }
-
-    /**
-     * 处理MQTT消息
-     *
-     * @param message MQTT发布消息
-     */
-    public void handle(MqttPublishMessage message) {
-        String topic = message.topicName();
-        String payload = message.payload().toString();
-        log.info("[messageHandler][接收到消息][topic: {}][payload: {}]", topic, payload);
-
-        try {
-            if (StrUtil.isEmpty(payload)) {
-                log.warn("[messageHandler][消息内容为空][topic: {}]", topic);
-                return;
-            }
-            handleMessage(topic, payload);
-        } catch (Exception e) {
-            log.error("[messageHandler][处理消息失败][topic: {}][payload: {}]", topic, payload, e);
-        }
-    }
-
-    /**
-     * 根据主题类型处理消息
-     *
-     * @param topic   主题
-     * @param payload 消息内容
-     */
-    private void handleMessage(String topic, String payload) {
-        // 校验前缀
-        if (!topic.startsWith(IotDeviceTopicEnum.SYS_TOPIC_PREFIX.getTopic())) {
-            log.warn("[handleMessage][未知的消息类型][topic: {}]", topic);
-            return;
-        }
-
-        // 处理设备属性上报消息
-        if (topic.endsWith(IotDeviceTopicEnum.PROPERTY_POST_TOPIC.getTopic())) {
-            log.info("[handleMessage][接收到设备属性上报][topic: {}]", topic);
-            handlePropertyPost(topic, payload);
-            return;
-        }
-
-        // 处理设备事件上报消息
-        if (topic.contains(IotDeviceTopicEnum.EVENT_POST_TOPIC_PREFIX.getTopic()) &&
-                topic.endsWith(IotDeviceTopicEnum.EVENT_POST_TOPIC_SUFFIX.getTopic())) {
-            log.info("[handleMessage][接收到设备事件上报][topic: {}]", topic);
-            handleEventPost(topic, payload);
-            return;
-        }
-
-        // 未知消息类型
-        log.warn("[handleMessage][未知的消息类型][topic: {}]", topic);
-    }
-
-    /**
-     * 处理设备属性上报消息
-     *
-     * @param topic   主题
-     * @param payload 消息内容
-     */
-    private void handlePropertyPost(String topic, String payload) {
-        try {
-            // 解析消息内容
-            JSONObject jsonObject = JSONUtil.parseObj(payload);
-            String[] topicParts = parseTopic(topic);
-            if (topicParts == null) {
-                return;
-            }
-
-            // 构建设备属性上报请求对象
-            IotDevicePropertyReportReqDTO reportReqDTO = buildPropertyReportDTO(jsonObject, topicParts);
-
-            // 调用上游 API 处理设备上报数据
-            deviceUpstreamApi.reportDeviceProperty(reportReqDTO);
-            log.info("[handlePropertyPost][处理设备属性上报成功][topic: {}]", topic);
-
-            // 发送响应消息
-            sendResponse(topic, jsonObject, PROPERTY_METHOD, null);
-        } catch (Exception e) {
-            log.error("[handlePropertyPost][处理设备属性上报失败][topic: {}][payload: {}]", topic, payload, e);
-        }
-    }
-
-    /**
-     * 处理设备事件上报消息
-     *
-     * @param topic   主题
-     * @param payload 消息内容
-     */
-    private void handleEventPost(String topic, String payload) {
-        try {
-            // 解析消息内容
-            JSONObject jsonObject = JSONUtil.parseObj(payload);
-            String[] topicParts = parseTopic(topic);
-            if (topicParts == null) {
-                return;
-            }
-
-            // 构建设备事件上报请求对象
-            IotDeviceEventReportReqDTO reportReqDTO = buildEventReportDTO(jsonObject, topicParts);
-
-            // 调用上游 API 处理设备上报数据
-            deviceUpstreamApi.reportDeviceEvent(reportReqDTO);
-            log.info("[handleEventPost][处理设备事件上报成功][topic: {}]", topic);
-
-            // 从 topic 中获取事件标识符
-            String eventIdentifier = getEventIdentifier(topicParts, topic);
-            if (eventIdentifier == null) {
-                return;
-            }
-
-            // 发送响应消息
-            String method = EVENT_METHOD_PREFIX + eventIdentifier + EVENT_METHOD_SUFFIX;
-            sendResponse(topic, jsonObject, method, null);
-        } catch (Exception e) {
-            log.error("[handleEventPost][处理设备事件上报失败][topic: {}][payload: {}]", topic, payload, e);
-        }
-    }
-
-    /**
-     * 解析主题,获取主题各部分
-     *
-     * @param topic 主题
-     * @return 主题各部分数组,如果解析失败返回null
-     */
-    private String[] parseTopic(String topic) {
-        String[] topicParts = topic.split("/");
-        if (topicParts.length < 7) {
-            log.warn("[parseTopic][主题格式不正确][topic: {}]", topic);
-            return null;
-        }
-        return topicParts;
-    }
-
-    /**
-     * 从主题部分中获取事件标识符
-     *
-     * @param topicParts 主题各部分
-     * @param topic      原始主题,用于日志
-     * @return 事件标识符,如果获取失败返回null
-     */
-    private String getEventIdentifier(String[] topicParts, String topic) {
-        try {
-            return topicParts[6];
-        } catch (ArrayIndexOutOfBoundsException e) {
-            log.warn("[getEventIdentifier][无法从主题中获取事件标识符][topic: {}][topicParts: {}]",
-                    topic, Arrays.toString(topicParts));
-            return null;
-        }
-    }
-
-    /**
-     * 发送响应消息
-     *
-     * @param topic      原始主题
-     * @param jsonObject 原始消息JSON对象
-     * @param method     响应方法
-     * @param customData 自定义数据,可为 null
-     */
-    private void sendResponse(String topic, JSONObject jsonObject, String method, Object customData) {
-        String replyTopic = IotDeviceTopicEnum.getReplyTopic(topic);
-
-        // 响应结果
-        IotStandardResponse response = IotStandardResponse.success(
-                jsonObject.getStr("id"), method, customData);
-        try {
-            mqttClient.publish(replyTopic, 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, e);
-        }
-    }
-
-    /**
-     * 构建设备属性上报请求对象
-     *
-     * @param jsonObject 消息内容
-     * @param topicParts 主题部分
-     * @return 设备属性上报请求对象
-     */
-    private IotDevicePropertyReportReqDTO buildPropertyReportDTO(JSONObject jsonObject, String[] topicParts) {
-        // TODO @haohao:IotDevicePropertyReportReqDTO 可以考虑链式哈。其它也是,尽量让同类参数在一行;这样,阅读起来更聚焦;
-        IotDevicePropertyReportReqDTO reportReqDTO = new IotDevicePropertyReportReqDTO();
-        reportReqDTO.setRequestId(jsonObject.getStr("id"));
-        reportReqDTO.setProcessId(IotNetComponentCommonUtils.getProcessId());
-        reportReqDTO.setReportTime(LocalDateTime.now());
-        reportReqDTO.setProductKey(topicParts[2]);
-        reportReqDTO.setDeviceName(topicParts[3]);
-
-        // 只使用标准 JSON格式处理属性数据
-        JSONObject params = jsonObject.getJSONObject("params");
-        if (params == null) {
-            log.warn("[buildPropertyReportDTO][消息格式不正确,缺少params字段][jsonObject: {}]", jsonObject);
-            params = new JSONObject();
-        }
-
-        // 将标准格式的params转换为平台需要的properties格式
-        Map<String, Object> properties = new HashMap<>();
-        for (Map.Entry<String, Object> 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;
-    }
-
-    /**
-     * 构建设备事件上报请求对象
-     *
-     * @param jsonObject 消息内容
-     * @param topicParts 主题部分
-     * @return 设备事件上报请求对象
-     */
-    private IotDeviceEventReportReqDTO buildEventReportDTO(JSONObject jsonObject, String[] topicParts) {
-        IotDeviceEventReportReqDTO reportReqDTO = new IotDeviceEventReportReqDTO();
-        reportReqDTO.setRequestId(jsonObject.getStr("id"));
-        reportReqDTO.setProcessId(IotNetComponentCommonUtils.getProcessId());
-        reportReqDTO.setReportTime(LocalDateTime.now());
-        reportReqDTO.setProductKey(topicParts[2]);
-        reportReqDTO.setDeviceName(topicParts[3]);
-        reportReqDTO.setIdentifier(topicParts[6]);
-
-        // 只使用标准JSON格式处理事件参数
-        JSONObject params = jsonObject.getJSONObject("params");
-        if (params == null) {
-            log.warn("[buildEventReportDTO][消息格式不正确,缺少params字段][jsonObject: {}]", jsonObject);
-            params = new JSONObject();
-        }
-        reportReqDTO.setParams(params);
-
-        return reportReqDTO;
-    }
-
-}

+ 0 - 152
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/router/IotDeviceWebhookVertxHandler.java

@@ -1,152 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.emqx.upstream.router;
-
-import cn.hutool.core.util.StrUtil;
-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.IotDeviceStateUpdateReqDTO;
-import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
-import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils;
-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.Collections;
-
-/**
- * IoT EMQX Webhook 事件处理的 Vert.x Handler
- * <p>
- * 参考:<a href="https://docs.emqx.com/zh/emqx/latest/data-integration/webhook.html">EMQX Webhook</a>
- * <p>
- * 注意:该处理器需要返回特定格式:{"result": "success"} 或 {"result": "error"},
- * 以符合 EMQX Webhook 插件的要求,因此不使用 IotStandardResponse 实体类。
- *
- * @author haohao
- */
-@RequiredArgsConstructor
-@Slf4j
-public class IotDeviceWebhookVertxHandler implements Handler<RoutingContext> {
-
-    public static final String PATH = "/mqtt/webhook";
-
-    private final IotDeviceUpstreamApi deviceUpstreamApi;
-
-    @Override
-    public void handle(RoutingContext routingContext) {
-        try {
-            // 解析请求体
-            JsonObject json = routingContext.body().asJsonObject();
-            String event = json.getString("event");
-            String clientId = json.getString("clientid");
-            String username = json.getString("username");
-
-            // 处理不同的事件类型
-            switch (event) {
-                case "client.connected":
-                    handleClientConnected(clientId, username);
-                    break;
-                case "client.disconnected":
-                    handleClientDisconnected(clientId, username);
-                    break;
-                default:
-                    log.info("[handle][未处理的 Webhook 事件] event={}, clientId={}, username={}", event, clientId, username);
-                    break;
-            }
-
-            // 返回成功响应
-            // 注意:这里必须返回 {"result": "success"} 格式,以符合 EMQX Webhook 插件的要求
-            IotNetComponentCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "success"));
-        } catch (Exception e) {
-            log.error("[handle][处理 Webhook 事件异常]", e);
-            // 注意:这里必须返回 {"result": "error"} 格式,以符合 EMQX Webhook 插件的要求
-            IotNetComponentCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "error"));
-        }
-    }
-
-    /**
-     * 处理客户端连接事件
-     *
-     * @param clientId 客户端ID
-     * @param username 用户名
-     */
-    private void handleClientConnected(String clientId, String username) {
-        // 解析产品标识和设备名称
-        if (StrUtil.isEmpty(username) || "undefined".equals(username)) {
-            log.warn("[handleClientConnected][客户端连接事件,但用户名为空] clientId={}", clientId);
-            return;
-        }
-        String[] parts = parseUsername(username);
-        if (parts == null) {
-            return;
-        }
-
-        // 更新设备状态为在线
-        IotDeviceStateUpdateReqDTO updateReqDTO = new IotDeviceStateUpdateReqDTO();
-        updateReqDTO.setProductKey(parts[1]);
-        updateReqDTO.setDeviceName(parts[0]);
-        updateReqDTO.setState(IotDeviceStateEnum.ONLINE.getState());
-        updateReqDTO.setProcessId(IotNetComponentCommonUtils.getProcessId());
-        updateReqDTO.setReportTime(LocalDateTime.now());
-        CommonResult<Boolean> result = deviceUpstreamApi.updateDeviceState(updateReqDTO);
-        if (result.getCode() != 0 || !result.getData()) {
-            log.error("[handleClientConnected][更新设备状态为在线失败] clientId={}, username={}, code={}, msg={}",
-                    clientId, username, result.getCode(), result.getMsg());
-        } else {
-            log.info("[handleClientConnected][更新设备状态为在线成功] clientId={}, username={}", clientId, username);
-        }
-    }
-
-    /**
-     * 处理客户端断开连接事件
-     *
-     * @param clientId 客户端ID
-     * @param username 用户名
-     */
-    private void handleClientDisconnected(String clientId, String username) {
-        // 解析产品标识和设备名称
-        if (StrUtil.isEmpty(username) || "undefined".equals(username)) {
-            log.warn("[handleClientDisconnected][客户端断开连接事件,但用户名为空] clientId={}", clientId);
-            return;
-        }
-        String[] parts = parseUsername(username);
-        if (parts == null) {
-            return;
-        }
-
-        // 更新设备状态为离线
-        IotDeviceStateUpdateReqDTO offlineReqDTO = new IotDeviceStateUpdateReqDTO();
-        offlineReqDTO.setProductKey(parts[1]);
-        offlineReqDTO.setDeviceName(parts[0]);
-        offlineReqDTO.setState(IotDeviceStateEnum.OFFLINE.getState());
-        offlineReqDTO.setProcessId(IotNetComponentCommonUtils.getProcessId());
-        offlineReqDTO.setReportTime(LocalDateTime.now());
-        CommonResult<Boolean> offlineResult = deviceUpstreamApi.updateDeviceState(offlineReqDTO);
-        if (offlineResult.getCode() != 0 || !offlineResult.getData()) {
-            log.error("[handleClientDisconnected][更新设备状态为离线失败] clientId={}, username={}, code={}, msg={}",
-                    clientId, username, offlineResult.getCode(), offlineResult.getMsg());
-        } else {
-            log.info("[handleClientDisconnected][更新设备状态为离线成功] clientId={}, username={}", clientId, username);
-        }
-    }
-
-    /**
-     * 解析用户名,格式为 deviceName&productKey
-     *
-     * @param username 用户名
-     * @return 解析结果,[0] 为 deviceName,[1] 为 productKey,解析失败返回 null
-     */
-    private String[] parseUsername(String username) {
-        if (StrUtil.isEmpty(username)) {
-            return null;
-        }
-        String[] parts = username.split("&");
-        if (parts.length != 2) {
-            log.warn("[parseUsername][用户名格式({})不正确,无法解析产品标识和设备名称]", username);
-            return null;
-        }
-        return parts;
-    }
-
-}

+ 0 - 1
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -1 +0,0 @@
-cn.iocoder.yudao.module.iot.net.component.emqx.config.IotNetComponentEmqxAutoConfiguration

+ 0 - 18
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/resources/application.yml

@@ -1,18 +0,0 @@
-# EMQX组件默认配置
-yudao:
-  iot:
-    component:
-      # 核心组件配置
-      core:
-        plugin-key: emqx # 插件的唯一标识
-      # EMQX组件配置
-#      emqx:
-#        enabled: true        # 启用EMQX组件
-#        mqtt-host: 127.0.0.1 # MQTT服务器主机地址
-#        mqtt-port: 1883      # MQTT服务器端口
-#        mqtt-username: yudao # MQTT服务器用户名
-#        mqtt-password: 123456 # MQTT服务器密码
-#        mqtt-ssl: false      # 是否启用SSL
-#        mqtt-topics:         # 订阅的主题列表
-#          - "/sys/#"
-#        auth-port: 8101      # 认证端口

+ 0 - 37
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/pom.xml

@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>cn.iocoder.boot</groupId>
-        <artifactId>yudao-module-iot-net-components</artifactId>
-        <version>${revision}</version>
-    </parent>
-
-    <artifactId>yudao-module-iot-net-component-server</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>
-        IoT 网络组件的独立运行服务,用于聚合和启动多个网络组件实例。
-    </description>
-
-    <dependencies>
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-        </dependency>
-
-        <!-- Net Component EMQX -->
-        <dependency>
-            <groupId>cn.iocoder.boot</groupId>
-            <artifactId>yudao-module-iot-net-component-emqx</artifactId>
-            <version>${revision}</version>
-        </dependency>
-
-
-
-    </dependencies>
-
-</project>

+ 0 - 52
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/config/IotNetComponentServerConfiguration.java

@@ -1,52 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.server.config;
-
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.net.component.server.upstream.IotComponentUpstreamClient;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.web.client.RestTemplateBuilder;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Primary;
-import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.web.client.RestTemplate;
-
-/**
- * IoT 网络组件服务器配置类
- *
- * @author haohao
- */
-@Configuration
-@EnableConfigurationProperties(IotNetComponentServerProperties.class)
-@EnableScheduling
-public class IotNetComponentServerConfiguration {
-
-    /**
-     * 配置 RestTemplate
-     *
-     * @param properties 配置
-     * @return RestTemplate
-     */
-    @Bean
-    // TODO @haohao:貌似要独立一个 restTemplate 的名字?不然容易冲突;
-    public RestTemplate restTemplate(IotNetComponentServerProperties properties) {
-        return new RestTemplateBuilder()
-                .connectTimeout(properties.getUpstreamConnectTimeout())
-                .readTimeout(properties.getUpstreamReadTimeout())
-                .build();
-    }
-
-    /**
-     * 配置设备上行客户端
-     *
-     * @param properties   配置
-     * @param restTemplate RestTemplate
-     * @return 上行客户端
-     */
-    @Bean
-    @Primary
-    public IotDeviceUpstreamApi deviceUpstreamApi(IotNetComponentServerProperties properties,
-            RestTemplate restTemplate) {
-        return new IotComponentUpstreamClient(properties, restTemplate);
-    }
-
-}

+ 0 - 34
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/config/IotNetComponentServerProperties.java

@@ -1,34 +0,0 @@
-package cn.iocoder.yudao.module.iot.net.component.server.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-
-import java.time.Duration;
-
-/**
- * IoT 网络组件服务配置属性
- *
- * @author haohao
- */
-@ConfigurationProperties(prefix = "yudao.iot.component.server")
-@Validated
-@Data
-public class IotNetComponentServerProperties {
-
-    /**
-     * 上行 URL,用于向主应用程序上报数据
-     */
-    private String upstreamUrl = "http://127.0.0.1:48080";
-
-    /**
-     * 上行连接超时时间
-     */
-    private Duration upstreamConnectTimeout = Duration.ofSeconds(30);
-
-    /**
-     * 上行读取超时时间
-     */
-    private Duration upstreamReadTimeout = Duration.ofSeconds(30);
-
-}

+ 0 - 254
yudao-module-iot/yudao-module-iot-protocol/README.md

@@ -1,254 +0,0 @@
-# IoT 协议模块 (yudao-module-iot-protocol)
-
-## 概述
-
-本模块是物联网协议处理的核心组件,提供统一的协议解析、转换和消息处理功能。作为 `yudao-module-iot-biz` 和
-`yudao-module-iot-gateway-server` 等模块的共享包,实现了协议层面的抽象和统一。
-
-## 主要功能
-
-### 1. 协议消息模型
-
-- **IotMqttMessage**: 基于 MQTT 协议规范的标准消息模型(默认实现)
-- **IotStandardResponse**: 统一的响应格式,支持 MQTT 和 HTTP 协议
-
-### 2. 主题管理
-
-- **IotTopicConstants**: 主题常量定义
-- **IotTopicUtils**: MQTT 主题构建和解析工具
-- **IotHttpTopicUtils**: HTTP 主题构建和解析工具
-- **IotTopicParser**: 高级主题解析器,支持提取设备信息、消息类型等
-
-### 3. 协议转换
-
-- **IotMessageParser**: 消息解析器接口
-- **IotMqttMessageParser**: MQTT 协议解析器实现(默认)
-- **IotHttpMessageParser**: HTTP 协议解析器实现
-- **IotProtocolConverter**: 协议转换器接口
-- **DefaultIotProtocolConverter**: 默认协议转换器实现
-
-### 4. 枚举定义
-
-- **IotProtocolTypeEnum**: 协议类型枚举
-- **IotMessageTypeEnum**: 消息类型枚举
-- **IotMessageDirectionEnum**: 消息方向枚举
-
-## 使用示例
-
-### 1. 构建主题
-
-#### MQTT 主题
-
-```java
-// 构建设备属性设置主题
-String topic = IotTopicUtils.buildPropertySetTopic("productKey", "deviceName");
-// 结果: /sys/productKey/deviceName/thing/service/property/set
-
-// 构建事件上报主题
-String eventTopic = IotTopicUtils.buildEventPostTopic("productKey", "deviceName", "temperature");
-// 结果: /sys/productKey/deviceName/thing/event/temperature/post
-
-// 获取响应主题
-String replyTopic = IotTopicUtils.getReplyTopic(topic);
-// 结果: /sys/productKey/deviceName/thing/service/property/set_reply
-```
-
-#### HTTP 主题
-
-```java
-// 构建属性设置路径
-String propSetPath = IotHttpTopicUtils.buildPropertySetPath("productKey", "deviceName");
-// 结果: /topic/sys/productKey/deviceName/thing/service/property/set
-
-// 构建属性获取路径
-String propGetPath = IotHttpTopicUtils.buildPropertyGetPath("productKey", "deviceName");
-// 结果: /topic/sys/productKey/deviceName/thing/service/property/get
-
-// 构建事件上报路径
-String eventPath = IotHttpTopicUtils.buildEventPostPath("productKey", "deviceName", "alarm");
-// 结果: /topic/sys/productKey/deviceName/thing/event/alarm/post
-
-// 构建自定义主题路径
-String customPath = IotHttpTopicUtils.buildCustomTopicPath("productKey", "deviceName", "user/get");
-// 结果: /topic/productKey/deviceName/user/get
-```
-
-### 2. 解析主题
-
-```java
-// 解析 MQTT 主题信息
-IotTopicParser.TopicInfo info = IotTopicParser.parse("/sys/pk/dn/thing/service/property/set");
-System.out.
-
-println("产品Key: "+info.getProductKey()); // pk
-        System.out.
-
-println("设备名称: "+info.getDeviceName()); // dn
-        System.out.
-
-println("消息类型: "+info.getMessageType()); // PROPERTY_SET
-        System.out.
-
-println("消息方向: "+info.getDirection()); // DOWNSTREAM
-
-// 解析 HTTP 主题信息
-String httpPath = "/topic/sys/pk/dn/thing/service/property/set";
-String actualTopic = IotHttpTopicUtils.extractActualTopic(httpPath);  // /sys/pk/dn/thing/service/property/set
-String productKey = IotHttpTopicUtils.parseProductKeyFromTopic(actualTopic);  // pk  
-String deviceName = IotHttpTopicUtils.parseDeviceNameFromTopic(actualTopic);  // dn
-```
-
-### 3. 创建 MQTT 消息
-
-```java
-// 创建属性设置消息
-Map<String, Object> properties = new HashMap<>();
-properties.
-
-put("temperature",25.5);
-
-IotMqttMessage message = IotMqttMessage.createPropertySetMessage("123456", properties);
-
-// 转换为 JSON 字符串
-String json = message.toJsonString();
-```
-
-### 4. HTTP 协议消息处理
-
-#### HTTP 消息格式
-
-```json
-{
-  "deviceKey": "productKey/deviceName",
-  "messageId": "123456",
-  "action": "property.set",
-  "version": "1.0",
-  "data": {
-    "temperature": 25.5,
-    "humidity": 60.0
-  }
-}
-```
-
-#### 使用 HTTP 协议解析器
-
-```java
-// 创建 HTTP 协议解析器
-IotHttpMessageParser httpParser = new IotHttpMessageParser();
-
-// 解析 HTTP 消息
-String topic = "/topic/sys/productKey/deviceName/thing/service/property/set";
-byte[] payload = httpMessage.getBytes(StandardCharsets.UTF_8);
-IotMqttMessage message = httpParser.parse(topic, payload);
-
-// 格式化 HTTP 响应
-IotStandardResponse response = IotStandardResponse.success("123456", "property.set", data);
-byte[] responseBytes = httpParser.formatResponse(response);
-```
-
-### 5. 使用协议转换器
-
-```java
-
-@Autowired
-private IotProtocolConverter protocolConverter;
-
-// 转换 MQTT 消息(推荐使用)
-IotMqttMessage mqttMessage = protocolConverter.convertToStandardMessage(mqttTopic, mqttPayload, "mqtt");
-
-// 转换 HTTP 消息
-IotMqttMessage httpMessage = protocolConverter.convertToStandardMessage(httpTopic, httpPayload, "http");
-
-// 创建响应
-IotStandardResponse response = IotStandardResponse.success("123456", "property.set", data);
-byte[] responseBytes = protocolConverter.convertFromStandardResponse(response, "mqtt");
-```
-
-### 6. 自定义协议解析器
-
-```java
-
-@Component
-public class CustomMessageParser implements IotMessageParser {
-
-    @Override
-    public IotMqttMessage parse(String topic, byte[] payload) {
-        // 实现自定义协议解析逻辑
-        return null;
-    }
-
-    @Override
-    public byte[] formatResponse(IotStandardResponse response) {
-        // 实现自定义响应格式化逻辑
-        return new byte[0];
-    }
-
-    @Override
-    public boolean canHandle(String topic) {
-        // 判断是否能处理该主题
-        return topic.startsWith("/custom/");
-    }
-}
-
-// 注册到协议转换器
-@Autowired
-private DefaultIotProtocolConverter converter;
-
-@PostConstruct
-public void init() {
-    converter.registerParser("custom", new CustomMessageParser());
-}
-```
-
-## 支持的协议类型
-
-- **MQTT**: 标准 MQTT 协议,支持设备属性、事件、服务调用(默认协议)
-- **HTTP**: HTTP 协议,支持设备通过 HTTP API 进行通信
-- **MQTT_RAW**: MQTT 原始协议
-- **TCP**: TCP 协议
-- **UDP**: UDP 协议
-- **CUSTOM**: 自定义协议
-
-## 协议对比
-
-| 协议类型     | 传输方式 | 消息格式 | 主题格式                                                                                                                       | 适用场景          |
-|----------|------|------|----------------------------------------------------------------------------------------------------------------------------|---------------|
-| MQTT     | MQTT | JSON | `/sys/{productKey}/{deviceName}/...`<br/>`/mqtt/{productKey}/{deviceName}/...`<br/>`/device/{productKey}/{deviceName}/...` | 实时性要求高的设备(推荐) |
-| HTTP     | HTTP | JSON | `/topic/sys/{productKey}/{deviceName}/...`<br/>`/topic/{productKey}/{deviceName}/...`                                      | 间歇性通信的设备      |
-| MQTT_RAW | MQTT | 原始   | 自定义格式                                                                                                                      | 特殊协议设备        |
-
-## 模块依赖
-
-本模块是一个基础模块,依赖项最小化:
-
-- `yudao-common`: 基础工具类
-- `hutool-all`: 工具库
-- `lombok`: 简化代码
-- `spring-boot-starter`: Spring Boot 基础支持
-
-## 扩展点
-
-### 1. 自定义消息解析器
-
-实现 `IotMessageParser` 接口,支持新的协议格式。
-
-### 2. 自定义协议转换器
-
-实现 `IotProtocolConverter` 接口,提供更复杂的转换逻辑。
-
-### 3. 自定义主题格式
-
-扩展 `IotTopicParser` 的 `parseCustomTopic` 方法,支持自定义主题格式。
-
-## 注意事项
-
-1. 本模块设计为无状态的工具模块,避免引入有状态的组件
-2. 所有的工具类都采用静态方法,便于直接调用
-3. 异常处理采用返回 null 的方式,调用方需要做好空值检查
-4. 日志级别建议设置为 INFO 或 WARN,避免过多的 DEBUG 日志
-5. HTTP 协议解析器使用设备标识 `deviceKey`(格式:`productKey/deviceName`)来标识设备
-
-## 版本更新
-
-- v1.0.0: 基础功能实现,支持 MQTT 协议和 HTTP 协议支持
-- 后续版本将支持更多协议类型和高级功能 

+ 0 - 71
yudao-module-iot/yudao-module-iot-protocol/pom.xml

@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xmlns="http://maven.apache.org/POM/4.0.0"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>yudao-module-iot</artifactId>
-        <groupId>cn.iocoder.boot</groupId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>yudao-module-iot-protocol</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>
-        物联网协议模块,提供 topic 解析、协议转换等功能
-        作为 iot-biz 和 iot-gateway 的共享包
-    </description>
-
-    <dependencies>
-        <!-- 项目内部依赖 -->
-        <dependency>
-            <groupId>cn.iocoder.boot</groupId>
-            <artifactId>yudao-common</artifactId>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>cn.iocoder.boot</groupId>
-            <artifactId>yudao-spring-boot-starter-web</artifactId>
-            <scope>provided</scope>            <!-- 设为 provided,只有 biz 需要使用 -->
-        </dependency>
-
-        <!-- 工具类相关 -->
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-all</artifactId>
-        </dependency>
-
-        <!-- IoT 相关依赖 -->
-        <dependency>
-            <groupId>io.vertx</groupId>
-            <artifactId>vertx-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.vertx</groupId>
-            <artifactId>vertx-web</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <!-- 测试相关 -->
-        <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>

+ 0 - 74
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/config/IotProtocolAutoConfiguration.java

@@ -1,74 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.config;
-
-import cn.iocoder.yudao.module.iot.protocol.convert.IotProtocolConverter;
-import cn.iocoder.yudao.module.iot.protocol.convert.impl.DefaultIotProtocolConverter;
-import cn.iocoder.yudao.module.iot.protocol.enums.IotProtocolTypeEnum;
-import cn.iocoder.yudao.module.iot.protocol.message.IotMessageParser;
-import cn.iocoder.yudao.module.iot.protocol.message.impl.IotHttpMessageParser;
-import cn.iocoder.yudao.module.iot.protocol.message.impl.IotMqttMessageParser;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * IoT 协议模块自动配置类
- *
- * @author haohao
- */
-@Configuration(proxyBeanMethods = false)
-public class IotProtocolAutoConfiguration {
-
-    /**
-     * Bean 名称常量
-     */
-    public static final String IOT_MQTT_MESSAGE_PARSER_BEAN_NAME = "iotMqttMessageParser";
-    public static final String IOT_HTTP_MESSAGE_PARSER_BEAN_NAME = "iotHttpMessageParser";
-
-    /**
-     * 注册 MQTT 协议消息解析器
-     *
-     * @return MQTT 协议消息解析器
-     */
-    @Bean
-    @ConditionalOnMissingBean(name = IOT_MQTT_MESSAGE_PARSER_BEAN_NAME)
-    public IotMessageParser iotMqttMessageParser() {
-        return new IotMqttMessageParser();
-    }
-
-
-    /**
-     * 注册 HTTP 协议消息解析器
-     *
-     * @return HTTP 协议消息解析器
-     */
-    @Bean
-    @ConditionalOnMissingBean(name = IOT_HTTP_MESSAGE_PARSER_BEAN_NAME)
-    public IotMessageParser iotHttpMessageParser() {
-        return new IotHttpMessageParser();
-    }
-
-    /**
-     * 注册默认协议转换器
-     * <p>
-     * 如果用户没有自定义协议转换器,则使用默认实现
-     * 默认会注册 MQTT 和 HTTP 协议解析器
-     *
-     * @param iotMqttMessageParser MQTT 协议解析器
-     * @param iotHttpMessageParser HTTP 协议解析器
-     * @return 默认协议转换器
-     */
-    @Bean
-    @ConditionalOnMissingBean
-    public IotProtocolConverter iotProtocolConverter(IotMessageParser iotMqttMessageParser,
-                                                     IotMessageParser iotHttpMessageParser) {
-        DefaultIotProtocolConverter converter = new DefaultIotProtocolConverter();
-
-        // 注册 MQTT 协议解析器(默认实现)
-        converter.registerParser(IotProtocolTypeEnum.MQTT.getCode(), iotMqttMessageParser);
-
-        // 注册 HTTP 协议解析器
-        converter.registerParser(IotProtocolTypeEnum.HTTP.getCode(), iotHttpMessageParser);
-
-        return converter;
-    }
-}

+ 0 - 166
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/constants/IotHttpConstants.java

@@ -1,166 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.constants;
-
-/**
- * IoT HTTP 协议常量类
- * <p>
- * 用于统一管理 HTTP 协议中的常量,包括路径、字段名、默认值等
- *
- * @author haohao
- */
-public class IotHttpConstants {
-
-    /**
-     * 路径常量
-     */
-    public static class Path {
-        /**
-         * 认证路径
-         */
-        public static final String AUTH = "/auth";
-
-        /**
-         * 主题路径前缀
-         */
-        public static final String TOPIC_PREFIX = "/topic";
-    }
-
-    /**
-     * 认证字段常量
-     */
-    public static class AuthField {
-        /**
-         * 产品Key
-         */
-        public static final String PRODUCT_KEY = "productKey";
-
-        /**
-         * 设备名称
-         */
-        public static final String DEVICE_NAME = "deviceName";
-
-        /**
-         * 客户端ID
-         */
-        public static final String CLIENT_ID = "clientId";
-
-        /**
-         * 时间戳
-         */
-        public static final String TIMESTAMP = "timestamp";
-
-        /**
-         * 签名
-         */
-        public static final String SIGN = "sign";
-
-        /**
-         * 签名方法
-         */
-        public static final String SIGN_METHOD = "signmethod";
-
-        /**
-         * 版本
-         */
-        public static final String VERSION = "version";
-    }
-
-    /**
-     * 消息字段常量
-     */
-    public static class MessageField {
-        /**
-         * 消息ID
-         */
-        public static final String ID = "id";
-
-        /**
-         * 方法名
-         */
-        public static final String METHOD = "method";
-
-        /**
-         * 版本
-         */
-        public static final String VERSION = "version";
-
-        /**
-         * 参数
-         */
-        public static final String PARAMS = "params";
-
-        /**
-         * 数据
-         */
-        public static final String DATA = "data";
-    }
-
-    /**
-     * 响应字段常量
-     */
-    public static class ResponseField {
-        /**
-         * 状态码
-         */
-        public static final String CODE = "code";
-
-        /**
-         * 消息
-         */
-        public static final String MESSAGE = "message";
-
-        /**
-         * 信息
-         */
-        public static final String INFO = "info";
-
-        /**
-         * 令牌
-         */
-        public static final String TOKEN = "token";
-
-        /**
-         * 消息ID
-         */
-        public static final String MESSAGE_ID = "messageId";
-    }
-
-    /**
-     * 默认值常量
-     */
-    public static class DefaultValue {
-        /**
-         * 默认签名方法
-         */
-        public static final String SIGN_METHOD = "hmacmd5";
-
-        /**
-         * 默认版本
-         */
-        public static final String VERSION = "default";
-
-        /**
-         * 默认消息版本
-         */
-        public static final String MESSAGE_VERSION = "1.0";
-
-        /**
-         * 未知方法名
-         */
-        public static final String UNKNOWN_METHOD = "unknown";
-    }
-
-    /**
-     * 方法名常量
-     */
-    public static class Method {
-        /**
-         * 设备认证
-         */
-        public static final String DEVICE_AUTH = "device.auth";
-
-        /**
-         * 自定义消息
-         */
-        public static final String CUSTOM_MESSAGE = "custom.message";
-    }
-}

+ 0 - 91
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/constants/IotLogConstants.java

@@ -1,91 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.constants;
-
-/**
- * IoT 协议日志消息常量类
- * <p>
- * 用于统一管理协议模块中的日志消息常量
- *
- * @author haohao
- */
-public class IotLogConstants {
-
-    /**
-     * HTTP 协议日志消息
-     */
-    public static class Http {
-        /**
-         * 收到空消息内容
-         */
-        public static final String RECEIVED_EMPTY_MESSAGE = "[HTTP] 收到空消息内容, topic={}";
-
-        /**
-         * 不支持的路径格式
-         */
-        public static final String UNSUPPORTED_PATH_FORMAT = "[HTTP] 不支持的路径格式, topic={}";
-
-        /**
-         * 解析消息失败
-         */
-        public static final String PARSE_MESSAGE_FAILED = "[HTTP] 解析消息失败, topic={}";
-
-        /**
-         * 认证消息非JSON格式
-         */
-        public static final String AUTH_MESSAGE_NOT_JSON = "[HTTP] 认证消息非JSON格式, message={}";
-
-        /**
-         * 认证消息缺少必需字段
-         */
-        public static final String AUTH_MESSAGE_MISSING_REQUIRED_FIELDS = "[HTTP] 认证消息缺少必需字段, message={}";
-
-        /**
-         * 格式化响应失败
-         */
-        public static final String FORMAT_RESPONSE_FAILED = "[HTTP] 格式化响应失败";
-    }
-
-    /**
-     * 协议转换器日志消息
-     */
-    public static class Converter {
-        /**
-         * 注册协议解析器
-         */
-        public static final String REGISTER_PARSER = "[协议转换器] 注册协议解析器: protocol={}, parser={}";
-
-        /**
-         * 移除协议解析器
-         */
-        public static final String REMOVE_PARSER = "[协议转换器] 移除协议解析器: protocol={}";
-
-        /**
-         * 不支持的协议类型
-         */
-        public static final String UNSUPPORTED_PROTOCOL = "[协议转换器] 不支持的协议类型: protocol={}";
-
-        /**
-         * 转换消息失败
-         */
-        public static final String CONVERT_MESSAGE_FAILED = "[协议转换器] 转换消息失败: protocol={}, topic={}";
-
-        /**
-         * 格式化响应失败
-         */
-        public static final String FORMAT_RESPONSE_FAILED = "[协议转换器] 格式化响应失败: protocol={}";
-
-        /**
-         * 自动选择协议
-         */
-        public static final String AUTO_SELECT_PROTOCOL = "[协议转换器] 自动选择协议: protocol={}, topic={}";
-
-        /**
-         * 协议解析失败,尝试下一个
-         */
-        public static final String PROTOCOL_PARSE_FAILED_TRY_NEXT = "[协议转换器] 协议解析失败,尝试下一个: protocol={}, topic={}";
-
-        /**
-         * 无法自动识别协议
-         */
-        public static final String CANNOT_AUTO_RECOGNIZE_PROTOCOL = "[协议转换器] 无法自动识别协议: topic={}";
-    }
-}

+ 0 - 157
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/constants/IotTopicConstants.java

@@ -1,157 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.constants;
-
-/**
- * IoT 设备主题常量类
- * <p>
- * 用于统一管理 MQTT 协议中的主题常量,基于 Alink 协议规范
- *
- * @author haohao
- */
-public class IotTopicConstants {
-
-    /**
-     * 系统主题前缀
-     */
-    public static final String SYS_TOPIC_PREFIX = "/sys/";
-
-    /**
-     * 服务调用主题前缀
-     */
-    public static final String SERVICE_TOPIC_PREFIX = "/thing/service/";
-
-    /**
-     * 设备属性设置主题
-     * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/set
-     * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/property/set_reply
-     */
-    public static final String PROPERTY_SET_TOPIC = "/thing/service/property/set";
-
-    /**
-     * 设备属性获取主题
-     * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/get
-     * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/property/get_reply
-     */
-    public static final String PROPERTY_GET_TOPIC = "/thing/service/property/get";
-
-    /**
-     * 设备配置设置主题
-     * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/config/set
-     * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/config/set_reply
-     */
-    public static final String CONFIG_SET_TOPIC = "/thing/service/config/set";
-
-    /**
-     * 设备OTA升级主题
-     * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade
-     * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade_reply
-     */
-    public static final String OTA_UPGRADE_TOPIC = "/thing/service/ota/upgrade";
-
-    /**
-     * 设备属性上报主题
-     * 请求Topic:/sys/${productKey}/${deviceName}/thing/event/property/post
-     * 响应Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply
-     */
-    public static final String PROPERTY_POST_TOPIC = "/thing/event/property/post";
-
-    /**
-     * 设备事件上报主题前缀
-     */
-    public static final String EVENT_POST_TOPIC_PREFIX = "/thing/event/";
-
-    /**
-     * 设备事件上报主题后缀
-     */
-    public static final String EVENT_POST_TOPIC_SUFFIX = "/post";
-
-    /**
-     * 响应主题后缀
-     */
-    public static final String REPLY_SUFFIX = "_reply";
-
-    /**
-     * 方法名前缀常量
-     */
-    public static class MethodPrefix {
-        /**
-         * 物模型服务前缀
-         */
-        public static final String THING_SERVICE = "thing.service.";
-
-        /**
-         * 物模型事件前缀
-         */
-        public static final String THING_EVENT = "thing.event.";
-    }
-
-    /**
-     * 完整方法名常量
-     */
-    public static class Method {
-        /**
-         * 属性设置方法
-         */
-        public static final String PROPERTY_SET = "thing.service.property.set";
-
-        /**
-         * 属性获取方法
-         */
-        public static final String PROPERTY_GET = "thing.service.property.get";
-
-        /**
-         * 属性上报方法
-         */
-        public static final String PROPERTY_POST = "thing.event.property.post";
-
-        /**
-         * 配置设置方法
-         */
-        public static final String CONFIG_SET = "thing.service.config.set";
-
-        /**
-         * OTA升级方法
-         */
-        public static final String OTA_UPGRADE = "thing.service.ota.upgrade";
-
-        /**
-         * 设备上线方法
-         */
-        public static final String DEVICE_ONLINE = "device.online";
-
-        /**
-         * 设备下线方法
-         */
-        public static final String DEVICE_OFFLINE = "device.offline";
-
-        /**
-         * 心跳方法
-         */
-        public static final String HEARTBEAT = "heartbeat";
-    }
-
-    /**
-     * 主题关键字常量
-     */
-    public static class Keyword {
-        /**
-         * 事件关键字
-         */
-        public static final String EVENT = "event";
-
-        /**
-         * 服务关键字
-         */
-        public static final String SERVICE = "service";
-
-        /**
-         * 属性关键字
-         */
-        public static final String PROPERTY = "property";
-
-        /**
-         * 上报关键字
-         */
-        public static final String POST = "post";
-    }
-
-}

+ 0 - 48
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/convert/IotProtocolConverter.java

@@ -1,48 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.convert;
-
-import cn.iocoder.yudao.module.iot.protocol.message.IotMqttMessage;
-import cn.iocoder.yudao.module.iot.protocol.message.IotStandardResponse;
-
-/**
- * IoT 协议转换器接口
- * <p>
- * 用于在不同协议之间进行转换
- *
- * @author haohao
- */
-public interface IotProtocolConverter {
-
-    /**
-     * 将字节数组转换为标准消息
-     *
-     * @param topic    主题
-     * @param payload  消息负载
-     * @param protocol 协议类型
-     * @return 标准消息对象,转换失败返回 null
-     */
-    IotMqttMessage convertToStandardMessage(String topic, byte[] payload, String protocol);
-
-    /**
-     * 将标准响应转换为字节数组
-     *
-     * @param response 标准响应
-     * @param protocol 协议类型
-     * @return 字节数组,转换失败返回空数组
-     */
-    byte[] convertFromStandardResponse(IotStandardResponse response, String protocol);
-
-    /**
-     * 检查是否支持指定协议
-     *
-     * @param protocol 协议类型
-     * @return 如果支持返回 true,否则返回 false
-     */
-    boolean supportsProtocol(String protocol);
-
-    /**
-     * 获取支持的协议类型列表
-     *
-     * @return 协议类型数组
-     */
-    String[] getSupportedProtocols();
-}

+ 0 - 132
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/convert/impl/DefaultIotProtocolConverter.java

@@ -1,132 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.convert.impl;
-
-import cn.iocoder.yudao.module.iot.protocol.constants.IotLogConstants;
-import cn.iocoder.yudao.module.iot.protocol.convert.IotProtocolConverter;
-import cn.iocoder.yudao.module.iot.protocol.enums.IotProtocolTypeEnum;
-import cn.iocoder.yudao.module.iot.protocol.message.IotMessageParser;
-import cn.iocoder.yudao.module.iot.protocol.message.IotMqttMessage;
-import cn.iocoder.yudao.module.iot.protocol.message.IotStandardResponse;
-import cn.iocoder.yudao.module.iot.protocol.message.impl.IotMqttMessageParser;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * 默认 IoT 协议转换器实现
- * <p>
- * 支持多种协议的转换,可以通过注册不同的消息解析器来扩展支持的协议
- *
- * @author haohao
- */
-@Slf4j
-public class DefaultIotProtocolConverter implements IotProtocolConverter {
-
-    /**
-     * 消息解析器映射
-     * Key: 协议类型,Value: 消息解析器
-     */
-    private final Map<String, IotMessageParser> parsers = new HashMap<>();
-
-    /**
-     * 构造函数,初始化默认支持的协议
-     */
-    public DefaultIotProtocolConverter() {
-        // 注册 MQTT 协议解析器作为默认实现
-        IotMqttMessageParser mqttParser = new IotMqttMessageParser();
-        registerParser(IotProtocolTypeEnum.MQTT.getCode(), mqttParser);
-    }
-
-    /**
-     * 注册消息解析器
-     *
-     * @param protocol 协议类型
-     * @param parser   消息解析器
-     */
-    public void registerParser(String protocol, IotMessageParser parser) {
-        parsers.put(protocol, parser);
-        log.info(IotLogConstants.Converter.REGISTER_PARSER, protocol, parser.getClass().getSimpleName());
-    }
-
-    /**
-     * 移除消息解析器
-     *
-     * @param protocol 协议类型
-     */
-    public void removeParser(String protocol) {
-        parsers.remove(protocol);
-        log.info(IotLogConstants.Converter.REMOVE_PARSER, protocol);
-    }
-
-    @Override
-    public IotMqttMessage convertToStandardMessage(String topic, byte[] payload, String protocol) {
-        IotMessageParser parser = parsers.get(protocol);
-        if (parser == null) {
-            log.warn(IotLogConstants.Converter.UNSUPPORTED_PROTOCOL, protocol);
-            return null;
-        }
-
-        try {
-            return parser.parse(topic, payload);
-        } catch (Exception e) {
-            log.error(IotLogConstants.Converter.CONVERT_MESSAGE_FAILED, protocol, topic, e);
-            return null;
-        }
-    }
-
-    @Override
-    public byte[] convertFromStandardResponse(IotStandardResponse response, String protocol) {
-        IotMessageParser parser = parsers.get(protocol);
-        if (parser == null) {
-            log.warn(IotLogConstants.Converter.UNSUPPORTED_PROTOCOL, protocol);
-            return new byte[0];
-        }
-
-        try {
-            return parser.formatResponse(response);
-        } catch (Exception e) {
-            log.error(IotLogConstants.Converter.FORMAT_RESPONSE_FAILED, protocol, e);
-            return new byte[0];
-        }
-    }
-
-    @Override
-    public boolean supportsProtocol(String protocol) {
-        return parsers.containsKey(protocol);
-    }
-
-    @Override
-    public String[] getSupportedProtocols() {
-        Set<String> protocols = parsers.keySet();
-        return protocols.toArray(new String[0]);
-    }
-
-    /**
-     * 根据主题自动选择合适的协议解析器
-     *
-     * @param topic   主题
-     * @param payload 消息负载
-     * @return 解析后的标准消息,如果无法解析返回 null
-     */
-    public IotMqttMessage autoConvert(String topic, byte[] payload) {
-        // 遍历所有解析器,找到能处理该主题的解析器
-        for (Map.Entry<String, IotMessageParser> entry : parsers.entrySet()) {
-            IotMessageParser parser = entry.getValue();
-            if (parser.canHandle(topic)) {
-                try {
-                    IotMqttMessage message = parser.parse(topic, payload);
-                    if (message != null) {
-                        log.debug(IotLogConstants.Converter.AUTO_SELECT_PROTOCOL, entry.getKey(), topic);
-                        return message;
-                    }
-                } catch (Exception e) {
-                    log.debug(IotLogConstants.Converter.PROTOCOL_PARSE_FAILED_TRY_NEXT, entry.getKey(), topic);
-                }
-            }
-        }
-
-        log.warn(IotLogConstants.Converter.CANNOT_AUTO_RECOGNIZE_PROTOCOL, topic);
-        return null;
-    }
-}

+ 0 - 49
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/enums/IotMessageDirectionEnum.java

@@ -1,49 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * IoT 消息方向枚举
- *
- * @author haohao
- */
-@Getter
-@AllArgsConstructor
-public enum IotMessageDirectionEnum {
-
-    /**
-     * 上行消息(设备到平台)
-     */
-    UPSTREAM("upstream", "上行"),
-
-    /**
-     * 下行消息(平台到设备)
-     */
-    DOWNSTREAM("downstream", "下行");
-
-    /**
-     * 方向编码
-     */
-    private final String code;
-
-    /**
-     * 方向名称
-     */
-    private final String name;
-
-    /**
-     * 根据编码获取消息方向
-     *
-     * @param code 方向编码
-     * @return 消息方向枚举,如果未找到返回 null
-     */
-    public static IotMessageDirectionEnum getByCode(String code) {
-        for (IotMessageDirectionEnum direction : values()) {
-            if (direction.getCode().equals(code)) {
-                return direction;
-            }
-        }
-        return null;
-    }
-}

+ 0 - 140
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/enums/IotMessageTypeEnum.java

@@ -1,140 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.enums;
-
-import cn.iocoder.yudao.module.iot.protocol.constants.IotTopicConstants;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * IoT 消息类型枚举
- *
- * @author haohao
- */
-@Getter
-@AllArgsConstructor
-public enum IotMessageTypeEnum {
-
-    /**
-     * 属性上报
-     */
-    PROPERTY_POST("property.post", "属性上报"),
-
-    /**
-     * 属性设置
-     */
-    PROPERTY_SET("property.set", "属性设置"),
-
-    /**
-     * 属性获取
-     */
-    PROPERTY_GET("property.get", "属性获取"),
-
-    /**
-     * 事件上报
-     */
-    EVENT_POST("event.post", "事件上报"),
-
-    /**
-     * 服务调用
-     */
-    SERVICE_INVOKE("service.invoke", "服务调用"),
-
-    /**
-     * 配置设置
-     */
-    CONFIG_SET("config.set", "配置设置"),
-
-    /**
-     * OTA 升级
-     */
-    OTA_UPGRADE("ota.upgrade", "OTA升级"),
-
-    /**
-     * 设备上线
-     */
-    DEVICE_ONLINE("device.online", "设备上线"),
-
-    /**
-     * 设备下线
-     */
-    DEVICE_OFFLINE("device.offline", "设备下线"),
-
-    /**
-     * 心跳
-     */
-    HEARTBEAT("heartbeat", "心跳");
-
-    /**
-     * 消息类型编码
-     */
-    private final String code;
-
-    /**
-     * 消息类型名称
-     */
-    private final String name;
-
-    /**
-     * 根据编码获取消息类型
-     *
-     * @param code 消息类型编码
-     * @return 消息类型枚举,如果未找到返回 null
-     */
-    public static IotMessageTypeEnum getByCode(String code) {
-        for (IotMessageTypeEnum type : values()) {
-            if (type.getCode().equals(code)) {
-                return type;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * 根据方法名获取消息类型
-     *
-     * @param method 方法名
-     * @return 消息类型枚举,如果未找到返回 null
-     */
-    public static IotMessageTypeEnum getByMethod(String method) {
-        if (method == null) {
-            return null;
-        }
-
-        // 处理 thing.service.xxx 格式
-        if (method.startsWith(IotTopicConstants.MethodPrefix.THING_SERVICE)) {
-            String servicePart = method.substring(IotTopicConstants.MethodPrefix.THING_SERVICE.length());
-            if ("property.set".equals(servicePart)) {
-                return PROPERTY_SET;
-            } else if ("property.get".equals(servicePart)) {
-                return PROPERTY_GET;
-            } else if ("config.set".equals(servicePart)) {
-                return CONFIG_SET;
-            } else if ("ota.upgrade".equals(servicePart)) {
-                return OTA_UPGRADE;
-            } else {
-                return SERVICE_INVOKE;
-            }
-        }
-
-        // 处理 thing.event.xxx 格式
-        if (method.startsWith(IotTopicConstants.MethodPrefix.THING_EVENT)) {
-            String eventPart = method.substring(IotTopicConstants.MethodPrefix.THING_EVENT.length());
-            if ("property.post".equals(eventPart)) {
-                return PROPERTY_POST;
-            } else {
-                return EVENT_POST;
-            }
-        }
-
-        // 其他类型
-        switch (method) {
-            case IotTopicConstants.Method.DEVICE_ONLINE:
-                return DEVICE_ONLINE;
-            case IotTopicConstants.Method.DEVICE_OFFLINE:
-                return DEVICE_OFFLINE;
-            case IotTopicConstants.Method.HEARTBEAT:
-                return HEARTBEAT;
-            default:
-                return null;
-        }
-    }
-}

+ 0 - 79
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/enums/IotProtocolTypeEnum.java

@@ -1,79 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * IoT 协议类型枚举
- *
- * @author haohao
- */
-@Getter
-@AllArgsConstructor
-public enum IotProtocolTypeEnum {
-
-    /**
-     * MQTT 协议(默认实现)
-     */
-    MQTT("mqtt", "MQTT 协议"),
-
-    /**
-     * MQTT 原始协议
-     */
-    MQTT_RAW("mqtt_raw", "MQTT 原始协议"),
-
-    /**
-     * HTTP 协议
-     */
-    HTTP("http", "HTTP 协议"),
-
-    /**
-     * TCP 协议
-     */
-    TCP("tcp", "TCP 协议"),
-
-    /**
-     * UDP 协议
-     */
-    UDP("udp", "UDP 协议"),
-
-    /**
-     * 自定义协议
-     */
-    CUSTOM("custom", "自定义协议");
-
-    /**
-     * 协议编码
-     */
-    private final String code;
-
-    /**
-     * 协议名称
-     */
-    private final String name;
-
-    /**
-     * 根据编码获取协议类型
-     *
-     * @param code 协议编码
-     * @return 协议类型枚举,如果未找到返回 null
-     */
-    public static IotProtocolTypeEnum getByCode(String code) {
-        for (IotProtocolTypeEnum type : values()) {
-            if (type.getCode().equals(code)) {
-                return type;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * 检查是否为有效的协议编码
-     *
-     * @param code 协议编码
-     * @return 如果有效返回 true,否则返回 false
-     */
-    public static boolean isValidCode(String code) {
-        return getByCode(code) != null;
-    }
-}

+ 0 - 36
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/message/IotMessageParser.java

@@ -1,36 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.message;
-
-/**
- * IoT 消息解析器接口
- * <p>
- * 用于解析不同协议的消息内容
- *
- * @author haohao
- */
-public interface IotMessageParser {
-
-    /**
-     * 解析消息
-     *
-     * @param topic   主题
-     * @param payload 消息负载
-     * @return 解析后的标准消息,如果解析失败返回 null
-     */
-    IotMqttMessage parse(String topic, byte[] payload);
-
-    /**
-     * 格式化响应消息
-     *
-     * @param response 标准响应
-     * @return 格式化后的响应字节数组
-     */
-    byte[] formatResponse(IotStandardResponse response);
-
-    /**
-     * 检查是否能够处理指定主题的消息
-     *
-     * @param topic 主题
-     * @return 如果能处理返回 true,否则返回 false
-     */
-    boolean canHandle(String topic);
-} 

+ 0 - 154
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/message/IotMqttMessage.java

@@ -1,154 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.message;
-
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.json.JSONObject;
-import lombok.Builder;
-import lombok.Data;
-
-import java.util.Map;
-
-/**
- * IoT MQTT 消息模型
- * <p>
- * 基于 MQTT 协议规范实现的标准消息格式,支持设备属性、事件、服务调用等标准功能
- *
- * @author haohao
- * @see <a href="https://mqtt.org/">MQTT 协议官方规范</a>
- */
-@Data
-@Builder
-public class IotMqttMessage {
-
-    /**
-     * 消息 ID
-     */
-    private String id;
-
-    /**
-     * 协议版本
-     */
-    @Builder.Default
-    private String version = "1.0";
-
-    /**
-     * 消息方法
-     */
-    private String method;
-
-    /**
-     * 消息参数
-     */
-    private Map<String, Object> params;
-
-    /**
-     * 转换为 JSONObject
-     *
-     * @return JSONObject 对象
-     */
-    public JSONObject toJsonObject() {
-        JSONObject json = new JSONObject();
-        json.set("id", id);
-        json.set("version", version);
-        json.set("method", method);
-        json.set("params", params != null ? params : new JSONObject());
-        return json;
-    }
-
-    /**
-     * 转换为 JSON 字符串
-     *
-     * @return JSON 字符串
-     */
-    public String toJsonString() {
-        return toJsonObject().toString();
-    }
-
-    /**
-     * 创建设备服务调用消息
-     *
-     * @param requestId         请求 ID,为空时自动生成
-     * @param serviceIdentifier 服务标识符
-     * @param params            服务参数
-     * @return MQTT 消息对象
-     */
-    public static IotMqttMessage createServiceInvokeMessage(String requestId, String serviceIdentifier,
-                                                            Map<String, Object> params) {
-        return IotMqttMessage.builder()
-                .id(requestId != null ? requestId : generateRequestId())
-                .method("thing.service." + serviceIdentifier)
-                .params(params)
-                .build();
-    }
-
-    /**
-     * 创建设备属性设置消息
-     *
-     * @param requestId  请求 ID,为空时自动生成
-     * @param properties 设备属性
-     * @return MQTT 消息对象
-     */
-    public static IotMqttMessage createPropertySetMessage(String requestId, Map<String, Object> properties) {
-        return IotMqttMessage.builder()
-                .id(requestId != null ? requestId : generateRequestId())
-                .method("thing.service.property.set")
-                .params(properties)
-                .build();
-    }
-
-    /**
-     * 创建设备属性获取消息
-     *
-     * @param requestId   请求 ID,为空时自动生成
-     * @param identifiers 要获取的属性标识符列表
-     * @return MQTT 消息对象
-     */
-    public static IotMqttMessage createPropertyGetMessage(String requestId, String[] identifiers) {
-        JSONObject params = new JSONObject();
-        params.set("identifiers", identifiers);
-
-        return IotMqttMessage.builder()
-                .id(requestId != null ? requestId : generateRequestId())
-                .method("thing.service.property.get")
-                .params(params)
-                .build();
-    }
-
-    /**
-     * 创建设备配置设置消息
-     *
-     * @param requestId 请求 ID,为空时自动生成
-     * @param configs   设备配置
-     * @return MQTT 消息对象
-     */
-    public static IotMqttMessage createConfigSetMessage(String requestId, Map<String, Object> configs) {
-        return IotMqttMessage.builder()
-                .id(requestId != null ? requestId : generateRequestId())
-                .method("thing.service.config.set")
-                .params(configs)
-                .build();
-    }
-
-    /**
-     * 创建设备 OTA 升级消息
-     *
-     * @param requestId 请求 ID,为空时自动生成
-     * @param otaInfo   OTA 升级信息
-     * @return MQTT 消息对象
-     */
-    public static IotMqttMessage createOtaUpgradeMessage(String requestId, Map<String, Object> otaInfo) {
-        return IotMqttMessage.builder()
-                .id(requestId != null ? requestId : generateRequestId())
-                .method("thing.service.ota.upgrade")
-                .params(otaInfo)
-                .build();
-    }
-
-    /**
-     * 生成请求 ID
-     *
-     * @return 请求 ID
-     */
-    public static String generateRequestId() {
-        return IdUtil.fastSimpleUUID();
-    }
-} 

+ 0 - 95
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/message/IotStandardResponse.java

@@ -1,95 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.message;
-
-import cn.hutool.core.util.StrUtil;
-import lombok.Data;
-import lombok.experimental.Accessors;
-
-/**
- * IoT 标准协议响应实体类
- * <p>
- * 用于统一 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(StrUtil.blankToDefault(message, "error"))
-                .setMethod(method)
-                .setVersion("1.0");
-    }
-} 

+ 0 - 348
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/message/impl/IotHttpMessageParser.java

@@ -1,348 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.message.impl;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import cn.iocoder.yudao.module.iot.protocol.constants.IotHttpConstants;
-import cn.iocoder.yudao.module.iot.protocol.constants.IotLogConstants;
-import cn.iocoder.yudao.module.iot.protocol.constants.IotTopicConstants;
-import cn.iocoder.yudao.module.iot.protocol.message.IotMessageParser;
-import cn.iocoder.yudao.module.iot.protocol.message.IotMqttMessage;
-import cn.iocoder.yudao.module.iot.protocol.message.IotStandardResponse;
-import lombok.extern.slf4j.Slf4j;
-
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * IoT HTTP 协议消息解析器实现
- * <p>
- * 参考阿里云IoT平台HTTPS协议标准,支持设备认证和数据上报两种消息类型:
- * <p>
- * 1. 设备认证消息格式:
- *
- * <pre>
- * POST /auth HTTP/1.1
- * Content-Type: application/json
- * {
- *   "productKey": "a1AbC***",
- *   "deviceName": "device01",
- *   "clientId": "device01_001",
- *   "timestamp": "1501668289957",
- *   "sign": "xxxxx",
- *   "signmethod": "hmacsha1",
- *   "version": "default"
- * }
- * </pre>
- * <p>
- * 2. 数据上报消息格式:
- *
- * <pre>
- * POST /topic/${topic} HTTP/1.1
- * password: ${token}
- * Content-Type: application/octet-stream
- * ${payload}
- * </pre>
- *
- * @author haohao
- */
-@Slf4j
-public class IotHttpMessageParser implements IotMessageParser {
-
-    /**
-     * 认证路径
-     */
-    public static final String AUTH_PATH = IotHttpConstants.Path.AUTH;
-
-    /**
-     * 主题路径前缀
-     */
-    public static final String TOPIC_PATH_PREFIX = IotHttpConstants.Path.TOPIC_PREFIX;
-
-    @Override
-    public IotMqttMessage parse(String topic, byte[] payload) {
-        if (payload == null || payload.length == 0) {
-            log.warn(IotLogConstants.Http.RECEIVED_EMPTY_MESSAGE, topic);
-            return null;
-        }
-
-        try {
-            String message = new String(payload, StandardCharsets.UTF_8);
-
-            // 判断是认证请求还是数据上报
-            if (AUTH_PATH.equals(topic)) {
-                return parseAuthMessage(message);
-            } else if (topic.startsWith(TOPIC_PATH_PREFIX)) {
-                return parseDataMessage(topic, message);
-            } else {
-                log.warn(IotLogConstants.Http.UNSUPPORTED_PATH_FORMAT, topic);
-                return null;
-            }
-
-        } catch (Exception e) {
-            log.error(IotLogConstants.Http.PARSE_MESSAGE_FAILED, topic, e);
-            return null;
-        }
-    }
-
-    /**
-     * 解析设备认证消息
-     *
-     * @param message 认证消息JSON
-     * @return 标准消息格式
-     */
-    private IotMqttMessage parseAuthMessage(String message) {
-        if (!JSONUtil.isTypeJSON(message)) {
-            log.warn(IotLogConstants.Http.AUTH_MESSAGE_NOT_JSON, message);
-            return null;
-        }
-
-        JSONObject json = JSONUtil.parseObj(message);
-
-        // 验证必需字段
-        String productKey = json.getStr(IotHttpConstants.AuthField.PRODUCT_KEY);
-        String deviceName = json.getStr(IotHttpConstants.AuthField.DEVICE_NAME);
-        String clientId = json.getStr(IotHttpConstants.AuthField.CLIENT_ID);
-        String sign = json.getStr(IotHttpConstants.AuthField.SIGN);
-
-        if (StrUtil.hasBlank(productKey, deviceName, clientId, sign)) {
-            log.warn(IotLogConstants.Http.AUTH_MESSAGE_MISSING_REQUIRED_FIELDS, message);
-            return null;
-        }
-
-        // 构建认证消息
-        Map<String, Object> params = new HashMap<>();
-        params.put(IotHttpConstants.AuthField.PRODUCT_KEY, productKey);
-        params.put(IotHttpConstants.AuthField.DEVICE_NAME, deviceName);
-        params.put(IotHttpConstants.AuthField.CLIENT_ID, clientId);
-        params.put(IotHttpConstants.AuthField.TIMESTAMP, json.getStr(IotHttpConstants.AuthField.TIMESTAMP));
-        params.put(IotHttpConstants.AuthField.SIGN, sign);
-        params.put(IotHttpConstants.AuthField.SIGN_METHOD,
-                json.getStr(IotHttpConstants.AuthField.SIGN_METHOD, IotHttpConstants.DefaultValue.SIGN_METHOD));
-
-        return IotMqttMessage.builder()
-                .id(generateMessageId())
-                .method(IotHttpConstants.Method.DEVICE_AUTH)
-                .version(json.getStr(IotHttpConstants.AuthField.VERSION, IotHttpConstants.DefaultValue.VERSION))
-                .params(params)
-                .build();
-    }
-
-    /**
-     * 解析数据上报消息
-     *
-     * @param topic   主题路径,格式:/topic/${actualTopic}
-     * @param message 消息内容
-     * @return 标准消息格式
-     */
-    private IotMqttMessage parseDataMessage(String topic, String message) {
-        // 提取实际的主题,去掉 /topic 前缀
-        String actualTopic = topic.substring(TOPIC_PATH_PREFIX.length()); // 直接移除/topic前缀
-
-        // 尝试解析为JSON格式
-        if (JSONUtil.isTypeJSON(message)) {
-            return parseJsonDataMessage(actualTopic, message);
-        } else {
-            // 原始数据格式
-            return parseRawDataMessage(actualTopic, message);
-        }
-    }
-
-    /**
-     * 解析JSON格式的数据消息
-     *
-     * @param topic   实际主题
-     * @param message JSON消息
-     * @return 标准消息格式
-     */
-    private IotMqttMessage parseJsonDataMessage(String topic, String message) {
-        JSONObject json = JSONUtil.parseObj(message);
-
-        // 生成消息ID
-        String messageId = json.getStr(IotHttpConstants.MessageField.ID);
-        if (StrUtil.isBlank(messageId)) {
-            messageId = generateMessageId();
-        }
-
-        // 获取方法名
-        String method = json.getStr(IotHttpConstants.MessageField.METHOD);
-        if (StrUtil.isBlank(method)) {
-            // 根据主题推断方法名
-            method = inferMethodFromTopic(topic);
-        }
-
-        // 获取参数
-        Object params = json.get(IotHttpConstants.MessageField.PARAMS);
-        Map<String, Object> paramsMap = new HashMap<>();
-        if (params instanceof Map) {
-            paramsMap.putAll((Map<String, Object>) params);
-        } else if (params != null) {
-            paramsMap.put(IotHttpConstants.MessageField.DATA, params);
-        }
-
-        return IotMqttMessage.builder()
-                .id(messageId)
-                .method(method)
-                .version(json.getStr(IotHttpConstants.MessageField.VERSION,
-                        IotHttpConstants.DefaultValue.MESSAGE_VERSION))
-                .params(paramsMap)
-                .build();
-    }
-
-    /**
-     * 解析原始数据消息
-     *
-     * @param topic   实际主题
-     * @param message 原始消息
-     * @return 标准消息格式
-     */
-    private IotMqttMessage parseRawDataMessage(String topic, String message) {
-        Map<String, Object> params = new HashMap<>();
-        params.put(IotHttpConstants.MessageField.DATA, message);
-
-        return IotMqttMessage.builder()
-                .id(generateMessageId())
-                .method(inferMethodFromTopic(topic))
-                .version(IotHttpConstants.DefaultValue.MESSAGE_VERSION)
-                .params(params)
-                .build();
-    }
-
-    /**
-     * 根据主题推断方法名
-     *
-     * @param topic 主题
-     * @return 方法名
-     */
-    private String inferMethodFromTopic(String topic) {
-        if (StrUtil.isBlank(topic)) {
-            return IotHttpConstants.DefaultValue.UNKNOWN_METHOD;
-        }
-
-        // 标准系统主题解析
-        if (topic.startsWith(IotTopicConstants.SYS_TOPIC_PREFIX)) {
-            if (topic.contains(IotTopicConstants.PROPERTY_SET_TOPIC)) {
-                return IotTopicConstants.Method.PROPERTY_SET;
-            } else if (topic.contains(IotTopicConstants.PROPERTY_GET_TOPIC)) {
-                return IotTopicConstants.Method.PROPERTY_GET;
-            } else if (topic.contains(IotTopicConstants.PROPERTY_POST_TOPIC)) {
-                return IotTopicConstants.Method.PROPERTY_POST;
-            } else if (topic.contains(IotTopicConstants.EVENT_POST_TOPIC_PREFIX)
-                    && topic.endsWith(IotTopicConstants.EVENT_POST_TOPIC_SUFFIX)) {
-                // 自定义事件上报
-                String[] parts = topic.split("/");
-                // 查找event关键字的位置
-                for (int i = 0; i < parts.length; i++) {
-                    if (IotTopicConstants.Keyword.EVENT.equals(parts[i]) && i + 1 < parts.length) {
-                        String eventId = parts[i + 1];
-                        return IotTopicConstants.MethodPrefix.THING_EVENT + eventId + ".post";
-                    }
-                }
-            } else if (topic.contains(IotTopicConstants.SERVICE_TOPIC_PREFIX)
-                    && !topic.contains(IotTopicConstants.Keyword.PROPERTY)) {
-                // 自定义服务调用
-                String[] parts = topic.split("/");
-                // 查找service关键字的位置
-                for (int i = 0; i < parts.length; i++) {
-                    if (IotTopicConstants.Keyword.SERVICE.equals(parts[i]) && i + 1 < parts.length) {
-                        String serviceId = parts[i + 1];
-                        return IotTopicConstants.MethodPrefix.THING_SERVICE + serviceId;
-                    }
-                }
-            }
-        }
-
-        // 自定义主题
-        return IotHttpConstants.Method.CUSTOM_MESSAGE;
-    }
-
-    /**
-     * 生成消息ID
-     *
-     * @return 消息ID
-     */
-    private String generateMessageId() {
-        return IotMqttMessage.generateRequestId();
-    }
-
-    @Override
-    public byte[] formatResponse(IotStandardResponse response) {
-        try {
-            JSONObject httpResponse = new JSONObject();
-
-            // 判断是否为认证响应
-            if (IotHttpConstants.Method.DEVICE_AUTH.equals(response.getMethod())) {
-                // 认证响应格式
-                httpResponse.set(IotHttpConstants.ResponseField.CODE, response.getCode());
-                httpResponse.set(IotHttpConstants.ResponseField.MESSAGE, response.getMessage());
-
-                if (response.getCode() == 200 && response.getData() != null) {
-                    JSONObject info = new JSONObject();
-                    if (response.getData() instanceof Map) {
-                        Map<String, Object> dataMap = (Map<String, Object>) response.getData();
-                        info.putAll(dataMap);
-                    } else {
-                        info.set(IotHttpConstants.ResponseField.TOKEN, response.getData().toString());
-                    }
-                    httpResponse.set(IotHttpConstants.ResponseField.INFO, info);
-                }
-            } else {
-                // 数据上报响应格式
-                httpResponse.set(IotHttpConstants.ResponseField.CODE, response.getCode());
-                httpResponse.set(IotHttpConstants.ResponseField.MESSAGE, response.getMessage());
-
-                if (response.getCode() == 200) {
-                    JSONObject info = new JSONObject();
-                    info.set(IotHttpConstants.ResponseField.MESSAGE_ID, response.getId());
-                    httpResponse.set(IotHttpConstants.ResponseField.INFO, info);
-                }
-            }
-
-            String json = httpResponse.toString();
-            return json.getBytes(StandardCharsets.UTF_8);
-        } catch (Exception e) {
-            log.error(IotLogConstants.Http.FORMAT_RESPONSE_FAILED, e);
-            return new byte[0];
-        }
-    }
-
-    @Override
-    public boolean canHandle(String topic) {
-        // 支持认证路径和主题路径
-        return topic != null && (AUTH_PATH.equals(topic) || topic.startsWith(TOPIC_PATH_PREFIX));
-    }
-
-    /**
-     * 从设备标识中解析产品Key和设备名称
-     *
-     * @param deviceKey 设备标识,格式:productKey/deviceName
-     * @return 包含产品Key和设备名称的数组,[0]为产品Key,[1]为设备名称
-     */
-    public static String[] parseDeviceKey(String deviceKey) {
-        if (StrUtil.isBlank(deviceKey)) {
-            return null;
-        }
-
-        String[] parts = deviceKey.split("/");
-        if (parts.length != 2) {
-            return null;
-        }
-
-        return new String[]{parts[0], parts[1]};
-    }
-
-    /**
-     * 构建设备标识
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @return 设备标识,格式:productKey/deviceName
-     */
-    public static String buildDeviceKey(String productKey, String deviceName) {
-        if (StrUtil.isBlank(productKey) || StrUtil.isBlank(deviceName)) {
-            return null;
-        }
-        return productKey + "/" + deviceName;
-    }
-}

+ 0 - 87
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/message/impl/IotMqttMessageParser.java

@@ -1,87 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.message.impl;
-
-import cn.hutool.core.util.StrUtil;
-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.protocol.message.IotMessageParser;
-import cn.iocoder.yudao.module.iot.protocol.message.IotMqttMessage;
-import cn.iocoder.yudao.module.iot.protocol.message.IotStandardResponse;
-import cn.iocoder.yudao.module.iot.protocol.util.IotTopicUtils;
-import lombok.extern.slf4j.Slf4j;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Map;
-
-/**
- * IoT MQTT 协议消息解析器实现
- * <p>
- * 基于 MQTT 协议规范实现的消息解析器,支持设备属性、事件、服务调用等标准功能
- *
- * @author haohao
- */
-@Slf4j
-public class IotMqttMessageParser implements IotMessageParser {
-
-    @Override
-    public IotMqttMessage parse(String topic, byte[] payload) {
-        if (payload == null || payload.length == 0) {
-            log.warn("[MQTT] 收到空消息内容, topic={}", topic);
-            return null;
-        }
-
-        try {
-            String message = new String(payload, StandardCharsets.UTF_8);
-            if (!JSONUtil.isTypeJSON(message)) {
-                log.warn("[MQTT] 收到非JSON格式消息, topic={}, message={}", topic, message);
-                return null;
-            }
-
-            JSONObject json = JSONUtil.parseObj(message);
-            String id = json.getStr("id");
-            String method = json.getStr("method");
-
-            if (StrUtil.isBlank(method)) {
-                // 尝试从 topic 中解析方法
-                method = IotTopicUtils.parseMethodFromTopic(topic);
-                if (StrUtil.isBlank(method)) {
-                    log.warn("[MQTT] 无法确定消息方法, topic={}, message={}", topic, message);
-                    return null;
-                }
-            }
-
-            @SuppressWarnings("unchecked")
-            Map<String, Object> params = (Map<String, Object>) json.getObj("params", Map.class);
-            return IotMqttMessage.builder()
-                    .id(id)
-                    .method(method)
-                    .version(json.getStr("version", "1.0"))
-                    .params(params)
-                    .build();
-        } catch (Exception e) {
-            log.error("[MQTT] 解析消息失败, topic={}", topic, e);
-            return null;
-        }
-    }
-
-    @Override
-    public byte[] formatResponse(IotStandardResponse response) {
-        try {
-            String json = JsonUtils.toJsonString(response);
-            return json.getBytes(StandardCharsets.UTF_8);
-        } catch (Exception e) {
-            log.error("[MQTT] 格式化响应失败", e);
-            return new byte[0];
-        }
-    }
-
-    @Override
-    public boolean canHandle(String topic) {
-        // MQTT 协议支持更多主题格式
-        return topic != null && (
-                topic.startsWith("/sys/") ||      // 兼容现有系统主题
-                        topic.startsWith("/mqtt/") ||     // 新的通用 MQTT 主题
-                        topic.startsWith("/device/")      // 设备主题
-        );
-    }
-} 

+ 0 - 279
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/util/IotHttpTopicUtils.java

@@ -1,279 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.util;
-
-import cn.hutool.core.util.StrUtil;
-
-/**
- * IoT HTTP 协议主题工具类
- * <p>
- * 参考阿里云IoT平台HTTPS协议标准,支持以下路径格式:
- * 1. 设备认证:/auth
- * 2. 数据上报:/topic/${actualTopic}
- * <p>
- * 其中 actualTopic 遵循MQTT主题规范,例如:
- * - /sys/{productKey}/{deviceName}/thing/service/property/set
- * - /{productKey}/{deviceName}/user/get
- *
- * @author haohao
- */
-public class IotHttpTopicUtils {
-
-    /**
-     * 设备认证路径
-     */
-    public static final String AUTH_PATH = "/auth";
-
-    /**
-     * 数据上报路径前缀
-     */
-    public static final String TOPIC_PATH_PREFIX = "/topic";
-
-    /**
-     * 系统主题前缀
-     */
-    public static final String SYS_TOPIC_PREFIX = "/sys";
-
-    /**
-     * 构建设备认证路径
-     *
-     * @return 认证路径
-     */
-    public static String buildAuthPath() {
-        return AUTH_PATH;
-    }
-
-    /**
-     * 构建数据上报路径
-     *
-     * @param actualTopic 实际的MQTT主题
-     * @return HTTP数据上报路径
-     */
-    public static String buildTopicPath(String actualTopic) {
-        if (StrUtil.isBlank(actualTopic)) {
-            return null;
-        }
-        return TOPIC_PATH_PREFIX + actualTopic;
-    }
-
-    /**
-     * 构建系统属性设置路径
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @return HTTP路径
-     */
-    public static String buildPropertySetPath(String productKey, String deviceName) {
-        if (StrUtil.hasBlank(productKey, deviceName)) {
-            return null;
-        }
-        String actualTopic = SYS_TOPIC_PREFIX + "/" + productKey + "/" + deviceName + "/thing/service/property/set";
-        return buildTopicPath(actualTopic);
-    }
-
-    /**
-     * 构建系统属性获取路径
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @return HTTP路径
-     */
-    public static String buildPropertyGetPath(String productKey, String deviceName) {
-        if (StrUtil.hasBlank(productKey, deviceName)) {
-            return null;
-        }
-        String actualTopic = SYS_TOPIC_PREFIX + "/" + productKey + "/" + deviceName + "/thing/service/property/get";
-        return buildTopicPath(actualTopic);
-    }
-
-    /**
-     * 构建系统属性上报路径
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @return HTTP路径
-     */
-    public static String buildPropertyPostPath(String productKey, String deviceName) {
-        if (StrUtil.hasBlank(productKey, deviceName)) {
-            return null;
-        }
-        String actualTopic = SYS_TOPIC_PREFIX + "/" + productKey + "/" + deviceName + "/thing/event/property/post";
-        return buildTopicPath(actualTopic);
-    }
-
-    /**
-     * 构建系统事件上报路径
-     *
-     * @param productKey      产品Key
-     * @param deviceName      设备名称
-     * @param eventIdentifier 事件标识符
-     * @return HTTP路径
-     */
-    public static String buildEventPostPath(String productKey, String deviceName, String eventIdentifier) {
-        if (StrUtil.hasBlank(productKey, deviceName, eventIdentifier)) {
-            return null;
-        }
-        String actualTopic = SYS_TOPIC_PREFIX + "/" + productKey + "/" + deviceName + "/thing/event/" + eventIdentifier
-                + "/post";
-        return buildTopicPath(actualTopic);
-    }
-
-    /**
-     * 构建系统服务调用路径
-     *
-     * @param productKey        产品Key
-     * @param deviceName        设备名称
-     * @param serviceIdentifier 服务标识符
-     * @return HTTP路径
-     */
-    public static String buildServiceInvokePath(String productKey, String deviceName, String serviceIdentifier) {
-        if (StrUtil.hasBlank(productKey, deviceName, serviceIdentifier)) {
-            return null;
-        }
-        String actualTopic = SYS_TOPIC_PREFIX + "/" + productKey + "/" + deviceName + "/thing/service/"
-                + serviceIdentifier;
-        return buildTopicPath(actualTopic);
-    }
-
-    /**
-     * 构建自定义主题路径
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @param customPath 自定义路径
-     * @return HTTP路径
-     */
-    public static String buildCustomTopicPath(String productKey, String deviceName, String customPath) {
-        if (StrUtil.hasBlank(productKey, deviceName, customPath)) {
-            return null;
-        }
-        String actualTopic = "/" + productKey + "/" + deviceName + "/" + customPath;
-        return buildTopicPath(actualTopic);
-    }
-
-    /**
-     * 从HTTP路径中提取实际主题
-     *
-     * @param httpPath HTTP路径,格式:/topic/${actualTopic}
-     * @return 实际主题,如果解析失败返回null
-     */
-    public static String extractActualTopic(String httpPath) {
-        if (StrUtil.isBlank(httpPath) || !httpPath.startsWith(TOPIC_PATH_PREFIX)) {
-            return null;
-        }
-        return httpPath.substring(TOPIC_PATH_PREFIX.length()); // 直接移除/topic前缀
-    }
-
-    /**
-     * 从主题中解析产品Key
-     *
-     * @param topic 主题,支持系统主题和自定义主题
-     * @return 产品Key,如果无法解析则返回null
-     */
-    public static String parseProductKeyFromTopic(String topic) {
-        if (StrUtil.isBlank(topic)) {
-            return null;
-        }
-
-        String[] parts = topic.split("/");
-
-        // 系统主题格式:/sys/{productKey}/{deviceName}/...
-        if (parts.length >= 4 && "sys".equals(parts[1])) {
-            return parts[2];
-        }
-
-        // 自定义主题格式:/{productKey}/{deviceName}/...
-        // 确保不是不完整的系统主题格式
-        if (parts.length >= 3 && StrUtil.isNotBlank(parts[1]) && !"sys".equals(parts[1])) {
-            return parts[1];
-        }
-
-        return null;
-    }
-
-    /**
-     * 从主题中解析设备名称
-     *
-     * @param topic 主题,支持系统主题和自定义主题
-     * @return 设备名称,如果无法解析则返回null
-     */
-    public static String parseDeviceNameFromTopic(String topic) {
-        if (StrUtil.isBlank(topic)) {
-            return null;
-        }
-
-        String[] parts = topic.split("/");
-
-        // 系统主题格式:/sys/{productKey}/{deviceName}/...
-        if (parts.length >= 4 && "sys".equals(parts[1])) {
-            return parts[3];
-        }
-
-        // 自定义主题格式:/{productKey}/{deviceName}/...
-        // 确保不是不完整的系统主题格式
-        if (parts.length >= 3 && StrUtil.isNotBlank(parts[2]) && !"sys".equals(parts[1])) {
-            return parts[2];
-        }
-
-        return null;
-    }
-
-    /**
-     * 检查是否为认证路径
-     *
-     * @param path 路径
-     * @return 如果是认证路径返回true,否则返回false
-     */
-    public static boolean isAuthPath(String path) {
-        return AUTH_PATH.equals(path);
-    }
-
-    /**
-     * 检查是否为数据上报路径
-     *
-     * @param path 路径
-     * @return 如果是数据上报路径返回true,否则返回false
-     */
-    public static boolean isTopicPath(String path) {
-        return path != null && path.startsWith(TOPIC_PATH_PREFIX);
-    }
-
-    /**
-     * 检查是否为有效的HTTP路径
-     *
-     * @param path 路径
-     * @return 如果是有效的HTTP路径返回true,否则返回false
-     */
-    public static boolean isValidHttpPath(String path) {
-        return isAuthPath(path) || isTopicPath(path);
-    }
-
-    /**
-     * 检查是否为系统主题
-     *
-     * @param topic 主题
-     * @return 如果是系统主题返回true,否则返回false
-     */
-    public static boolean isSystemTopic(String topic) {
-        return topic != null && topic.startsWith(SYS_TOPIC_PREFIX);
-    }
-
-    /**
-     * 构建响应主题路径
-     *
-     * @param requestPath 请求路径
-     * @return 响应路径,如果无法构建返回null
-     */
-    public static String buildReplyPath(String requestPath) {
-        String actualTopic = extractActualTopic(requestPath);
-        if (actualTopic == null) {
-            return null;
-        }
-
-        // 为系统主题添加_reply后缀
-        if (isSystemTopic(actualTopic)) {
-            String replyTopic = actualTopic + "_reply";
-            return buildTopicPath(replyTopic);
-        }
-
-        return null;
-    }
-}

+ 0 - 237
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/util/IotTopicParser.java

@@ -1,237 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.util;
-
-import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.module.iot.protocol.constants.IotTopicConstants;
-import cn.iocoder.yudao.module.iot.protocol.enums.IotMessageDirectionEnum;
-import cn.iocoder.yudao.module.iot.protocol.enums.IotMessageTypeEnum;
-import lombok.Data;
-
-/**
- * IoT 主题解析器
- * <p>
- * 用于解析各种格式的 IoT 主题,提取其中的关键信息
- *
- * @author haohao
- */
-public class IotTopicParser {
-
-    /**
-     * 主题解析结果
-     */
-    @Data
-    public static class TopicInfo {
-        /**
-         * 产品Key
-         */
-        private String productKey;
-
-        /**
-         * 设备名称
-         */
-        private String deviceName;
-
-        /**
-         * 消息类型
-         */
-        private IotMessageTypeEnum messageType;
-
-        /**
-         * 消息方向
-         */
-        private IotMessageDirectionEnum direction;
-
-        /**
-         * 服务标识符(仅服务调用时有效)
-         */
-        private String serviceIdentifier;
-
-        /**
-         * 事件标识符(仅事件上报时有效)
-         */
-        private String eventIdentifier;
-
-        /**
-         * 是否为响应主题
-         */
-        private boolean isReply;
-
-        /**
-         * 原始主题
-         */
-        private String originalTopic;
-    }
-
-    /**
-     * 解析主题
-     *
-     * @param topic 主题字符串
-     * @return 解析结果,如果解析失败返回 null
-     */
-    public static TopicInfo parse(String topic) {
-        if (StrUtil.isBlank(topic)) {
-            return null;
-        }
-
-        TopicInfo info = new TopicInfo();
-        info.setOriginalTopic(topic);
-
-        // 检查是否为响应主题
-        boolean isReply = topic.endsWith(IotTopicConstants.REPLY_SUFFIX);
-        info.setReply(isReply);
-
-        // 移除响应后缀,便于后续解析
-        String normalizedTopic = isReply ? topic.substring(0, topic.length() - IotTopicConstants.REPLY_SUFFIX.length())
-                : topic;
-
-        // 解析系统主题
-        if (normalizedTopic.startsWith(IotTopicConstants.SYS_TOPIC_PREFIX)) {
-            return parseSystemTopic(info, normalizedTopic);
-        }
-
-        // 解析自定义主题
-        return parseCustomTopic(info, normalizedTopic);
-    }
-
-    /**
-     * 解析系统主题
-     * 格式:/sys/{productKey}/{deviceName}/thing/service/{identifier}
-     * 或:/sys/{productKey}/{deviceName}/thing/event/{identifier}/post
-     */
-    private static TopicInfo parseSystemTopic(TopicInfo info, String topic) {
-        String[] parts = topic.split("/");
-        if (parts.length < 6) {
-            return null;
-        }
-
-        // 解析产品Key和设备名称
-        info.setProductKey(parts[2]);
-        info.setDeviceName(parts[3]);
-
-        // 判断消息方向:包含 /post 通常是上行,其他是下行
-        info.setDirection(topic.contains("/post") || topic.contains("/reply") ? IotMessageDirectionEnum.UPSTREAM
-                : IotMessageDirectionEnum.DOWNSTREAM);
-
-        // 解析具体的消息类型
-        if (topic.contains("/thing/service/")) {
-            return parseServiceTopic(info, topic, parts);
-        } else if (topic.contains("/thing/event/")) {
-            return parseEventTopic(info, topic, parts);
-        }
-
-        return null;
-    }
-
-    /**
-     * 解析服务相关主题
-     */
-    private static TopicInfo parseServiceTopic(TopicInfo info, String topic, String[] parts) {
-        // 查找 service 关键字的位置
-        int serviceIndex = -1;
-        for (int i = 0; i < parts.length; i++) {
-            if ("service".equals(parts[i])) {
-                serviceIndex = i;
-                break;
-            }
-        }
-
-        if (serviceIndex == -1 || serviceIndex + 1 >= parts.length) {
-            return null;
-        }
-
-        String serviceType = parts[serviceIndex + 1];
-
-        // 根据服务类型确定消息类型
-        switch (serviceType) {
-            case "property":
-                if (serviceIndex + 2 < parts.length) {
-                    String operation = parts[serviceIndex + 2];
-                    if ("set".equals(operation)) {
-                        info.setMessageType(IotMessageTypeEnum.PROPERTY_SET);
-                    } else if ("get".equals(operation)) {
-                        info.setMessageType(IotMessageTypeEnum.PROPERTY_GET);
-                    }
-                }
-                break;
-            case "config":
-                if (serviceIndex + 2 < parts.length && "set".equals(parts[serviceIndex + 2])) {
-                    info.setMessageType(IotMessageTypeEnum.CONFIG_SET);
-                }
-                break;
-            case "ota":
-                if (serviceIndex + 2 < parts.length && "upgrade".equals(parts[serviceIndex + 2])) {
-                    info.setMessageType(IotMessageTypeEnum.OTA_UPGRADE);
-                }
-                break;
-            default:
-                // 自定义服务
-                info.setMessageType(IotMessageTypeEnum.SERVICE_INVOKE);
-                info.setServiceIdentifier(serviceType);
-                break;
-        }
-
-        return info;
-    }
-
-    /**
-     * 解析事件相关主题
-     */
-    private static TopicInfo parseEventTopic(TopicInfo info, String topic, String[] parts) {
-        // 查找 event 关键字的位置
-        int eventIndex = -1;
-        for (int i = 0; i < parts.length; i++) {
-            if ("event".equals(parts[i])) {
-                eventIndex = i;
-                break;
-            }
-        }
-
-        if (eventIndex == -1 || eventIndex + 1 >= parts.length) {
-            return null;
-        }
-
-        String eventType = parts[eventIndex + 1];
-
-        if ("property".equals(eventType) && eventIndex + 2 < parts.length && "post".equals(parts[eventIndex + 2])) {
-            info.setMessageType(IotMessageTypeEnum.PROPERTY_POST);
-        } else {
-            // 自定义事件
-            info.setMessageType(IotMessageTypeEnum.EVENT_POST);
-            info.setEventIdentifier(eventType);
-        }
-
-        return info;
-    }
-
-    /**
-     * 解析自定义主题
-     * 这里可以根据实际需求扩展自定义主题的解析逻辑
-     */
-    private static TopicInfo parseCustomTopic(TopicInfo info, String topic) {
-        // TODO: 根据业务需要实现自定义主题解析逻辑
-        return info;
-    }
-
-    /**
-     * 检查主题是否为有效的系统主题
-     *
-     * @param topic 主题
-     * @return 如果是有效的系统主题返回 true,否则返回 false
-     */
-    public static boolean isValidSystemTopic(String topic) {
-        TopicInfo info = parse(topic);
-        return info != null &&
-                StrUtil.isNotBlank(info.getProductKey()) &&
-                StrUtil.isNotBlank(info.getDeviceName()) &&
-                info.getMessageType() != null;
-    }
-
-    /**
-     * 检查主题是否为响应主题
-     *
-     * @param topic 主题
-     * @return 如果是响应主题返回 true,否则返回 false
-     */
-    public static boolean isReplyTopic(String topic) {
-        return topic != null && topic.endsWith(IotTopicConstants.REPLY_SUFFIX);
-    }
-}

+ 0 - 184
yudao-module-iot/yudao-module-iot-protocol/src/main/java/cn/iocoder/yudao/module/iot/protocol/util/IotTopicUtils.java

@@ -1,184 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.util;
-
-import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.module.iot.protocol.constants.IotTopicConstants;
-
-/**
- * IoT 主题工具类
- * <p>
- * 用于构建和解析设备主题
- *
- * @author haohao
- */
-public class IotTopicUtils {
-
-    /**
-     * 构建设备服务调用主题
-     *
-     * @param productKey        产品Key
-     * @param deviceName        设备名称
-     * @param serviceIdentifier 服务标识符
-     * @return 完整的主题路径
-     */
-    public static String buildServiceTopic(String productKey, String deviceName, String serviceIdentifier) {
-        return buildDeviceBaseTopic(productKey, deviceName) +
-                IotTopicConstants.SERVICE_TOPIC_PREFIX + serviceIdentifier;
-    }
-
-    /**
-     * 构建设备属性设置主题
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @return 完整的主题路径
-     */
-    public static String buildPropertySetTopic(String productKey, String deviceName) {
-        return buildDeviceBaseTopic(productKey, deviceName) + IotTopicConstants.PROPERTY_SET_TOPIC;
-    }
-
-    /**
-     * 构建设备属性获取主题
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @return 完整的主题路径
-     */
-    public static String buildPropertyGetTopic(String productKey, String deviceName) {
-        return buildDeviceBaseTopic(productKey, deviceName) + IotTopicConstants.PROPERTY_GET_TOPIC;
-    }
-
-    /**
-     * 构建设备配置设置主题
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @return 完整的主题路径
-     */
-    public static String buildConfigSetTopic(String productKey, String deviceName) {
-        return buildDeviceBaseTopic(productKey, deviceName) + IotTopicConstants.CONFIG_SET_TOPIC;
-    }
-
-    /**
-     * 构建设备 OTA 升级主题
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @return 完整的主题路径
-     */
-    public static String buildOtaUpgradeTopic(String productKey, String deviceName) {
-        return buildDeviceBaseTopic(productKey, deviceName) + IotTopicConstants.OTA_UPGRADE_TOPIC;
-    }
-
-    /**
-     * 构建设备属性上报主题
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @return 完整的主题路径
-     */
-    public static String buildPropertyPostTopic(String productKey, String deviceName) {
-        return buildDeviceBaseTopic(productKey, deviceName) + IotTopicConstants.PROPERTY_POST_TOPIC;
-    }
-
-    /**
-     * 构建设备事件上报主题
-     *
-     * @param productKey      产品Key
-     * @param deviceName      设备名称
-     * @param eventIdentifier 事件标识符
-     * @return 完整的主题路径
-     */
-    public static String buildEventPostTopic(String productKey, String deviceName, String eventIdentifier) {
-        return buildDeviceBaseTopic(productKey, deviceName) +
-                IotTopicConstants.EVENT_POST_TOPIC_PREFIX + eventIdentifier + IotTopicConstants.EVENT_POST_TOPIC_SUFFIX;
-    }
-
-    /**
-     * 获取响应主题
-     *
-     * @param requestTopic 请求主题
-     * @return 响应主题
-     */
-    public static String getReplyTopic(String requestTopic) {
-        return requestTopic + IotTopicConstants.REPLY_SUFFIX;
-    }
-
-    /**
-     * 构建设备基础主题
-     * 格式: /sys/${productKey}/${deviceName}
-     *
-     * @param productKey 产品Key
-     * @param deviceName 设备名称
-     * @return 设备基础主题
-     */
-    public static String buildDeviceBaseTopic(String productKey, String deviceName) {
-        return IotTopicConstants.SYS_TOPIC_PREFIX + productKey + "/" + deviceName;
-    }
-
-    /**
-     * 从主题中解析产品Key
-     * 格式: /sys/${productKey}/${deviceName}/...
-     *
-     * @param topic 主题
-     * @return 产品Key,如果无法解析则返回null
-     */
-    public static String parseProductKeyFromTopic(String topic) {
-        if (StrUtil.isBlank(topic) || !topic.startsWith(IotTopicConstants.SYS_TOPIC_PREFIX)) {
-            return null;
-        }
-
-        String[] parts = topic.split("/");
-        if (parts.length < 4) {
-            return null;
-        }
-
-        return parts[2];
-    }
-
-    /**
-     * 从主题中解析设备名称
-     * 格式: /sys/${productKey}/${deviceName}/...
-     *
-     * @param topic 主题
-     * @return 设备名称,如果无法解析则返回null
-     */
-    public static String parseDeviceNameFromTopic(String topic) {
-        if (StrUtil.isBlank(topic) || !topic.startsWith(IotTopicConstants.SYS_TOPIC_PREFIX)) {
-            return null;
-        }
-
-        String[] parts = topic.split("/");
-        if (parts.length < 4) {
-            return null;
-        }
-
-        return parts[3];
-    }
-
-    /**
-     * 从主题中解析方法名
-     * 例如:从 /sys/pk/dn/thing/service/property/set 解析出 property.set
-     *
-     * @param topic 主题
-     * @return 方法名,如果无法解析则返回null
-     */
-    public static String parseMethodFromTopic(String topic) {
-        if (StrUtil.isBlank(topic) || !topic.startsWith(IotTopicConstants.SYS_TOPIC_PREFIX)) {
-            return null;
-        }
-
-        // 服务调用主题
-        if (topic.contains("/thing/service/")) {
-            String servicePart = topic.substring(topic.indexOf("/thing/service/") + "/thing/service/".length());
-            return servicePart.replace("/", ".");
-        }
-
-        // 事件上报主题
-        if (topic.contains("/thing/event/")) {
-            String eventPart = topic.substring(topic.indexOf("/thing/event/") + "/thing/event/".length());
-            return "event." + eventPart.replace("/", ".");
-        }
-
-        return null;
-    }
-} 

+ 0 - 1
yudao-module-iot/yudao-module-iot-protocol/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -1 +0,0 @@
-cn.iocoder.yudao.module.iot.protocol.config.IotProtocolAutoConfiguration 

+ 0 - 71
yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/config/IotProtocolAutoConfigurationTest.java

@@ -1,71 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.config;
-
-import cn.iocoder.yudao.module.iot.protocol.convert.IotProtocolConverter;
-import cn.iocoder.yudao.module.iot.protocol.enums.IotProtocolTypeEnum;
-import cn.iocoder.yudao.module.iot.protocol.message.IotMessageParser;
-import cn.iocoder.yudao.module.iot.protocol.message.impl.IotHttpMessageParser;
-import cn.iocoder.yudao.module.iot.protocol.message.impl.IotMqttMessageParser;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link IotProtocolAutoConfiguration} 单元测试
- *
- * @author haohao
- */
-class IotProtocolAutoConfigurationTest {
-
-    private IotProtocolAutoConfiguration configuration;
-
-    @BeforeEach
-    void setUp() {
-        configuration = new IotProtocolAutoConfiguration();
-    }
-
-    @Test
-    void testIotMqttMessageParser() {
-        // 测试 MQTT 协议解析器 Bean 创建
-        IotMessageParser parser = configuration.iotMqttMessageParser();
-
-        assertNotNull(parser);
-        assertInstanceOf(IotMqttMessageParser.class, parser);
-    }
-
-    @Test
-    void testIotHttpMessageParser() {
-        // 测试 HTTP 协议解析器 Bean 创建
-        IotMessageParser parser = configuration.iotHttpMessageParser();
-
-        assertNotNull(parser);
-        assertInstanceOf(IotHttpMessageParser.class, parser);
-    }
-
-    @Test
-    void testIotProtocolConverter() {
-        // 创建解析器实例
-        IotMessageParser mqttParser = configuration.iotMqttMessageParser();
-        IotMessageParser httpParser = configuration.iotHttpMessageParser();
-
-        // 测试协议转换器 Bean 创建
-        IotProtocolConverter converter = configuration.iotProtocolConverter(mqttParser, httpParser);
-
-        assertNotNull(converter);
-
-        // 验证支持的协议
-        assertTrue(converter.supportsProtocol(IotProtocolTypeEnum.MQTT.getCode()));
-        assertTrue(converter.supportsProtocol(IotProtocolTypeEnum.HTTP.getCode()));
-
-        // 验证支持的协议数量
-        String[] supportedProtocols = converter.getSupportedProtocols();
-        assertEquals(2, supportedProtocols.length);
-    }
-
-    @Test
-    void testBeanNameConstants() {
-        // 测试 Bean 名称常量定义
-        assertEquals("iotMqttMessageParser", IotProtocolAutoConfiguration.IOT_MQTT_MESSAGE_PARSER_BEAN_NAME);
-        assertEquals("iotHttpMessageParser", IotProtocolAutoConfiguration.IOT_HTTP_MESSAGE_PARSER_BEAN_NAME);
-    }
-}

+ 0 - 166
yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/example/AliyunHttpProtocolExample.java

@@ -1,166 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.example;
-
-import cn.hutool.json.JSONObject;
-import cn.iocoder.yudao.module.iot.protocol.util.IotHttpTopicUtils;
-
-/**
- * 阿里云IoT平台HTTPS协议示例
- * <p>
- * 参考阿里云IoT平台HTTPS连接通信标准,演示设备认证和数据上报的完整流程
- *
- * @author haohao
- */
-public class AliyunHttpProtocolExample {
-
-    public static void main(String[] args) {
-        System.out.println("=== 阿里云IoT平台HTTPS协议演示 ===\n");
-
-        // 演示设备认证
-        demonstrateDeviceAuth();
-
-        // 演示数据上报
-        demonstrateDataUpload();
-
-        // 演示路径构建
-        demonstratePathBuilding();
-    }
-
-    /**
-     * 演示设备认证流程
-     */
-    private static void demonstrateDeviceAuth() {
-        System.out.println("1. 设备认证流程:");
-        System.out.println("认证路径: " + IotHttpTopicUtils.buildAuthPath());
-
-        // 构建认证请求消息
-        JSONObject authRequest = new JSONObject();
-        authRequest.set("productKey", "a1GFjLP****");
-        authRequest.set("deviceName", "device123");
-        authRequest.set("clientId", "device123_001");
-        authRequest.set("timestamp", String.valueOf(System.currentTimeMillis()));
-        authRequest.set("sign", "4870141D4067227128CBB4377906C3731CAC221C");
-        authRequest.set("signmethod", "hmacsha1");
-        authRequest.set("version", "default");
-
-        System.out.println("认证请求消息:");
-        System.out.println(authRequest.toString());
-
-        // 模拟认证响应
-        JSONObject authResponse = new JSONObject();
-        authResponse.set("code", 0);
-        authResponse.set("message", "success");
-
-        JSONObject info = new JSONObject();
-        info.set("token", "6944e5bfb92e4d4ea3918d1eda39****");
-        authResponse.set("info", info);
-
-        System.out.println("认证响应:");
-        System.out.println(authResponse.toString());
-        System.out.println();
-    }
-
-    /**
-     * 演示数据上报流程
-     */
-    private static void demonstrateDataUpload() {
-        System.out.println("2. 数据上报流程:");
-
-        String productKey = "a1GFjLP****";
-        String deviceName = "device123";
-
-        // 属性上报
-        String propertyPostPath = IotHttpTopicUtils.buildPropertyPostPath(productKey, deviceName);
-        System.out.println("属性上报路径: " + propertyPostPath);
-
-        // Alink格式的属性上报消息
-        JSONObject propertyMessage = new JSONObject();
-        propertyMessage.set("id", "123456");
-        propertyMessage.set("version", "1.0");
-        propertyMessage.set("method", "thing.event.property.post");
-
-        JSONObject propertyParams = new JSONObject();
-        JSONObject properties = new JSONObject();
-        properties.set("temperature", 25.6);
-        properties.set("humidity", 60.3);
-        propertyParams.set("properties", properties);
-        propertyMessage.set("params", propertyParams);
-
-        System.out.println("属性上报消息:");
-        System.out.println(propertyMessage.toString());
-
-        // 事件上报
-        String eventPostPath = IotHttpTopicUtils.buildEventPostPath(productKey, deviceName, "temperatureAlert");
-        System.out.println("\n事件上报路径: " + eventPostPath);
-
-        JSONObject eventMessage = new JSONObject();
-        eventMessage.set("id", "123457");
-        eventMessage.set("version", "1.0");
-        eventMessage.set("method", "thing.event.temperatureAlert.post");
-
-        JSONObject eventParams = new JSONObject();
-        eventParams.set("value", new JSONObject().set("alertLevel", "high").set("currentTemp", 45.2));
-        eventParams.set("time", System.currentTimeMillis());
-        eventMessage.set("params", eventParams);
-
-        System.out.println("事件上报消息:");
-        System.out.println(eventMessage.toString());
-
-        // 模拟数据上报响应
-        JSONObject uploadResponse = new JSONObject();
-        uploadResponse.set("code", 0);
-        uploadResponse.set("message", "success");
-
-        JSONObject responseInfo = new JSONObject();
-        responseInfo.set("messageId", 892687470447040L);
-        uploadResponse.set("info", responseInfo);
-
-        System.out.println("\n数据上报响应:");
-        System.out.println(uploadResponse.toString());
-        System.out.println();
-    }
-
-    /**
-     * 演示路径构建功能
-     */
-    private static void demonstratePathBuilding() {
-        System.out.println("3. 路径构建功能:");
-
-        String productKey = "smartProduct";
-        String deviceName = "sensor001";
-
-        // 系统主题路径
-        System.out.println("系统主题路径:");
-        System.out.println("  属性设置: " + IotHttpTopicUtils.buildPropertySetPath(productKey, deviceName));
-        System.out.println("  属性获取: " + IotHttpTopicUtils.buildPropertyGetPath(productKey, deviceName));
-        System.out.println("  属性上报: " + IotHttpTopicUtils.buildPropertyPostPath(productKey, deviceName));
-        System.out.println("  事件上报: " + IotHttpTopicUtils.buildEventPostPath(productKey, deviceName, "alarm"));
-        System.out.println("  服务调用: " + IotHttpTopicUtils.buildServiceInvokePath(productKey, deviceName, "reboot"));
-
-        // 自定义主题路径
-        System.out.println("\n自定义主题路径:");
-        System.out.println("  用户主题: " + IotHttpTopicUtils.buildCustomTopicPath(productKey, deviceName, "user/get"));
-
-        // 响应路径
-        String requestPath = IotHttpTopicUtils.buildPropertySetPath(productKey, deviceName);
-        String replyPath = IotHttpTopicUtils.buildReplyPath(requestPath);
-        System.out.println("\n响应路径:");
-        System.out.println("  请求路径: " + requestPath);
-        System.out.println("  响应路径: " + replyPath);
-
-        // 路径解析
-        System.out.println("\n路径解析:");
-        String testPath = "/topic/sys/smartProduct/sensor001/thing/service/property/set";
-        String actualTopic = IotHttpTopicUtils.extractActualTopic(testPath);
-        System.out.println("  HTTP路径: " + testPath);
-        System.out.println("  实际主题: " + actualTopic);
-        System.out.println("  产品Key: " + IotHttpTopicUtils.parseProductKeyFromTopic(actualTopic));
-        System.out.println("  设备名称: " + IotHttpTopicUtils.parseDeviceNameFromTopic(actualTopic));
-        System.out.println("  是否为系统主题: " + IotHttpTopicUtils.isSystemTopic(actualTopic));
-
-        // 路径类型检查
-        System.out.println("\n路径类型检查:");
-        System.out.println("  认证路径检查: " + IotHttpTopicUtils.isAuthPath("/auth"));
-        System.out.println("  数据路径检查: " + IotHttpTopicUtils.isTopicPath("/topic/test"));
-        System.out.println("  有效路径检查: " + IotHttpTopicUtils.isValidHttpPath("/topic/sys/test/device/property"));
-    }
-}

+ 0 - 259
yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/message/impl/IotHttpMessageParserTest.java

@@ -1,259 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.message.impl;
-
-import cn.hutool.json.JSONObject;
-import cn.iocoder.yudao.module.iot.protocol.message.IotMqttMessage;
-import cn.iocoder.yudao.module.iot.protocol.message.IotStandardResponse;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link IotHttpMessageParser} 单元测试
- * <p>
- * 测试阿里云IoT平台HTTPS协议标准的消息解析功能
- *
- * @author haohao
- */
-class IotHttpMessageParserTest {
-
-    private IotHttpMessageParser parser;
-
-    @BeforeEach
-    void setUp() {
-        parser = new IotHttpMessageParser();
-    }
-
-    @Test
-    void testCanHandle() {
-        // 测试能处理的路径
-        assertTrue(parser.canHandle("/auth"));
-        assertTrue(parser.canHandle("/topic/sys/test/device1/thing/service/property/set"));
-        assertTrue(parser.canHandle("/topic/test/device1/user/get"));
-
-        // 测试不能处理的路径
-        assertFalse(parser.canHandle("/sys/test/device1/thing/service/property/set"));
-        assertFalse(parser.canHandle("/unknown/path"));
-        assertFalse(parser.canHandle(null));
-        assertFalse(parser.canHandle(""));
-    }
-
-    @Test
-    void testParseAuthMessage() {
-        // 构建认证消息
-        JSONObject authMessage = new JSONObject();
-        authMessage.set("productKey", "a1GFjLP****");
-        authMessage.set("deviceName", "device123");
-        authMessage.set("clientId", "device123_001");
-        authMessage.set("timestamp", "1501668289957");
-        authMessage.set("sign", "4870141D4067227128CBB4377906C3731CAC221C");
-        authMessage.set("signmethod", "hmacsha1");
-        authMessage.set("version", "default");
-
-        String topic = "/auth";
-        byte[] payload = authMessage.toString().getBytes(StandardCharsets.UTF_8);
-
-        // 解析消息
-        IotMqttMessage result = parser.parse(topic, payload);
-
-        // 验证结果
-        assertNotNull(result);
-        assertNotNull(result.getId());
-        assertEquals("device.auth", result.getMethod());
-        assertEquals("default", result.getVersion());
-        assertNotNull(result.getParams());
-
-        Map<String, Object> params = result.getParams();
-        assertEquals("a1GFjLP****", params.get("productKey"));
-        assertEquals("device123", params.get("deviceName"));
-        assertEquals("device123_001", params.get("clientId"));
-        assertEquals("1501668289957", params.get("timestamp"));
-        assertEquals("4870141D4067227128CBB4377906C3731CAC221C", params.get("sign"));
-        assertEquals("hmacsha1", params.get("signmethod"));
-    }
-
-    @Test
-    void testParseAuthMessageWithMissingFields() {
-        // 构建缺少必需字段的认证消息
-        JSONObject authMessage = new JSONObject();
-        authMessage.set("productKey", "a1GFjLP****");
-        authMessage.set("deviceName", "device123");
-        // 缺少 clientId 和 sign
-
-        String topic = "/auth";
-        byte[] payload = authMessage.toString().getBytes(StandardCharsets.UTF_8);
-
-        // 解析消息
-        IotMqttMessage result = parser.parse(topic, payload);
-
-        // 验证结果
-        assertNull(result);
-    }
-
-    @Test
-    void testParseJsonDataMessage() {
-        // 构建JSON格式的数据消息
-        JSONObject dataMessage = new JSONObject();
-        dataMessage.set("id", "123456");
-        dataMessage.set("version", "1.0");
-        dataMessage.set("method", "thing.event.property.post");
-
-        JSONObject params = new JSONObject();
-        JSONObject properties = new JSONObject();
-        properties.set("temperature", 25.6);
-        properties.set("humidity", 60.3);
-        params.set("properties", properties);
-        dataMessage.set("params", params);
-
-        String topic = "/topic/sys/a1GFjLP****/device123/thing/event/property/post";
-        byte[] payload = dataMessage.toString().getBytes(StandardCharsets.UTF_8);
-
-        // 解析消息
-        IotMqttMessage result = parser.parse(topic, payload);
-
-        // 验证结果
-        assertNotNull(result);
-        assertEquals("123456", result.getId());
-        assertEquals("thing.event.property.post", result.getMethod());
-        assertEquals("1.0", result.getVersion());
-        assertNotNull(result.getParams());
-        assertNotNull(result.getParams().get("properties"));
-    }
-
-    @Test
-    void testParseRawDataMessage() {
-        // 原始数据消息
-        String rawData = "temperature:25.6,humidity:60.3";
-        String topic = "/topic/sys/a1GFjLP****/device123/thing/event/property/post";
-        byte[] payload = rawData.getBytes(StandardCharsets.UTF_8);
-
-        // 解析消息
-        IotMqttMessage result = parser.parse(topic, payload);
-
-        // 验证结果
-        assertNotNull(result);
-        assertNotNull(result.getId());
-        assertEquals("thing.event.property.post", result.getMethod());
-        assertEquals("1.0", result.getVersion());
-        assertNotNull(result.getParams());
-        assertEquals(rawData, result.getParams().get("data"));
-    }
-
-    @Test
-    void testInferMethodFromTopic() {
-        // 测试系统主题方法推断
-        testInferMethod("/sys/test/device/thing/service/property/set", "thing.service.property.set");
-        testInferMethod("/sys/test/device/thing/service/property/get", "thing.service.property.get");
-        testInferMethod("/sys/test/device/thing/event/property/post", "thing.event.property.post");
-        testInferMethod("/sys/test/device/thing/event/alarm/post", "thing.event.alarm.post");
-        testInferMethod("/sys/test/device/thing/service/reboot", "thing.service.reboot");
-
-        // 测试自定义主题
-        testInferMethod("/test/device/user/get", "custom.message");
-    }
-
-    private void testInferMethod(String actualTopic, String expectedMethod) {
-        String topic = "/topic" + actualTopic;
-        String rawData = "test data";
-        byte[] payload = rawData.getBytes(StandardCharsets.UTF_8);
-
-        IotMqttMessage result = parser.parse(topic, payload);
-        assertNotNull(result);
-        assertEquals(expectedMethod, result.getMethod());
-    }
-
-    @Test
-    void testFormatAuthResponse() {
-        // 创建认证成功响应
-        Map<String, Object> data = new HashMap<>();
-        data.put("token", "6944e5bfb92e4d4ea3918d1eda39****");
-
-        IotStandardResponse response = IotStandardResponse.success("auth123", "device.auth", data);
-
-        // 格式化响应
-        byte[] result = parser.formatResponse(response);
-
-        // 验证结果
-        assertNotNull(result);
-        assertTrue(result.length > 0);
-
-        String responseStr = new String(result, StandardCharsets.UTF_8);
-        JSONObject responseJson = new JSONObject(responseStr);
-
-        assertEquals(200, responseJson.getInt("code"));
-        assertEquals("success", responseJson.getStr("message"));
-        assertNotNull(responseJson.get("info"));
-
-        JSONObject info = responseJson.getJSONObject("info");
-        assertEquals("6944e5bfb92e4d4ea3918d1eda39****", info.getStr("token"));
-    }
-
-    @Test
-    void testFormatDataResponse() {
-        // 创建数据上报响应
-        IotStandardResponse response = IotStandardResponse.success("123456", "thing.event.property.post", null);
-
-        // 格式化响应
-        byte[] result = parser.formatResponse(response);
-
-        // 验证结果
-        assertNotNull(result);
-        assertTrue(result.length > 0);
-
-        String responseStr = new String(result, StandardCharsets.UTF_8);
-        JSONObject responseJson = new JSONObject(responseStr);
-
-        assertEquals(200, responseJson.getInt("code"));
-        assertEquals("success", responseJson.getStr("message"));
-        assertNotNull(responseJson.get("info"));
-
-        JSONObject info = responseJson.getJSONObject("info");
-        assertEquals("123456", info.getStr("messageId"));
-    }
-
-    @Test
-    void testParseInvalidMessage() {
-        String topic = "/topic/sys/test/device/thing/service/property/set";
-
-        // 测试空消息
-        assertNull(parser.parse(topic, null));
-        assertNull(parser.parse(topic, new byte[0]));
-
-        // 测试不支持的路径
-        byte[] validPayload = "test data".getBytes(StandardCharsets.UTF_8);
-        assertNull(parser.parse("/unknown/path", validPayload));
-    }
-
-    @Test
-    void testParseDeviceKey() {
-        // 测试有效的设备标识
-        String[] result1 = IotHttpMessageParser.parseDeviceKey("productKey/deviceName");
-        assertNotNull(result1);
-        assertEquals(2, result1.length);
-        assertEquals("productKey", result1[0]);
-        assertEquals("deviceName", result1[1]);
-
-        // 测试无效的设备标识
-        assertNull(IotHttpMessageParser.parseDeviceKey(null));
-        assertNull(IotHttpMessageParser.parseDeviceKey(""));
-        assertNull(IotHttpMessageParser.parseDeviceKey("invalid"));
-        assertNull(IotHttpMessageParser.parseDeviceKey("product/device/extra"));
-    }
-
-    @Test
-    void testBuildDeviceKey() {
-        // 测试构建设备标识
-        assertEquals("productKey/deviceName",
-                IotHttpMessageParser.buildDeviceKey("productKey", "deviceName"));
-
-        // 测试无效参数
-        assertNull(IotHttpMessageParser.buildDeviceKey(null, "deviceName"));
-        assertNull(IotHttpMessageParser.buildDeviceKey("productKey", null));
-        assertNull(IotHttpMessageParser.buildDeviceKey("", "deviceName"));
-        assertNull(IotHttpMessageParser.buildDeviceKey("productKey", ""));
-    }
-}

+ 0 - 190
yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/message/impl/IotMqttMessageParserTest.java

@@ -1,190 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.message.impl;
-
-import cn.hutool.json.JSONObject;
-import cn.iocoder.yudao.module.iot.protocol.message.IotMqttMessage;
-import cn.iocoder.yudao.module.iot.protocol.message.IotStandardResponse;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * IoT MQTT 消息解析器测试类
- *
- * @author haohao
- */
-class IotMqttMessageParserTest {
-
-    private IotMqttMessageParser parser;
-
-    @BeforeEach
-    void setUp() {
-        parser = new IotMqttMessageParser();
-    }
-
-    @Test
-    void testParseValidJsonMessage() {
-        // 构建有效的 JSON 消息
-        JSONObject message = new JSONObject();
-        message.set("id", "123456");
-        message.set("version", "1.0");
-        message.set("method", "thing.service.property.set");
-
-        Map<String, Object> params = new HashMap<>();
-        params.put("temperature", 25.5);
-        params.put("humidity", 60.0);
-        message.set("params", params);
-
-        String topic = "/sys/productKey/deviceName/thing/service/property/set";
-        byte[] payload = message.toString().getBytes(StandardCharsets.UTF_8);
-
-        // 解析消息
-        IotMqttMessage result = parser.parse(topic, payload);
-
-        // 验证结果
-        assertNotNull(result);
-        assertEquals("123456", result.getId());
-        assertEquals("1.0", result.getVersion());
-        assertEquals("thing.service.property.set", result.getMethod());
-        assertNotNull(result.getParams());
-        assertEquals(25.5, ((Number) result.getParams().get("temperature")).doubleValue());
-        assertEquals(60.0, ((Number) result.getParams().get("humidity")).doubleValue());
-    }
-
-    @Test
-    void testParseMessageWithoutMethod() {
-        // 构建没有 method 字段的消息,应该从 topic 中解析
-        JSONObject message = new JSONObject();
-        message.set("id", "789012");
-        message.set("version", "1.0");
-
-        Map<String, Object> params = new HashMap<>();
-        params.put("voltage", 3.3);
-        message.set("params", params);
-
-        String topic = "/sys/productKey/deviceName/thing/service/property/set";
-        byte[] payload = message.toString().getBytes(StandardCharsets.UTF_8);
-
-        // 解析消息
-        IotMqttMessage result = parser.parse(topic, payload);
-
-        // 验证结果
-        assertNotNull(result);
-        assertEquals("789012", result.getId());
-        assertEquals("1.0", result.getVersion());
-        assertNotNull(result.getMethod()); // 应该从 topic 中解析出方法
-        assertNotNull(result.getParams());
-        assertEquals(3.3, ((Number) result.getParams().get("voltage")).doubleValue());
-    }
-
-    @Test
-    void testParseInvalidJsonMessage() {
-        String topic = "/sys/productKey/deviceName/thing/service/property/set";
-        byte[] payload = "invalid json".getBytes(StandardCharsets.UTF_8);
-
-        // 解析消息
-        IotMqttMessage result = parser.parse(topic, payload);
-
-        // 验证结果
-        assertNull(result);
-    }
-
-    @Test
-    void testParseEmptyPayload() {
-        String topic = "/sys/productKey/deviceName/thing/service/property/set";
-
-        // 测试 null payload
-        IotMqttMessage result1 = parser.parse(topic, null);
-        assertNull(result1);
-
-        // 测试空 payload
-        IotMqttMessage result2 = parser.parse(topic, new byte[0]);
-        assertNull(result2);
-    }
-
-    @Test
-    void testFormatResponse() {
-        // 创建标准响应
-        IotStandardResponse response = IotStandardResponse.success("123456", "property.set", null);
-
-        // 格式化响应
-        byte[] result = parser.formatResponse(response);
-
-        // 验证结果
-        assertNotNull(result);
-        assertTrue(result.length > 0);
-
-        // 验证 JSON 格式
-        String jsonString = new String(result, StandardCharsets.UTF_8);
-        assertTrue(jsonString.contains("123456"));
-        assertTrue(jsonString.contains("property.set"));
-    }
-
-    @Test
-    void testCanHandle() {
-        // 测试支持的主题格式
-        assertTrue(parser.canHandle("/sys/productKey/deviceName/thing/service/property/set"));
-        assertTrue(parser.canHandle("/mqtt/productKey/deviceName/property/set"));
-        assertTrue(parser.canHandle("/device/productKey/deviceName/data"));
-
-        // 测试不支持的主题格式
-        assertFalse(parser.canHandle("/http/device/productKey/deviceName/property/set"));
-        assertFalse(parser.canHandle("/unknown/topic"));
-        assertFalse(parser.canHandle(null));
-        assertFalse(parser.canHandle(""));
-    }
-
-    @Test
-    void testParseMqttTopicFormat() {
-        // 测试新的 MQTT 主题格式
-        JSONObject message = new JSONObject();
-        message.set("id", "mqtt001");
-        message.set("version", "1.0");
-        message.set("method", "device.property.report");
-
-        Map<String, Object> params = new HashMap<>();
-        params.put("signal", 85);
-        message.set("params", params);
-
-        String topic = "/mqtt/productKey/deviceName/property/report";
-        byte[] payload = message.toString().getBytes(StandardCharsets.UTF_8);
-
-        // 解析消息
-        IotMqttMessage result = parser.parse(topic, payload);
-
-        // 验证结果
-        assertNotNull(result);
-        assertEquals("mqtt001", result.getId());
-        assertEquals("device.property.report", result.getMethod());
-        assertEquals(85, ((Number) result.getParams().get("signal")).intValue());
-    }
-
-    @Test
-    void testParseDeviceTopicFormat() {
-        // 测试设备主题格式
-        JSONObject message = new JSONObject();
-        message.set("id", "device001");
-        message.set("version", "1.0");
-        message.set("method", "sensor.data");
-
-        Map<String, Object> params = new HashMap<>();
-        params.put("timestamp", System.currentTimeMillis());
-        message.set("params", params);
-
-        String topic = "/device/productKey/deviceName/sensor/data";
-        byte[] payload = message.toString().getBytes(StandardCharsets.UTF_8);
-
-        // 解析消息
-        IotMqttMessage result = parser.parse(topic, payload);
-
-        // 验证结果
-        assertNotNull(result);
-        assertEquals("device001", result.getId());
-        assertEquals("sensor.data", result.getMethod());
-        assertNotNull(result.getParams().get("timestamp"));
-    }
-} 

+ 0 - 186
yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/util/IotHttpTopicUtilsTest.java

@@ -1,186 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.util;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link IotHttpTopicUtils} 单元测试
- *
- * @author haohao
- */
-class IotHttpTopicUtilsTest {
-
-    @Test
-    void testBuildAuthPath() {
-        assertEquals("/auth", IotHttpTopicUtils.buildAuthPath());
-    }
-
-    @Test
-    void testBuildTopicPath() {
-        // 测试正常路径
-        assertEquals("/topic/sys/test/device/thing/service/property/set",
-                IotHttpTopicUtils.buildTopicPath("/sys/test/device/thing/service/property/set"));
-
-        // 测试空路径
-        assertNull(IotHttpTopicUtils.buildTopicPath(null));
-        assertNull(IotHttpTopicUtils.buildTopicPath(""));
-    }
-
-    @Test
-    void testBuildPropertySetPath() {
-        String result = IotHttpTopicUtils.buildPropertySetPath("testProduct", "testDevice");
-        assertEquals("/topic/sys/testProduct/testDevice/thing/service/property/set", result);
-
-        // 测试无效参数
-        assertNull(IotHttpTopicUtils.buildPropertySetPath(null, "testDevice"));
-        assertNull(IotHttpTopicUtils.buildPropertySetPath("testProduct", null));
-        assertNull(IotHttpTopicUtils.buildPropertySetPath("", "testDevice"));
-        assertNull(IotHttpTopicUtils.buildPropertySetPath("testProduct", ""));
-    }
-
-    @Test
-    void testBuildPropertyGetPath() {
-        String result = IotHttpTopicUtils.buildPropertyGetPath("testProduct", "testDevice");
-        assertEquals("/topic/sys/testProduct/testDevice/thing/service/property/get", result);
-    }
-
-    @Test
-    void testBuildPropertyPostPath() {
-        String result = IotHttpTopicUtils.buildPropertyPostPath("testProduct", "testDevice");
-        assertEquals("/topic/sys/testProduct/testDevice/thing/event/property/post", result);
-    }
-
-    @Test
-    void testBuildEventPostPath() {
-        String result = IotHttpTopicUtils.buildEventPostPath("testProduct", "testDevice", "alarm");
-        assertEquals("/topic/sys/testProduct/testDevice/thing/event/alarm/post", result);
-
-        // 测试无效参数
-        assertNull(IotHttpTopicUtils.buildEventPostPath(null, "testDevice", "alarm"));
-        assertNull(IotHttpTopicUtils.buildEventPostPath("testProduct", null, "alarm"));
-        assertNull(IotHttpTopicUtils.buildEventPostPath("testProduct", "testDevice", null));
-    }
-
-    @Test
-    void testBuildServiceInvokePath() {
-        String result = IotHttpTopicUtils.buildServiceInvokePath("testProduct", "testDevice", "reboot");
-        assertEquals("/topic/sys/testProduct/testDevice/thing/service/reboot", result);
-
-        // 测试无效参数
-        assertNull(IotHttpTopicUtils.buildServiceInvokePath(null, "testDevice", "reboot"));
-        assertNull(IotHttpTopicUtils.buildServiceInvokePath("testProduct", null, "reboot"));
-        assertNull(IotHttpTopicUtils.buildServiceInvokePath("testProduct", "testDevice", null));
-    }
-
-    @Test
-    void testBuildCustomTopicPath() {
-        String result = IotHttpTopicUtils.buildCustomTopicPath("testProduct", "testDevice", "user/get");
-        assertEquals("/topic/testProduct/testDevice/user/get", result);
-
-        // 测试无效参数
-        assertNull(IotHttpTopicUtils.buildCustomTopicPath(null, "testDevice", "user/get"));
-        assertNull(IotHttpTopicUtils.buildCustomTopicPath("testProduct", null, "user/get"));
-        assertNull(IotHttpTopicUtils.buildCustomTopicPath("testProduct", "testDevice", null));
-    }
-
-    @Test
-    void testExtractActualTopic() {
-        // 测试正常提取
-        String actualTopic = IotHttpTopicUtils
-                .extractActualTopic("/topic/sys/testProduct/testDevice/thing/service/property/set");
-        assertEquals("/sys/testProduct/testDevice/thing/service/property/set", actualTopic);
-
-        // 测试无效路径
-        assertNull(IotHttpTopicUtils.extractActualTopic("/auth"));
-        assertNull(IotHttpTopicUtils.extractActualTopic("/unknown/path"));
-        assertNull(IotHttpTopicUtils.extractActualTopic(null));
-        assertNull(IotHttpTopicUtils.extractActualTopic(""));
-    }
-
-    @Test
-    void testParseProductKeyFromTopic() {
-        // 测试系统主题
-        assertEquals("testProduct",
-                IotHttpTopicUtils.parseProductKeyFromTopic("/sys/testProduct/testDevice/thing/service/property/set"));
-
-        // 测试自定义主题
-        assertEquals("testProduct", IotHttpTopicUtils.parseProductKeyFromTopic("/testProduct/testDevice/user/get"));
-
-        // 测试无效主题
-        assertNull(IotHttpTopicUtils.parseProductKeyFromTopic("/sys"));
-        assertNull(IotHttpTopicUtils.parseProductKeyFromTopic("/single"));
-        assertNull(IotHttpTopicUtils.parseProductKeyFromTopic(""));
-        assertNull(IotHttpTopicUtils.parseProductKeyFromTopic(null));
-    }
-
-    @Test
-    void testParseDeviceNameFromTopic() {
-        // 测试系统主题
-        assertEquals("testDevice",
-                IotHttpTopicUtils.parseDeviceNameFromTopic("/sys/testProduct/testDevice/thing/service/property/set"));
-
-        // 测试自定义主题
-        assertEquals("testDevice", IotHttpTopicUtils.parseDeviceNameFromTopic("/testProduct/testDevice/user/get"));
-
-        // 测试无效主题
-        assertNull(IotHttpTopicUtils.parseDeviceNameFromTopic("/sys/testProduct"));
-        assertNull(IotHttpTopicUtils.parseDeviceNameFromTopic("/testProduct"));
-        assertNull(IotHttpTopicUtils.parseDeviceNameFromTopic(""));
-        assertNull(IotHttpTopicUtils.parseDeviceNameFromTopic(null));
-    }
-
-    @Test
-    void testIsAuthPath() {
-        assertTrue(IotHttpTopicUtils.isAuthPath("/auth"));
-        assertFalse(IotHttpTopicUtils.isAuthPath("/topic/test"));
-        assertFalse(IotHttpTopicUtils.isAuthPath("/unknown"));
-        assertFalse(IotHttpTopicUtils.isAuthPath(null));
-        assertFalse(IotHttpTopicUtils.isAuthPath(""));
-    }
-
-    @Test
-    void testIsTopicPath() {
-        assertTrue(IotHttpTopicUtils.isTopicPath("/topic/sys/test/device/property"));
-        assertTrue(IotHttpTopicUtils.isTopicPath("/topic/test"));
-        assertFalse(IotHttpTopicUtils.isTopicPath("/auth"));
-        assertFalse(IotHttpTopicUtils.isTopicPath("/unknown"));
-        assertFalse(IotHttpTopicUtils.isTopicPath(null));
-        assertFalse(IotHttpTopicUtils.isTopicPath(""));
-    }
-
-    @Test
-    void testIsValidHttpPath() {
-        assertTrue(IotHttpTopicUtils.isValidHttpPath("/auth"));
-        assertTrue(IotHttpTopicUtils.isValidHttpPath("/topic/test"));
-        assertFalse(IotHttpTopicUtils.isValidHttpPath("/unknown"));
-        assertFalse(IotHttpTopicUtils.isValidHttpPath(null));
-        assertFalse(IotHttpTopicUtils.isValidHttpPath(""));
-    }
-
-    @Test
-    void testIsSystemTopic() {
-        assertTrue(IotHttpTopicUtils.isSystemTopic("/sys/testProduct/testDevice/thing/service/property/set"));
-        assertFalse(IotHttpTopicUtils.isSystemTopic("/testProduct/testDevice/user/get"));
-        assertFalse(IotHttpTopicUtils.isSystemTopic("/unknown"));
-        assertFalse(IotHttpTopicUtils.isSystemTopic(null));
-        assertFalse(IotHttpTopicUtils.isSystemTopic(""));
-    }
-
-    @Test
-    void testBuildReplyPath() {
-        // 测试系统主题响应路径
-        String requestPath = "/topic/sys/testProduct/testDevice/thing/service/property/set";
-        String replyPath = IotHttpTopicUtils.buildReplyPath(requestPath);
-        assertEquals("/topic/sys/testProduct/testDevice/thing/service/property/set_reply", replyPath);
-
-        // 测试非系统主题
-        String customPath = "/topic/testProduct/testDevice/user/get";
-        assertNull(IotHttpTopicUtils.buildReplyPath(customPath));
-
-        // 测试无效路径
-        assertNull(IotHttpTopicUtils.buildReplyPath("/auth"));
-        assertNull(IotHttpTopicUtils.buildReplyPath("/unknown"));
-        assertNull(IotHttpTopicUtils.buildReplyPath(null));
-    }
-}

+ 0 - 81
yudao-module-iot/yudao-module-iot-protocol/src/test/java/cn/iocoder/yudao/module/iot/protocol/util/IotTopicUtilsTest.java

@@ -1,81 +0,0 @@
-package cn.iocoder.yudao.module.iot.protocol.util;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-
-/**
- * {@link IotTopicUtils} 单元测试
- *
- * @author haohao
- */
-class IotTopicUtilsTest {
-
-    @Test
-    void testBuildPropertySetTopic() {
-        String topic = IotTopicUtils.buildPropertySetTopic("testProduct", "testDevice");
-        assertEquals("/sys/testProduct/testDevice/thing/service/property/set", topic);
-    }
-
-    @Test
-    void testBuildPropertyGetTopic() {
-        String topic = IotTopicUtils.buildPropertyGetTopic("testProduct", "testDevice");
-        assertEquals("/sys/testProduct/testDevice/thing/service/property/get", topic);
-    }
-
-    @Test
-    void testBuildEventPostTopic() {
-        String topic = IotTopicUtils.buildEventPostTopic("testProduct", "testDevice", "temperature");
-        assertEquals("/sys/testProduct/testDevice/thing/event/temperature/post", topic);
-    }
-
-    @Test
-    void testGetReplyTopic() {
-        String requestTopic = "/sys/testProduct/testDevice/thing/service/property/set";
-        String replyTopic = IotTopicUtils.getReplyTopic(requestTopic);
-        assertEquals("/sys/testProduct/testDevice/thing/service/property/set_reply", replyTopic);
-    }
-
-    @Test
-    void testParseProductKeyFromTopic() {
-        String topic = "/sys/testProduct/testDevice/thing/service/property/set";
-        String productKey = IotTopicUtils.parseProductKeyFromTopic(topic);
-        assertEquals("testProduct", productKey);
-    }
-
-    @Test
-    void testParseDeviceNameFromTopic() {
-        String topic = "/sys/testProduct/testDevice/thing/service/property/set";
-        String deviceName = IotTopicUtils.parseDeviceNameFromTopic(topic);
-        assertEquals("testDevice", deviceName);
-    }
-
-    @Test
-    void testParseMethodFromTopic() {
-        // 测试属性设置
-        String topic1 = "/sys/testProduct/testDevice/thing/service/property/set";
-        String method1 = IotTopicUtils.parseMethodFromTopic(topic1);
-        assertEquals("property.set", method1);
-
-        // 测试事件上报
-        String topic2 = "/sys/testProduct/testDevice/thing/event/temperature/post";
-        String method2 = IotTopicUtils.parseMethodFromTopic(topic2);
-        assertEquals("event.temperature.post", method2);
-
-        // 测试无效主题
-        String method3 = IotTopicUtils.parseMethodFromTopic("/invalid/topic");
-        assertNull(method3);
-    }
-
-    @Test
-    void testParseInvalidTopic() {
-        // 测试空主题
-        assertNull(IotTopicUtils.parseProductKeyFromTopic(""));
-        assertNull(IotTopicUtils.parseProductKeyFromTopic(null));
-
-        // 测试格式错误的主题
-        assertNull(IotTopicUtils.parseProductKeyFromTopic("/invalid"));
-        assertNull(IotTopicUtils.parseDeviceNameFromTopic("/sys/product"));
-    }
-}