TRX 1 anno fa
parent
commit
37b0121aed

+ 55 - 27
src/main/java/com/zswl/dataservice/controller/iot/IotController.java

@@ -1,5 +1,6 @@
 package com.zswl.dataservice.controller.iot;
 
+import com.zswl.dataservice.model.baseParam.NameModel;
 import com.zswl.dataservice.model.iot.*;
 import com.zswl.dataservice.model.mqtt.DeviceInfoAddParam;
 import com.zswl.dataservice.model.mqtt.DeviceInfoModel;
@@ -22,6 +23,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 /**
  * 设备管理 服务
  *
@@ -68,44 +71,36 @@ public class IotController {
         return iotService.getIotTemplate(id);
     }
 
-    //-------------------------- 模版 end--------------------------------
-
-    //-------------------------- Topic start------------------------------
     @Parameter(in = ParameterIn.HEADER, name = "accessToken", required = false, description = "accessToken")
-    @Operation(summary = "添加-编辑Topic")
-    @RequestMapping(value = "addIotTopic", method = {RequestMethod.POST})
-    public ResultContent addIotTopic(@RequestBody IotTopicParam param) {
-        Assert.hasText(param.getTopic(), "topic不能为空");
-        return iotService.addIotTopic(param);
+    @Operation(summary = "得到设备的物模型列表")
+    @RequestMapping(value = "getDeviceTemplateList", method = {RequestMethod.GET})
+    public ResultContent<List<IotTemplateModel>> getDeviceTemplateList(
+            @Parameter(name = "deviceId", description = "设备ID") String deviceId
+    ) {
+        return iotService.getDeviceTemplateList(deviceId);
     }
 
     @Parameter(in = ParameterIn.HEADER, name = "accessToken", required = false, description = "accessToken")
-    @Operation(summary = "Topic列表-分页查询")
-    @RequestMapping(value = {"pageIotTopic"}, method = {RequestMethod.POST})
-    public ResultContent<Page<IotTopicModel>> pageIotTopic(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable,
-            @Parameter(required = false) IotTopicSearch param) {
-        return iotService.pageIotTopic(pageable, param);
+    @Operation(summary = "修改模型名称")
+    @RequestMapping(value = "updateIotTemplateName", method = {RequestMethod.POST})
+    public ResultContent<List<IotTemplateModel>> updateIotTemplateName(@RequestBody NameModel param
+    ) {
+        return iotService.updateIotTemplateName(param);
     }
 
-    @Parameter(in = ParameterIn.HEADER, name = "accessToken", required = false, description = "accessToken")
-    @Operation(summary = "删除Topic")
-    @RequestMapping(value = "deleteIotTopic", method = {RequestMethod.GET})
-    public ResultContent deleteIotTopic(@Parameter(name = "id", description = "数据id") String id) {
-        return iotService.deleteIotTopic(id);
-    }
+    //-------------------------- 模版 end--------------------------------
+
+    //-------------------------- 物模型 start------------------------------
 
     @Parameter(in = ParameterIn.HEADER, name = "accessToken", required = false, description = "accessToken")
-    @Operation(summary = "查询Topic")
-    @RequestMapping(value = "getIotTopic", method = {RequestMethod.GET})
-    public ResultContent<IotTopicModel> getIotTopic(@Parameter(name = "id", description = "数据id") String id) {
-        return iotService.getIotTopic(id);
+    @Operation(summary = "设备引用模版")
+    @RequestMapping(value = "deviceBindIotTemplate", method = {RequestMethod.POST})
+    public ResultContent deviceBindIotTemplate(@RequestBody DeviceBindIotTemplate param) {
+        return iotService.deviceBindIotTemplate(param);
     }
 
-    //-------------------------- Topic end--------------------------------
-
-    //-------------------------- 物模型 start------------------------------
     @Parameter(in = ParameterIn.HEADER, name = "accessToken", required = false, description = "accessToken")
-    @Operation(summary = "添加-编辑物模型")
+    @Operation(summary = "添加-编辑物属性等")
     @RequestMapping(value = "addIotMain", method = {RequestMethod.POST})
     public ResultContent addIotMain(@RequestBody IotMainParam param) {
         Assert.hasText(param.getName(), "name不能为空");
@@ -137,4 +132,37 @@ public class IotController {
     //-------------------------- 物模型 end--------------------------------
 
 
+    //-------------------------- Topic start------------------------------
+    @Parameter(in = ParameterIn.HEADER, name = "accessToken", required = false, description = "accessToken")
+    @Operation(summary = "添加-编辑Topic", hidden = true)
+    @RequestMapping(value = "addIotTopic", method = {RequestMethod.POST})
+    public ResultContent addIotTopic(@RequestBody IotTopicParam param) {
+        Assert.hasText(param.getTopic(), "topic不能为空");
+        return iotService.addIotTopic(param);
+    }
+
+    @Parameter(in = ParameterIn.HEADER, name = "accessToken", required = false, description = "accessToken")
+    @Operation(summary = "Topic列表-分页查询", hidden = true)
+    @RequestMapping(value = {"pageIotTopic"}, method = {RequestMethod.POST})
+    public ResultContent<Page<IotTopicModel>> pageIotTopic(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable,
+            @Parameter(required = false) IotTopicSearch param) {
+        return iotService.pageIotTopic(pageable, param);
+    }
+
+    @Parameter(in = ParameterIn.HEADER, name = "accessToken", required = false, description = "accessToken")
+    @Operation(summary = "删除Topic", hidden = true)
+    @RequestMapping(value = "deleteIotTopic", method = {RequestMethod.GET})
+    public ResultContent deleteIotTopic(@Parameter(name = "id", description = "数据id") String id) {
+        return iotService.deleteIotTopic(id);
+    }
+
+    @Parameter(in = ParameterIn.HEADER, name = "accessToken", required = false, description = "accessToken")
+    @Operation(summary = "查询Topic", hidden = true)
+    @RequestMapping(value = "getIotTopic", method = {RequestMethod.GET})
+    public ResultContent<IotTopicModel> getIotTopic(@Parameter(name = "id", description = "数据id") String id) {
+        return iotService.getIotTopic(id);
+    }
+
+    //-------------------------- Topic end--------------------------------
+
 }

+ 5 - 0
src/main/java/com/zswl/dataservice/dao/iot/IotMainDao.java

@@ -5,6 +5,7 @@ import com.zswl.dataservice.dao.iot.extend.IotMainDaoExtend;
 import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
 import com.zswl.dataservice.domain.iot.IotMain;
 import com.zswl.dataservice.domain.iot.IotTemplate;
+import com.zswl.dataservice.domain.iot.IotTopic;
 import com.zswl.dataservice.type.FunctionType;
 
 import java.util.List;
@@ -17,6 +18,10 @@ public interface IotMainDao extends MongoDao<IotMain>, IotMainDaoExtend {
 
     IotMain findTopById(String id);
 
+    IotMain findTopByNameAndIotTemplate(String name, IotTemplate iotTemplate);
+
+    IotMain findTopByIotTopicAndIotTemplate(String iotTopic, IotTemplate iotTemplate);
+
     List<IotMain> findByIotTemplateOrderByCreateTimeAsc(IotTemplate iotTemplate);
 
     List<IotMain> findByIotTemplateAndFunctionTypeOrderByCreateTimeAsc(IotTemplate iotTemplate, FunctionType functionType);

+ 10 - 1
src/main/java/com/zswl/dataservice/dao/iot/IotTemplateDao.java

@@ -5,6 +5,9 @@ import com.zswl.dataservice.dao.iot.extend.IotTemplateDaoExtend;
 import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
 import com.zswl.dataservice.domain.iot.IotTemplate;
 import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.type.IotDataType;
+
+import java.util.List;
 
 /**
  * @author TRX
@@ -14,5 +17,11 @@ public interface IotTemplateDao extends MongoDao<IotTemplate>, IotTemplateDaoExt
 
     IotTemplate findTopById(String id);
 
-    IotTemplate findTopByName(String name);
+    IotTemplate findTopByNameAndIotDataType(String name, IotDataType iotDataType);
+
+    IotTemplate findTopByNameAndDeviceIdAndIotDataType(String name, String deviceId, IotDataType iotDataType);
+
+    List<IotTemplate> findByDeviceIdAndIotDataTypeOrderByCreateTimeAsc(String deviceId, IotDataType iotDataType);
+
+    IotTemplate findTopByDeviceIdAndIotTemplateIdAndIotDataType(String deviceId, String iotTemplateId, IotDataType iotDataType);
 }

+ 26 - 4
src/main/java/com/zswl/dataservice/dao/iot/impl/IotMainDaoImpl.java

@@ -40,24 +40,46 @@ public class IotMainDaoImpl extends BaseImpl implements IotMainDaoExtend {
     public Page<IotMain> page(Pageable pageable, IotMainSearch param) {
         Criteria criteria = new Criteria();
 
-        if (StringUtils.isNotEmpty(param.getEpId())) {
-            criteria.and("epId").is(param.getEpId());
-        }
-
         if (StringUtils.isNotEmpty(param.getIotTemplateId())) {
             criteria.and("iotTemplate").is(IotTemplate.build(param.getIotTemplateId()));
         }
 
+        if (param.getFunctionType() != null) {
+            criteria.and("functionType").is(param.getFunctionType());
+        }
+
+        if (param.getDataType() != null) {
+            criteria.and("dataType").is(param.getDataType());
+        }
+
         // 模糊搜索
         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.getIdentifier())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getIdentifier() + ".*$");
+            criterias.add(Criteria.where("identifier").is(pattern));
+        }
+        if (StringUtils.isNotEmpty(param.getIotTopic())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getIotTopic() + ".*$");
+            criterias.add(Criteria.where("iotTopic").is(pattern));
+        }
         if (!CollectionUtils.isEmpty(criterias)) {
             criteria.andOperator(criterias.toArray(new Criteria[]{}));
         }
 
+        // 关键字搜索
+        if (StringUtils.isNotEmpty(param.getKeyWord())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getKeyWord() + ".*$");
+            criteria.orOperator(
+                    Criteria.where("name").regex(pattern),
+                    Criteria.where("identifier").regex(pattern),
+                    Criteria.where("iotTopic").regex(pattern)
+            );
+        }
+
         criteria.and("isDelete").is(Boolean.FALSE);
         Sort sort = buildSort(param);
         Query query = Query.query(criteria);

+ 5 - 0
src/main/java/com/zswl/dataservice/dao/iot/impl/IotTemplateDaoImpl.java

@@ -43,6 +43,11 @@ public class IotTemplateDaoImpl extends BaseImpl implements IotTemplateDaoExtend
             criteria.and("epId").is(param.getEpId());
         }
 
+        // 类型:模型 还是物模型
+        if (param.getIotDataType() != null) {
+            criteria.and("iotDataType").is(param.getIotDataType());
+        }
+
         // 模糊搜索
         List<Criteria> criterias = new ArrayList<>();
         if (StringUtils.isNotEmpty(param.getName())) {

+ 2 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/DeviceInfoDao.java

@@ -16,5 +16,7 @@ public interface DeviceInfoDao extends MongoDao<DeviceInfo>, DeviceInfoDaoExtend
 
     DeviceInfo findTopByDeviceId(String deviceId);
 
+    DeviceInfo findTopByDeviceIdAndProjectInfoCode(String deviceId, String projectInfoCode);
+
     List<DeviceInfo> findByDeviceIdIn(List<String> deviceIds);
 }

+ 1 - 1
src/main/java/com/zswl/dataservice/domain/iot/IotTemplate.java

@@ -34,7 +34,7 @@ public class IotTemplate extends SuperEntity {
     @Schema(description = "关联的设备")
     private String deviceId;
 
-    @Schema(description = "所属分code")
+    @Schema(description = "所属分code")
     private String projectCode;
 
     @Schema(description = "物模型所属模版ID,就是管理设备时绑定的那个模版")

+ 16 - 0
src/main/java/com/zswl/dataservice/model/baseParam/NameModel.java

@@ -0,0 +1,16 @@
+package com.zswl.dataservice.model.baseParam;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author TRX
+ * @date 2024/7/12
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class NameModel extends IDParam {
+    private String name;
+}

+ 26 - 0
src/main/java/com/zswl/dataservice/model/iot/DeviceBindIotTemplate.java

@@ -0,0 +1,26 @@
+package com.zswl.dataservice.model.iot;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author TRX
+ * @date 2024/7/12
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DeviceBindIotTemplate {
+
+    @Schema(description = "设备ID")
+    private String deviceId;
+
+    @Schema(description = "分组ID")
+    private String projectInfoCode;
+
+    @Schema(description = "模版ID")
+    private String templateId;
+
+}

+ 3 - 3
src/main/java/com/zswl/dataservice/model/iot/IotMainSearch.java

@@ -30,12 +30,12 @@ public class IotMainSearch extends SuperSearchParam {
     @Schema(description = "数据类型")
     private DataType dataType;
 
-    @Schema(description = "数据定义")
-    private LinkedHashMap<String, Object> data;
-
     @Schema(description = "物模型Topic")
     private String iotTopic;
 
     @Schema(description = "模版ID")
     private String iotTemplateId;
+
+    @Schema(description = "搜索关键字")
+    private String keyWord;
 }

+ 14 - 0
src/main/java/com/zswl/dataservice/model/iot/IotTemplateModel.java

@@ -2,6 +2,7 @@ package com.zswl.dataservice.model.iot;
 
 import com.zswl.dataservice.model.baseParam.SuperModel;
 import com.zswl.dataservice.type.DataState;
+import com.zswl.dataservice.type.IotDataType;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -20,4 +21,17 @@ public class IotTemplateModel  extends SuperModel {
 
     @Schema(description = "数据状态")
     private DataState state = DataState.Enable;
+
+    @Schema(description = "区分是模版还是设备关联的物模型")
+    private IotDataType iotDataType;
+
+    @Schema(description = "关联的设备")
+    private String deviceId;
+
+    @Schema(description = "所属分组code")
+    private String projectCode;
+
+    @Schema(description = "物模型所属模版ID,就是管理设备时绑定的那个模版")
+    private String iotTemplateId;
+
 }

+ 4 - 0
src/main/java/com/zswl/dataservice/model/iot/IotTemplateSearch.java

@@ -2,6 +2,7 @@ package com.zswl.dataservice.model.iot;
 
 import com.zswl.dataservice.model.baseParam.SuperSearchParam;
 import com.zswl.dataservice.type.DataState;
+import com.zswl.dataservice.type.IotDataType;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -20,4 +21,7 @@ public class IotTemplateSearch extends SuperSearchParam {
 
     @Schema(description = "数据状态")
     private DataState state = DataState.Enable;
+
+    @Schema(description = "区分是模版还是设备关联的物模型", hidden = true)
+    private IotDataType iotDataType;
 }

+ 177 - 9
src/main/java/com/zswl/dataservice/service/iot/IotServiceImpl.java

@@ -1,14 +1,17 @@
 package com.zswl.dataservice.service.iot;
 
+import ch.qos.logback.core.model.NamedModel;
 import com.zswl.dataservice.dao.UserDao;
 import com.zswl.dataservice.dao.iot.IotMainDao;
 import com.zswl.dataservice.dao.iot.IotTemplateDao;
 import com.zswl.dataservice.dao.iot.IotTopicDao;
+import com.zswl.dataservice.dao.mqtt.DeviceInfoDao;
 import com.zswl.dataservice.dataConfig.ResultMessage;
 import com.zswl.dataservice.domain.iot.IotMain;
 import com.zswl.dataservice.domain.iot.IotTemplate;
 import com.zswl.dataservice.domain.iot.IotTopic;
 import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.model.baseParam.NameModel;
 import com.zswl.dataservice.model.iot.*;
 import com.zswl.dataservice.model.mqtt.DeviceInfoModel;
 import com.zswl.dataservice.model.mqtt.DeviceInfoSearchParam;
@@ -27,9 +30,12 @@ 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 org.springframework.util.Assert;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 /**
@@ -52,31 +58,48 @@ public class IotServiceImpl extends SuperService {
     @Autowired
     UserDao userDao;
 
+    @Autowired
+    DeviceInfoDao deviceInfoDao;
+
     //----------------------------- 模版 start----------------------------
+
+    /**
+     * 添加模版
+     *
+     * @param param
+     * @return
+     */
     public ResultContent addIotTemplate(IotTemplateParam param) {
         IotTemplate template = null;
         initDefaultUser(param);
+
+        IotTemplate temp = iotTemplateDao.findTopByNameAndIotDataType(param.getName(), IotDataType.IotTemplate);
         if (StringUtils.isNotEmpty(param.getId())) {
             template = iotTemplateDao.findTopById(param.getId());
             if (ObjectUtils.isEmpty(template)) {
                 return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
             }
-            IotTemplate temp = iotTemplateDao.findTopByName(param.getName());
             if (ObjectUtils.isNotEmpty(temp) && !temp.getId().equals(param.getId())) {
                 return ResultContent.buildFail(String.format(ResultMessage.NAME_EXIT, param.getName()));
             }
         } else {
             template = new IotTemplate();
-            IotTemplate temp = iotTemplateDao.findTopByName(param.getName());
             if (ObjectUtils.isNotEmpty(temp)) {
                 return ResultContent.buildFail(String.format(ResultMessage.NAME_EXIT, param.getName()));
             }
+            template.setIotDataType(IotDataType.IotTemplate);
         }
         BeanUtils.copyProperties(param, template);
         iotTemplateDao.save(template);
         return ResultContent.buildSuccess();
     }
 
+    /**
+     * 删除模版
+     *
+     * @param id
+     * @return
+     */
     public ResultContent deleteTemplate(String id) {
         IotTemplate template = iotTemplateDao.findTopById(id);
         if (ObjectUtils.isEmpty(template)) {
@@ -86,6 +109,12 @@ public class IotServiceImpl extends SuperService {
         return ResultContent.buildSuccess();
     }
 
+    /**
+     * 查询模版详情
+     *
+     * @param id
+     * @return
+     */
     public ResultContent<IotTemplateModel> getIotTemplate(String id) {
         IotTemplate template = iotTemplateDao.findTopById(id);
         if (ObjectUtils.isEmpty(template)) {
@@ -94,13 +123,73 @@ public class IotServiceImpl extends SuperService {
         return ResultContent.buildSuccess(toModel(template));
     }
 
+    /**
+     * 模版分页
+     *
+     * @param pageable
+     * @param param
+     * @return
+     */
     public ResultContent<Page<IotTemplateModel>> pageTemplate(Pageable pageable, IotTemplateSearch param) {
         initSearchParam(param);
+        param.setIotDataType(IotDataType.IotTemplate);
         Page<IotTemplate> page = iotTemplateDao.page(pageable, param);
         return ResultContent.buildSuccess(PageEntityUtil.toPageModel(page, this::toModel));
     }
+
+    /**
+     * 查询设备的物模型列表
+     *
+     * @param deviceId
+     * @return
+     */
+    public ResultContent<List<IotTemplateModel>> getDeviceTemplateList(String deviceId) {
+        List<IotTemplate> list = iotTemplateDao.findByDeviceIdAndIotDataTypeOrderByCreateTimeAsc(deviceId, IotDataType.Device);
+        List<IotTemplateModel> models = new ArrayList<>();
+        if (ObjectUtils.isNotEmpty(list)) {
+            models = list.stream().map(this::toModel).collect(Collectors.toList());
+        }
+        return ResultContent.buildSuccess(models);
+    }
+
+    /**
+     * 修改名称
+     *
+     * @param param
+     * @return
+     */
+    public ResultContent updateIotTemplateName(NameModel param) {
+        Assert.hasText(param.getName(), "name不能为空");
+        IotTemplate template = iotTemplateDao.findTopById(param.getId());
+        if (ObjectUtils.isEmpty(template)) {
+            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
+        }
+
+        // 检查名称是否重复
+        if (template.getIotDataType() == IotDataType.IotTemplate) {
+            // 模版
+            IotTemplate temp = iotTemplateDao.findTopByNameAndIotDataType(param.getName(), IotDataType.IotTemplate);
+            if (ObjectUtils.isNotEmpty(temp) && !temp.getId().equals(template.getId())) {
+                return ResultContent.buildFail(String.format(ResultMessage.NAME_EXIT, param.getName()));
+            }
+        } else if (template.getIotDataType() == IotDataType.Device) {
+            // 物模型
+            IotTemplate temp = iotTemplateDao.findTopByNameAndDeviceIdAndIotDataType(
+                    param.getName(),
+                    template.getDeviceId(),
+                    IotDataType.Device);
+            if (ObjectUtils.isNotEmpty(temp) && !temp.getId().equals(template.getId())) {
+                return ResultContent.buildFail(String.format(ResultMessage.NAME_EXIT, param.getName()));
+            }
+        }
+        BeanUtils.copyProperties(param, template);
+        iotTemplateDao.save(template);
+        return ResultContent.buildSuccess();
+    }
+
     //----------------------------- 模版 end------------------------------
 
+
     //----------------------------- Topic start----------------------------
     public ResultContent addIotTopic(IotTopicParam param) {
         initDefaultUser(param);
@@ -166,6 +255,59 @@ public class IotServiceImpl extends SuperService {
 
     //----------------------------- 物模型 start----------------------------
 
+    /**
+     * 设备绑定模版
+     *
+     * @param param
+     * @return
+     */
+    @Transactional
+    public ResultContent deviceBindIotTemplate(DeviceBindIotTemplate param) {
+        DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceIdAndProjectInfoCode(param.getDeviceId(), param.getProjectInfoCode());
+        if (ObjectUtils.isEmpty(deviceInfo)) {
+            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getDeviceId()));
+        }
+        // 模版信息
+        IotTemplate iotTemplate = iotTemplateDao.findTopById(param.getTemplateId());
+        if (ObjectUtils.isEmpty(iotTemplate)) {
+            return ResultContent.buildFail(String.format("模版ID不存在", param.getTemplateId()));
+        }
+        // 判断该设备是否已绑定该模版
+        IotTemplate temp = iotTemplateDao.findTopByDeviceIdAndIotTemplateIdAndIotDataType(param.getDeviceId(),
+                iotTemplate.getId(),
+                IotDataType.Device);
+        if (ObjectUtils.isNotEmpty(temp)) {
+            return ResultContent.buildFail(String.format("设备【%s】已绑定模版%s", deviceInfo.getDeviceName(), iotTemplate.getName()));
+        }
+
+        IotTemplate newIotTemplate = new IotTemplate();
+        BeanUtils.copyProperties(param, newIotTemplate, "id", "createTime", "updateTime");
+        newIotTemplate.setIotDataType(IotDataType.Device);
+        newIotTemplate.setIotTemplateId(param.getTemplateId());
+        newIotTemplate.setDeviceId(deviceInfo.getDeviceId());
+        newIotTemplate.setProjectCode(deviceInfo.getProjectInfoCode());
+        iotTemplateDao.save(newIotTemplate);
+
+        // 属性等数据
+        List<IotMain> saveList = new ArrayList<>();
+        List<IotMain> list = iotMainDao.findByIotTemplateOrderByCreateTimeAsc(iotTemplate);
+        if (list != null) {
+            list.stream().forEach(it -> {
+                IotMain main = new IotMain();
+                BeanUtils.copyProperties(it, main, "id", "createTime", "updateTime");
+                main.setIotTemplate(newIotTemplate);
+                main.setIotDataType(IotDataType.Device);
+                main.setDeviceId(deviceInfo.getDeviceId());
+                main.setProjectCode(deviceInfo.getProjectInfoCode());
+                main.setAddTime(System.currentTimeMillis());
+                initRealTopic(main);
+                saveList.add(main);
+            });
+        }
+        iotMainDao.saveAll(saveList);
+        return ResultContent.buildSuccess();
+    }
+
     /**
      * 添加属性  事件
      *
@@ -174,6 +316,12 @@ public class IotServiceImpl extends SuperService {
      */
     public ResultContent addIotMain(IotMainParam param) {
         initDefaultUser(param);
+        if (param.getFunctionType() == null) {
+            return ResultContent.buildFail("functionType 不能为空");
+        }
+        Assert.hasText(param.getName(), "name不能为空");
+        Assert.hasText(param.getIdentifier(), "identifier不能为空");
+        Assert.hasText(param.getIotTopic(), "iotTopic不能为空");
 
         String iotTemplateId = param.getIotTemplateId();
         IotTemplate iotTemplate = iotTemplateDao.findTopById(iotTemplateId);
@@ -183,7 +331,8 @@ public class IotServiceImpl extends SuperService {
 
         IotMain entity = null;
         // 判断名称是否重复
-        IotTopic nameTemp = iotTopicDao.findTopByTopicAndIotTemplate(param.getName(), iotTemplate);
+        IotMain nameTemp = iotMainDao.findTopByNameAndIotTemplate(param.getName(), iotTemplate);
+        IotMain topicTemp = iotMainDao.findTopByIotTopicAndIotTemplate(param.getIotTopic(), iotTemplate);
         if (StringUtils.isNotEmpty(param.getId())) {
             entity = iotMainDao.findTopById(param.getId());
             if (ObjectUtils.isEmpty(entity)) {
@@ -192,27 +341,43 @@ public class IotServiceImpl extends SuperService {
             if (ObjectUtils.isNotEmpty(nameTemp) && !nameTemp.getId().equals(param.getId())) {
                 return ResultContent.buildFail(String.format(ResultMessage.NAME_EXIT, param.getName()));
             }
+            if (ObjectUtils.isNotEmpty(topicTemp) && !topicTemp.getId().equals(param.getId())) {
+                return ResultContent.buildFail(String.format("iotTopic已存在:%s", param.getIotTopic()));
+            }
         } else {
             entity = new IotMain();
             if (ObjectUtils.isNotEmpty(nameTemp)) {
                 return ResultContent.buildFail(String.format(ResultMessage.NAME_EXIT, param.getName()));
             }
+            if (ObjectUtils.isNotEmpty(topicTemp)) {
+                return ResultContent.buildFail(String.format("iotTopic已存在:%s", param.getIotTopic()));
+            }
         }
 
         BeanUtils.copyProperties(param, entity);
+        // 设备所属模型
         entity.setIotTemplate(iotTemplate);
+        entity.setIotDataType(iotTemplate.getIotDataType());
         if (iotTemplate.getIotDataType() == IotDataType.Device) {
+            entity.setDeviceId(iotTemplate.getDeviceId());
+            entity.setProjectCode(iotTemplate.getProjectCode());
+            initRealTopic(entity);
+        }
+        iotMainDao.save(entity);
+        return ResultContent.buildSuccess();
+    }
+
+    private void initRealTopic(IotMain iotMain) {
+        if (iotMain != null && iotMain.getIotDataType() == IotDataType.Device) {
             // 把 topic有占位符的换为具体的值
-            String deviceId = iotTemplate.getDeviceId();
-            String iotTopic = entity.getIotTopic();
+            String deviceId = iotMain.getDeviceId();
+            String iotTopic = iotMain.getIotTopic();
             String realIotTopic = "";
             if (StringUtils.isNotEmpty(iotTopic)) {
-                realIotTopic = iotTopic.replaceAll("$\\{deviceId\\}", deviceId);
+                realIotTopic = iotTopic.replaceAll(Pattern.quote("${deviceId}"), deviceId);
             }
-            entity.setRealIotTopic(realIotTopic);
+            iotMain.setRealIotTopic(realIotTopic);
         }
-        iotMainDao.save(entity);
-        return ResultContent.buildSuccess();
     }
 
     public ResultContent deleteIotMain(String id) {
@@ -234,6 +399,9 @@ public class IotServiceImpl extends SuperService {
 
     public ResultContent<Page<IotMainModel>> pageIotMain(Pageable pageable, IotMainSearch param) {
         initSearchParam(param);
+        if (StringUtils.isEmpty(param.getIotTemplateId())) {
+            return ResultContent.buildFail("iotTemplateId不能为空");
+        }
         Page<IotMain> page = iotMainDao.page(pageable, param);
         return ResultContent.buildSuccess(PageEntityUtil.toPageModel(page, this::toModel));
     }

+ 16 - 0
src/main/java/com/zswl/dataservice/utils/test/TestReplace.java

@@ -0,0 +1,16 @@
+package com.zswl.dataservice.utils.test;
+
+import java.util.regex.Pattern;
+
+/**
+ * @author TRX
+ * @date 2024/7/12
+ */
+public class TestReplace {
+    public static void main(String[] args) {
+        String str = "/v1/gateway/${deviceId}/on";
+        String str1 = str.replaceAll(Pattern.quote("${deviceId}"), "aaa");
+
+        System.out.println(str1);
+    }
+}