24282 2 lat temu
rodzic
commit
eb27e097c8
54 zmienionych plików z 2526 dodań i 0 usunięć
  1. 17 0
      code/src/test/java/IotDataSource.java
  2. 5 0
      hx-admin/pom.xml
  3. 4 0
      hx-admin/src/main/resources/application-dev.yml
  4. 2 0
      hx-common/src/main/java/com/fjhx/common/constant/SourceConstant.java
  5. 27 0
      hx-iot/pom.xml
  6. 36 0
      hx-iot/src/main/java/com/fjhx/iot/config/IoTDAConfig.java
  7. 16 0
      hx-iot/src/main/java/com/fjhx/iot/constants/RedisConstant.java
  8. 66 0
      hx-iot/src/main/java/com/fjhx/iot/controller/tda/TdaApplicationController.java
  9. 71 0
      hx-iot/src/main/java/com/fjhx/iot/controller/tda/TdaConfigController.java
  10. 60 0
      hx-iot/src/main/java/com/fjhx/iot/controller/tda/TdaDeviceController.java
  11. 63 0
      hx-iot/src/main/java/com/fjhx/iot/controller/tda/TdaProductController.java
  12. 50 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/MessageBody.java
  13. 28 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/OpcUaData.java
  14. 17 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaApplicationDto.java
  15. 17 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaApplicationSelectDto.java
  16. 17 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaConfigDto.java
  17. 17 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaConfigSelectDto.java
  18. 17 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaDeviceDto.java
  19. 17 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaDeviceSelectDto.java
  20. 17 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaProductDto.java
  21. 17 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaProductSelectDto.java
  22. 46 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/UpperComputerData.java
  23. 100 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/ZSJDto.java
  24. 42 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/po/TdaApplication.java
  25. 66 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/po/TdaConfig.java
  26. 52 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/po/TdaDevice.java
  27. 62 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/po/TdaProduct.java
  28. 22 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/vo/TdaApplicationVo.java
  29. 17 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/vo/TdaConfigVo.java
  30. 27 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/vo/TdaDeviceVo.java
  31. 22 0
      hx-iot/src/main/java/com/fjhx/iot/entity/tda/vo/TdaProductVo.java
  32. 50 0
      hx-iot/src/main/java/com/fjhx/iot/enums/ProductEnum.java
  33. 46 0
      hx-iot/src/main/java/com/fjhx/iot/enums/UpperComputerEnum.java
  34. 252 0
      hx-iot/src/main/java/com/fjhx/iot/listener/DtaListener.java
  35. 26 0
      hx-iot/src/main/java/com/fjhx/iot/mapper/tda/TdaApplicationMapper.java
  36. 26 0
      hx-iot/src/main/java/com/fjhx/iot/mapper/tda/TdaConfigMapper.java
  37. 26 0
      hx-iot/src/main/java/com/fjhx/iot/mapper/tda/TdaDeviceMapper.java
  38. 26 0
      hx-iot/src/main/java/com/fjhx/iot/mapper/tda/TdaProductMapper.java
  39. 41 0
      hx-iot/src/main/java/com/fjhx/iot/service/tda/TdaApplicationService.java
  40. 46 0
      hx-iot/src/main/java/com/fjhx/iot/service/tda/TdaConfigService.java
  41. 41 0
      hx-iot/src/main/java/com/fjhx/iot/service/tda/TdaDeviceService.java
  42. 41 0
      hx-iot/src/main/java/com/fjhx/iot/service/tda/TdaProductService.java
  43. 59 0
      hx-iot/src/main/java/com/fjhx/iot/service/tda/impl/TdaApplicationServiceImpl.java
  44. 87 0
      hx-iot/src/main/java/com/fjhx/iot/service/tda/impl/TdaConfigServiceImpl.java
  45. 93 0
      hx-iot/src/main/java/com/fjhx/iot/service/tda/impl/TdaDeviceServiceImpl.java
  46. 81 0
      hx-iot/src/main/java/com/fjhx/iot/service/tda/impl/TdaProductServiceImpl.java
  47. 204 0
      hx-iot/src/main/java/com/fjhx/iot/utils/IoTDAUtil.java
  48. 96 0
      hx-iot/src/main/java/com/fjhx/iot/utils/amqp/AmqpClient.java
  49. 118 0
      hx-iot/src/main/java/com/fjhx/iot/utils/amqp/AmqpClientOptions.java
  50. 37 0
      hx-iot/src/main/java/com/fjhx/iot/utils/amqp/AmqpConstants.java
  51. 20 0
      hx-iot/src/main/resources/mapper/tda/TdaApplicationMapper.xml
  52. 24 0
      hx-iot/src/main/resources/mapper/tda/TdaConfigMapper.xml
  53. 24 0
      hx-iot/src/main/resources/mapper/tda/TdaDeviceMapper.xml
  54. 25 0
      hx-iot/src/main/resources/mapper/tda/TdaProductMapper.xml

+ 17 - 0
code/src/test/java/IotDataSource.java

@@ -0,0 +1,17 @@
+import fly.generator.GeneratorApplication;
+
+public class IotDataSource {
+
+    public static void main(String[] args) {
+        GeneratorApplication.builder()
+                .url("jdbc:mysql://36.134.91.96:17330/bytesailing_iot?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true")
+                .username("fjhx2012mysql")
+                .password("3PN-Mzn#vnP&q6d")
+                .port(9099)
+                .module("hx-iot")
+                .parent("com.fjhx.iot")
+                .superServiceClass("com.ruoyi.common.core.service.BaseService")
+                .build();
+    }
+
+}

+ 5 - 0
hx-admin/pom.xml

@@ -29,6 +29,11 @@
             <artifactId>hx-supply</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.fjhx</groupId>
+            <artifactId>hx-iot</artifactId>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 4 - 0
hx-admin/src/main/resources/application-dev.yml

@@ -17,6 +17,10 @@ spring:
                     url: jdbc:mysql://36.134.91.96:17330/bytesailing_base?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                     username: fjhx2012mysql
                     password: 3PN-Mzn#vnP&q6d
+                iot:
+                    url: jdbc:mysql://36.134.91.96:17330/bytesailing_iot?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: fjhx2012mysql
+                    password: 3PN-Mzn#vnP&q6d
 
     # redis 配置
     redis:

+ 2 - 0
hx-common/src/main/java/com/fjhx/common/constant/SourceConstant.java

@@ -6,4 +6,6 @@ public interface SourceConstant {
 
     String SUPPLY = "supply";
 
+    String IOT = "iot";
+
 }

+ 27 - 0
hx-iot/pom.xml

@@ -12,5 +12,32 @@
 
     <artifactId>hx-iot</artifactId>
 
+    <dependencies>
+
+        <dependency>
+            <groupId>com.fjhx</groupId>
+            <artifactId>hx-base</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fjhx</groupId>
+            <artifactId>hx-common</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.huaweicloud.sdk</groupId>
+            <artifactId>huaweicloud-sdk-all</artifactId>
+            <version>3.0.92</version>
+        </dependency>
+
+        <!-- amqp -->
+        <dependency>
+            <groupId>org.apache.qpid</groupId>
+            <artifactId>qpid-jms-client</artifactId>
+            <version>0.61.0</version>
+        </dependency>
+
+
+    </dependencies>
 
 </project>

+ 36 - 0
hx-iot/src/main/java/com/fjhx/iot/config/IoTDAConfig.java

@@ -0,0 +1,36 @@
+package com.fjhx.iot.config;
+
+public class IoTDAConfig {
+
+    // REGION_ID:如果是上海一,请填写"cn-east-3";如果是北京四,请填写"cn-north-4";如果是华南广州,请填写"cn-south-4"
+    private static final String REGION_ID = "cn-north-4";
+    // ENDPOINT:请在控制台的"总览"界面的"平台接入地址"中查看“应用侧”的https接入地址。
+    private static final String ENDPOINT = "a1625d5cc8.iotda.cn-north-4.myhuaweicloud.com";
+
+    private static final String ak = "VPOCS8WGONHWOBOZNVVJ";
+    private static final String sk = "4mvyTAn75I0hvyAm8rKxuXi6TSyGDG5yblW43ci1";
+    private static final String projectId = "0f130b202d00f4e52fc0c01deb21f36a";
+
+    /**
+     * IoTDA 操作
+     */
+    // @Bean
+    // public IoTDAClient ioTDAClient() {
+    //     // 创建认证
+    //     ICredential auth = new IoTDACredentials()
+    //             .withAk(ak)
+    //             .withSk(sk)
+    //             .withProjectId(projectId);
+    //
+    //     // 创建IoTDAClient实例并初始化
+    //     return IoTDAClient.newBuilder()
+    //             .withCredential(auth)
+    //             // 基础版:请选择IoTDARegion中的Region对象
+    //             .withRegion(IoTDARegion.CN_NORTH_4)
+    //             // 标准版/企业版:需自行创建Region对象
+    //             // .withRegion(new Region(REGION_ID, ENDPOINT))
+    //             .build();
+    // }
+
+
+}

+ 16 - 0
hx-iot/src/main/java/com/fjhx/iot/constants/RedisConstant.java

@@ -0,0 +1,16 @@
+package com.fjhx.iot.constants;
+
+public interface RedisConstant {
+
+    String PREFIX = "syringe-production:";
+
+    String DATA_AUTOCLAVES = PREFIX + "dataAutoclaves:";
+
+    String DATA_PACKER = PREFIX + "dataPacker:";
+
+    /**
+     * 设备数据前缀
+     */
+    String DEVICE_PREFIX = "device:";
+
+}

+ 66 - 0
hx-iot/src/main/java/com/fjhx/iot/controller/tda/TdaApplicationController.java

@@ -0,0 +1,66 @@
+package com.fjhx.iot.controller.tda;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.common.constant.SourceConstant;
+import com.fjhx.iot.entity.tda.dto.TdaApplicationDto;
+import com.fjhx.iot.entity.tda.dto.TdaApplicationSelectDto;
+import com.fjhx.iot.entity.tda.vo.TdaApplicationVo;
+import com.fjhx.iot.service.tda.TdaApplicationService;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * <p>
+ * 行业管理 前端控制器
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@DS(SourceConstant.IOT)
+@RestController
+@RequestMapping("/tdaApplication")
+public class TdaApplicationController {
+
+    @Autowired
+    private TdaApplicationService tdaApplicationService;
+
+    /**
+     * 行业管理分页
+     */
+    @PostMapping("/page")
+    public Page<TdaApplicationVo> page(@RequestBody TdaApplicationSelectDto dto) {
+        return tdaApplicationService.getPage(dto);
+    }
+
+    /**
+     * 行业管理明细
+     */
+    @PostMapping("/detail")
+    public TdaApplicationVo detail(@RequestBody BaseSelectDto dto) {
+        return tdaApplicationService.detail(dto.getId());
+    }
+
+    /**
+     * 行业管理新增
+     */
+    @PostMapping("/add")
+    public void add(@RequestBody TdaApplicationDto tdaApplicationDto) {
+        tdaApplicationService.add(tdaApplicationDto);
+    }
+
+    /**
+     * 行业管理删除
+     */
+    @PostMapping("/delete")
+    public void delete(@RequestBody BaseSelectDto dto) {
+        tdaApplicationService.delete(dto.getId());
+    }
+
+}

+ 71 - 0
hx-iot/src/main/java/com/fjhx/iot/controller/tda/TdaConfigController.java

@@ -0,0 +1,71 @@
+package com.fjhx.iot.controller.tda;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.fjhx.common.constant.SourceConstant;
+import org.springframework.web.bind.annotation.*;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.vo.TdaConfigVo;
+import com.fjhx.iot.entity.tda.dto.TdaConfigSelectDto;
+import com.fjhx.iot.entity.tda.dto.TdaConfigDto;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import com.fjhx.iot.service.tda.TdaConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+/**
+ * <p>
+ * iot配置 前端控制器
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@DS(SourceConstant.IOT)
+@RestController
+@RequestMapping("/tdaConfig")
+public class TdaConfigController {
+
+    @Autowired
+    private TdaConfigService tdaConfigService;
+
+    /**
+     * iot配置分页
+     */
+    @PostMapping("/page")
+    public Page<TdaConfigVo> page(@RequestBody TdaConfigSelectDto dto) {
+        return tdaConfigService.getPage(dto);
+    }
+
+    /**
+     * iot配置明细
+     */
+    @PostMapping("/detail")
+    public TdaConfigVo detail(@RequestBody BaseSelectDto dto) {
+        return tdaConfigService.detail(dto.getId());
+    }
+
+    /**
+     * iot配置新增
+     */
+    @PostMapping("/add")
+    public void add(@RequestBody TdaConfigDto tdaConfigDto) {
+        tdaConfigService.add(tdaConfigDto);
+    }
+
+    /**
+     * iot配置编辑
+     */
+    @PostMapping("/edit")
+    public void edit(@RequestBody TdaConfigDto tdaConfigDto) {
+        tdaConfigService.edit(tdaConfigDto);
+    }
+
+    /**
+     * iot配置删除
+     */
+    @PostMapping("/delete")
+    public void delete(@RequestBody BaseSelectDto dto) {
+        tdaConfigService.delete(dto.getId());
+    }
+
+}

+ 60 - 0
hx-iot/src/main/java/com/fjhx/iot/controller/tda/TdaDeviceController.java

@@ -0,0 +1,60 @@
+package com.fjhx.iot.controller.tda;
+
+import org.springframework.web.bind.annotation.*;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.vo.TdaDeviceVo;
+import com.fjhx.iot.entity.tda.dto.TdaDeviceSelectDto;
+import com.fjhx.iot.entity.tda.dto.TdaDeviceDto;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import com.fjhx.iot.service.tda.TdaDeviceService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+/**
+ * <p>
+ * 设备管理 前端控制器
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@RestController
+@RequestMapping("/tdaDevice")
+public class TdaDeviceController {
+
+    @Autowired
+    private TdaDeviceService tdaDeviceService;
+
+    /**
+     * 设备管理分页
+     */
+    @PostMapping("/page")
+    public Page<TdaDeviceVo> page(@RequestBody TdaDeviceSelectDto dto) {
+        return tdaDeviceService.getPage(dto);
+    }
+
+    /**
+     * 设备管理明细
+     */
+    @PostMapping("/detail")
+    public TdaDeviceVo detail(@RequestBody BaseSelectDto dto) {
+        return tdaDeviceService.detail(dto.getId());
+    }
+
+    /**
+     * 设备管理新增
+     */
+    @PostMapping("/add")
+    public void add(@RequestBody TdaDeviceDto tdaDeviceDto) {
+        tdaDeviceService.add(tdaDeviceDto);
+    }
+
+    /**
+     * 设备管理删除
+     */
+    @PostMapping("/delete")
+    public void delete(@RequestBody BaseSelectDto dto) {
+        tdaDeviceService.delete(dto.getId());
+    }
+
+}

+ 63 - 0
hx-iot/src/main/java/com/fjhx/iot/controller/tda/TdaProductController.java

@@ -0,0 +1,63 @@
+package com.fjhx.iot.controller.tda;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.dto.TdaProductDto;
+import com.fjhx.iot.entity.tda.dto.TdaProductSelectDto;
+import com.fjhx.iot.entity.tda.vo.TdaProductVo;
+import com.fjhx.iot.service.tda.TdaProductService;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * <p>
+ * 产品管理 前端控制器
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@RestController
+@RequestMapping("/tdaProduct")
+public class TdaProductController {
+
+    @Autowired
+    private TdaProductService tdaProductService;
+
+    /**
+     * 产品管理分页
+     */
+    @PostMapping("/page")
+    public Page<TdaProductVo> page(@RequestBody TdaProductSelectDto dto) {
+        return tdaProductService.getPage(dto);
+    }
+
+    /**
+     * 产品管理明细
+     */
+    @PostMapping("/detail")
+    public TdaProductVo detail(@RequestBody BaseSelectDto dto) {
+        return tdaProductService.detail(dto.getId());
+    }
+
+    /**
+     * 产品管理新增
+     */
+    @PostMapping("/add")
+    public void add(@RequestBody TdaProductDto tdaProductDto) {
+        tdaProductService.add(tdaProductDto);
+    }
+
+    /**
+     * 产品管理删除
+     */
+    @PostMapping("/delete")
+    public void delete(@RequestBody BaseSelectDto dto) {
+        tdaProductService.delete(dto.getId());
+    }
+
+}

+ 50 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/MessageBody.java

@@ -0,0 +1,50 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 华为云推送数据
+ *
+ * @author zlj
+ */
+@Data
+public class MessageBody {
+
+    private String resource;
+    private String event;
+    private String requestId;
+    private Date eventTime;
+    private NotifyData notifyData;
+
+    @Data
+    public static class NotifyData {
+        private Header header;
+        private Body body;
+    }
+
+    @Data
+    public static class Header {
+        private String deviceId;
+        private String productId;
+        private String appId;
+        private String gatewayId;
+        private String nodeId;
+    }
+
+    @Data
+    public static class Body {
+        private List<Service> services;
+    }
+
+    @Data
+    public static class Service {
+        private String serviceId;
+        private JSONObject properties;
+        private Date eventTime;
+    }
+
+}

+ 28 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/OpcUaData.java

@@ -0,0 +1,28 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import lombok.Data;
+
+@Data
+public class OpcUaData {
+
+    /**
+     * 节点id
+     */
+    private String id;
+
+    /**
+     * 节点名称
+     */
+    private String nodeName;
+
+    /**
+     * ns
+     */
+    private String ns;
+
+    /**
+     * 节点类型
+     */
+    private String type;
+
+}

+ 17 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaApplicationDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import com.fjhx.iot.entity.tda.po.TdaApplication;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 行业管理新增编辑入参实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaApplicationDto extends TdaApplication {
+
+}

+ 17 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaApplicationSelectDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 行业管理列表查询入参实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaApplicationSelectDto extends BaseSelectDto {
+
+}

+ 17 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaConfigDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import com.fjhx.iot.entity.tda.po.TdaConfig;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * iot配置新增编辑入参实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaConfigDto extends TdaConfig {
+
+}

+ 17 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaConfigSelectDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * iot配置列表查询入参实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaConfigSelectDto extends BaseSelectDto {
+
+}

+ 17 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaDeviceDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import com.fjhx.iot.entity.tda.po.TdaDevice;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 设备管理新增编辑入参实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaDeviceDto extends TdaDevice {
+
+}

+ 17 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaDeviceSelectDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 设备管理列表查询入参实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaDeviceSelectDto extends BaseSelectDto {
+
+}

+ 17 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaProductDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import com.fjhx.iot.entity.tda.po.TdaProduct;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 产品管理新增编辑入参实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaProductDto extends TdaProduct {
+
+}

+ 17 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/TdaProductSelectDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 产品管理列表查询入参实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaProductSelectDto extends BaseSelectDto {
+
+}

+ 46 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/UpperComputerData.java

@@ -0,0 +1,46 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class UpperComputerData {
+
+    /**
+     * 设备编号
+     */
+    private String equipmentNo;
+
+    /**
+     * 设备ip地址
+     */
+    private String ipAddress;
+
+    /**
+     * 设备端口号
+     */
+    private Integer port;
+
+    /**
+     * 设备类型
+     */
+    private Integer type;
+
+    /**
+     * 其他配置
+     */
+    private JSONObject other;
+
+    /**
+     * 记录时间
+     */
+    private Date createTime;
+
+    /**
+     * 生成数据
+     */
+    private Object data;
+
+}

+ 100 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/dto/ZSJDto.java

@@ -0,0 +1,100 @@
+package com.fjhx.iot.entity.tda.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class ZSJDto {
+
+    /**
+     * 在线状态(设备状态)
+     * 0:离线
+     * 1:在线
+     */
+    private Integer tmOnlineState;
+
+    /**
+     * 操作状态(工作模式)
+     * 0:手动
+     * 1:半自动
+     * 2:电眼自动
+     * 3:时间自动
+     * 4:调模使用
+     * >=5 其它
+     */
+    private Integer tmOperateMode;
+
+    /**
+     * 马达状态(模具状态)
+     * 0:关
+     * 1:开
+     */
+    private Integer tmMotorState;
+
+    /**
+     * 电热状态(液压机)
+     * 0:关
+     * 1:开
+     */
+    private Integer tmHeatState;
+
+    /**
+     * 油温(液压油温度)
+     * 原名(tmTempOil_Current)
+     */
+    private BigDecimal tmTempOilCurrent;
+
+    /**
+     * 实际温度(简体温度)
+     * ( tmTemp1_Current ~ tmTemp9_Current )平均值
+     */
+    private BigDecimal tmTempCurrent;
+
+    /**
+     * 储料1段压力B(通道1)
+     */
+    private BigDecimal tmChargePressB1;
+
+    /**
+     * 储料2段压力B(通道2)
+     */
+    private BigDecimal tmChargePressB2;
+
+    /**
+     * 储料3段压力B(通道3)
+     */
+    private BigDecimal tmChargePressB3;
+
+    /**
+     * 储料4段压力B(通道4)
+     */
+    private BigDecimal tmChargePressB4;
+
+    /**
+     * 储料1段速度 B(速度1)
+     */
+    private BigDecimal tmChargeSpeedB1;
+
+    /**
+     * 储料2段速度 B(速度2)
+     */
+    private BigDecimal tmChargeSpeedB2;
+
+    /**
+     * 储料3段速度 B(速度3)
+     */
+    private BigDecimal tmChargeSpeedB3;
+
+    /**
+     * 储料4段速度 B(速度4)
+     */
+    private BigDecimal tmChargeSpeedB4;
+
+    /**
+     * 上传时间
+     */
+    private Date date;
+
+}

+ 42 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/po/TdaApplication.java

@@ -0,0 +1,42 @@
+package com.fjhx.iot.entity.tda.po;
+
+import com.ruoyi.common.core.domain.BasePo;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 行业管理
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+@TableName("tda_application")
+public class TdaApplication extends BasePo {
+
+    /**
+     * iot配置id
+     */
+    private Long tdaConfigId;
+
+    /**
+     * AppId
+     */
+    private String appId;
+
+    /**
+     * 行业名称
+     */
+    private String appName;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 66 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/po/TdaConfig.java

@@ -0,0 +1,66 @@
+package com.fjhx.iot.entity.tda.po;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.domain.BasePo;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * iot配置
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+@TableName("tda_config")
+public class TdaConfig extends BasePo {
+
+    /**
+     * 类型 1华为
+     */
+    private Integer type;
+
+    /**
+     * 平台名称
+     */
+    private String name;
+
+    /**
+     * EndPoint
+     */
+    private String endPoint;
+
+    /**
+     * Access Key Id
+     */
+    private String accessKeyId;
+
+    /**
+     * Secret Access Key
+     */
+    private String secretAccessKey;
+
+    /**
+     * accessKey
+     */
+    private String accessKey;
+
+    /**
+     * accessCode
+     */
+    private String accessCode;
+
+    /**
+     * 项目 ID
+     */
+    private String productId;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 52 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/po/TdaDevice.java

@@ -0,0 +1,52 @@
+package com.fjhx.iot.entity.tda.po;
+
+import com.ruoyi.common.core.domain.BasePo;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 设备管理
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+@TableName("tda_device")
+public class TdaDevice extends BasePo {
+
+    /**
+     * 产品表id
+     */
+    private Long tdaProductId;
+
+    /**
+     * 华为tda产品id
+     */
+    private String productId;
+
+    /**
+     * 设备节点(设备标识)
+     */
+    private String nodeId;
+
+    /**
+     * 设备名称
+     */
+    private String deviceName;
+
+    /**
+     * 设备id
+     */
+    private String deviceId;
+
+    /**
+     * 设备密匙
+     */
+    private String secret;
+
+}

+ 62 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/po/TdaProduct.java

@@ -0,0 +1,62 @@
+package com.fjhx.iot.entity.tda.po;
+
+import com.ruoyi.common.core.domain.BasePo;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 产品管理
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+@TableName("tda_product")
+public class TdaProduct extends BasePo {
+
+    /**
+     * 资源空间表id
+     */
+    private Long tdaApplicationId;
+
+    /**
+     * 华为tda资源空间id
+     */
+    private String appId;
+
+    /**
+     * 华为tda产品id
+     */
+    private String productId;
+
+    /**
+     * 华为tda产品名称
+     */
+    private String name;
+
+    /**
+     * 华为tda产品设备类型
+     */
+    private String deviceType;
+
+    /**
+     * 华为tda产品厂商名称
+     */
+    private String manufacturerName;
+
+    /**
+     * 协议类型 默认MQTT
+     */
+    private String protocolType;
+
+    /**
+     * 数据格式 默认json
+     */
+    private String dataFormat;
+
+}

+ 22 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/vo/TdaApplicationVo.java

@@ -0,0 +1,22 @@
+package com.fjhx.iot.entity.tda.vo;
+
+import com.fjhx.iot.entity.tda.po.TdaApplication;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 行业管理列表查询返回值实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaApplicationVo extends TdaApplication {
+
+    /**
+     * 平台名称
+     */
+    private String configName;
+
+}

+ 17 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/vo/TdaConfigVo.java

@@ -0,0 +1,17 @@
+package com.fjhx.iot.entity.tda.vo;
+
+import com.fjhx.iot.entity.tda.po.TdaConfig;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * iot配置列表查询返回值实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaConfigVo extends TdaConfig {
+
+}

+ 27 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/vo/TdaDeviceVo.java

@@ -0,0 +1,27 @@
+package com.fjhx.iot.entity.tda.vo;
+
+import com.fjhx.iot.entity.tda.po.TdaDevice;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 设备管理列表查询返回值实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaDeviceVo extends TdaDevice {
+
+    /**
+     * 行业名称
+     */
+    private String appName;
+
+    /**
+     * 产品名称
+     */
+    private String productName;
+
+}

+ 22 - 0
hx-iot/src/main/java/com/fjhx/iot/entity/tda/vo/TdaProductVo.java

@@ -0,0 +1,22 @@
+package com.fjhx.iot.entity.tda.vo;
+
+import com.fjhx.iot.entity.tda.po.TdaProduct;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 产品管理列表查询返回值实体
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Getter
+@Setter
+public class TdaProductVo extends TdaProduct {
+
+    /**
+     * 行业名称
+     */
+    private String appName;
+
+}

+ 50 - 0
hx-iot/src/main/java/com/fjhx/iot/enums/ProductEnum.java

@@ -0,0 +1,50 @@
+package com.fjhx.iot.enums;
+
+import lombok.Getter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 设备枚举
+ *
+ * @author zlj
+ */
+@Getter
+public enum ProductEnum {
+    // 经编机
+    JBJ("6350ae233ec34a6d03c89020", "经编机"),
+    // 验布机
+    YBJ("635897db3ec34a6d03c9616a", "验布机"),
+    ;
+
+    /**
+     * 设备id
+     */
+    private final String productId;
+    /**
+     * 设备名称
+     */
+    private final String productName;
+
+    ProductEnum(String productId, String productName) {
+        this.productId = productId;
+        this.productName = productName;
+    }
+
+    private static final Map<String, ProductEnum> CLASS_MAP = new HashMap<>();
+
+    static {
+        for (ProductEnum value : ProductEnum.values()) {
+            CLASS_MAP.put(value.getProductId(), value);
+        }
+    }
+
+    /**
+     * 根据设备id获取枚举
+     */
+    public static ProductEnum getEnumByProductId(String productId) {
+        return CLASS_MAP.get(productId);
+    }
+
+}

+ 46 - 0
hx-iot/src/main/java/com/fjhx/iot/enums/UpperComputerEnum.java

@@ -0,0 +1,46 @@
+package com.fjhx.iot.enums;
+
+import lombok.Getter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Getter
+public enum UpperComputerEnum {
+
+    ZSJ(1, "注塑机"),
+    GYJ(2, "滚印机"),
+    ZZJ(3, "组装机"),
+    LWT(4, "螺纹头"),
+    ZSZ(5, "注射针");
+
+    /**
+     * 设备类型
+     */
+    private final Integer type;
+    /**
+     * 类型名称
+     */
+    private final String typeName;
+
+    UpperComputerEnum(Integer type, String typeName) {
+        this.type = type;
+        this.typeName = typeName;
+    }
+
+    private static final Map<Integer, UpperComputerEnum> CLASS_MAP = new HashMap<>();
+
+    static {
+        for (UpperComputerEnum value : UpperComputerEnum.values()) {
+            CLASS_MAP.put(value.getType(), value);
+        }
+    }
+
+    /**
+     * 根据设备id获取枚举
+     */
+    public static UpperComputerEnum getUpperComputerEnum(Integer type) {
+        return CLASS_MAP.get(type);
+    }
+
+}

+ 252 - 0
hx-iot/src/main/java/com/fjhx/iot/listener/DtaListener.java

@@ -0,0 +1,252 @@
+package com.fjhx.iot.listener;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.extra.spring.SpringUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
+import com.fjhx.common.constant.SourceConstant;
+import com.fjhx.iot.constants.RedisConstant;
+import com.fjhx.iot.entity.tda.dto.MessageBody;
+import com.fjhx.iot.entity.tda.dto.OpcUaData;
+import com.fjhx.iot.entity.tda.dto.UpperComputerData;
+import com.fjhx.iot.entity.tda.dto.ZSJDto;
+import com.fjhx.iot.entity.tda.po.TdaConfig;
+import com.fjhx.iot.enums.ProductEnum;
+import com.fjhx.iot.enums.UpperComputerEnum;
+import com.fjhx.iot.service.tda.TdaConfigService;
+import com.fjhx.iot.utils.amqp.AmqpClient;
+import com.fjhx.iot.utils.amqp.AmqpClientOptions;
+import com.fjhx.iot.utils.amqp.AmqpConstants;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.framework.mybatis.holder.TenantHolder;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+/**
+ * iot数据推送监听器
+ *
+ * @author zlj
+ */
+@Slf4j
+@Component
+public class DtaListener {
+
+    private static final RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
+
+    private static final TdaConfigService tdaConfigService = SpringUtil.getBean(TdaConfigService.class);
+
+    public static final Map<Long, MessageConsumer> listenerMap = new ConcurrentHashMap<>();
+
+    @PostConstruct
+    public void listener() {
+
+        TenantHolder.setIgnore(true);
+        DynamicDataSourceContextHolder.push(SourceConstant.IOT);
+
+        List<TdaConfig> list = tdaConfigService.list();
+
+        for (TdaConfig tdaConfig : list) {
+            MessageConsumer consumer = getMessageConsumer(tdaConfig);
+            listenerMap.put(tdaConfig.getId(), consumer);
+        }
+
+        DynamicDataSourceContextHolder.clear();
+        TenantHolder.clear();
+    }
+
+    public static MessageConsumer getMessageConsumer(TdaConfig tdaConfig) {
+        try {
+            AmqpClientOptions options = AmqpClientOptions.builder()
+                    .host(tdaConfig.getEndPoint())
+                    .port(AmqpConstants.PORT)
+                    .accessKey(tdaConfig.getAccessKey())
+                    .accessCode(tdaConfig.getAccessCode())
+                    .queuePrefetch(1000)
+                    .build();
+            AmqpClient amqpClient = new AmqpClient(options);
+            amqpClient.initialize();
+            MessageConsumer consumer = amqpClient.newConsumer(AmqpConstants.DEFAULT_QUEUE);
+            // 此处进行消息处理。如果处理比较耗时,最好进行开启新的线程处理,否则可能造成心跳超时链接断开。
+            consumer.setMessageListener(DtaListener::handleData);
+            return consumer;
+        } catch (Exception e) {
+            log.error("链接失败,tdaConfig:{}", tdaConfig.getId(), e);
+            throw new ServiceException("连接iot失败");
+        }
+    }
+
+    /**
+     * 处理推送数据
+     * <p>
+     * remarks: 添加成功必须手动 message.acknowledge();
+     * </p>
+     *
+     * @param message 推送消息
+     */
+    public static void handleData(Message message) {
+        try {
+            MessageBody messageBody = JSONObject.parseObject(message.getBody(String.class), MessageBody.class);
+            if (messageBody == null) {
+                return;
+            }
+            MessageBody.NotifyData notifyData = messageBody.getNotifyData();
+            if (notifyData == null) {
+                return;
+            }
+            MessageBody.Header header = notifyData.getHeader();
+            if (header == null) {
+                return;
+            }
+            String productId = header.getProductId();
+            if (productId == null || productId.isEmpty()) {
+                return;
+            }
+            MessageBody.Body body = notifyData.getBody();
+            if (body == null) {
+                return;
+            }
+            List<MessageBody.Service> services = body.getServices();
+            if (services == null || services.size() == 0) {
+                return;
+            }
+
+            ProductEnum productEnum = ProductEnum.getEnumByProductId(productId);
+            if (productEnum != null) {
+                appointProductHandle(header.getDeviceId(), message, services);
+            } else {
+                upperComputerHandle(message, services);
+            }
+
+            log.error(JSONObject.toJSONString(messageBody));
+
+        } catch (JMSException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 指定设备处理方式
+     *
+     * @param deviceId 设备id
+     * @param message  message
+     * @param services 设备消息列表
+     */
+    private static void appointProductHandle(String deviceId, Message message, List<MessageBody.Service> services) {
+        String redisKey = RedisConstant.DEVICE_PREFIX + deviceId;
+
+        MessageBody.Service oldService = redisCache.getCacheObject(redisKey);
+        MessageBody.Service newService = services.get(0);
+
+        if (oldService == null || newService.getEventTime().compareTo(oldService.getEventTime()) > 0) {
+            redisCache.setCacheObject(redisKey, newService);
+        }
+
+        try {
+            message.acknowledge();
+        } catch (JMSException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 上位机连接设备处理
+     */
+    private static void upperComputerHandle(Message message, List<MessageBody.Service> services) {
+        MessageBody.Service service = services.get(0);
+
+        UpperComputerData newData = service.getProperties().toJavaObject(UpperComputerData.class);
+
+        UpperComputerEnum upperComputerEnum = UpperComputerEnum.getUpperComputerEnum(newData.getType());
+
+        if (upperComputerEnum == UpperComputerEnum.ZSJ) {
+            handleZSJ(message, newData);
+            return;
+        }
+
+        String redisKey = RedisConstant.DEVICE_PREFIX + newData.getEquipmentNo();
+        UpperComputerData oldData = redisCache.getCacheObject(redisKey);
+
+        if (oldData == null || newData.getCreateTime().compareTo(oldData.getCreateTime()) > 0) {
+            redisCache.setCacheObject(redisKey, newData);
+        }
+
+        try {
+            message.acknowledge();
+        } catch (JMSException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 注塑机解析
+     */
+    private static void handleZSJ(Message message, UpperComputerData upperComputerData) {
+
+        log.error("注塑机推送数据:{}", JSONObject.toJSONString(upperComputerData));
+
+        String redisKey = RedisConstant.DEVICE_PREFIX + upperComputerData.getEquipmentNo();
+        ZSJDto oldZsjDto = redisCache.getCacheObject(redisKey);
+        if (oldZsjDto != null && upperComputerData.getCreateTime().compareTo(oldZsjDto.getDate()) > 0) {
+            return;
+        }
+        ZSJDto zsjDto = createZSJDto(upperComputerData);
+        redisCache.setCacheObject(redisKey, zsjDto);
+
+        try {
+            message.acknowledge();
+        } catch (JMSException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static ZSJDto createZSJDto(UpperComputerData upperComputerData) {
+        List<OpcUaData> opcUaDataList = Convert.toList(OpcUaData.class, upperComputerData.getData());
+
+        Map<String, String> collect = opcUaDataList.stream().collect(Collectors.toMap(
+                OpcUaData::getId,
+                OpcUaData::getNs
+        ));
+
+        ZSJDto zsjDto = new ZSJDto();
+        zsjDto.setDate(upperComputerData.getCreateTime());
+        zsjDto.setTmOnlineState(Convert.toInt(collect.get("tmOnlineState")));
+        zsjDto.setTmOperateMode(Convert.toInt(collect.get("tmOperateMode")));
+        zsjDto.setTmMotorState(Convert.toInt(collect.get("tmMotorState")));
+        zsjDto.setTmHeatState(Convert.toInt(collect.get("tmHeatState")));
+        zsjDto.setTmTempOilCurrent(Convert.toBigDecimal(collect.get("tmTempOil_Current")));
+
+        BigDecimal tmTempCurrent = Convert.toBigDecimal(collect.get("tmTemp1_Current"))
+                .add(Convert.toBigDecimal(collect.get("tmTemp2_Current")))
+                .add(Convert.toBigDecimal(collect.get("tmTemp3_Current")))
+                .add(Convert.toBigDecimal(collect.get("tmTemp4_Current")))
+                .add(Convert.toBigDecimal(collect.get("tmTemp5_Current")))
+                .add(Convert.toBigDecimal(collect.get("tmTemp6_Current")))
+                .add(Convert.toBigDecimal(collect.get("tmTemp7_Current")))
+                .add(Convert.toBigDecimal(collect.get("tmTemp8_Current")))
+                .add(Convert.toBigDecimal(collect.get("tmTemp9_Current")))
+                .divide(new BigDecimal("9"), 1, RoundingMode.HALF_UP);
+        zsjDto.setTmTempCurrent(tmTempCurrent);
+        zsjDto.setTmChargePressB1(Convert.toBigDecimal(collect.get("tmChargePressB1")));
+        zsjDto.setTmChargePressB2(Convert.toBigDecimal(collect.get("tmChargePressB2")));
+        zsjDto.setTmChargePressB3(Convert.toBigDecimal(collect.get("tmChargePressB3")));
+        zsjDto.setTmChargePressB4(Convert.toBigDecimal(collect.get("tmChargePressB4")));
+        zsjDto.setTmChargeSpeedB1(Convert.toBigDecimal(collect.get("tmChargeSpeedB1")));
+        zsjDto.setTmChargeSpeedB2(Convert.toBigDecimal(collect.get("tmChargeSpeedB2")));
+        zsjDto.setTmChargeSpeedB3(Convert.toBigDecimal(collect.get("tmChargeSpeedB3")));
+        zsjDto.setTmChargeSpeedB4(Convert.toBigDecimal(collect.get("tmChargeSpeedB4")));
+        return zsjDto;
+    }
+
+}

+ 26 - 0
hx-iot/src/main/java/com/fjhx/iot/mapper/tda/TdaApplicationMapper.java

@@ -0,0 +1,26 @@
+package com.fjhx.iot.mapper.tda;
+
+import com.fjhx.iot.entity.tda.po.TdaApplication;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.vo.TdaApplicationVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
+
+
+/**
+ * <p>
+ * 行业管理 Mapper 接口
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+public interface TdaApplicationMapper extends BaseMapper<TdaApplication> {
+
+    /**
+     * 行业管理分页
+     */
+    Page<TdaApplicationVo> getPage(@Param("page") Page<Object> page, @Param("ew") IWrapper<TdaApplication> wrapper);
+
+}

+ 26 - 0
hx-iot/src/main/java/com/fjhx/iot/mapper/tda/TdaConfigMapper.java

@@ -0,0 +1,26 @@
+package com.fjhx.iot.mapper.tda;
+
+import com.fjhx.iot.entity.tda.po.TdaConfig;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.vo.TdaConfigVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
+
+
+/**
+ * <p>
+ * iot配置 Mapper 接口
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+public interface TdaConfigMapper extends BaseMapper<TdaConfig> {
+
+    /**
+     * iot配置分页
+     */
+    Page<TdaConfigVo> getPage(@Param("page") Page<Object> page, @Param("ew") IWrapper<TdaConfig> wrapper);
+
+}

+ 26 - 0
hx-iot/src/main/java/com/fjhx/iot/mapper/tda/TdaDeviceMapper.java

@@ -0,0 +1,26 @@
+package com.fjhx.iot.mapper.tda;
+
+import com.fjhx.iot.entity.tda.po.TdaDevice;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.vo.TdaDeviceVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
+
+
+/**
+ * <p>
+ * 设备管理 Mapper 接口
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+public interface TdaDeviceMapper extends BaseMapper<TdaDevice> {
+
+    /**
+     * 设备管理分页
+     */
+    Page<TdaDeviceVo> getPage(@Param("page") Page<Object> page, @Param("ew") IWrapper<TdaDevice> wrapper);
+
+}

+ 26 - 0
hx-iot/src/main/java/com/fjhx/iot/mapper/tda/TdaProductMapper.java

@@ -0,0 +1,26 @@
+package com.fjhx.iot.mapper.tda;
+
+import com.fjhx.iot.entity.tda.po.TdaProduct;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.vo.TdaProductVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
+
+
+/**
+ * <p>
+ * 产品管理 Mapper 接口
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+public interface TdaProductMapper extends BaseMapper<TdaProduct> {
+
+    /**
+     * 产品管理分页
+     */
+    Page<TdaProductVo> getPage(@Param("page") Page<Object> page, @Param("ew") IWrapper<TdaProduct> wrapper);
+
+}

+ 41 - 0
hx-iot/src/main/java/com/fjhx/iot/service/tda/TdaApplicationService.java

@@ -0,0 +1,41 @@
+package com.fjhx.iot.service.tda;
+
+import com.fjhx.iot.entity.tda.po.TdaApplication;
+import com.ruoyi.common.core.service.BaseService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.vo.TdaApplicationVo;
+import com.fjhx.iot.entity.tda.dto.TdaApplicationSelectDto;
+import com.fjhx.iot.entity.tda.dto.TdaApplicationDto;
+
+
+/**
+ * <p>
+ * 行业管理 服务类
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+public interface TdaApplicationService extends BaseService<TdaApplication> {
+
+    /**
+     * 行业管理分页
+     */
+    Page<TdaApplicationVo> getPage(TdaApplicationSelectDto dto);
+
+    /**
+     * 行业管理明细
+     */
+    TdaApplicationVo detail(Long id);
+
+    /**
+     * 行业管理新增
+     */
+    void add(TdaApplicationDto tdaApplicationDto);
+
+    /**
+     * 行业管理删除
+     */
+    void delete(Long id);
+
+}

+ 46 - 0
hx-iot/src/main/java/com/fjhx/iot/service/tda/TdaConfigService.java

@@ -0,0 +1,46 @@
+package com.fjhx.iot.service.tda;
+
+import com.fjhx.iot.entity.tda.po.TdaConfig;
+import com.ruoyi.common.core.service.BaseService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.vo.TdaConfigVo;
+import com.fjhx.iot.entity.tda.dto.TdaConfigSelectDto;
+import com.fjhx.iot.entity.tda.dto.TdaConfigDto;
+
+
+/**
+ * <p>
+ * iot配置 服务类
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+public interface TdaConfigService extends BaseService<TdaConfig> {
+
+    /**
+     * iot配置分页
+     */
+    Page<TdaConfigVo> getPage(TdaConfigSelectDto dto);
+
+    /**
+     * iot配置明细
+     */
+    TdaConfigVo detail(Long id);
+
+    /**
+     * iot配置新增
+     */
+    void add(TdaConfigDto tdaConfigDto);
+
+    /**
+     * iot配置编辑
+     */
+    void edit(TdaConfigDto tdaConfigDto);
+
+    /**
+     * iot配置删除
+     */
+    void delete(Long id);
+
+}

+ 41 - 0
hx-iot/src/main/java/com/fjhx/iot/service/tda/TdaDeviceService.java

@@ -0,0 +1,41 @@
+package com.fjhx.iot.service.tda;
+
+import com.fjhx.iot.entity.tda.po.TdaDevice;
+import com.ruoyi.common.core.service.BaseService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.vo.TdaDeviceVo;
+import com.fjhx.iot.entity.tda.dto.TdaDeviceSelectDto;
+import com.fjhx.iot.entity.tda.dto.TdaDeviceDto;
+
+
+/**
+ * <p>
+ * 设备管理 服务类
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+public interface TdaDeviceService extends BaseService<TdaDevice> {
+
+    /**
+     * 设备管理分页
+     */
+    Page<TdaDeviceVo> getPage(TdaDeviceSelectDto dto);
+
+    /**
+     * 设备管理明细
+     */
+    TdaDeviceVo detail(Long id);
+
+    /**
+     * 设备管理新增
+     */
+    void add(TdaDeviceDto tdaDeviceDto);
+
+    /**
+     * 设备管理删除
+     */
+    void delete(Long id);
+
+}

+ 41 - 0
hx-iot/src/main/java/com/fjhx/iot/service/tda/TdaProductService.java

@@ -0,0 +1,41 @@
+package com.fjhx.iot.service.tda;
+
+import com.fjhx.iot.entity.tda.po.TdaProduct;
+import com.ruoyi.common.core.service.BaseService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.iot.entity.tda.vo.TdaProductVo;
+import com.fjhx.iot.entity.tda.dto.TdaProductSelectDto;
+import com.fjhx.iot.entity.tda.dto.TdaProductDto;
+
+
+/**
+ * <p>
+ * 产品管理 服务类
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+public interface TdaProductService extends BaseService<TdaProduct> {
+
+    /**
+     * 产品管理分页
+     */
+    Page<TdaProductVo> getPage(TdaProductSelectDto dto);
+
+    /**
+     * 产品管理明细
+     */
+    TdaProductVo detail(Long id);
+
+    /**
+     * 产品管理新增
+     */
+    void add(TdaProductDto tdaProductDto);
+
+    /**
+     * 产品管理删除
+     */
+    void delete(Long id);
+
+}

+ 59 - 0
hx-iot/src/main/java/com/fjhx/iot/service/tda/impl/TdaApplicationServiceImpl.java

@@ -0,0 +1,59 @@
+package com.fjhx.iot.service.tda.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.iot.entity.tda.dto.TdaApplicationDto;
+import com.fjhx.iot.entity.tda.dto.TdaApplicationSelectDto;
+import com.fjhx.iot.entity.tda.po.TdaApplication;
+import com.fjhx.iot.entity.tda.vo.TdaApplicationVo;
+import com.fjhx.iot.mapper.tda.TdaApplicationMapper;
+import com.fjhx.iot.service.tda.TdaApplicationService;
+import com.fjhx.iot.utils.IoTDAUtil;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * <p>
+ * 行业管理 服务实现类
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Service
+public class TdaApplicationServiceImpl extends ServiceImpl<TdaApplicationMapper, TdaApplication> implements TdaApplicationService {
+
+    @Override
+    public Page<TdaApplicationVo> getPage(TdaApplicationSelectDto dto) {
+        IWrapper<TdaApplication> wrapper = getWrapper();
+        wrapper.orderByDesc("ta", TdaApplication::getId);
+        Page<TdaApplicationVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
+        return page;
+    }
+
+    @Override
+    public TdaApplicationVo detail(Long id) {
+        TdaApplication TdaApplication = this.getById(id);
+        TdaApplicationVo result = BeanUtil.toBean(TdaApplication, TdaApplicationVo.class);
+        return result;
+    }
+
+    @Override
+    public void add(TdaApplicationDto tdaApplicationDto) {
+        // 华为ioDta添加资源空间
+        String appId = IoTDAUtil.addApplication(tdaApplicationDto.getTdaConfigId(), tdaApplicationDto.getAppName());
+        tdaApplicationDto.setAppId(appId);
+        this.save(tdaApplicationDto);
+    }
+
+    @Override
+    public void delete(Long id) {
+        // 华为ioDta删除资源空间
+        TdaApplication tdaApplication = getById(id);
+        IoTDAUtil.deleteApplication(tdaApplication.getTdaConfigId(), tdaApplication.getAppId());
+        this.removeById(id);
+    }
+
+}

+ 87 - 0
hx-iot/src/main/java/com/fjhx/iot/service/tda/impl/TdaConfigServiceImpl.java

@@ -0,0 +1,87 @@
+package com.fjhx.iot.service.tda.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.iot.entity.tda.dto.TdaConfigDto;
+import com.fjhx.iot.entity.tda.dto.TdaConfigSelectDto;
+import com.fjhx.iot.entity.tda.po.TdaConfig;
+import com.fjhx.iot.entity.tda.vo.TdaConfigVo;
+import com.fjhx.iot.listener.DtaListener;
+import com.fjhx.iot.mapper.tda.TdaConfigMapper;
+import com.fjhx.iot.service.tda.TdaConfigService;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.springframework.stereotype.Service;
+
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+
+
+/**
+ * <p>
+ * iot配置 服务实现类
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Service
+public class TdaConfigServiceImpl extends ServiceImpl<TdaConfigMapper, TdaConfig> implements TdaConfigService {
+
+    @Override
+    public Page<TdaConfigVo> getPage(TdaConfigSelectDto dto) {
+        IWrapper<TdaConfig> wrapper = getWrapper();
+        wrapper.orderByDesc("tc", TdaConfig::getId);
+        Page<TdaConfigVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
+        return page;
+    }
+
+    @Override
+    public TdaConfigVo detail(Long id) {
+        TdaConfig TdaConfig = this.getById(id);
+        TdaConfigVo result = BeanUtil.toBean(TdaConfig, TdaConfigVo.class);
+        return result;
+    }
+
+    @Override
+    public void add(TdaConfigDto tdaConfigDto) {
+        tdaConfigDto.setId(IdWorker.getId());
+        MessageConsumer messageConsumer = DtaListener.getMessageConsumer(tdaConfigDto);
+        this.save(tdaConfigDto);
+        DtaListener.listenerMap.put(tdaConfigDto.getId(), messageConsumer);
+    }
+
+    @Override
+    public void edit(TdaConfigDto tdaConfigDto) {
+        MessageConsumer messageConsumer = DtaListener.getMessageConsumer(tdaConfigDto);
+
+        MessageConsumer oldMessageConsumer = DtaListener.listenerMap.get(tdaConfigDto.getId());
+        if (oldMessageConsumer != null) {
+            try {
+                oldMessageConsumer.close();
+            } catch (JMSException e) {
+                log.error("关闭失败");
+            }
+            DtaListener.listenerMap.remove(tdaConfigDto.getId());
+        }
+
+        this.updateById(tdaConfigDto);
+        DtaListener.listenerMap.put(tdaConfigDto.getId(), messageConsumer);
+    }
+
+    @Override
+    public void delete(Long id) {
+        this.removeById(id);
+        MessageConsumer oldMessageConsumer = DtaListener.listenerMap.get(id);
+        if (oldMessageConsumer != null) {
+            try {
+                oldMessageConsumer.close();
+            } catch (JMSException e) {
+                log.error("关闭失败");
+            }
+            DtaListener.listenerMap.remove(id);
+        }
+    }
+
+}

+ 93 - 0
hx-iot/src/main/java/com/fjhx/iot/service/tda/impl/TdaDeviceServiceImpl.java

@@ -0,0 +1,93 @@
+package com.fjhx.iot.service.tda.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.iot.entity.tda.dto.TdaDeviceDto;
+import com.fjhx.iot.entity.tda.dto.TdaDeviceSelectDto;
+import com.fjhx.iot.entity.tda.po.TdaApplication;
+import com.fjhx.iot.entity.tda.po.TdaDevice;
+import com.fjhx.iot.entity.tda.po.TdaProduct;
+import com.fjhx.iot.entity.tda.vo.TdaDeviceVo;
+import com.fjhx.iot.mapper.tda.TdaDeviceMapper;
+import com.fjhx.iot.service.tda.TdaApplicationService;
+import com.fjhx.iot.service.tda.TdaDeviceService;
+import com.fjhx.iot.service.tda.TdaProductService;
+import com.fjhx.iot.utils.IoTDAUtil;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * <p>
+ * 设备管理 服务实现类
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Service
+public class TdaDeviceServiceImpl extends ServiceImpl<TdaDeviceMapper, TdaDevice> implements TdaDeviceService {
+
+    @Lazy
+    @Autowired
+    private TdaProductService tdaProductService;
+
+    @Lazy
+    @Autowired
+    private TdaApplicationService tdaApplicationService;
+
+
+    @Override
+    public Page<TdaDeviceVo> getPage(TdaDeviceSelectDto dto) {
+        IWrapper<TdaDevice> wrapper = getWrapper();
+        wrapper.orderByDesc("td", TdaDevice::getId);
+        Page<TdaDeviceVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
+        return page;
+    }
+
+    @Override
+    public TdaDeviceVo detail(Long id) {
+        TdaDevice TdaDevice = this.getById(id);
+        TdaDeviceVo result = BeanUtil.toBean(TdaDevice, TdaDeviceVo.class);
+        return result;
+    }
+
+    @Override
+    public void add(TdaDeviceDto tdaDeviceDto) {
+        String nodeId = tdaDeviceDto.getNodeId();
+        String deviceName = tdaDeviceDto.getDeviceName();
+        Long tdaProductId = tdaDeviceDto.getTdaProductId();
+
+        // 查询资源所在空间和产品id
+        TdaProduct tdaProduct = tdaProductService.getById(tdaProductId);
+        String productId = tdaProduct.getProductId();
+
+        TdaApplication tdaApplication = tdaApplicationService.getById(tdaProduct.getTdaApplicationId());
+
+        // 华为ioDta添加设备
+        IoTDAUtil.DeviceKey deviceKey = IoTDAUtil.addDevice(
+                tdaApplication.getTdaConfigId(), nodeId, deviceName, tdaProduct.getAppId(), productId);
+
+        tdaDeviceDto.setProductId(productId);
+        tdaDeviceDto.setDeviceId(deviceKey.getDeviceId());
+        tdaDeviceDto.setSecret(deviceKey.getSecret());
+
+        this.save(tdaDeviceDto);
+    }
+
+    @Override
+    public void delete(Long id) {
+
+        TdaDevice tdaDevice = getById(id);
+        TdaProduct tdaProduct = tdaProductService.getById(tdaDevice.getTdaProductId());
+        TdaApplication tdaApplication = tdaApplicationService.getById(tdaProduct.getTdaApplicationId());
+
+        IoTDAUtil.deleteDevice(tdaApplication.getTdaConfigId(), tdaDevice.getDeviceId());
+
+        this.removeById(id);
+    }
+
+}

+ 81 - 0
hx-iot/src/main/java/com/fjhx/iot/service/tda/impl/TdaProductServiceImpl.java

@@ -0,0 +1,81 @@
+package com.fjhx.iot.service.tda.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.iot.entity.tda.dto.TdaProductDto;
+import com.fjhx.iot.entity.tda.dto.TdaProductSelectDto;
+import com.fjhx.iot.entity.tda.po.TdaApplication;
+import com.fjhx.iot.entity.tda.po.TdaProduct;
+import com.fjhx.iot.entity.tda.vo.TdaProductVo;
+import com.fjhx.iot.mapper.tda.TdaProductMapper;
+import com.fjhx.iot.service.tda.TdaApplicationService;
+import com.fjhx.iot.service.tda.TdaProductService;
+import com.fjhx.iot.utils.IoTDAUtil;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * <p>
+ * 产品管理 服务实现类
+ * </p>
+ *
+ * @author zlj
+ * @since 2023-03-21
+ */
+@Service
+public class TdaProductServiceImpl extends ServiceImpl<TdaProductMapper, TdaProduct> implements TdaProductService {
+
+    @Autowired
+    private TdaApplicationService tdaApplicationService;
+
+    @Override
+    public Page<TdaProductVo> getPage(TdaProductSelectDto dto) {
+        IWrapper<TdaProduct> wrapper = getWrapper();
+        wrapper.orderByDesc("tp", TdaProduct::getId);
+        Page<TdaProductVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
+        return page;
+    }
+
+    @Override
+    public TdaProductVo detail(Long id) {
+        TdaProduct TdaProduct = this.getById(id);
+        TdaProductVo result = BeanUtil.toBean(TdaProduct, TdaProductVo.class);
+        return result;
+    }
+
+    @Override
+    public void add(TdaProductDto tdaProductDto) {
+
+        TdaApplication tdaApplication = tdaApplicationService.getById(tdaProductDto.getTdaApplicationId());
+        String appId = tdaApplication.getAppId();
+
+        // 华为ioDta添加产品
+        String productId = IoTDAUtil.createProduct(tdaApplication.getTdaConfigId(), appId, tdaProductDto.getName(),
+                tdaProductDto.getDeviceType(), tdaProductDto.getManufacturerName());
+
+        tdaProductDto.setAppId(appId);
+        tdaProductDto.setProductId(productId);
+        this.save(tdaProductDto);
+    }
+
+    @Override
+    public void delete(Long id) {
+
+        // // 查询产品是否已添加设备,已添加设备则不可删除
+        // Long count = tdaDeviceService.count(TdaDevice::getTdaProductId, id);
+        // if (count > 0) {
+        //     throw new ServiceException("产品已添加设备,无法删除");
+        // }
+
+        // 华为ioDta删除产品
+        TdaProduct tdaProduct = getById(id);
+        TdaApplication tdaApplication = tdaApplicationService.getById(tdaProduct.getTdaApplicationId());
+        IoTDAUtil.deleteProduct(tdaApplication.getTdaConfigId(), tdaProduct.getAppId(), tdaProduct.getProductId());
+
+        this.removeById(id);
+    }
+
+}

+ 204 - 0
hx-iot/src/main/java/com/fjhx/iot/utils/IoTDAUtil.java

@@ -0,0 +1,204 @@
+package com.fjhx.iot.utils;
+
+import cn.hutool.extra.spring.SpringUtil;
+import com.fjhx.iot.entity.tda.po.TdaConfig;
+import com.fjhx.iot.service.tda.TdaConfigService;
+import com.huaweicloud.sdk.core.auth.ICredential;
+import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
+import com.huaweicloud.sdk.iotda.v5.auth.IoTDACredentials;
+import com.huaweicloud.sdk.iotda.v5.model.*;
+import com.huaweicloud.sdk.iotda.v5.region.IoTDARegion;
+import com.ruoyi.common.exception.ServiceException;
+import lombok.Data;
+
+import java.util.Collections;
+
+public class IoTDAUtil {
+
+    private static TdaConfigService tdaConfigService = SpringUtil.getBean(TdaConfigService.class);
+
+    /**
+     * 创建资源空间
+     *
+     * @param appName 资源空间名称
+     * @return 资源空间id
+     */
+    public static String addApplication(Long configId, String appName) {
+        AddApplicationRequest addApplicationRequest = new AddApplicationRequest();
+        AddApplication addApplication = new AddApplication();
+        addApplication.setAppName(appName);
+        addApplicationRequest.setBody(addApplication);
+        AddApplicationResponse addApplicationResponse = getIoTDAClient(configId).addApplication(addApplicationRequest);
+        return addApplicationResponse.getAppId();
+    }
+
+    /**
+     * 删除资源空间
+     *
+     * @param appId 资源空间Id
+     */
+    public static void deleteApplication(Long configId, String appId) {
+        try {
+            DeleteApplicationRequest deleteApplicationRequest = new DeleteApplicationRequest();
+            deleteApplicationRequest.setAppId(appId);
+            getIoTDAClient(configId).deleteApplication(deleteApplicationRequest);
+        } catch (Exception e) {
+            throw new ServiceException("资源空间删除失败");
+        }
+    }
+
+    /**
+     * 创建产品
+     *
+     * @param appId            资源空间Id
+     * @param name             产品名称
+     * @param deviceType       设备类型
+     * @param manufacturerName 厂商名称
+     * @return 产品id
+     */
+    public static String createProduct(Long configId, String appId, String name, String deviceType, String manufacturerName) {
+        CreateProductRequest createProductRequest = new CreateProductRequest();
+        AddProduct addProduct = new AddProduct();
+        // 资源空间
+        addProduct.setAppId(appId);
+        // 产品名称
+        addProduct.setName(name);
+        addProduct.setDeviceType(deviceType);
+        addProduct.setManufacturerName(manufacturerName);
+
+        addProduct.setProtocolType("MQTT");
+        addProduct.setDataFormat("json");
+
+        // 添加产品属性
+        ServiceCapability serviceCapability = new ServiceCapability();
+        serviceCapability.setServiceId("Data");
+        serviceCapability.setServiceType("data");
+        // 添加命名空间
+        ServiceProperty serviceProperty = new ServiceProperty();
+        serviceProperty.setPropertyName("DeviceData");
+        serviceProperty.setDataType("string");
+        serviceProperty.setRequired(false);
+        serviceProperty.setMaxLength(2000000);
+        serviceProperty.setStep(0.0D);
+        serviceProperty.setMethod("RW");
+        serviceCapability.setProperties(Collections.singletonList(serviceProperty));
+        addProduct.setServiceCapabilities(Collections.singletonList(serviceCapability));
+
+        createProductRequest.setBody(addProduct);
+        CreateProductResponse product = getIoTDAClient(configId).createProduct(createProductRequest);
+        return product.getProductId();
+    }
+
+    /**
+     * 修改产品
+     *
+     * @param productId        产品id
+     * @param appId            资源空间Id
+     * @param name             产品名称
+     * @param deviceType       设备类型
+     * @param manufacturerName 厂商名称
+     */
+    public static void updateProduct(Long configId, String productId, String appId, String name, String deviceType, String manufacturerName) {
+        UpdateProductRequest updateProductRequest = new UpdateProductRequest();
+        updateProductRequest.setProductId(productId);
+        UpdateProduct updateProduct = new UpdateProduct();
+        updateProduct.setAppId(appId);
+        updateProduct.setName(name);
+        updateProduct.setDeviceType(deviceType);
+        updateProduct.setManufacturerName(manufacturerName);
+        updateProductRequest.setBody(updateProduct);
+        getIoTDAClient(configId).updateProduct(updateProductRequest);
+    }
+
+    /**
+     * 删除产品
+     *
+     * @param appId     资源空间Id
+     * @param productId 产品id
+     */
+    public static void deleteProduct(Long configId, String appId, String productId) {
+        try {
+            DeleteProductRequest deleteProductRequest = new DeleteProductRequest();
+            deleteProductRequest.setAppId(appId);
+            deleteProductRequest.setProductId(productId);
+            getIoTDAClient(configId).deleteProduct(deleteProductRequest);
+        } catch (Exception e) {
+            throw new ServiceException("产品删除失败");
+        }
+    }
+
+    /**
+     * 添加设备
+     *
+     * @param nodeId     设备标识
+     * @param deviceName 设备名称
+     * @param appId      资源空间Id
+     * @param productId  产品id
+     * @return 设备secret
+     */
+    public static DeviceKey addDevice(Long configId, String nodeId, String deviceName, String appId, String productId) {
+        AddDeviceRequest addDeviceRequest = new AddDeviceRequest();
+        AddDevice addDevice = new AddDevice();
+        addDevice.setNodeId(nodeId);
+        addDevice.setDeviceName(deviceName);
+        addDevice.setAppId(appId);
+        addDevice.setProductId(productId);
+
+        addDeviceRequest.setBody(addDevice);
+        AddDeviceResponse addDeviceResponse = getIoTDAClient(configId).addDevice(addDeviceRequest);
+
+        DeviceKey deviceKey = new DeviceKey();
+        deviceKey.setDeviceId(addDeviceResponse.getDeviceId());
+        deviceKey.setSecret(addDeviceResponse.getAuthInfo().getSecret());
+
+        return deviceKey;
+    }
+
+    /**
+     * 删除设备
+     *
+     * @param deviceId 设备Id
+     */
+    public static void deleteDevice(Long configId, String deviceId) {
+        try {
+            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
+            deleteDeviceRequest.setDeviceId(deviceId);
+            getIoTDAClient(configId).deleteDevice(deleteDeviceRequest);
+        } catch (Exception e) {
+            throw new ServiceException("产品删除失败");
+        }
+    }
+
+    @Data
+    public static class DeviceKey {
+        // 设备id
+        private String deviceId;
+        // 设备密匙
+        private String secret;
+    }
+
+    public static IoTDAClient getIoTDAClient(Long configId) {
+
+        TdaConfig tdaConfig = tdaConfigService.getById(configId);
+
+        if (tdaConfig == null) {
+            throw new ServiceException("没有找到iot配置");
+        }
+
+        // 创建认证
+        ICredential auth = new IoTDACredentials()
+                .withAk(tdaConfig.getAccessKeyId())
+                .withSk(tdaConfig.getSecretAccessKey())
+                .withProjectId(tdaConfig.getProductId());
+
+        // 创建IoTDAClient实例并初始化
+        return IoTDAClient.newBuilder()
+                .withCredential(auth)
+                // 基础版:请选择IoTDARegion中的Region对象
+                .withRegion(IoTDARegion.CN_NORTH_4)
+                // 标准版/企业版:需自行创建Region对象
+                // .withRegion(new Region(REGION_ID, ENDPOINT))
+                .build();
+    }
+
+}

+ 96 - 0
hx-iot/src/main/java/com/fjhx/iot/utils/amqp/AmqpClient.java

@@ -0,0 +1,96 @@
+package com.fjhx.iot.utils.amqp;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.qpid.jms.JmsConnection;
+import org.apache.qpid.jms.JmsConnectionExtensions;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.JmsQueue;
+import org.apache.qpid.jms.transports.TransportOptions;
+import org.apache.qpid.jms.transports.TransportSupport;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.Session;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+@Slf4j
+public class AmqpClient {
+    private final AmqpClientOptions options;
+    private Connection connection;
+    private Session session;
+    private final Set<MessageConsumer> consumerSet = Collections.synchronizedSet(new HashSet<>());
+
+    public AmqpClient(AmqpClientOptions options) {
+        this.options = options;
+    }
+
+    public String getId() {
+        return options.getClientId();
+    }
+
+    public void initialize() throws Exception {
+        String connectionUrl = options.generateConnectUrl();
+        log.info("connectionUrl={}", connectionUrl);
+        JmsConnectionFactory cf = new JmsConnectionFactory(connectionUrl);
+        // 信任服务端
+        TransportOptions to = new TransportOptions();
+        to.setTrustAll(true);
+        cf.setSslContext(TransportSupport.createJdkSslContext(to));
+        String userName = "accessKey=" + options.getAccessKey();
+        cf.setExtension(JmsConnectionExtensions.USERNAME_OVERRIDE.toString(), (connection, uri) -> {
+            // IoTDA的userName组成格式如下:“accessKey=${accessKey}|timestamp=${timestamp}”
+            String newUserName = userName;
+            if (connection instanceof JmsConnection) {
+                newUserName = ((JmsConnection) connection).getUsername();
+            }
+            return newUserName + "|timestamp=" + System.currentTimeMillis();
+        });
+        // 创建连接
+        connection = cf.createConnection(userName, options.getAccessCode());
+        // 创建 Session, Session.CLIENT_ACKNOWLEDGE: 收到消息后,需要手动调用message.acknowledge()。Session.AUTO_ACKNOWLEDGE: SDK自动ACK(推荐)。
+        session = connection.createSession(false, options.isAutoAcknowledge() ? Session.AUTO_ACKNOWLEDGE : Session.CLIENT_ACKNOWLEDGE);
+        connection.start();
+    }
+
+    public MessageConsumer newConsumer(String queueName) throws Exception {
+        if (connection == null || ((JmsConnection) connection).isClosed()) {
+            throw new Exception("create consumer failed,the connection is disconnected.");
+        }
+        MessageConsumer consumer;
+
+        consumer = session.createConsumer(new JmsQueue(queueName));
+        if (consumer != null) {
+            consumerSet.add(consumer);
+        }
+        return consumer;
+    }
+
+    public void close() {
+        consumerSet.forEach(consumer -> {
+            try {
+                consumer.close();
+            } catch (JMSException e) {
+                log.warn("consumer close error,exception is ", e);
+            }
+        });
+
+        if (session != null) {
+            try {
+                session.close();
+            } catch (JMSException e) {
+                log.warn("session close error,exception is ", e);
+            }
+        }
+
+        if (connection != null) {
+            try {
+                connection.close();
+            } catch (JMSException e) {
+                log.warn("connection close error,exception is", e);
+            }
+        }
+    }
+}

+ 118 - 0
hx-iot/src/main/java/com/fjhx/iot/utils/amqp/AmqpClientOptions.java

@@ -0,0 +1,118 @@
+package com.fjhx.iot.utils.amqp;
+
+
+import cn.hutool.core.util.ObjectUtil;
+import lombok.Builder;
+import lombok.Data;
+
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+@Data
+@Builder
+public class AmqpClientOptions {
+    private String host;
+    @Builder.Default
+    private int port = 5671;
+    private String accessKey;
+    private String accessCode;
+    private String clientId;
+    /**
+     * 仅支持true
+     */
+    @Builder.Default
+    private boolean useSsl = true;
+
+    /**
+     * IoTDA仅支持default
+     */
+    @Builder.Default
+    private String vhost = "default";
+
+    /**
+     * IoTDA仅支持PLAIN
+     */
+    @Builder.Default
+    private String saslMechanisms = "PLAIN";
+
+    /**
+     * true: SDK自动ACK(默认)
+     * false:收到消息后,需要手动调用message.acknowledge()
+     */
+    @Builder.Default
+    private boolean isAutoAcknowledge = false;
+
+    /**
+     * 重连时延(ms)
+     */
+    @Builder.Default
+    private long reconnectDelay = 3000L;
+
+    /**
+     * 最大重连时延(ms),随着重连次数增加重连时延逐渐增加
+     */
+    @Builder.Default
+    private long maxReconnectDelay = 30 * 1000L;
+
+    /**
+     * 最大重连次数,默认值-1,代表没有限制
+     */
+    @Builder.Default
+    private long maxReconnectAttempts = -1;
+
+    /**
+     * 空闲超时,对端在这个时间段内没有发送AMQP帧则会导致连接断开。默认值为30000。单位:毫秒。
+     */
+    @Builder.Default
+    private long idleTimeout = 30 * 1000L;
+
+    /**
+     * The values below control how many messages the remote peer can send to the client and be held in a pre-fetch buffer for each consumer instance.
+     */
+    @Builder.Default
+    private int queuePrefetch = 1000;
+
+    /**
+     * 扩展参数
+     */
+    private Map<String, String> extendedOptions;
+
+    public String generateConnectUrl() {
+        String uri = MessageFormat.format("{0}://{1}:{2}", (useSsl ? "amqps" : "amqp"), host, String.valueOf(port));
+        Map<String, String> uriOptions = new HashMap<>();
+        uriOptions.put("amqp.vhost", vhost);
+        uriOptions.put("amqp.idleTimeout", String.valueOf(idleTimeout));
+        uriOptions.put("amqp.saslMechanisms", saslMechanisms);
+
+        Map<String, String> jmsOptions = new HashMap<>();
+        jmsOptions.put("jms.prefetchPolicy.queuePrefetch", String.valueOf(queuePrefetch));
+        if (ObjectUtil.isNotEmpty(clientId)) {
+            jmsOptions.put("jms.clientID", clientId);
+        } else {
+            jmsOptions.put("jms.clientID", UUID.randomUUID().toString());
+        }
+        jmsOptions.put("failover.reconnectDelay", String.valueOf(reconnectDelay));
+        jmsOptions.put("failover.maxReconnectDelay", String.valueOf(maxReconnectDelay));
+        if (maxReconnectAttempts > 0) {
+            jmsOptions.put("failover.maxReconnectAttempts", String.valueOf(maxReconnectAttempts));
+        }
+        if (extendedOptions != null) {
+            for (Map.Entry<String, String> option : extendedOptions.entrySet()) {
+                if (option.getKey().startsWith("amqp.") || option.getKey().startsWith("transport.")) {
+                    uriOptions.put(option.getKey(), option.getValue());
+                } else {
+                    jmsOptions.put(option.getKey(), option.getValue());
+                }
+            }
+        }
+        return uriOptions.entrySet().stream()
+                .map(option -> MessageFormat.format("{0}={1}", option.getKey(), option.getValue()))
+                .collect(Collectors.joining("&", "failover:(" + uri + "?", ")")) +
+                jmsOptions.entrySet().stream()
+                        .map(option -> MessageFormat.format("{0}={1}", option.getKey(), option.getValue()))
+                        .collect(Collectors.joining("&", "?", ""));
+    }
+}

+ 37 - 0
hx-iot/src/main/java/com/fjhx/iot/utils/amqp/AmqpConstants.java

@@ -0,0 +1,37 @@
+package com.fjhx.iot.utils.amqp;
+
+
+public interface AmqpConstants {
+
+    // /**
+    //  * AMQP接入域名
+    //  * 参考:https://support.huaweicloud.com/usermanual-iothub/iot_01_00100_2.html#section2
+    //  * eg: "****.iot-amqps.cn-north-4.myhuaweicloud.com";
+    //  */
+    // String HOST = "a1625d5cc8.iot-amqps.cn-north-4.myhuaweicloud.com";
+
+    /**
+     * AMQP接入端口
+     * 参考:https://support.huaweicloud.com/usermanual-iothub/iot_01_00100_2.html#section2
+     */
+    int PORT = 5671;
+
+    // /**
+    //  * 接入凭证键值
+    //  * 参考:https://support.huaweicloud.com/usermanual-iothub/iot_01_00100_2.html#section3
+    //  * 不需要拼接时间戳timestamp
+    //  */
+    // String ACCESS_KEY = "SwGUHYzA";
+    //
+    // /**
+    //  * 接入凭证密钥
+    //  * 参考:https://support.huaweicloud.com/usermanual-iothub/iot_01_00100_2.html#section3
+    //  */
+    // String ACCESS_CODE = "mGYgxmOtPhWDNHaAMU76aiSy0P3OtaWE";
+
+    /**
+     * 默认队列
+     */
+    String DEFAULT_QUEUE = "DefaultQueue";
+
+}

+ 20 - 0
hx-iot/src/main/resources/mapper/tda/TdaApplicationMapper.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.iot.mapper.tda.TdaApplicationMapper">
+    <select id="getPage" resultType="com.fjhx.iot.entity.tda.vo.TdaApplicationVo">
+        select ta.id,
+               ta.tda_config_id,
+               ta.app_id,
+               ta.app_name,
+               ta.remark,
+               ta.create_user,
+               ta.create_time,
+               ta.update_user,
+               ta.update_time,
+               tc.name configName
+        from tda_application ta
+                 left join tda_config tc on ta.tda_config_id = tc.id
+            ${ew.customSqlSegment}
+    </select>
+
+</mapper>

+ 24 - 0
hx-iot/src/main/resources/mapper/tda/TdaConfigMapper.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.iot.mapper.tda.TdaConfigMapper">
+    <select id="getPage" resultType="com.fjhx.iot.entity.tda.vo.TdaConfigVo">
+        select
+            tc.id,
+            tc.type,
+            tc.name,
+            tc.end_point,
+            tc.access_key_id,
+            tc.secret_access_key,
+            tc.access_key,
+            tc.access_code,
+            tc.product_id,
+            tc.remark,
+            tc.create_user,
+            tc.create_time,
+            tc.update_user,
+            tc.update_time
+        from tda_config tc
+            ${ew.customSqlSegment}
+    </select>
+
+</mapper>

+ 24 - 0
hx-iot/src/main/resources/mapper/tda/TdaDeviceMapper.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.iot.mapper.tda.TdaDeviceMapper">
+    <select id="getPage" resultType="com.fjhx.iot.entity.tda.vo.TdaDeviceVo">
+        select td.id,
+               td.tda_product_id,
+               td.product_id,
+               td.node_id,
+               td.device_name,
+               td.device_id,
+               td.secret,
+               td.create_user,
+               td.create_time,
+               td.update_user,
+               td.update_time,
+               tp.name productName,
+               ta.app_name
+        from tda_device td
+                 left join tda_product tp on td.tda_product_id = tp.id
+                 left join tda_application ta on tp.tda_application_id = ta.id
+            ${ew.customSqlSegment}
+    </select>
+
+</mapper>

+ 25 - 0
hx-iot/src/main/resources/mapper/tda/TdaProductMapper.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.iot.mapper.tda.TdaProductMapper">
+    <select id="getPage" resultType="com.fjhx.iot.entity.tda.vo.TdaProductVo">
+        select
+            tp.id,
+            tp.tda_application_id,
+            tp.app_id,
+            tp.product_id,
+            tp.name,
+            tp.device_type,
+            tp.manufacturer_name,
+            tp.protocol_type,
+            tp.data_format,
+            tp.create_user,
+            tp.create_time,
+            tp.update_user,
+            tp.update_time,
+            ta.app_name
+        from tda_product tp
+            left join tda_application ta on tp.tda_application_id = ta.id
+            ${ew.customSqlSegment}
+    </select>
+
+</mapper>