浏览代码

更新!

TRX 1 年之前
父节点
当前提交
63165d7e6a
共有 14 个文件被更改,包括 332 次插入60 次删除
  1. 1 1
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThing2DeviceBind.java
  2. 28 2
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThingModel.java
  3. 3 3
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThingParam.java
  4. 5 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThingSearch.java
  5. 7 7
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/controller/iot/IotController.java
  6. 99 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/controller/iot/IotThingController.java
  7. 2 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/IotMainDao.java
  8. 3 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/IotTemplateDao.java
  9. 3 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/IotThing2DeviceDao.java
  10. 0 3
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/GateWayInfoService.java
  11. 6 2
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotServiceImpl.java
  12. 22 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotTemplateManagerService.java
  13. 53 4
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotThing2DeviceService.java
  14. 100 38
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotThingService.java

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

@@ -14,7 +14,7 @@ import java.util.List;
 public class IotThing2DeviceBind {
 
     @Schema(description = "物模型id")
-    private String thingId;
+    private String id;
 
     @Schema(description = "设备id集合")
     private List<String> deviceIds = new ArrayList<>();

+ 28 - 2
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/thing/IotThingModel.java

@@ -1,7 +1,9 @@
 package com.zhongshu.iot.client.model.iot.thing;
 
+import com.github.microservice.types.deviceUse.DeviceCategory;
 import com.github.microservice.types.deviceUse.ThingType;
 import com.zhongshu.iot.client.model.baseParam.SuperModel;
+import com.zhongshu.iot.client.model.mqtt.ProjectInfoModel;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
@@ -15,6 +17,15 @@ public class IotThingModel extends SuperModel {
     @Schema(description = "物模型类型:自动、手动创建")
     private ThingType thingType;
 
+    public String thingTypeStr;
+
+    public String getThingTypeStr() {
+        if (thingType != null) {
+            return thingType.getRemark();
+        }
+        return "";
+    }
+
     @Schema(description = "编码")
     private String code;
 
@@ -27,8 +38,8 @@ public class IotThingModel extends SuperModel {
     @Schema(description = "所属分组")
     private String projectCode;
 
-    @Schema(description = "分组名称")
-    private String projectName;
+    @Schema(description = "分组信息")
+    private ProjectInfoModel projectInfo;
 
     //-----------------所属产品 start-----------
     @Schema(description = "所属产品数据id")
@@ -39,4 +50,19 @@ public class IotThingModel extends SuperModel {
 
     //-----------------管理的设备类型 start ---------
 
+    @Schema(description = "设备id")
+    private String deviceId;
+
+    @Schema(description = "设备品类")
+    private DeviceCategory deviceCategory;
+
+    private String deviceCategoryStr;
+
+    public String getDeviceCategoryStr() {
+        if (deviceCategory != null) {
+            return deviceCategory.getRemark();
+        }
+        return "";
+    }
+
 }

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

@@ -2,6 +2,7 @@ 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 jakarta.validation.constraints.NotEmpty;
 import lombok.Data;
 
 /**
@@ -11,12 +12,11 @@ import lombok.Data;
 @Data
 public class IotThingParam extends SuperParam {
 
-    @Schema(description = "编码")
-    private String code;
-
+    @NotEmpty
     @Schema(description = "名称")
     private String name;
 
+    @NotEmpty
     @Schema(description = "所属分组")
     private String projectCode;
 

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

@@ -5,6 +5,8 @@ import com.zhongshu.iot.client.model.baseParam.SuperSearchParam;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.util.List;
+
 /**
  * @author TRX
  * @date 2025/2/25
@@ -33,4 +35,7 @@ public class IotThingSearch extends SuperSearchParam {
 
     //-----------------管理的设备类型 start ---------
 
+    @Schema(description = "修改时间")
+    private List<Long> updateTimes;
+
 }

+ 7 - 7
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/controller/iot/IotController.java

@@ -28,7 +28,7 @@ import java.util.List;
 @RequestMapping("/iot")
 @RestController
 @Validated
-@Tag(name = "物模型-物模型管理")
+@Tag(name = "产品-产品管理")
 public class IotController {
 
     @Autowired
@@ -69,7 +69,7 @@ public class IotController {
     }
 
     @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "得到设备的物模型列表")
+    @Operation(summary = "得到设备的产品列表")
     @RequestMapping(value = "getDeviceTemplateList", method = {RequestMethod.GET})
     public ResultContent<List<IotTemplateModel>> getDeviceTemplateList(
             @RequestParam(name = "deviceId") @Parameter(name = "deviceId", description = "设备ID") String deviceId) {
@@ -85,7 +85,7 @@ public class IotController {
 
     //-------------------------- 模版 end--------------------------------
 
-    //-------------------------- 物模型 start------------------------------
+    //-------------------------- 产品 start------------------------------
 
     @ResourceAuth(value = "user", type = AuthType.User)
     @Operation(summary = "设备引用模版")
@@ -103,7 +103,7 @@ public class IotController {
     }
 
     @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "物模型属性-服务-方法列表-分页查询")
+    @Operation(summary = "产品属性-服务-方法列表-分页查询")
     @RequestMapping(value = {"pageIotMain"}, method = {RequestMethod.POST})
     public ResultContent<Page<IotMainModel>> pageIotMain(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable,
             @Parameter(required = false) IotMainSearch param) {
@@ -111,7 +111,7 @@ public class IotController {
     }
 
     @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "删除物模型")
+    @Operation(summary = "删除产品")
     @RequestMapping(value = "deleteIotMain", method = {RequestMethod.GET})
     public ResultContent deleteIotMain(
             @RequestParam(name = "id")
@@ -120,7 +120,7 @@ public class IotController {
     }
 
     @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "查询物模型")
+    @Operation(summary = "查询产品")
     @RequestMapping(value = "getIotMain", method = {RequestMethod.GET})
     public ResultContent<IotMainModel> getIotMain(
             @RequestParam(name = "id")
@@ -128,7 +128,7 @@ public class IotController {
         return iotService.getIotMain(id);
     }
 
-    //-------------------------- 物模型 end--------------------------------
+    //-------------------------- 产品 end--------------------------------
 
 
     //-------------------------- Topic start------------------------------

+ 99 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/controller/iot/IotThingController.java

@@ -0,0 +1,99 @@
+package com.zhongshu.iot.server.core.controller.iot;
+
+import com.github.microservice.auth.security.annotations.ResourceAuth;
+import com.github.microservice.auth.security.type.AuthType;
+import com.github.microservice.net.ResultContent;
+import com.zhongshu.iot.client.model.baseParam.IDParam;
+import com.zhongshu.iot.client.model.iot.thing.*;
+import com.zhongshu.iot.server.core.service.iot.IotThing2DeviceService;
+import com.zhongshu.iot.server.core.service.iot.IotThingService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.util.Assert;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 物模型管理
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+@RequestMapping("/iotThing")
+@RestController
+@Validated
+@Tag(name = "物模型-物模型管理")
+public class IotThingController {
+
+    @Autowired
+    private IotThingService iotThingService;
+
+    @Autowired
+    private IotThing2DeviceService iotThing2DeviceService;
+
+    //-------------------------- 物模型 start------------------------------
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "添加-编辑物模型")
+    @RequestMapping(value = "saveIotThing", method = {RequestMethod.POST})
+    public ResultContent saveIotThing(@RequestBody IotThingParam param) {
+        Assert.hasText(param.getName(), "name不能为空");
+        return iotThingService.saveIotThing(param);
+    }
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "物模型列表-分页查询")
+    @RequestMapping(value = {"page"}, method = {RequestMethod.POST})
+    public ResultContent<Page<IotThingModel>> page(
+            @Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable,
+            @Parameter(required = false) IotThingSearch param) {
+        return iotThingService.page(pageable, param);
+    }
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "删除物模型")
+    @RequestMapping(value = "deleteIotThing", method = {RequestMethod.POST})
+    public ResultContent deleteIotThing(@RequestBody IDParam param) {
+        return iotThingService.deleteIotThing(param.getId());
+    }
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "物模型详情")
+    @RequestMapping(value = "getDetail", method = {RequestMethod.POST})
+    public ResultContent getDetail(@RequestBody IDParam param) {
+        return iotThingService.getDetail(param.getId());
+    }
+
+    //--------------------------------物模型设备信息 start-----------------
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "物模型设备列表-分页查询")
+    @RequestMapping(value = {"pageDevice"}, method = {RequestMethod.POST})
+    public ResultContent<Page<IotThing2DeviceModel>> pageDevice(
+            @Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable,
+            @Parameter(required = false) IotThing2DeviceSearch param) {
+        return iotThing2DeviceService.page(pageable, param);
+    }
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "删除物模型下的设备")
+    @RequestMapping(value = {"deleteDevice"}, method = {RequestMethod.POST})
+    public ResultContent deleteDevice(@RequestBody IDParam param) {
+        return iotThing2DeviceService.delete(param.getId());
+    }
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "物模型绑定设备(手动创建的才行)")
+    @RequestMapping(value = {"bindDevices"}, method = {RequestMethod.POST})
+    public ResultContent bindDevices(@RequestBody IotThing2DeviceBind param) {
+        return iotThing2DeviceService.bindDevices(param);
+    }
+
+}

+ 2 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/iot/IotMainDao.java

@@ -36,4 +36,6 @@ public interface IotMainDao extends IotMainDaoExtend, org.springframework.data.m
 
     List<IotMain> findByDeviceIdAndIotDataType(String deviceId, IotDataType iotDataType);
 
+    void deleteByIotThingId(String iotThingId);
+
 }

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

@@ -27,4 +27,7 @@ public interface IotTemplateDao extends IotTemplateDaoExtend, org.springframewor
     IotTemplate findTopByIotThingIdAndIotDataType(String iotThingId, IotDataType iotDataType);
 
     IotTemplate findTopByIotThingIdAndIotDataTypeAndIotTemplateId(String iotThingId, IotDataType iotDataType, String iotTemplateId);
+
+    void deleteByIotThingId(String iotThingId);
+
 }

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

@@ -21,4 +21,7 @@ public interface IotThing2DeviceDao extends IotThing2DeviceDaoExtend, MongoRepos
     IotThing2Device findTopByIotThingId(String iotThingId);
 
     List<IotThing2Device> findByIotThingId(String iotThingId);
+
+    IotThing2Device findTopByIotThingIdAndDeviceId(String iotThingId, String deviceId);
+
 }

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

@@ -203,9 +203,6 @@ public class GateWayInfoService extends SuperService {
 
         gateWayInfoDao.save(gateWayInfo);
 
-        // 初始网关关联的物模型
-        iotThingService.initAutoThingByGateWay(gateWayInfo);
-
         log.info("网关注册成功");
         // 通知同步 (网关信息)
         deviceSyncFullCardService.noticeSyncGateWay(gateWayInfo);

+ 6 - 2
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotServiceImpl.java

@@ -2,6 +2,7 @@ package com.zhongshu.iot.server.core.service.iot;
 
 import com.github.microservice.net.ResultContent;
 import com.github.microservice.types.FunctionType;
+import com.github.microservice.types.deviceUse.DeviceCategory;
 import com.github.microservice.types.deviceUse.DeviceSpecType;
 import com.zhongshu.iot.client.model.baseParam.NameModel;
 import com.zhongshu.iot.client.model.iot.*;
@@ -97,9 +98,12 @@ public class IotServiceImpl extends SuperService {
         if (param.getDeviceCategory() == null) {
             return ResultContent.buildFail("deviceCategory is empty");
         }
-        if (param.getDeviceType() == null) {
-            return ResultContent.buildFail("deviceType is empty");
+        if (param.getDeviceCategory() == DeviceCategory.DE) {
+            if (param.getDeviceType() == null) {
+                return ResultContent.buildFail("deviceType is empty");
+            }
         }
+
         if (param.getSpecType() == null) {
             param.setSpecType(DeviceSpecType.Common);
         }

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

@@ -165,8 +165,30 @@ public class IotTemplateManagerService extends SuperService {
             List<String> ids = new ArrayList<>(map.keySet());
             iotMainDao.deleteAllById(ids);
         }
+        return ResultContent.buildSuccess();
+    }
+
+    /**
+     * 删除属性等所有分组信息
+     *
+     * @param iotThingId
+     * @return
+     */
+    public ResultContent deleteIotTemplateByThingId(String iotThingId) {
+        iotTemplateDao.deleteByIotThingId(iotThingId);
+        return ResultContent.buildSuccess();
+    }
 
+    /**
+     * 删除所有属性等信息
+     *
+     * @param iotThingId
+     * @return
+     */
+    public ResultContent deleteIotMainByThingId(String iotThingId) {
+        iotMainDao.deleteByIotThingId(iotThingId);
         return ResultContent.buildSuccess();
     }
 
+
 }

+ 53 - 4
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotThing2DeviceService.java

@@ -3,6 +3,7 @@ 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.IotThing2DeviceBind;
 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;
@@ -76,19 +77,28 @@ public class IotThing2DeviceService extends SuperService {
         return ResultContent.buildSuccess();
     }
 
-
-    public ResultContent initAutoBindDevice(IotThing iotThing, DeviceInfo deviceInfo) {
+    /**
+     * 绑定物模型和设备
+     *
+     * @param iotThing
+     * @param deviceInfo
+     * @return
+     */
+    public ResultContent bindDevice(IotThing iotThing, DeviceInfo deviceInfo) {
         if (ObjectUtils.isNotEmpty(iotThing) && ObjectUtils.isNotEmpty(deviceInfo)) {
-            IotThing2Device entity = iotThing2DeviceDao.findTopByIotThingId(iotThing.getId());
+            IotThing2Device entity = iotThing2DeviceDao.findTopByIotThingIdAndDeviceId(iotThing.getId(), deviceInfo.getDeviceId());
             if (ObjectUtils.isEmpty(entity)) {
                 entity = new IotThing2Device();
             }
+            // 物模型信息
             entity.setIotThing(iotThing);
             entity.setIotThingId(iotThing.getId());
+
+            // 设备关联信息
+            entity.setDeviceCategory(deviceInfo.getDeviceCategory());
             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());
@@ -98,6 +108,39 @@ public class IotThing2DeviceService extends SuperService {
         return ResultContent.buildSuccess();
     }
 
+    /**
+     * 物模型绑定设备(多个)
+     *
+     * @param param
+     * @return
+     */
+    public ResultContent bindDevices(IotThing2DeviceBind param) {
+        String id = param.getId();
+        if (ObjectUtils.isEmpty(param.getDeviceIds())) {
+            return ResultContent.buildFail("deviceIds不能为空");
+        }
+        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("不能绑定设备");
+            }
+        }
+        List<DeviceInfo> list = deviceInfoDao.findByDeviceIdIn(param.getDeviceIds());
+        if (ObjectUtils.isEmpty(list)) {
+            return ResultContent.buildFail("未查询到设备信息");
+        }
+        for (DeviceInfo deviceInfo : list) {
+            bindDevice(iotThing, deviceInfo);
+        }
+        // 更新物模型上的设备数量
+        iotThingService.updateThingDeviceCount(iotThing);
+        return ResultContent.buildSuccess();
+    }
+
     /**
      * 删除物模型绑定的设备
      *
@@ -138,6 +181,12 @@ public class IotThing2DeviceService extends SuperService {
         return ResultContent.buildSuccess(PageEntityUtil.toPageModel(page, this::toModel));
     }
 
+    /**
+     * 统计物模型上的设备总数
+     *
+     * @param iotThingId
+     * @return
+     */
     public Long countByIotThingId(String iotThingId) {
         if (StringUtils.isEmpty(iotThingId)) {
             return 0L;

+ 100 - 38
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotThingService.java

@@ -1,27 +1,37 @@
 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.DeviceType;
 import com.github.microservice.types.deviceUse.ThingType;
+import com.zhongshu.iot.client.model.iot.thing.IotThingModel;
 import com.zhongshu.iot.client.model.iot.thing.IotThingParam;
+import com.zhongshu.iot.client.model.iot.thing.IotThingSearch;
 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.dao.mqtt.ProjectInfoDao;
 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.domain.iot.mqtt.ProjectInfo;
 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.ProjectInfoService;
 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;
 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 org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -60,6 +70,12 @@ public class IotThingService extends SuperService {
     @Autowired
     private IotTemplateManagerService iotTemplateManagerService;
 
+    @Autowired
+    private ProjectInfoDao projectInfoDao;
+
+    @Autowired
+    private ProjectInfoService projectInfoService;
+
     /**
      * 添加/编辑设备时 初始物模型
      *
@@ -76,6 +92,7 @@ public class IotThingService extends SuperService {
             if (ObjectUtils.isEmpty(iotTemplate)) {
                 return ResultContent.buildFail(String.format("产品code不存在", productCode));
             }
+            String projectCode = deviceInfo.getProjectInfoCode();
             IotThing iotThing = iotThingDao.findTopByDeviceIdAndThingType(deviceInfo.getDeviceId(), ThingType.Auto);
             if (ObjectUtils.isEmpty(iotThing)) {
                 iotThing = new IotThing();
@@ -88,7 +105,7 @@ public class IotThingService extends SuperService {
             iotThing.setThingType(ThingType.Auto);
             iotThing.setIotTemplateId(iotTemplate.getId());
             // 分组code
-            iotThing.setProjectCode(iotTemplate.getProjectCode());
+            iotThing.setProjectCode(projectCode);
 
             iotThing.setDeviceId(deviceInfo.getDeviceId());
             iotThing.setDeviceCategory(iotTemplate.getDeviceCategory());
@@ -100,7 +117,9 @@ public class IotThingService extends SuperService {
                 }
             }
             iotThingDao.save(iotThing);
-            iotThing2DeviceService.initAutoBindDevice(iotThing, deviceInfo);
+            // 物模型 绑定设备
+            iotThing2DeviceService.bindDevice(iotThing, deviceInfo);
+            // 更新物模型 对应的设备数量
             updateThingDeviceCount(iotThing);
             // 绑定物模型属性信息
             iotTemplateManagerService.deviceBindAutoIotTemplate(iotThing, deviceInfo);
@@ -108,51 +127,84 @@ public class IotThingService extends SuperService {
         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));
+    /**
+     * 保存物模型
+     *
+     * @param param
+     * @return
+     */
+    public ResultContent saveIotThing(IotThingParam param) {
+        IotThing entity = null;
+        if (StringUtils.isEmpty(param.getId())) {
+            entity = iotThingDao.findTopById(param.getId());
+            if (ObjectUtils.isEmpty(entity)) {
+                return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
             }
-            IotThing iotThing = iotThingDao.findTopByDeviceIdAndThingType(gateWayInfo.getGateWayId(), ThingType.Auto);
-            if (ObjectUtils.isEmpty(iotThing)) {
-                iotThing = new IotThing();
-                initEntity(iotThing);
-            } else {
+            if (entity.getThingType() == ThingType.Auto) {
+                return ResultContent.buildFail("该数据不能修改");
             }
-            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);
+        } else {
+            entity = new IotThing();
+            entity.setThingType(ThingType.Manual);
+            entity.setCode(String.format("ML%s", CommonUtil.randomStr(10)));
         }
+        BeanUtils.copyProperties(param, entity);
+        ProjectInfo projectInfo = projectInfoDao.findTopByCode(param.getProjectCode());
+        if (ObjectUtils.isEmpty(projectInfo)) {
+            return ResultContent.buildFail(String.format("分组不存在"));
+        }
+        entity.setProjectCode(projectInfo.getCode());
+        iotThingDao.save(entity);
         return ResultContent.buildSuccess();
     }
 
-    public ResultContent saveIotThing(IotThingParam param) {
+    /**
+     * 物模型分页查询
+     *
+     * @param pageable
+     * @param param
+     * @return
+     */
+    public ResultContent<Page<IotThingModel>> page(Pageable pageable, IotThingSearch param) {
+        Page<IotThing> page = iotThingDao.page(pageable, param);
+        return ResultContent.buildSuccess(PageEntityUtil.toPageModel(page, this::toModel));
+    }
+
+    /**
+     * 删除物模型
+     *
+     * @param id
+     * @return
+     */
+    @Transactional
+    public ResultContent deleteIotThing(String id) {
+        IotThing entity = iotThingDao.findTopById(id);
+        if (ObjectUtils.isEmpty(entity)) {
+            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
+        }
+        if (entity.getThingType() == ThingType.Auto) {
+            return ResultContent.buildFail("改物模型不能删除");
+        }
+        // 删除物模型和设备的绑定
+        iotThing2DeviceService.deleteByThingId(entity.getId());
+        // 删除物模型的 属性分组
+        iotTemplateManagerService.deleteIotTemplateByThingId(entity.getId());
+        // 删除物模型的属性、方法、服务等信息
+        iotTemplateManagerService.deleteIotMainByThingId(entity.getId());
+        // 删除自己
+        iotThingDao.delete(entity);
 
         return ResultContent.buildSuccess();
     }
 
+    public ResultContent<IotThingModel> getDetail(String id) {
+        IotThing entity = iotThingDao.findTopById(id);
+        if (ObjectUtils.isEmpty(entity)) {
+            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
+        }
+        return ResultContent.buildSuccess(toModel(entity));
+    }
+
     /**
      * 更新设备数量
      *
@@ -191,4 +243,14 @@ public class IotThingService extends SuperService {
         }
     }
 
+    public IotThingModel toModel(IotThing entity) {
+        IotThingModel model = null;
+        if (ObjectUtils.isNotEmpty(entity)) {
+            model = new IotThingModel();
+            BeanUtils.copyProperties(entity, model);
+            model.setProjectInfo(projectInfoService.toModel(projectInfoDao.findTopByCode(entity.getProjectCode())));
+        }
+        return model;
+    }
+
 }