TRX 1 rok temu
rodzic
commit
b166ee77c6
34 zmienionych plików z 1215 dodań i 34 usunięć
  1. 1 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/baseParam/SuperParam.java
  2. 49 2
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/IotTemplateModel.java
  3. 21 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThing2DeviceBind.java
  4. 60 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThing2DeviceModel.java
  5. 34 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThing2DeviceSearch.java
  6. 42 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThingModel.java
  7. 23 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThingParam.java
  8. 36 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThingSearch.java
  9. 7 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/mqtt/DeviceInfoAddParam.java
  10. 7 3
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/mqtt/DeviceInfoRegistParam.java
  11. 3 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/mqtt/DeviceInfoSearchParam.java
  12. 1 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/mqtt/ProjectInfoModel.java
  13. 2 2
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/type/IotDataType.java
  14. 6 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/IotTemplateDao.java
  15. 24 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/IotThing2DeviceDao.java
  16. 20 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/IotThingDao.java
  17. 17 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/extend/IotThing2DeviceDaoExtend.java
  18. 19 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/extend/IotThingDaoExtend.java
  19. 79 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/impl/IotThing2DeviceDaoImpl.java
  20. 82 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/impl/IotThingDaoImpl.java
  21. 3 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/DeviceInfoDao.java
  22. 4 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/impl/DeviceInfoDaoImpl.java
  23. 5 5
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/IotMain.java
  24. 10 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/IotThing.java
  25. 23 1
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/IotThing2Device.java
  26. 4 1
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/mqtt/DeviceInfo.java
  27. 3 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/mqtt/GateWayInfo.java
  28. 30 2
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/DeviceInfoService.java
  29. 15 1
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/DevicePingInfoService.java
  30. 40 16
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/GateWayInfoService.java
  31. 7 1
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotServiceImpl.java
  32. 172 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotTemplateManagerService.java
  33. 172 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotThing2DeviceService.java
  34. 194 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotThingService.java

+ 1 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/baseParam/SuperParam.java

@@ -11,6 +11,7 @@ import java.io.Serializable;
  */
 @Data
 public class SuperParam implements Serializable {
+
     @Schema(description = "数据ID", example = "")
     private String id = null;
 

+ 49 - 2
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/IotTemplateModel.java

@@ -1,5 +1,8 @@
 package com.zhongshu.iot.client.model.iot;
 
+import com.github.microservice.types.deviceUse.DeviceCategory;
+import com.github.microservice.types.deviceUse.DeviceSpecType;
+import com.github.microservice.types.deviceUse.DeviceType;
 import com.zhongshu.iot.client.model.baseParam.SuperModel;
 import com.zhongshu.iot.client.type.DataState;
 import com.zhongshu.iot.client.type.IotDataType;
@@ -12,6 +15,8 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
+ * 产品信息
+ *
  * @author TRX
  * @date 2024/6/20
  */
@@ -19,14 +24,54 @@ import java.util.List;
 @AllArgsConstructor
 @NoArgsConstructor
 public class IotTemplateModel extends SuperModel {
+
     @Schema(description = "模版名称")
     private String name;
 
     @Schema(description = "数据状态")
     private DataState state = DataState.Enable;
 
-    @Schema(description = "区分是模版还是设备关联的物模型")
-    private IotDataType iotDataType;
+    @Schema(description = "所属物模型id")
+    private String iotThingId;
+
+    @Schema(description = "关联code,产品code")
+    private String productCode;
+
+    @Schema(description = "产品品类,直连设备、网关子设备、网关设备")
+    private DeviceCategory deviceCategory;
+
+    private String deviceCategoryStr;
+
+    public String getDeviceCategoryStr() {
+        if (deviceCategory != null) {
+            return deviceCategory.getRemark();
+        }
+        return "";
+    }
+
+    @Schema(description = "适用设备类型")
+    private DeviceType deviceType;
+
+    private String deviceTypeStr;
+
+    public String getDeviceTypeStr() {
+        if (deviceType != null) {
+            return deviceType.getRemark();
+        }
+        return "";
+    }
+
+    @Schema(description = "适用设备型号")
+    private DeviceSpecType specType;
+
+    private String specTypeStr;
+
+    public String getSpecTypeStr() {
+        if (specType != null) {
+            return specType.getRemark();
+        }
+        return "";
+    }
 
     @Schema(description = "关联的设备")
     private String deviceId;
@@ -40,4 +85,6 @@ public class IotTemplateModel extends SuperModel {
     @Schema(description = "物模型所属模版ID,就是管理设备时绑定的那个模版")
     private String iotTemplateId;
 
+    @Schema(description = "设备数量")
+    private Long deviceCount = 0L;
 }

+ 21 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThing2DeviceBind.java

@@ -0,0 +1,21 @@
+package com.zhongshu.iot.client.model.iot.thing;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author TRX
+ * @date 2025/2/25
+ */
+@Data
+public class IotThing2DeviceBind {
+
+    @Schema(description = "物模型id")
+    private String thingId;
+
+    @Schema(description = "设备id集合")
+    private List<String> deviceIds = new ArrayList<>();
+}

+ 60 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThing2DeviceModel.java

@@ -0,0 +1,60 @@
+package com.zhongshu.iot.client.model.iot.thing;
+
+import com.github.microservice.auth.client.type.DeviceType;
+import com.github.microservice.types.deviceUse.OnLineState;
+import com.zhongshu.iot.client.model.baseParam.SuperModel;
+import com.zhongshu.iot.client.model.mqtt.DeviceInfoModel;
+import com.zhongshu.iot.client.model.mqtt.ProjectInfoModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2025/2/25
+ */
+@Data
+public class IotThing2DeviceModel extends SuperModel {
+
+    @Schema(description = "物模型id")
+    private String iotThingId;
+
+    @Schema(description = "设备id")
+    private String deviceId;
+
+    @Schema(description = "设备类型")
+    private DeviceType deviceType;
+
+    private String deviceTypeStr;
+
+    public String getDeviceTypeStr() {
+        if (deviceType != null) {
+            return deviceType.getRemark();
+        }
+        return "";
+    }
+
+    @Schema(description = "设备名称")
+    private String deviceName;
+
+    @Schema(description = "关联设备信息")
+    private DeviceInfoModel deviceInfo;
+
+    @Schema(description = "所属项目")
+    private ProjectInfoModel projectInfo;
+
+    @Schema(description = "项目code")
+    private String projectInfoCode;
+
+    @Schema(description = "在线状态")
+    private OnLineState onLineState;
+
+    private String onLineStateStr;
+
+    public String getOnLineStateStr() {
+        if (onLineState != null) {
+            return onLineState.getRemark();
+        }
+        return "";
+    }
+
+}

+ 34 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThing2DeviceSearch.java

@@ -0,0 +1,34 @@
+package com.zhongshu.iot.client.model.iot.thing;
+
+import com.github.microservice.auth.client.type.DeviceType;
+import com.github.microservice.types.deviceUse.OnLineState;
+import com.zhongshu.iot.client.model.baseParam.SuperSearchParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2025/2/25
+ */
+@Data
+public class IotThing2DeviceSearch extends SuperSearchParam {
+
+    @Schema(description = "物模型id")
+    private String iotThingId;
+
+    @Schema(description = "设备id")
+    private String deviceId;
+
+    @Schema(description = "设备类型")
+    private DeviceType deviceType;
+
+    @Schema(description = "设备名称")
+    private String deviceName;
+
+    @Schema(description = "项目code")
+    private String projectCode;
+
+    @Schema(description = "在线状态")
+    private OnLineState onLineState;
+
+}

+ 42 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThingModel.java

@@ -0,0 +1,42 @@
+package com.zhongshu.iot.client.model.iot.thing;
+
+import com.github.microservice.types.deviceUse.ThingType;
+import com.zhongshu.iot.client.model.baseParam.SuperModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2025/2/25
+ */
+@Data
+public class IotThingModel extends SuperModel {
+
+    @Schema(description = "物模型类型:自动、手动创建")
+    private ThingType thingType;
+
+    @Schema(description = "编码")
+    private String code;
+
+    @Schema(description = "名称")
+    private String name;
+
+    @Schema(description = "设备数量")
+    private Long deviceCount = 0L;
+
+    @Schema(description = "所属分组")
+    private String projectCode;
+
+    @Schema(description = "分组名称")
+    private String projectName;
+
+    //-----------------所属产品 start-----------
+    @Schema(description = "所属产品数据id")
+    private String iotTemplateId;
+
+    @Schema(description = "关联code,产品code")
+    private String productCode;
+
+    //-----------------管理的设备类型 start ---------
+
+}

+ 23 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThingParam.java

@@ -0,0 +1,23 @@
+package com.zhongshu.iot.client.model.iot.thing;
+
+import com.zhongshu.iot.client.model.baseParam.SuperParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2025/2/25
+ */
+@Data
+public class IotThingParam extends SuperParam {
+
+    @Schema(description = "编码")
+    private String code;
+
+    @Schema(description = "名称")
+    private String name;
+
+    @Schema(description = "所属分组")
+    private String projectCode;
+
+}

+ 36 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThingSearch.java

@@ -0,0 +1,36 @@
+package com.zhongshu.iot.client.model.iot.thing;
+
+import com.github.microservice.types.deviceUse.ThingType;
+import com.zhongshu.iot.client.model.baseParam.SuperSearchParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2025/2/25
+ */
+@Data
+public class IotThingSearch extends SuperSearchParam {
+
+    @Schema(description = "物模型类型:自动、手动创建")
+    private ThingType thingType;
+
+    @Schema(description = "编码")
+    private String code;
+
+    @Schema(description = "名称")
+    private String name;
+
+    @Schema(description = "所属分组")
+    private String projectCode;
+
+    //-----------------所属产品 start-----------
+    @Schema(description = "所属产品数据id")
+    private String iotTemplateId;
+
+    @Schema(description = "关联code,产品code")
+    private String productCode;
+
+    //-----------------管理的设备类型 start ---------
+
+}

+ 7 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/mqtt/DeviceInfoAddParam.java

@@ -1,6 +1,7 @@
 package com.zhongshu.iot.client.model.mqtt;
 
 import cn.hutool.json.JSONObject;
+import com.github.microservice.types.deviceUse.DeviceCategory;
 import com.github.microservice.types.deviceUse.DeviceSpecType;
 import com.github.microservice.types.deviceUse.DeviceType;
 import com.github.microservice.types.deviceUse.RegistType;
@@ -15,6 +16,12 @@ import lombok.Data;
 @Data
 public class DeviceInfoAddParam extends SuperParam {
 
+    @Schema(description = "产品code")
+    private String productCode;
+
+    @Schema(description = "区分是网关还是设备")
+    private DeviceCategory deviceCategory;
+
     @Schema(description = "mqtt账号名称")
     private String mqttUserName;
 

+ 7 - 3
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/mqtt/DeviceInfoRegistParam.java

@@ -1,6 +1,7 @@
 package com.zhongshu.iot.client.model.mqtt;
 
 import cn.hutool.json.JSONObject;
+import com.github.microservice.types.deviceUse.DeviceCategory;
 import com.github.microservice.types.deviceUse.DeviceSpecType;
 import com.github.microservice.types.deviceUse.DeviceType;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -13,6 +14,9 @@ import lombok.Data;
 @Data
 public class DeviceInfoRegistParam {
 
+    @Schema(description = "产品code")
+    private String productCode;
+
     @Schema(description = "mqtt账号名称")
     private String mqttUserName;
 
@@ -43,9 +47,9 @@ public class DeviceInfoRegistParam {
     @Schema(description = "连接参数")
     private JSONObject connectParam;
 
-    @Schema(description = "设备类型")
-    private String deviceCate;
-
     @Schema(description = "心跳间隔,单位:秒")
     private Long hbInterval = 30l;
+
+    @Schema(description = "是网关还是设备")
+    private DeviceCategory deviceCategory;
 }

+ 3 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/mqtt/DeviceInfoSearchParam.java

@@ -1,5 +1,6 @@
 package com.zhongshu.iot.client.model.mqtt;
 
+import com.github.microservice.types.deviceUse.DeviceCategory;
 import com.github.microservice.types.deviceUse.DeviceSpecType;
 import com.github.microservice.types.deviceUse.DeviceType;
 import com.github.microservice.types.deviceUse.OnLineState;
@@ -32,4 +33,6 @@ public class DeviceInfoSearchParam extends SuperSearchParam {
     @Schema(description = "在线状态")
     private OnLineState onLineState;
 
+    @Schema(description = "区分是网关还是设备")
+    private DeviceCategory deviceCategory = DeviceCategory.DE;
 }

+ 1 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/mqtt/ProjectInfoModel.java

@@ -12,6 +12,7 @@ import lombok.Data;
 @Data
 @Schema(description = "项目信息")
 public class ProjectInfoModel extends SuperModel {
+
     @Schema(description = "名称")
     private String name;
 

+ 2 - 2
OneCardIotClient/src/main/java/com/zhongshu/iot/client/type/IotDataType.java

@@ -6,8 +6,8 @@ import lombok.Getter;
  * 数据类型
  */
 public enum IotDataType {
-    IotTemplate("模块"),
-    Device("设备物模型"),
+    IotTemplate("产品"),
+    Device("设备物模型绑定"),
     ;
 
     @Getter

+ 6 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/IotTemplateDao.java

@@ -21,4 +21,10 @@ public interface IotTemplateDao extends IotTemplateDaoExtend, org.springframewor
     List<IotTemplate> findByDeviceIdAndIotDataTypeOrderByCreateTimeAsc(String deviceId, IotDataType iotDataType);
 
     IotTemplate findTopByDeviceIdAndIotTemplateIdAndIotDataType(String deviceId, String iotTemplateId, IotDataType iotDataType);
+
+    IotTemplate findTopByProductCodeAndIotDataType(String productCode, IotDataType iotDataType);
+
+    IotTemplate findTopByIotThingIdAndIotDataType(String iotThingId, IotDataType iotDataType);
+
+    IotTemplate findTopByIotThingIdAndIotDataTypeAndIotTemplateId(String iotThingId, IotDataType iotDataType, String iotTemplateId);
 }

+ 24 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/IotThing2DeviceDao.java

@@ -0,0 +1,24 @@
+package com.zhongshu.iot.server.core.dao.iot;
+
+import com.zhongshu.iot.server.core.dao.iot.extend.IotThing2DeviceDaoExtend;
+import com.zhongshu.iot.server.core.domain.iot.IotThing2Device;
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+import java.util.List;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface IotThing2DeviceDao extends IotThing2DeviceDaoExtend, MongoRepository<IotThing2Device, String> {
+
+    IotThing2Device findTopById(String id);
+
+    Long countByIotThingId(String iotThingId);
+
+    void deleteByIotThingId(String iotThingId);
+
+    IotThing2Device findTopByIotThingId(String iotThingId);
+
+    List<IotThing2Device> findByIotThingId(String iotThingId);
+}

+ 20 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/IotThingDao.java

@@ -0,0 +1,20 @@
+package com.zhongshu.iot.server.core.dao.iot;
+
+import com.github.microservice.types.deviceUse.ThingType;
+import com.zhongshu.iot.server.core.dao.iot.extend.IotTemplateDaoExtend;
+import com.zhongshu.iot.server.core.dao.iot.extend.IotThingDaoExtend;
+import com.zhongshu.iot.server.core.domain.iot.IotThing;
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface IotThingDao extends IotThingDaoExtend, MongoRepository<IotThing, String> {
+
+    IotThing findTopById(String id);
+
+    IotThing findTopByDeviceId(String deviceId);
+
+    IotThing findTopByDeviceIdAndThingType(String deviceId, ThingType thingType);
+}

+ 17 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/extend/IotThing2DeviceDaoExtend.java

@@ -0,0 +1,17 @@
+package com.zhongshu.iot.server.core.dao.iot.extend;
+
+import com.zhongshu.iot.client.model.iot.thing.IotThing2DeviceSearch;
+import com.zhongshu.iot.server.core.domain.iot.IotThing2Device;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/7/7
+ * @Version: 1.0
+ */
+public interface IotThing2DeviceDaoExtend {
+
+    Page<IotThing2Device> page(Pageable pageable, IotThing2DeviceSearch param);
+
+}

+ 19 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/extend/IotThingDaoExtend.java

@@ -0,0 +1,19 @@
+package com.zhongshu.iot.server.core.dao.iot.extend;
+
+import com.zhongshu.iot.client.model.iot.IotTemplateSearch;
+import com.zhongshu.iot.client.model.iot.thing.IotThingSearch;
+import com.zhongshu.iot.server.core.domain.iot.IotTemplate;
+import com.zhongshu.iot.server.core.domain.iot.IotThing;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/7/7
+ * @Version: 1.0
+ */
+public interface IotThingDaoExtend {
+
+    Page<IotThing> page(Pageable pageable, IotThingSearch param);
+
+}

+ 79 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/impl/IotThing2DeviceDaoImpl.java

@@ -0,0 +1,79 @@
+package com.zhongshu.iot.server.core.dao.iot.impl;
+
+import com.github.microservice.components.data.mongo.mongo.helper.DBHelper;
+import com.zhongshu.iot.client.model.iot.thing.IotThing2DeviceSearch;
+import com.zhongshu.iot.server.core.dao.base.BaseImpl;
+import com.zhongshu.iot.server.core.dao.iot.extend.IotThing2DeviceDaoExtend;
+import com.zhongshu.iot.server.core.domain.iot.IotThing2Device;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/4/12
+ * @Version: 1.0
+ */
+public class IotThing2DeviceDaoImpl extends BaseImpl implements IotThing2DeviceDaoExtend {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DBHelper dbHelper;
+
+    @Override
+    public Page<IotThing2Device> page(Pageable pageable, IotThing2DeviceSearch param) {
+        Criteria criteria = buildFilterCriteria(param);
+        Sort sort = buildSort(param);
+        Query query = Query.query(criteria);
+        query.with(sort);
+        return dbHelper.pages(query, pageable, IotThing2Device.class);
+    }
+
+    private Criteria buildFilterCriteria(IotThing2DeviceSearch param) {
+        Criteria criteria = buildCriteriaAboutTime(param);
+
+        if (StringUtils.isNotEmpty(param.getIotThingId())) {
+            criteria.and("iotThingId").is(param.getIotThingId());
+        }
+
+        if (param.getDeviceType() != null) {
+            criteria.and("deviceType").is(param.getDeviceType());
+        }
+
+        if (StringUtils.isNotEmpty(param.getProjectCode())) {
+            criteria.and("projectCode").is(param.getProjectCode());
+        }
+
+        if (param.getOnLineState() != null) {
+            criteria.and("onLineState").is(param.getOnLineState());
+        }
+
+        // 模糊搜索
+        List<Criteria> criterias = new ArrayList<>();
+        if (StringUtils.isNotEmpty(param.getDeviceId())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getDeviceId() + ".*$");
+            criterias.add(Criteria.where("deviceId").is(pattern));
+        }
+        if (StringUtils.isNotEmpty(param.getDeviceName())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getDeviceName() + ".*$");
+            criterias.add(Criteria.where("deviceName").is(pattern));
+        }
+        if (!CollectionUtils.isEmpty(criterias)) {
+            criteria.andOperator(criterias.toArray(new Criteria[]{}));
+        }
+        return criteria;
+    }
+
+}

+ 82 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/impl/IotThingDaoImpl.java

@@ -0,0 +1,82 @@
+package com.zhongshu.iot.server.core.dao.iot.impl;
+
+import com.github.microservice.components.data.mongo.mongo.helper.DBHelper;
+import com.zhongshu.iot.client.model.iot.thing.IotThingSearch;
+import com.zhongshu.iot.server.core.dao.base.BaseImpl;
+import com.zhongshu.iot.server.core.dao.iot.extend.IotThingDaoExtend;
+import com.zhongshu.iot.server.core.domain.iot.IotThing;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/4/12
+ * @Version: 1.0
+ */
+public class IotThingDaoImpl extends BaseImpl implements IotThingDaoExtend {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DBHelper dbHelper;
+
+    @Override
+    public Page<IotThing> page(Pageable pageable, IotThingSearch param) {
+        Criteria criteria = buildFilterCriteria(param);
+        Sort sort = buildSort(param);
+        Query query = Query.query(criteria);
+        query.with(sort);
+        return dbHelper.pages(query, pageable, IotThing.class);
+    }
+
+    private Criteria buildFilterCriteria(IotThingSearch param) {
+        Criteria criteria = buildCriteriaAboutTime(param);
+
+        if (param.getThingType() != null) {
+            criteria.and("thingType").is(param.getThingType());
+        }
+
+        // 分组
+        if (StringUtils.isNotEmpty(param.getProjectCode())) {
+            criteria.and("projectCode").is(param.getProjectCode());
+        }
+
+        if (StringUtils.isNotEmpty(param.getIotTemplateId())) {
+            criteria.and("iotTemplateId").is(param.getIotTemplateId());
+        }
+
+        // 模糊搜索
+        List<Criteria> criterias = new ArrayList<>();
+        if (StringUtils.isNotEmpty(param.getName())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getName() + ".*$");
+            criterias.add(Criteria.where("name").is(pattern));
+        }
+        if (StringUtils.isNotEmpty(param.getCode())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getCode() + ".*$");
+            criterias.add(Criteria.where("code").is(pattern));
+        }
+        if (StringUtils.isNotEmpty(param.getProductCode())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getProductCode() + ".*$");
+            criterias.add(Criteria.where("productCode").is(pattern));
+        }
+
+        if (!CollectionUtils.isEmpty(criterias)) {
+            criteria.andOperator(criterias.toArray(new Criteria[]{}));
+        }
+
+        return criteria;
+    }
+
+}

+ 3 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/DeviceInfoDao.java

@@ -23,4 +23,7 @@ public interface DeviceInfoDao extends DeviceInfoDaoExtend, org.springframework.
     long countByMqttUserNameAndIsDelete(String mqttUserName, Boolean isDelete);
 
     List<DeviceInfo> findByRegistTypeIn(List<RegistType> registTypes);
+
+    Long countByProductCode(String productCode);
+
 }

+ 4 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/impl/DeviceInfoDaoImpl.java

@@ -36,6 +36,10 @@ public class DeviceInfoDaoImpl extends BaseImpl implements DeviceInfoDaoExtend {
     public Page<DeviceInfo> page(Pageable pageable, DeviceInfoSearchParam param) {
         Criteria criteria = new Criteria();
 
+        if (param.getDeviceCategory() != null) {
+            criteria.and("deviceCategory").is(param.getDeviceCategory());
+        }
+
         if (StringUtils.isNotEmpty(param.getDeviceId())) {
             criteria.and("deviceId").is(param.getDeviceId());
         }

+ 5 - 5
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/IotMain.java

@@ -33,6 +33,10 @@ public class IotMain extends SuperEntity {
     @Schema(description = "模版id")
     private String iotMainTemplateId;
 
+    @Schema(description = "所属模版、物模型")
+    @DBRef(lazy = true)
+    private IotTemplate iotTemplate;
+
     @Schema(description = "所属物模型id")
     private String iotThingId;
 
@@ -68,10 +72,6 @@ public class IotMain extends SuperEntity {
     @Schema(description = "响应的真实的topic")
     private String replyRealIotTopic;
 
-    @Schema(description = "所属模版、物模型")
-    @DBRef(lazy = true)
-    private IotTemplate iotTemplate;
-
     @Schema(description = "是否返回数据")
     private Boolean isReturnData = Boolean.TRUE;
 
@@ -130,7 +130,7 @@ public class IotMain extends SuperEntity {
     @Schema(description = "关联的设备")
     private String deviceId;
 
-    @Schema(description = "所属分code")
+    @Schema(description = "所属分code")
     private String projectCode;
 
     @Schema(description = "关联时间")

+ 10 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/IotThing.java

@@ -1,5 +1,6 @@
 package com.zhongshu.iot.server.core.domain.iot;
 
+import com.github.microservice.types.deviceUse.DeviceCategory;
 import com.github.microservice.types.deviceUse.DeviceType;
 import com.github.microservice.types.deviceUse.ThingType;
 import com.zhongshu.iot.server.core.domain.base.SuperEntity;
@@ -27,6 +28,9 @@ public class IotThing extends SuperEntity {
     @Schema(description = "物模型类型:自动、手动创建")
     private ThingType thingType;
 
+    @Schema(description = "编码")
+    private String code;
+
     @Schema(description = "名称")
     private String name;
 
@@ -45,6 +49,12 @@ public class IotThing extends SuperEntity {
 
     //-----------------管理的设备类型 start ---------
 
+    @Schema(description = "设备id")
+    private String deviceId;
+
+    @Schema(description = "设备品类")
+    private DeviceCategory deviceCategory;
+
     @Schema(description = "设备id集合")
     private List<String> deviceIds = new ArrayList<>();
 

+ 23 - 1
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/IotThing2Device.java

@@ -1,8 +1,11 @@
 package com.zhongshu.iot.server.core.domain.iot;
 
-import com.github.microservice.auth.client.type.DeviceType;
+import com.github.microservice.types.deviceUse.DeviceCategory;
+import com.github.microservice.types.deviceUse.DeviceType;
+import com.github.microservice.types.deviceUse.OnLineState;
 import com.zhongshu.iot.server.core.domain.base.SuperEntity;
 import com.zhongshu.iot.server.core.domain.iot.mqtt.DeviceInfo;
+import com.zhongshu.iot.server.core.domain.iot.mqtt.ProjectInfo;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -24,14 +27,33 @@ public class IotThing2Device extends SuperEntity {
     @DBRef(lazy = true)
     private IotThing iotThing;
 
+    @Schema(description = "物模型id")
+    private String iotThingId;
+
     @Schema(description = "设备id")
     private String deviceId;
 
+    @Schema(description = "设备名称")
+    private String deviceName;
+
     @Schema(description = "设备类型")
     private DeviceType deviceType;
 
+    @Schema(description = "设备品类")
+    private DeviceCategory deviceCategory;
+
     @Schema(description = "关联设备信息")
     @DBRef(lazy = true)
     private DeviceInfo deviceInfo;
 
+    @Schema(description = "所属项目")
+    @DBRef(lazy = true)
+    private ProjectInfo projectInfo;
+
+    @Schema(description = "项目code")
+    private String projectCode;
+
+    @Schema(description = "在线状态")
+    private OnLineState onLineState;
+
 }

+ 4 - 1
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/mqtt/DeviceInfo.java

@@ -33,7 +33,7 @@ public class DeviceInfo extends SuperEntity {
     private String deviceName;
 
     @Schema(description = "设备code,产品code")
-    private String projectCode;
+    private String productCode;
 
     @Schema(description = "设备类型:消费机 闸机")
     private DeviceType deviceType;
@@ -41,6 +41,9 @@ public class DeviceInfo extends SuperEntity {
     @Schema(description = "设备注册方式")
     private RegistType registType = RegistType.Gateway;
 
+    @Schema(description = "区分是网关、设备")
+    private DeviceCategory deviceCategory = DeviceCategory.GW;
+
     @Schema(description = "设备型号")
     private DeviceSpecType specType;
 

+ 3 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/mqtt/GateWayInfo.java

@@ -22,6 +22,9 @@ import org.springframework.data.mongodb.core.mapping.Document;
 @AllArgsConstructor
 public class GateWayInfo extends SuperEntity {
 
+    @Schema(description = "设备code,产品code")
+    private String productCode;
+
     @Schema(description = "mqtt账号名称")
     private String mqttUserName;
 

+ 30 - 2
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/DeviceInfoService.java

@@ -1,14 +1,15 @@
 package com.zhongshu.iot.server.core.service.device;
 
-import com.github.microservice.types.deviceUse.DeviceState;
-import com.github.microservice.types.deviceUse.OnLineState;
 import com.github.microservice.net.ResultContent;
 import com.github.microservice.types.FunctionType;
+import com.github.microservice.types.deviceUse.DeviceState;
+import com.github.microservice.types.deviceUse.OnLineState;
 import com.zhongshu.iot.client.model.iot.IotMainModel;
 import com.zhongshu.iot.client.model.mqtt.DeviceInfoAddParam;
 import com.zhongshu.iot.client.model.mqtt.DeviceInfoModel;
 import com.zhongshu.iot.client.model.mqtt.DeviceInfoSearchParam;
 import com.zhongshu.iot.client.model.mqtt.DeviceInfoUpdateRemark;
+import com.zhongshu.iot.client.type.IotDataType;
 import com.zhongshu.iot.client.type.type.LogsLevel;
 import com.zhongshu.iot.server.core.dao.iot.IotTemplateDao;
 import com.zhongshu.iot.server.core.dao.mqtt.DeviceInfoDao;
@@ -18,6 +19,7 @@ import com.zhongshu.iot.server.core.domain.iot.IotTemplate;
 import com.zhongshu.iot.server.core.domain.iot.mqtt.DeviceInfo;
 import com.zhongshu.iot.server.core.domain.iot.mqtt.ProjectInfo;
 import com.zhongshu.iot.server.core.service.iot.IotServiceImpl;
+import com.zhongshu.iot.server.core.service.iot.IotThingService;
 import com.zhongshu.iot.server.core.service.sync.DeviceSyncFullCardService;
 import com.zhongshu.iot.server.core.service.user.OperationLogsService;
 import com.zhongshu.iot.server.core.util.DateUtils;
@@ -68,6 +70,9 @@ public class DeviceInfoService {
     @Autowired
     private JMXSyncService jmxSyncService;
 
+    @Autowired
+    private IotThingService iotThingService;
+
     public ResultContent initSyncAllDevice() {
         // 同步所有的设备
         List<DeviceInfo> deviceInfos = deviceInfoDao.findAll();
@@ -96,10 +101,18 @@ public class DeviceInfoService {
             deviceInfo.setState(DeviceState.Enable);
         }
         BeanUtils.copyProperties(param, deviceInfo, "id");
+
         deviceInfo.setLastOnlineTime(System.currentTimeMillis());
         deviceInfo.setLastOnlineTimeStr(DateUtils.paresTime(System.currentTimeMillis(), DateUtils.FORMAT_LONG));
         deviceInfo.setOnLineState(OnLineState.OnLine);
 
+        // 关联的产品信息
+        IotTemplate iotTemplate = iotTemplateDao.findTopByProductCodeAndIotDataType(param.getProductCode(), IotDataType.IotTemplate);
+        if (ObjectUtils.isNotEmpty(iotTemplate)) {
+            deviceInfo.setDeviceType(iotTemplate.getDeviceType());
+            deviceInfo.setSpecType(iotTemplate.getSpecType());
+        }
+
         // 项目
         if (StringUtils.isNotEmpty(param.getProjectInfoCode())) {
             ProjectInfo projectInfo = projectInfoDao.findTopByCode(param.getProjectInfoCode());
@@ -111,6 +124,8 @@ public class DeviceInfoService {
 
         DeviceInfo finalDeviceInfo = deviceInfo;
         CompletableFuture.runAsync(() -> {
+
+            iotThingService.initAutoThingByDevice(finalDeviceInfo);
             // 日志
             operationLogsService.addLogs(String.format("添加了设备;%s", finalDeviceInfo.getDeviceName()), LogsLevel.Middle, finalDeviceInfo);
 
@@ -320,6 +335,19 @@ public class DeviceInfoService {
         return ResultContent.buildSuccess();
     }
 
+    /**
+     * 统计产品关联的设备数量
+     *
+     * @param productCode
+     * @return
+     */
+    public Long countByProductCode(String productCode) {
+        if (StringUtils.isEmpty(productCode)) {
+            return 0L;
+        }
+        return deviceInfoDao.countByProductCode(productCode);
+    }
+
     public ResultContent<DeviceInfoModel> getDeviceById(String deviceId) {
         DeviceInfoModel model = null;
         DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);

+ 15 - 1
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/DevicePingInfoService.java

@@ -4,15 +4,16 @@ import cn.hutool.json.JSONUtil;
 import com.github.microservice.models.hxz.DevicePingInfoParam;
 import com.github.microservice.models.hxz.GateWayPingInfoParam;
 import com.github.microservice.models.hxz.PingResult;
+import com.github.microservice.net.ResultContent;
 import com.github.microservice.types.deviceUse.DeviceType;
 import com.github.microservice.types.deviceUse.OnLineDeviceType;
 import com.github.microservice.types.deviceUse.OnLineState;
-import com.github.microservice.net.ResultContent;
 import com.zhongshu.iot.server.core.dao.mqtt.DeviceInfoDao;
 import com.zhongshu.iot.server.core.dao.mqtt.DeviceOnLineInfoDao;
 import com.zhongshu.iot.server.core.dao.mqtt.DevicePingInfoDao;
 import com.zhongshu.iot.server.core.dao.mqtt.GateWayInfoDao;
 import com.zhongshu.iot.server.core.dataConfig.CommonTTLTimeConfig;
+import com.zhongshu.iot.server.core.domain.iot.IotThing2Device;
 import com.zhongshu.iot.server.core.domain.iot.mqtt.*;
 import com.zhongshu.iot.server.core.service.base.CommonService;
 import com.zhongshu.iot.server.core.service.base.RedisService;
@@ -272,6 +273,13 @@ public class DevicePingInfoService extends SuperService {
         }
     }
 
+    /**
+     * 更新设备在线状态
+     *
+     * @param id
+     * @param deviceId
+     * @param onLineState
+     */
     private void updateDeviceOnLine(String id, String deviceId, OnLineState onLineState) {
         Map<String, Object> standardData = new HashMap<String, Object>();
         standardData.put("id", id);
@@ -281,6 +289,12 @@ public class DevicePingInfoService extends SuperService {
         }
         commonService.updateData(standardData, DeviceInfo.class.getSimpleName());
 
+        Map<String, Object> where = new HashMap<>();
+        where.put("deviceId", deviceId);
+        Map<String, Object> updateData = new HashMap<>();
+        updateData.put("onLineState", onLineState);
+        commonService.updateData(where, updateData, IotThing2Device.class.getSimpleName());
+
         // 通知业务平台
         deviceSyncFullCardService.noticeSyncDeviceOnlineStateChange(deviceId);
     }

+ 40 - 16
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/GateWayInfoService.java

@@ -4,20 +4,22 @@ import cn.hutool.json.JSONUtil;
 import com.github.microservice.http.APIResponseModel;
 import com.github.microservice.models.common.CommonResult;
 import com.github.microservice.models.project.ProjectConfigQueryParam;
+import com.github.microservice.net.ResultContent;
 import com.github.microservice.types.deviceUse.DeviceState;
-import com.github.microservice.types.deviceUse.DeviceType;
 import com.github.microservice.types.deviceUse.OnLineState;
 import com.github.microservice.types.deviceUse.RegistType;
-import com.github.microservice.net.ResultContent;
 import com.zhongshu.iot.client.model.mqtt.*;
+import com.zhongshu.iot.client.type.IotDataType;
+import com.zhongshu.iot.server.core.dao.iot.IotTemplateDao;
 import com.zhongshu.iot.server.core.dao.mqtt.*;
+import com.zhongshu.iot.server.core.domain.iot.IotTemplate;
 import com.zhongshu.iot.server.core.domain.iot.mqtt.*;
 import com.zhongshu.iot.server.core.httpRequest.ApiRequestService;
 import com.zhongshu.iot.server.core.httpRequest.conf.FullCardAPIConfig;
 import com.zhongshu.iot.server.core.service.base.SuperService;
 import com.zhongshu.iot.server.core.service.iot.IotServiceImpl;
+import com.zhongshu.iot.server.core.service.iot.IotThingService;
 import com.zhongshu.iot.server.core.service.sync.DeviceSyncFullCardService;
-import com.zhongshu.iot.server.core.util.CommonUtil;
 import com.zhongshu.iot.server.core.util.DateUtils;
 import com.zhongshu.iot.server.core.util.JMXUtil;
 import com.zhongshu.iot.server.core.util.bean.BeanUtils;
@@ -97,6 +99,11 @@ public class GateWayInfoService extends SuperService {
     @Autowired
     private GateWayUserInfoDao gateWayUserInfoDao;
 
+    @Autowired
+    private IotTemplateDao iotTemplateDao;
+    @Autowired
+    private IotThingService iotThingService;
+
     /**
      * 注册 网关
      *
@@ -168,7 +175,6 @@ public class GateWayInfoService extends SuperService {
             return ResultContent.buildFail(checkNameContent.getMsg());
         }
 
-
         ProjectInfo projectInfo = null;
         if (StringUtils.isNotEmpty(param.getProjectInfoCode())) {
             projectInfo = projectInfoDao.findTopByCode(param.getProjectInfoCode());
@@ -196,6 +202,10 @@ public class GateWayInfoService extends SuperService {
         }
 
         gateWayInfoDao.save(gateWayInfo);
+
+        // 初始网关关联的物模型
+        iotThingService.initAutoThingByGateWay(gateWayInfo);
+
         log.info("网关注册成功");
         // 通知同步 (网关信息)
         deviceSyncFullCardService.noticeSyncGateWay(gateWayInfo);
@@ -261,15 +271,17 @@ public class GateWayInfoService extends SuperService {
      * @return
      */
     public ResultContent<DeviceInfo> addDevice(DeviceInfoRegistParam param) {
+        // 产品code
+        if (StringUtils.isEmpty(param.getProductCode())) {
+            return ResultContent.buildFail("productCode不能为空");
+        }
         if (StringUtils.isEmpty(param.getDeviceId())) {
             return ResultContent.buildFail("deviceId不能为空");
         }
         if (StringUtils.isEmpty(param.getDeviceName())) {
             return ResultContent.buildFail("deviceName不能为空");
         }
-        if (StringUtils.isEmpty(param.getDeviceCate())) {
-            return ResultContent.buildFail("deviceCate不能为空");
-        }
+        // 分组code
         if (StringUtils.isEmpty(param.getProjectInfoCode())) {
             return ResultContent.buildFail("projectInfoCode不能为空");
         }
@@ -282,6 +294,13 @@ public class GateWayInfoService extends SuperService {
             return ResultContent.buildFail(checkNameContent.getMsg());
         }
 
+        // 检查产品是否存在
+        IotTemplate iotTemplate = iotTemplateDao.findTopByProductCodeAndIotDataType(param.getProductCode(), IotDataType.IotTemplate);
+        if (ObjectUtils.isEmpty(iotTemplate)) {
+            return ResultContent.buildFail(String.format("productCode不存在", param.getProductCode()));
+        }
+
+        // 检查分组是否存在
         ProjectInfo projectInfo = projectInfoDao.findTopByCode(param.getProjectInfoCode());
         if (ObjectUtils.isEmpty(projectInfo)) {
             return ResultContent.buildFail("projectInfoCode不存在");
@@ -309,15 +328,7 @@ public class GateWayInfoService extends SuperService {
         DeviceInfoAddParam deviceInfoAddParam = new DeviceInfoAddParam();
         BeanUtils.copyProperties(param, deviceInfoAddParam);
         deviceInfoAddParam.setRegistType(registType);
-        if (StringUtils.isNotEmpty(param.getDeviceCate())) {
-            DeviceType deviceType = CommonUtil.getEnumByName(DeviceType.class, param.getDeviceCate());
-            if (deviceType == null) {
-                return ResultContent.buildFail("deviceCate不存在");
-            }
-            if (deviceType != null) {
-                deviceInfoAddParam.setDeviceType(deviceType);
-            }
-        }
+        deviceInfoAddParam.setDeviceCategory(iotTemplate.getDeviceCategory());
         devices.add(deviceInfoAddParam);
 
         // 设备列表
@@ -595,4 +606,17 @@ public class GateWayInfoService extends SuperService {
         return ResultContent.buildSuccess();
     }
 
+    /**
+     * 得到设备的网关信息
+     *
+     * @param deviceInfo
+     * @return
+     */
+    public GateWayInfo getDeviceGateWayInfo(DeviceInfo deviceInfo) {
+        GateWay2Device gateWay2Device = gateWay2DeviceDao.findTopByDeviceInfoOrderByUpdateTimeDesc(deviceInfo);
+        if (gateWay2Device == null) {
+            return null;
+        }
+        return gateWay2Device.getGateWayInfo();
+    }
 }

+ 7 - 1
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotServiceImpl.java

@@ -22,6 +22,7 @@ import com.zhongshu.iot.server.core.domain.iot.mqtt.DeviceInfo;
 import com.zhongshu.iot.server.core.domain.iot.mqtt.GateWay2Device;
 import com.zhongshu.iot.server.core.service.base.CommonService;
 import com.zhongshu.iot.server.core.service.base.SuperService;
+import com.zhongshu.iot.server.core.service.device.DeviceInfoService;
 import com.zhongshu.iot.server.core.util.CommonUtil;
 import com.zhongshu.iot.server.core.util.bean.BeanUtils;
 import com.zhongshu.iot.server.core.util.page.PageEntityUtil;
@@ -76,6 +77,9 @@ public class IotServiceImpl extends SuperService {
     @Autowired
     private IotTemplate2DeviceService iotTemplate2DeviceService;
 
+    @Autowired
+    private DeviceInfoService deviceInfoService;
+
     //----------------------------- 模版 start----------------------------
 
     /**
@@ -440,7 +444,7 @@ public class IotServiceImpl extends SuperService {
         return ResultContent.buildSuccess();
     }
 
-    private void initRealTopic(IotMain iotMain) {
+    public void initRealTopic(IotMain iotMain) {
         if (iotMain != null && iotMain.getIotDataType() == IotDataType.Device) {
             // 把 topic有占位符的换为具体的值
             String deviceId = iotMain.getDeviceId();
@@ -564,6 +568,8 @@ public class IotServiceImpl extends SuperService {
         if (ObjectUtils.isNotEmpty(entity)) {
             model = new IotTemplateModel();
             BeanUtils.copyProperties(entity, model);
+            // 设备数量
+            model.setDeviceCount(deviceInfoService.countByProductCode(entity.getProductCode()));
         }
         return model;
     }

+ 172 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotTemplateManagerService.java

@@ -0,0 +1,172 @@
+package com.zhongshu.iot.server.core.service.iot;
+
+import com.github.microservice.net.ResultContent;
+import com.zhongshu.iot.client.type.IotDataType;
+import com.zhongshu.iot.server.core.dao.UserDao;
+import com.zhongshu.iot.server.core.dao.iot.IotDeviceDataDao;
+import com.zhongshu.iot.server.core.dao.iot.IotMainDao;
+import com.zhongshu.iot.server.core.dao.iot.IotTemplateDao;
+import com.zhongshu.iot.server.core.dao.iot.IotTopicDao;
+import com.zhongshu.iot.server.core.dao.mqtt.DeviceInfoDao;
+import com.zhongshu.iot.server.core.dao.mqtt.GateWay2DeviceDao;
+import com.zhongshu.iot.server.core.domain.iot.IotMain;
+import com.zhongshu.iot.server.core.domain.iot.IotTemplate;
+import com.zhongshu.iot.server.core.domain.iot.IotThing;
+import com.zhongshu.iot.server.core.domain.iot.mqtt.DeviceInfo;
+import com.zhongshu.iot.server.core.domain.iot.mqtt.GateWayInfo;
+import com.zhongshu.iot.server.core.service.base.CommonService;
+import com.zhongshu.iot.server.core.service.base.SuperService;
+import com.zhongshu.iot.server.core.service.device.DeviceInfoService;
+import com.zhongshu.iot.server.core.service.device.GateWayInfoService;
+import com.zhongshu.iot.server.core.util.bean.BeanUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * 物模型 属性等管理 服务
+ *
+ * @author TRX
+ * @date 2025/2/25
+ */
+@Slf4j
+@Service
+public class IotTemplateManagerService extends SuperService {
+
+    @Autowired
+    private IotTemplateDao iotTemplateDao;
+
+    @Autowired
+    private IotMainDao iotMainDao;
+
+    @Autowired
+    private IotTopicDao iotTopicDao;
+
+    @Autowired
+    private UserDao userDao;
+
+    @Autowired
+    private DeviceInfoDao deviceInfoDao;
+
+    @Autowired
+    private GateWay2DeviceDao gateWay2DeviceDao;
+
+    @Autowired
+    private IotDeviceDataDao iotDeviceDataDao;
+
+    @Autowired
+    private CommonService commonService;
+
+    @Autowired
+    private IotTemplate2DeviceService iotTemplate2DeviceService;
+
+    @Autowired
+    private DeviceInfoService deviceInfoService;
+
+    @Autowired
+    private IotServiceImpl iotService;
+
+    @Autowired
+    private GateWayInfoService gateWayInfoService;
+
+    /**
+     * 自动绑定:更加物模型 绑定属性的信息 (添加或更新物模型)
+     *
+     * @param iotThing
+     * @param deviceInfo
+     * @return
+     */
+    public ResultContent deviceBindAutoIotTemplate(IotThing iotThing, DeviceInfo deviceInfo) {
+        if (ObjectUtils.isEmpty(iotThing) || ObjectUtils.isEmpty(deviceInfo)) {
+            return ResultContent.buildFail("数据不全");
+        }
+        // 所属产品信息
+        IotTemplate iotTemplate = iotTemplateDao.findTopById(iotThing.getIotTemplateId());
+        return deviceBindAutoIotTemplate(iotTemplate, deviceInfo, iotThing.getId());
+    }
+
+    public ResultContent deviceBindAutoIotTemplate(IotTemplate iotTemplate, DeviceInfo deviceInfo, String iotThingId) {
+        if (ObjectUtils.isEmpty(iotTemplate) || ObjectUtils.isEmpty(deviceInfo)) {
+            return ResultContent.buildFail("数据不全");
+        }
+        // 分组code
+        String projectInfoCode = deviceInfo.getProjectInfoCode();
+
+        // 判断该设备是否已绑定该模版
+        IotTemplate temp = iotTemplateDao.findTopByIotThingIdAndIotDataTypeAndIotTemplateId(iotThingId, IotDataType.Device, iotTemplate.getId());
+        IotTemplate newIotTemplate = null;
+        if (ObjectUtils.isNotEmpty(temp)) {
+            newIotTemplate = temp;
+        } else {
+            newIotTemplate = new IotTemplate();
+        }
+
+        BeanUtils.copyProperties(iotTemplate, newIotTemplate, "id", "createTime", "updateTime");
+        newIotTemplate.setIotDataType(IotDataType.Device);
+        newIotTemplate.setIotThingId(iotThingId);
+        newIotTemplate.setIotTemplateId(iotTemplate.getId());
+        newIotTemplate.setDeviceId(deviceInfo.getDeviceId());
+        newIotTemplate.setProjectCode(projectInfoCode);
+        iotTemplateDao.save(newIotTemplate);
+
+        // 绑定 物模型 和 设备的关系
+        iotTemplate2DeviceService.bind(newIotTemplate, deviceInfo);
+
+        // 属性等数据
+        List<IotMain> saveList = new ArrayList<>();
+        // 模版对应的数据
+        List<IotMain> list = iotMainDao.findByIotTemplateOrderByCreateTimeAsc(iotTemplate);
+        // 以前绑定的数据
+        List<IotMain> oldList = iotMainDao.findByIotTemplateOrderByCreateTimeAsc(newIotTemplate);
+
+        HashMap<String, String> map = new HashMap<>();
+        if (ObjectUtils.isNotEmpty(oldList)) {
+            oldList.stream().forEach(it -> {
+                map.put(it.getIotMainTemplateId(), it.getId());
+            });
+        }
+        GateWayInfo gateWayInfo = gateWayInfoService.getDeviceGateWayInfo(deviceInfo);
+
+        if (list != null) {
+            IotTemplate finalNewIotTemplate = newIotTemplate;
+            list.stream().forEach(it -> {
+                IotMain main = new IotMain();
+                BeanUtils.copyProperties(it, main, "id", "createTime", "updateTime");
+                if (oldList.contains(it.getId())) {
+                    main.setId(map.get(it.getId()));
+                    map.remove(it.getId());
+                }
+                main.setIotThingId(iotThingId);
+                // 所属
+                main.setIotTemplate(finalNewIotTemplate);
+                // 所属产品code
+                main.setProductCode(finalNewIotTemplate.getProductCode());
+                // 所属模版内容数据ID
+                main.setIotMainTemplateId(it.getId());
+
+                main.setIotDataType(IotDataType.Device);
+                main.setDeviceId(deviceInfo.getDeviceId());
+                main.setProjectCode(projectInfoCode);
+                main.setAddTime(System.currentTimeMillis());
+                if (ObjectUtils.isNotEmpty(gateWayInfo)) {
+                    main.setGateWayId(gateWayInfo.getGateWayId());
+                }
+                iotService.initRealTopic(main);
+                saveList.add(main);
+            });
+        }
+        iotMainDao.saveAll(saveList);
+        if (!map.isEmpty()) {
+            List<String> ids = new ArrayList<>(map.keySet());
+            iotMainDao.deleteAllById(ids);
+        }
+
+        return ResultContent.buildSuccess();
+    }
+
+}

+ 172 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotThing2DeviceService.java

@@ -0,0 +1,172 @@
+package com.zhongshu.iot.server.core.service.iot;
+
+import com.github.microservice.net.ResultContent;
+import com.github.microservice.net.ResultMessage;
+import com.github.microservice.types.deviceUse.ThingType;
+import com.zhongshu.iot.client.model.iot.thing.IotThing2DeviceModel;
+import com.zhongshu.iot.client.model.iot.thing.IotThing2DeviceSearch;
+import com.zhongshu.iot.server.core.dao.iot.IotThing2DeviceDao;
+import com.zhongshu.iot.server.core.dao.mqtt.DeviceInfoDao;
+import com.zhongshu.iot.server.core.domain.iot.IotThing;
+import com.zhongshu.iot.server.core.domain.iot.IotThing2Device;
+import com.zhongshu.iot.server.core.domain.iot.mqtt.DeviceInfo;
+import com.zhongshu.iot.server.core.domain.iot.mqtt.GateWayInfo;
+import com.zhongshu.iot.server.core.service.base.SuperService;
+import com.zhongshu.iot.server.core.service.device.DeviceInfoService;
+import com.zhongshu.iot.server.core.service.device.ProjectInfoService;
+import com.zhongshu.iot.server.core.util.bean.BeanUtils;
+import com.zhongshu.iot.server.core.util.page.PageEntityUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author TRX
+ * @date 2025/2/25
+ */
+@Slf4j
+@Service
+public class IotThing2DeviceService extends SuperService {
+
+    @Autowired
+    private IotThing2DeviceDao iotThing2DeviceDao;
+
+    @Autowired
+    private ProjectInfoService projectInfoService;
+
+    @Autowired
+    private DeviceInfoDao deviceInfoDao;
+
+    @Autowired
+    private DeviceInfoService deviceInfoService;
+
+    @Autowired
+    private IotThingService iotThingService;
+
+    /**
+     * 物模型绑定设备
+     *
+     * @param iotThing
+     * @param gateWayInfo
+     * @return
+     */
+    public ResultContent initAutoBindGateWay(IotThing iotThing, GateWayInfo gateWayInfo) {
+        if (ObjectUtils.isNotEmpty(iotThing) && ObjectUtils.isNotEmpty(gateWayInfo)) {
+            IotThing2Device entity = iotThing2DeviceDao.findTopByIotThingId(iotThing.getId());
+            if (ObjectUtils.isEmpty(entity)) {
+                entity = new IotThing2Device();
+            }
+            entity.setIotThing(iotThing);
+            entity.setIotThingId(iotThing.getId());
+            entity.setDeviceId(gateWayInfo.getGateWayId());
+            entity.setDeviceName(gateWayInfo.getGateWayName());
+            entity.setDeviceCategory(iotThing.getDeviceCategory());
+            entity.setProjectInfo(gateWayInfo.getProjectInfo());
+            entity.setProjectCode(gateWayInfo.getProjectInfoCode());
+            entity.setOnLineState(gateWayInfo.getOnLineState());
+            iotThing2DeviceDao.save(entity);
+        }
+        return ResultContent.buildSuccess();
+    }
+
+
+    public ResultContent initAutoBindDevice(IotThing iotThing, DeviceInfo deviceInfo) {
+        if (ObjectUtils.isNotEmpty(iotThing) && ObjectUtils.isNotEmpty(deviceInfo)) {
+            IotThing2Device entity = iotThing2DeviceDao.findTopByIotThingId(iotThing.getId());
+            if (ObjectUtils.isEmpty(entity)) {
+                entity = new IotThing2Device();
+            }
+            entity.setIotThing(iotThing);
+            entity.setIotThingId(iotThing.getId());
+            entity.setDeviceId(deviceInfo.getDeviceId());
+            entity.setDeviceName(deviceInfo.getDeviceName());
+            entity.setDeviceType(deviceInfo.getDeviceType());
+            entity.setDeviceCategory(iotThing.getDeviceCategory());
+            entity.setDeviceInfo(deviceInfo);
+            entity.setProjectInfo(deviceInfo.getProjectInfo());
+            entity.setProjectCode(deviceInfo.getProjectInfoCode());
+            entity.setOnLineState(deviceInfo.getOnLineState());
+            iotThing2DeviceDao.save(entity);
+        }
+        return ResultContent.buildSuccess();
+    }
+
+    /**
+     * 删除物模型绑定的设备
+     *
+     * @param id
+     * @return
+     */
+    public ResultContent delete(String id) {
+        IotThing2Device entity = iotThing2DeviceDao.findTopById(id);
+        if (ObjectUtils.isNotEmpty(entity)) {
+            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
+        }
+        IotThing iotThing = entity.getIotThing();
+        if (ObjectUtils.isNotEmpty(iotThing)) {
+            if (iotThing.getThingType() == ThingType.Auto) {
+                return ResultContent.buildFail("不能解绑改设备");
+            }
+        }
+        iotThing2DeviceDao.deleteById(id);
+        iotThingService.updateThingDeviceCount(entity.getIotThingId());
+        return ResultContent.buildSuccess();
+    }
+
+    /**
+     * 根据物模型删除所有的绑定设备数据
+     *
+     * @param thingId
+     * @return
+     */
+    public ResultContent deleteByThingId(String thingId) {
+        if (StringUtils.isNotEmpty(thingId)) {
+            iotThing2DeviceDao.deleteByIotThingId(thingId);
+        }
+        return ResultContent.buildSuccess();
+    }
+
+    public ResultContent<Page<IotThing2DeviceModel>> page(Pageable pageable, IotThing2DeviceSearch param) {
+        Page<IotThing2Device> page = iotThing2DeviceDao.page(pageable, param);
+        return ResultContent.buildSuccess(PageEntityUtil.toPageModel(page, this::toModel));
+    }
+
+    public Long countByIotThingId(String iotThingId) {
+        if (StringUtils.isEmpty(iotThingId)) {
+            return 0L;
+        }
+        return iotThing2DeviceDao.countByIotThingId(iotThingId);
+    }
+
+    /**
+     * 得到物模型所有的设备
+     *
+     * @param iotThingId
+     * @return
+     */
+    public List<IotThing2Device> getListByIotThingId(String iotThingId) {
+        if (StringUtils.isEmpty(iotThingId)) {
+            return new ArrayList<>();
+        }
+        return iotThing2DeviceDao.findByIotThingId(iotThingId);
+    }
+
+    public IotThing2DeviceModel toModel(IotThing2Device entity) {
+        IotThing2DeviceModel model = null;
+        if (entity != null) {
+            model = new IotThing2DeviceModel();
+            BeanUtils.copyProperties(entity, model);
+            model.setDeviceInfo(deviceInfoService.toModel(entity.getDeviceInfo()));
+            model.setProjectInfo(projectInfoService.toModel(entity.getProjectInfo()));
+        }
+        return model;
+    }
+
+}

+ 194 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotThingService.java

@@ -0,0 +1,194 @@
+package com.zhongshu.iot.server.core.service.iot;
+
+import com.github.microservice.net.ResultContent;
+import com.github.microservice.types.deviceUse.DeviceType;
+import com.github.microservice.types.deviceUse.ThingType;
+import com.zhongshu.iot.client.model.iot.thing.IotThingParam;
+import com.zhongshu.iot.client.type.IotDataType;
+import com.zhongshu.iot.server.core.dao.iot.IotTemplateDao;
+import com.zhongshu.iot.server.core.dao.iot.IotThingDao;
+import com.zhongshu.iot.server.core.dao.mqtt.DeviceInfoDao;
+import com.zhongshu.iot.server.core.domain.iot.IotTemplate;
+import com.zhongshu.iot.server.core.domain.iot.IotThing;
+import com.zhongshu.iot.server.core.domain.iot.IotThing2Device;
+import com.zhongshu.iot.server.core.domain.iot.mqtt.DeviceInfo;
+import com.zhongshu.iot.server.core.domain.iot.mqtt.GateWayInfo;
+import com.zhongshu.iot.server.core.service.base.CommonService;
+import com.zhongshu.iot.server.core.service.base.SuperService;
+import com.zhongshu.iot.server.core.service.device.DeviceInfoService;
+import com.zhongshu.iot.server.core.util.CommonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 物模型 管理服务
+ *
+ * @author TRX
+ * @date 2025/2/25
+ */
+@Slf4j
+@Service
+public class IotThingService extends SuperService {
+
+    @Autowired
+    private IotThingDao iotThingDao;
+
+    @Autowired
+    private IotThing2DeviceService iotThing2DeviceService;
+
+    @Autowired
+    private DeviceInfoDao deviceInfoDao;
+
+    @Autowired
+    private DeviceInfoService deviceInfoService;
+
+    @Autowired
+    private IotTemplateDao iotTemplateDao;
+
+    @Autowired
+    private CommonService commonService;
+
+    @Autowired
+    private IotTemplateManagerService iotTemplateManagerService;
+
+    /**
+     * 添加/编辑设备时 初始物模型
+     *
+     * @param deviceInfo
+     * @return
+     */
+    public ResultContent initAutoThingByDevice(DeviceInfo deviceInfo) {
+        if (ObjectUtils.isNotEmpty(deviceInfo)) {
+            String productCode = deviceInfo.getProductCode();
+            if (StringUtils.isEmpty(productCode)) {
+                return ResultContent.buildFail("关联的产品code为空");
+            }
+            IotTemplate iotTemplate = iotTemplateDao.findTopByProductCodeAndIotDataType(productCode, IotDataType.IotTemplate);
+            if (ObjectUtils.isEmpty(iotTemplate)) {
+                return ResultContent.buildFail(String.format("产品code不存在", productCode));
+            }
+            IotThing iotThing = iotThingDao.findTopByDeviceIdAndThingType(deviceInfo.getDeviceId(), ThingType.Auto);
+            if (ObjectUtils.isEmpty(iotThing)) {
+                iotThing = new IotThing();
+                initEntity(iotThing);
+            } else {
+            }
+            iotThing.setName(deviceInfo.getDeviceName());
+            // 产品code
+            iotThing.setProductCode(productCode);
+            iotThing.setThingType(ThingType.Auto);
+            iotThing.setIotTemplateId(iotTemplate.getId());
+            // 分组code
+            iotThing.setProjectCode(iotTemplate.getProjectCode());
+
+            iotThing.setDeviceId(deviceInfo.getDeviceId());
+            iotThing.setDeviceCategory(iotTemplate.getDeviceCategory());
+            if (StringUtils.isEmpty(iotThing.getCode())) {
+                if (iotThing.getDeviceCategory() != null) {
+                    iotThing.setCode(String.format("%s%s", iotThing.getDeviceCategory().name(), CommonUtil.randomStr(10)));
+                } else {
+                    iotThing.setCode(String.format("%s%s", CommonUtil.randomStr(10)));
+                }
+            }
+            iotThingDao.save(iotThing);
+            iotThing2DeviceService.initAutoBindDevice(iotThing, deviceInfo);
+            updateThingDeviceCount(iotThing);
+            // 绑定物模型属性信息
+            iotTemplateManagerService.deviceBindAutoIotTemplate(iotThing, deviceInfo);
+        }
+        return ResultContent.buildSuccess();
+    }
+
+    public ResultContent initAutoThingByGateWay(GateWayInfo gateWayInfo) {
+        if (ObjectUtils.isNotEmpty(gateWayInfo)) {
+            String productCode = gateWayInfo.getProductCode();
+            if (StringUtils.isEmpty(productCode)) {
+                return ResultContent.buildFail("关联的产品code为空");
+            }
+            IotTemplate iotTemplate = iotTemplateDao.findTopByProductCodeAndIotDataType(productCode, IotDataType.IotTemplate);
+            if (ObjectUtils.isEmpty(iotTemplate)) {
+                return ResultContent.buildFail(String.format("产品code不存在", productCode));
+            }
+            IotThing iotThing = iotThingDao.findTopByDeviceIdAndThingType(gateWayInfo.getGateWayId(), ThingType.Auto);
+            if (ObjectUtils.isEmpty(iotThing)) {
+                iotThing = new IotThing();
+                initEntity(iotThing);
+            } else {
+            }
+            iotThing.setName(gateWayInfo.getGateWayName());
+            // 产品code
+            iotThing.setProductCode(productCode);
+            iotThing.setThingType(ThingType.Auto);
+            iotThing.setIotTemplateId(iotTemplate.getId());
+            // 分组code
+            iotThing.setProjectCode(iotTemplate.getProjectCode());
+
+            iotThing.setDeviceId(gateWayInfo.getGateWayId());
+            iotThing.setDeviceCategory(iotTemplate.getDeviceCategory());
+            if (StringUtils.isEmpty(iotThing.getCode())) {
+                if (iotThing.getDeviceCategory() != null) {
+                    iotThing.setCode(String.format("%s%s", iotThing.getDeviceCategory().name(), CommonUtil.randomStr(10)));
+                } else {
+                    iotThing.setCode(String.format("%s%s", CommonUtil.randomStr(10)));
+                }
+            }
+            iotThingDao.save(iotThing);
+            iotThing2DeviceService.initAutoBindGateWay(iotThing, gateWayInfo);
+            updateThingDeviceCount(iotThing);
+        }
+        return ResultContent.buildSuccess();
+    }
+
+    public ResultContent saveIotThing(IotThingParam param) {
+
+        return ResultContent.buildSuccess();
+    }
+
+    /**
+     * 更新设备数量
+     *
+     * @param thingId
+     */
+    public void updateThingDeviceCount(String thingId) {
+        if (StringUtils.isNotEmpty(thingId)) {
+            IotThing entity = iotThingDao.findTopById(thingId);
+            updateThingDeviceCount(entity);
+        }
+    }
+
+    /**
+     * 更新物模型绑定设备的数量等信息
+     *
+     * @param entity
+     */
+    public void updateThingDeviceCount(IotThing entity) {
+        if (entity != null) {
+            java.util.Map<String, Object> where = new HashMap<>();
+            where.put("id", entity.getId());
+
+            Map<String, Object> standardData = new HashMap<>();
+            standardData.put("deviceCount", iotThing2DeviceService.countByIotThingId(entity.getId()));
+
+            List<IotThing2Device> list = iotThing2DeviceService.getListByIotThingId(entity.getId());
+            List<String> deviceIds = new ArrayList<>();
+            List<DeviceType> deviceTypes = new ArrayList<>();
+            if (ObjectUtils.isNotEmpty(list)) {
+                deviceIds = list.stream().map(IotThing2Device::getDeviceId).collect(Collectors.toList());
+                deviceTypes = list.stream().map(IotThing2Device::getDeviceType).collect(Collectors.toList());
+            }
+            standardData.put("deviceIds", deviceIds);
+            standardData.put("deviceTypes", deviceTypes);
+            commonService.updateData(where, standardData, IotThing.class.getSimpleName());
+        }
+    }
+
+}