Selaa lähdekoodia

refactor 设备服务

jay 2 vuotta sitten
vanhempi
commit
f152e95010
18 muutettua tiedostoa jossa 1275 lisäystä ja 297 poistoa
  1. 2 0
      iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/dao/DeviceInfoRepository.java
  2. 1 1
      iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/service/DeviceInfoDataImpl.java
  3. 114 296
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java
  4. 74 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/device/DeviceInfoBo.java
  5. 37 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/device/DeviceLogQueryBo.java
  6. 32 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/device/DevicePropertyLogQueryBo.java
  7. 64 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/device/DeviceQueryBo.java
  8. 40 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/device/DeviceTagAddBo.java
  9. 31 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/deviceconfig/DeviceConfigAddBo.java
  10. 53 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/deviceconfig/DeviceConfigBo.java
  11. 30 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/devicegroup/DeviceAddGroupBo.java
  12. 55 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/devicegroup/DeviceGroupBo.java
  13. 88 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/thingmodel/ThingModelMessageBo.java
  14. 53 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/vo/deviceconfig/DeviceConfigVo.java
  15. 53 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/vo/devicegroup/DeviceGroupVo.java
  16. 77 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/vo/deviceinfo/DeviceInfoVo.java
  17. 74 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/IDeviceService.java
  18. 397 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/DeviceServiceImpl.java

+ 2 - 0
iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/dao/DeviceInfoRepository.java

@@ -1,6 +1,8 @@
 package cc.iotkit.data.dao;
 
 import cc.iotkit.data.model.TbDeviceInfo;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.querydsl.QuerydslPredicateExecutor;
 

+ 1 - 1
iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/service/DeviceInfoDataImpl.java

@@ -153,7 +153,7 @@ public class DeviceInfoDataImpl implements IDeviceInfoData {
 
     @Override
     public List<DeviceInfo> findByParentId(String parentId) {
-        return parseVoToDto(deviceInfoRepository.findByParentId(parentId));
+        return parseVoToDto(deviceInfoRepository.findByParentId(parentId ));
     }
 
     @Override

+ 114 - 296
iot-module/iot-manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java

@@ -9,24 +9,24 @@
  */
 package cc.iotkit.manager.controller;
 
+import cc.iotkit.common.api.PageRequest;
+import cc.iotkit.common.api.Request;
 import cc.iotkit.common.constant.Constants;
 import cc.iotkit.common.enums.ErrCode;
 import cc.iotkit.common.exception.BizException;
 import cc.iotkit.common.satoken.utils.AuthUtil;
-import cc.iotkit.common.utils.DeviceUtil;
 import cc.iotkit.common.utils.ReflectUtil;
 import cc.iotkit.common.utils.UniqueIdUtil;
-import cc.iotkit.comps.service.DeviceBehaviourService;
-import cc.iotkit.data.manager.IDeviceConfigData;
-import cc.iotkit.data.manager.IDeviceGroupData;
-import cc.iotkit.data.manager.IDeviceInfoData;
-import cc.iotkit.data.manager.IProductData;
+import cc.iotkit.manager.dto.bo.device.*;
+import cc.iotkit.manager.dto.bo.deviceconfig.DeviceConfigAddBo;
+import cc.iotkit.manager.dto.bo.devicegroup.DeviceAddGroupBo;
+import cc.iotkit.manager.dto.bo.devicegroup.DeviceGroupBo;
+import cc.iotkit.manager.dto.bo.thingmodel.ThingModelMessageBo;
+import cc.iotkit.manager.dto.vo.deviceconfig.DeviceConfigVo;
+import cc.iotkit.manager.dto.vo.devicegroup.DeviceGroupVo;
+import cc.iotkit.manager.dto.vo.deviceinfo.DeviceInfoVo;
 import cc.iotkit.manager.dto.vo.thingmodel.ThingModelVo;
-import cc.iotkit.manager.model.query.DeviceQuery;
-import cc.iotkit.manager.service.DataOwnerService;
-import cc.iotkit.manager.service.DeferredDataConsumer;
-import cc.iotkit.manager.service.DeviceService;
-import cc.iotkit.manager.service.IProductService;
+import cc.iotkit.manager.service.*;
 import cc.iotkit.model.InvokeResult;
 import cc.iotkit.common.api.Paging;
 import cc.iotkit.model.device.DeviceConfig;
@@ -34,19 +34,11 @@ import cc.iotkit.model.device.DeviceGroup;
 import cc.iotkit.model.device.DeviceInfo;
 import cc.iotkit.model.device.message.DeviceProperty;
 import cc.iotkit.model.device.message.ThingModelMessage;
-import cc.iotkit.model.product.Product;
-import cc.iotkit.model.product.ThingModel;
-import cc.iotkit.temporal.IDevicePropertyData;
-import cc.iotkit.temporal.IThingModelMessageData;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.*;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.context.annotation.Lazy;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.context.request.async.DeferredResult;
 
@@ -63,32 +55,12 @@ public class DeviceController {
 
     @Autowired
     IProductService productService;
+
     @Autowired
     private DeviceService deviceService;
     @Autowired
-    @Qualifier("deviceInfoDataCache")
-    private IDeviceInfoData deviceInfoData;
-    @Autowired
-    @Qualifier("productDataCache")
-    private IProductData productData;
-    @Autowired
-    private DataOwnerService dataOwnerService;
-    @Autowired
-    private ProductController productController;
-    @Lazy
-    @Autowired
-    private IThingModelMessageData thingModelMessageData;
-    @Lazy
-    @Autowired
-    private IDevicePropertyData devicePropertyData;
-    @Autowired
-    private DeviceBehaviourService behaviourService;
-    @Autowired
-    DeferredDataConsumer deferredDataConsumer;
-    @Autowired
-    private IDeviceGroupData deviceGroupData;
-    @Autowired
-    private IDeviceConfigData deviceConfigData;
+    private IDeviceService deviceServiceImpl;
+
 
     @ApiOperation(value = "服务调用", notes = "服务调用", httpMethod = "POST")
     @ApiImplicitParams({
@@ -132,349 +104,195 @@ public class DeviceController {
     }
 
     @ApiOperation(value = "设备列表", notes = "设备列表", httpMethod = "POST")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "size", value = "长度", dataTypeClass = Integer.class, paramType = "path"),
-            @ApiImplicitParam(name = "page", value = "页数", dataTypeClass = Integer.class, paramType = "path")
-    })
-    @PostMapping("/list/{size}/{page}")
-    public Paging<DeviceInfo> getDevices(
-            @PathVariable("size") int size,
-            @PathVariable("page") int page,
-            @RequestBody DeviceQuery query) {
-        String uid = "";
-        String subUid = "";
-        if (!AuthUtil.isAdmin()) {
-            //客户端用户使用绑定子用户查询
-            if (AuthUtil.isClientUser()) {
-                subUid = AuthUtil.getUserId();
-            } else {
-                uid = AuthUtil.getUserId();
-            }
-        }
-
-        String pk = query.getProductKey();
-        //关键字查询
-        String keyword = query.getKeyword();
-        String group = query.getGroup();
-        String state = query.getState();
+    @PostMapping("/list")
+    public Paging<DeviceInfo> getDevices(@Validated @RequestBody PageRequest<DeviceQueryBo> pageRequest) {
 
-        return deviceInfoData.findByConditions(uid, subUid, pk, group,
-                state, keyword, page, size);
+        return deviceServiceImpl.getDevices(pageRequest);
     }
 
-    @ApiOperation(value = "创建设备", notes = "创建设备", httpMethod = "POST")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "productKey", value = "产品key", dataTypeClass = String.class, paramType = "form"),
-            @ApiImplicitParam(name = "deviceName", value = "设备名称", dataTypeClass = String.class, paramType = "form"),
-            @ApiImplicitParam(name = "parentId", value = "父设备ID", dataTypeClass = String.class, paramType = "form")
-    })
-    @PostMapping("/create")
-    public void createDevice(String productKey, String deviceName, String parentId) {
-        Product product = productData.findById(productKey);
-        if (product == null) {
-            throw new BizException(ErrCode.PRODUCT_NOT_FOUND);
-        }
-
-        //生成设备密钥
-        String chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
-        int maxPos = chars.length();
-        StringBuilder secret = new StringBuilder();
-        for (var i = 0; i < 16; i++) {
-            secret.append(chars.charAt((int) Math.floor(Math.random() * maxPos)));
-        }
-
-        DeviceInfo device = new DeviceInfo();
-        device.setId(DeviceUtil.newDeviceId(deviceName));
-        device.setUid(product.getUid());
-        device.setDeviceId(device.getId());
-        device.setProductKey(productKey);
-        device.setDeviceName(deviceName);
-        device.setSecret(secret.toString());
-        device.setState(new DeviceInfo.State(false, null, null));
-        device.setCreateAt(System.currentTimeMillis());
-        if (StringUtils.isNotBlank(parentId)) {
-            device.setParentId(parentId);
-        }
-        deviceInfoData.save(device);
+    @ApiOperation(value = "创建设备")
+    @PostMapping("/add")
+    public boolean createDevice(@RequestBody @Validated Request<DeviceInfoBo> bo) {
+        return deviceServiceImpl.addDevice(bo.getData());
     }
 
     @ApiOperation(value = "获取子设备", notes = "获取子设备", httpMethod = "GET")
     @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class, paramType = "form")
-    @GetMapping("/{deviceId}/children")
-    public List<DeviceInfo> getChildren(@PathVariable("deviceId") String deviceId) {
-        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
-        if (deviceInfo == null) {
-            throw new BizException(ErrCode.DEVICE_NOT_FOUND);
-        }
+    @PostMapping("/children/list")
+    public List<DeviceInfoVo> getChildren(@Validated @RequestBody PageRequest<String> request) {
+        String deviceId = request.getData();
 
-        dataOwnerService.checkOwner(deviceInfo);
-        return deviceInfoData.findByParentId(deviceId);
+        return deviceServiceImpl.selectChildrenPageList(deviceId);
     }
 
-    @GetMapping("/parentDevices")
+    @ApiOperation("获取网关")
+    @PostMapping("/parentDevices")
     public List<Map<String, Object>> getParentDevices() {
-        String uid = "";
-        if (!AuthUtil.isAdmin()) {
-            uid = AuthUtil.getUserId();
-        }
-        return deviceInfoData.findByProductNodeType(uid);
+        return deviceServiceImpl.getParentDevices();
     }
 
-    @GetMapping(Constants.API_DEVICE.DETAIL)
+    @ApiOperation("获取设备详情")
+    @PostMapping(Constants.API_DEVICE.DETAIL)
     public DeviceInfo getDetail(@PathVariable("deviceId") String deviceId) {
-        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
-        dataOwnerService.checkOwner(deviceInfo);
-        deviceInfo.setProperty(deviceInfoData.getProperties(deviceId));
-        return deviceInfo;
+        return deviceServiceImpl.getDetail(deviceId);
     }
 
-    @GetMapping("/{pk}/{dn}")
+    @ApiOperation("获取设备详情")
+    @PostMapping("/{pk}/{dn}")
     public DeviceInfo getByPkDn(@PathVariable("pk") String pk,
                                 @PathVariable("dn") String dn) {
-        return dataOwnerService.checkOwner(
-                deviceInfoData.findByProductKeyAndDeviceName(pk, dn));
+        return deviceServiceImpl.getByPkDn(pk, dn);
     }
 
-    @PostMapping("/{deviceId}/delete")
-    public void deleteDevice(@PathVariable("deviceId") String deviceId) {
-        deviceId = getDetail(deviceId).getDeviceId();
-        deviceInfoData.deleteById(deviceId);
+    @ApiOperation("删除设备")
+    @PostMapping("/delete")
+    public boolean deleteDevice(@Validated @RequestBody Request<String> request) {
+        return deviceServiceImpl.deleteDevice(request.getData());
     }
 
-    @PostMapping("/{deviceId}/logs/{size}/{page}")
-    public Paging<ThingModelMessage> logs(
-            @PathVariable("deviceId") String deviceId,
-            @PathVariable("size") int size,
-            @PathVariable("page") int page,
-            String type, String identifier) {
-        return thingModelMessageData.findByTypeAndIdentifier(deviceId, type, identifier, page, size);
+    @ApiOperation("设备物模型日志")
+    @PostMapping("/deviceLogs/list")
+    public Paging<ThingModelMessage> logs(@Validated @RequestBody PageRequest<DeviceLogQueryBo> request) {
+        return deviceServiceImpl.logs(request);
     }
 
-    @GetMapping("/{deviceId}/property/{name}/{start}/{end}")
-    public List<DeviceProperty> getPropertyHistory(
-            @PathVariable("deviceId") String deviceId,
-            @PathVariable("name") String name,
-            @PathVariable("start") long start,
-            @PathVariable("end") long end) {
-        return devicePropertyData.findDevicePropertyHistory(deviceId, name, start, end);
+    @ApiOperation("设备属性日志")
+    @PostMapping("/deviceProperty/log/list")
+    public List<DeviceProperty> getPropertyHistory(@Validated @RequestBody
+                                                   Request<DevicePropertyLogQueryBo> query) {
+        DevicePropertyLogQueryBo data = query.getData();
+        String deviceId = data.getDeviceId();
+        String name = data.getName();
+        long start = data.getStart();
+        long end = data.getEnd();
+        return deviceServiceImpl.getPropertyHistory(deviceId, name, start, end);
     }
 
-    @PostMapping("/{deviceId}/unbind")
-    public void unbindDevice(@PathVariable("deviceId") String deviceId) {
-        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
-        dataOwnerService.checkOwner(deviceInfo);
-        deviceService.unbindDevice(deviceId);
+    @ApiOperation("设备解绑")
+    @PostMapping("/unbind")
+    public boolean unbindDevice(@Validated @RequestBody Request<String> request) {
+        return deviceServiceImpl.unbindDevice(request.getData());
     }
 
-    @GetMapping("/{deviceId}/thingModel")
-    public ThingModelVo getThingModel(@PathVariable("deviceId") String deviceId) {
+    @ApiOperation("获取设备物模型")
+    @PostMapping("/getThingModel")
+    public ThingModelVo getThingModel(@Validated @RequestBody Request<String> request) {
+        String deviceId = request.getData();
         DeviceInfo deviceInfo = getDetail(deviceId);
         return productService.getThingModelByProductKey(deviceInfo.getProductKey());
     }
 
-    @PostMapping("/{deviceId}/tag/add")
-    public void addTag(@PathVariable("deviceId") String deviceId,
-                       DeviceInfo.Tag tag) {
-        DeviceInfo device = deviceInfoData.findByDeviceId(deviceId);
-        dataOwnerService.checkOwner(device);
-        deviceInfoData.updateTag(deviceId, tag);
+    @PostMapping("/tag/add")
+    public boolean addTag(@Validated @RequestBody Request<DeviceTagAddBo> bo) {
+        return deviceServiceImpl.addTag(bo.getData());
     }
 
-    @PostMapping("/{deviceId}/simulateSend")
-    public void simulateSend(
-            @PathVariable("deviceId") String deviceId,
-            @RequestBody ThingModelMessage message) {
-        DeviceInfo device = deviceInfoData.findByDeviceId(deviceId);
-        dataOwnerService.checkOwner(device);
-
-        message.setMid(UniqueIdUtil.newRequestId());
-        message.setOccurred(System.currentTimeMillis());
-        message.setTime(System.currentTimeMillis());
-        behaviourService.reportMessage(message);
+    @ApiOperation("模拟设备上报")
+    @PostMapping("/simulateSend")
+    public boolean simulateSend(
+            @Validated @RequestBody Request<ThingModelMessageBo> bo) {
+        ThingModelMessage message = bo.getData().to(ThingModelMessage.class);
+        return deviceServiceImpl.simulateSend(message);
     }
 
     /**
      * 消费设备信息消息(实时推送设备信息)
      */
-    @GetMapping("/{deviceId}/consumer/{clientId}")
+    @PostMapping("/{deviceId}/consumer/{clientId}")
     public DeferredResult<ThingModelMessage> consumerDeviceInfo(
             @PathVariable("deviceId") String deviceId,
             @PathVariable("clientId") String clientId
     ) {
-        String uid = AuthUtil.getUserId();
-        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
-        dataOwnerService.checkOwner(deviceInfo);
 
-        //按用户+客户端ID订阅
-        return deferredDataConsumer.newConsumer(uid + clientId,
-                Constants.HTTP_CONSUMER_DEVICE_INFO_TOPIC + deviceId);
+        return deviceServiceImpl.addConsumer(deviceId, clientId);
+
     }
 
     /**
      * 获取分组列表
      */
-    @PostMapping("/groups/{size}/{page}")
-    public Paging<DeviceGroup> getDevices(
-            @PathVariable("size") int size,
-            @PathVariable("page") int page,
-            String name
-    ) {
-        return deviceGroupData.findByNameLike(name, page, size);
+    @PostMapping("/groups/list")
+    public Paging<DeviceGroupVo> getDeviceGroups(
+            @Validated @RequestBody PageRequest<DeviceGroupBo> pageRequest) {
+        return deviceServiceImpl.selectGroupPageList(pageRequest);
     }
 
     /**
      * 添加设备分组
      */
+    @ApiOperation(value = "添加设备分组")
     @PostMapping("/group/add")
-    public void addGroup(DeviceGroup group) {
-        group.setUid(AuthUtil.getUserId());
-        if (deviceGroupData.findById(group.getId()) != null) {
-            throw new BizException(ErrCode.GROUP_ALREADY);
-        }
-        deviceGroupData.save(group);
+    public boolean addGroup(@Validated @RequestBody Request<DeviceGroupBo> group) {
+        return deviceServiceImpl.addGroup(group.getData().to(DeviceGroup.class));
     }
 
     /**
      * 修改设备分组
      */
-    @PostMapping("/group/save")
-    public void saveGroup(DeviceGroup group) {
-        DeviceGroup dbGroup = deviceGroupData.findById(group.getId());
-        if (dbGroup == null) {
-            throw new BizException(ErrCode.GROUP_NOT_FOUND);
-        }
-        dataOwnerService.checkOwner(dbGroup);
-        ReflectUtil.copyNoNulls(group, dbGroup);
+    @ApiOperation(value = "修改设备分组")
+    @PostMapping("/group/edit")
+    public boolean editGroup(@RequestBody @Validated Request<DeviceGroupBo> bo) {
+        return deviceServiceImpl.updateGroup(bo.getData());
 
-        deviceGroupData.save(dbGroup);
-        //更新设备中的组信息
-        deviceInfoData.updateGroup(dbGroup.getId(), new DeviceInfo.Group(dbGroup.getId(), dbGroup.getName()));
     }
 
     /**
      * 删除分组
      */
-    @DeleteMapping("/group/delete/{id}")
-    public void deleteGroup(@PathVariable("id") String id) {
-        DeviceGroup group = deviceGroupData.findById(id);
-        if (group == null) {
-            throw new BizException(ErrCode.GROUP_NOT_FOUND);
-        }
-        dataOwnerService.checkOwner(group);
-        //删除分组
-        deviceGroupData.deleteById(id);
-
-        //移除设备信息中的分组
-        deviceInfoData.removeGroup(group.getId());
+    @ApiOperation(value = "删除分组")
+    @DeleteMapping("/group/delete")
+    public boolean deleteGroup(@Validated @RequestBody Request<String> request) {
+        String id = request.getData();
+        return deviceServiceImpl.deleteGroup(id);
     }
 
     /**
      * 清空组下所有设备
      */
-    @PostMapping("/group/clear/{id}")
-    public void clearGroup(@PathVariable("id") String id) {
-        DeviceGroup group = deviceGroupData.findById(id);
-        if (group == null) {
-            throw new BizException(ErrCode.GROUP_NOT_FOUND);
-        }
-        dataOwnerService.checkOwner(group);
-
-        //设备数量清零
-        group.setDeviceQty(0);
-        deviceGroupData.save(group);
-
-        //移除设备信息中的分组
-        deviceInfoData.removeGroup(group.getId());
+    @ApiOperation(value = "清空组下所有设备")
+    @PostMapping("/group/clear")
+    public boolean clearGroup(@Validated @RequestBody Request<String> request) {
+        String id = request.getData();
+        return deviceServiceImpl.clearGroup(id);
     }
 
     /**
      * 添加设备到组
      */
-    @PostMapping("/group/addDevices/{group}")
-    public void addToGroup(@PathVariable("group") String group, @RequestBody List<String> devices) {
-        DeviceGroup deviceGroup = deviceGroupData.findById(group);
-        if (deviceGroup == null) {
-            throw new BizException(ErrCode.GROUP_NOT_FOUND);
-        }
-        dataOwnerService.checkOwner(deviceGroup);
-
-        for (String device : devices) {
-            DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(device);
-            if (deviceInfo == null) {
-                continue;
-            }
-
-            dataOwnerService.checkOwner(deviceInfo);
-            //添加设备到组
-            deviceInfoData.addToGroup(device, new DeviceInfo.Group(group, deviceGroup.getName()));
-        }
-        //统计组下设备数量
-        long qty = deviceInfoData.countByGroupId(group);
-        //更新组信息
-        deviceGroup.setDeviceQty((int) qty);
-        deviceGroupData.save(deviceGroup);
+    @ApiOperation(value = "添加设备到组")
+    @PostMapping("/group/addDevices")
+    public boolean addToGroup(@Validated @RequestBody Request<DeviceAddGroupBo> bo) {
+        return deviceServiceImpl.addDevice2Group(bo.getData());
     }
 
     /**
      * 将设备从组中移除
      */
-    @PostMapping("/group/removeDevices/{group}")
-    public void removeDevices(@PathVariable("group") String group, @RequestBody List<String> devices) {
-        DeviceGroup deviceGroup = deviceGroupData.findById(group);
-        if (deviceGroup == null) {
-            throw new BizException(ErrCode.GROUP_NOT_FOUND);
-        }
-        dataOwnerService.checkOwner(deviceGroup);
-
-        for (String device : devices) {
-            DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(device);
-            if (deviceInfo == null) {
-                continue;
-            }
-
-            dataOwnerService.checkOwner(deviceInfo);
-            //删除设备所在组
-            deviceInfoData.removeGroup(device, group);
-        }
-        //统计组下设备数量
-        long qty = deviceInfoData.countByGroupId(group);
-        //更新组信息
-        deviceGroup.setDeviceQty((int) qty);
-        deviceGroupData.save(deviceGroup);
+    @ApiOperation(value = "将设备从组中移除")
+    @PostMapping("/group/removeDevices")
+    public boolean removeDevices(@Validated @RequestBody Request<DeviceAddGroupBo> bo) {
+        DeviceAddGroupBo data = bo.getData();
+       return deviceServiceImpl.removeDevices(data.getGroup(), data.getDevices());
     }
 
     /**
      * 保存设备配置
      */
-    @PostMapping("/config/{deviceId}/save")
-    public void saveConfig(@PathVariable("deviceId") String deviceId, String config) {
-        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
-        dataOwnerService.checkOwner(deviceInfo);
-
-        DeviceConfig deviceConfig = deviceConfigData.findByDeviceId(deviceId);
-        if (deviceConfig == null) {
-            deviceConfig = DeviceConfig.builder()
-                    .deviceId(deviceId)
-                    .deviceName(deviceInfo.getDeviceName())
-                    .productKey(deviceInfo.getProductKey())
-                    .config(config)
-                    .createAt(System.currentTimeMillis())
-                    .build();
-        } else {
-            deviceConfig.setConfig(config);
-        }
-
-        deviceConfigData.save(deviceConfig);
+    @ApiOperation(value = "保存设备配置")
+    @PostMapping("/config/save")
+    public boolean saveConfig(@Validated @RequestBody Request<DeviceConfigAddBo> request) {
+        DeviceConfig data = request.getData().to(DeviceConfig.class);
+        return deviceServiceImpl.saveConfig(data);
     }
 
     /**
      * 获取设备配置
      */
-    @GetMapping("/config/{deviceId}/get")
-    public DeviceConfig getConfig(@PathVariable("deviceId") String deviceId) {
-        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
-        dataOwnerService.checkOwner(deviceInfo);
-        return deviceConfigData.findByDeviceId(deviceId);
+    @ApiOperation(value = "获取设备配置")
+    @PostMapping("/config/get")
+    public DeviceConfigVo getConfig(@Validated @RequestBody Request<String> request) {
+        String deviceId = request.getData();
+        return deviceServiceImpl.getConfig(deviceId);
     }
 
     /**

+ 74 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/device/DeviceInfoBo.java

@@ -0,0 +1,74 @@
+package cc.iotkit.manager.dto.bo.device;
+
+import cc.iotkit.model.device.DeviceInfo;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import jakarta.validation.constraints.Size;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.math.BigDecimal;
+
+import cc.iotkit.common.api.BaseDto;
+import cc.iotkit.common.validate.AddGroup;
+import cc.iotkit.common.validate.EditGroup;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+@ApiModel(value = "DeviceInfoBo")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = DeviceInfo.class, reverseConvertGenerate = false)
+public class DeviceInfoBo extends BaseDto  {
+
+	private static final long serialVersionUID = -1L;
+
+	@ApiModelProperty(value="创建时间")
+    	private Long createAt;
+
+    	@ApiModelProperty(value="设备id")
+	@Size(max = 255, message = "设备id长度不正确")
+    	private String deviceId;
+
+    	@ApiModelProperty(value="设备名称")
+	@Size(max = 255, message = "设备名称长度不正确")
+    	private String deviceName;
+
+    	@ApiModelProperty(value="设备类型")
+	@Size(max = 255, message = "设备类型长度不正确")
+    	private String model;
+
+    	@ApiModelProperty(value="设备离线时间")
+    	private Long offlineTime;
+
+    	@ApiModelProperty(value="设备在线时间")
+    	private Long onlineTime;
+
+    	@ApiModelProperty(value="父级id")
+	@Size(max = 255, message = "父级id长度不正确")
+    	private String parentId;
+
+    	@ApiModelProperty(value="产品key")
+	@Size(max = 255, message = "产品key长度不正确")
+    	private String productKey;
+
+    	@ApiModelProperty(value="设备描述")
+	@Size(max = 255, message = "设备描述长度不正确")
+    	private String secret;
+
+    	@ApiModelProperty(value="设备状态")
+	@Size(max = 255, message = "设备状态长度不正确")
+    	private String state;
+
+    	@ApiModelProperty(value="用户id")
+	@Size(max = 255, message = "用户id长度不正确")
+    	private String uid;
+
+    }

+ 37 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/device/DeviceLogQueryBo.java

@@ -0,0 +1,37 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.manager.dto.bo.device;
+
+import cc.iotkit.common.api.BaseDto;
+import cc.iotkit.manager.model.vo.DeviceLog;
+import cc.iotkit.model.device.DeviceInfo;
+import io.github.linpeilie.annotations.AutoMapper;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springframework.web.bind.annotation.PathVariable;
+
+@ApiModel(value = "DeviceLogQueryBo")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = DeviceLog.class, reverseConvertGenerate = false)
+public class DeviceLogQueryBo extends BaseDto {
+
+
+    @ApiModelProperty(value="设备id")
+    private String deviceId;
+
+    @ApiModelProperty(value="类型")
+    private String type;
+    @ApiModelProperty(value="属性名")
+    private String identifier;
+}

+ 32 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/device/DevicePropertyLogQueryBo.java

@@ -0,0 +1,32 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.manager.dto.bo.device;
+
+import cc.iotkit.common.api.BaseDto;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@ApiModel(value = "DevicePropertiesLogQueryBo")
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class DevicePropertyLogQueryBo extends BaseDto {
+
+
+    @ApiModelProperty(value="设备id")
+    private String deviceId;
+    @ApiModelProperty(value="属性名称")
+    private String name;
+    @ApiModelProperty(value="开始时间")
+    private long start;
+    @ApiModelProperty(value="结束时间")
+    private long end;
+}

+ 64 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/device/DeviceQueryBo.java

@@ -0,0 +1,64 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.manager.dto.bo.device;
+
+import cc.iotkit.common.api.BaseDto;
+import cc.iotkit.model.device.DeviceInfo;
+import cc.iotkit.model.product.Category;
+import io.github.linpeilie.annotations.AutoMapper;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@ApiModel(value = "DeviceQueryBo")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = DeviceInfo.class, reverseConvertGenerate = false)
+public class DeviceQueryBo extends BaseDto {
+
+
+    @ApiModelProperty(value="关键字")
+    private String keyword;
+
+    @ApiModelProperty(value="分组")
+    private String group;
+
+    @ApiModelProperty(value="设备id")
+    @Size(max = 255, message = "设备id长度不正确")
+    private String deviceId;
+
+    @ApiModelProperty(value="设备名称")
+    @Size(max = 255, message = "设备名称长度不正确")
+    private String deviceName;
+
+    @ApiModelProperty(value="设备类型")
+    @Size(max = 255, message = "设备类型长度不正确")
+    private String model;
+
+    @ApiModelProperty(value="父级id")
+    @Size(max = 255, message = "父级id长度不正确")
+    private String parentId;
+
+    @ApiModelProperty(value="产品key")
+    @Size(max = 255, message = "产品key长度不正确")
+    private String productKey;
+
+
+    @ApiModelProperty(value="设备状态")
+    @Size(max = 255, message = "设备状态长度不正确")
+    private String state;
+
+    @ApiModelProperty(value="用户id")
+    @Size(max = 255, message = "用户id长度不正确")
+    private String uid;
+
+}

+ 40 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/device/DeviceTagAddBo.java

@@ -0,0 +1,40 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.manager.dto.bo.device;
+
+import cc.iotkit.common.api.BaseDto;
+import cc.iotkit.model.device.DeviceInfo;
+import io.github.linpeilie.annotations.AutoMapper;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@ApiModel(value = "DeviceTagAddBo")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = DeviceInfo.Tag.class, reverseConvertGenerate = false)
+public class DeviceTagAddBo extends BaseDto {
+
+
+    @ApiModelProperty(value="设备")
+    private String deviceId;
+
+
+    @ApiModelProperty(value="tag id")
+
+    private String id;
+    @ApiModelProperty(value="tag名称")
+
+    private String name;
+    @ApiModelProperty(value="tag值")
+
+    private String value;
+}

+ 31 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/deviceconfig/DeviceConfigAddBo.java

@@ -0,0 +1,31 @@
+package cc.iotkit.manager.dto.bo.deviceconfig;
+
+import cc.iotkit.common.api.BaseDto;
+import cc.iotkit.model.device.DeviceConfig;
+import io.github.linpeilie.annotations.AutoMapper;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+@ApiModel(value = "DeviceConfigAddBo")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = DeviceConfig.class, reverseConvertGenerate = false)
+public class DeviceConfigAddBo extends BaseDto {
+
+    private static final long serialVersionUID = -1L;
+
+    @ApiModelProperty(value = "设备配置json内容")
+    @Size(max = 65535, message = "设备配置json内容长度不正确")
+    private String config;
+
+
+    @ApiModelProperty(value = "设备id")
+    @Size(max = 255, message = "设备id长度不正确")
+    private String deviceId;
+
+
+}

+ 53 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/deviceconfig/DeviceConfigBo.java

@@ -0,0 +1,53 @@
+package cc.iotkit.manager.dto.bo.deviceconfig;
+
+import cc.iotkit.model.device.DeviceConfig;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import jakarta.validation.constraints.Size;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.math.BigDecimal;
+
+import cc.iotkit.common.api.BaseDto;
+import cc.iotkit.common.validate.AddGroup;
+import cc.iotkit.common.validate.EditGroup;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+@ApiModel(value = "DeviceConfigBo")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = DeviceConfig.class, reverseConvertGenerate = false)
+public class DeviceConfigBo extends BaseDto {
+
+    private static final long serialVersionUID = -1L;
+
+    @ApiModelProperty(value = "设备配置json内容")
+    @Size(max = 65535, message = "设备配置json内容长度不正确")
+    private String config;
+
+    @ApiModelProperty(value = "创建时间")
+    private Long createAt;
+
+    @ApiModelProperty(value = "设备id")
+    @Size(max = 255, message = "设备id长度不正确")
+    private String deviceId;
+
+    @ApiModelProperty(value = "设备名称")
+    @Size(max = 255, message = "设备名称长度不正确")
+    private String deviceName;
+
+    @ApiModelProperty(value = "产品key")
+    @Size(max = 255, message = "产品key长度不正确")
+    private String productKey;
+
+}

+ 30 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/devicegroup/DeviceAddGroupBo.java

@@ -0,0 +1,30 @@
+package cc.iotkit.manager.dto.bo.devicegroup;
+
+import cc.iotkit.common.api.BaseDto;
+import cc.iotkit.model.device.DeviceGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+
+
+@ApiModel(value = "DeviceAddGroupBo")
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class DeviceAddGroupBo extends BaseDto {
+
+    private static final long serialVersionUID = -1L;
+
+    @ApiModelProperty("组id")
+    private String group;
+    @ApiModelProperty("设备列表")
+    private  List<String> devices;
+
+}

+ 55 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/devicegroup/DeviceGroupBo.java

@@ -0,0 +1,55 @@
+package cc.iotkit.manager.dto.bo.devicegroup;
+
+import cc.iotkit.model.device.DeviceGroup;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import jakarta.validation.constraints.NotNull;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import jakarta.validation.constraints.Size;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.math.BigDecimal;
+
+import cc.iotkit.common.api.BaseDto;
+import cc.iotkit.common.validate.AddGroup;
+import cc.iotkit.common.validate.EditGroup;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+@ApiModel(value = "DeviceGroupBo")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = DeviceGroup.class, reverseConvertGenerate = false)
+public class DeviceGroupBo extends BaseDto {
+
+    private static final long serialVersionUID = -1L;
+
+    @ApiModelProperty(value = "创建时间")
+    @NotNull(message = "创建时间不能为空")
+    private Long createAt;
+
+    @ApiModelProperty(value = "设备数量")
+    @NotNull(message = "设备数量不能为空")
+    private Integer deviceQty;
+
+    @ApiModelProperty(value = "设备组名称")
+    @Size(max = 255, message = "设备组名称长度不正确")
+    private String name;
+
+    @ApiModelProperty(value = "分组说明")
+    @Size(max = 255, message = "分组说明长度不正确")
+    private String remark;
+
+    @ApiModelProperty(value = "所属用户")
+    @Size(max = 255, message = "所属用户长度不正确")
+    private String uid;
+
+}

+ 88 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/bo/thingmodel/ThingModelMessageBo.java

@@ -0,0 +1,88 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.manager.dto.bo.thingmodel;
+
+import cc.iotkit.common.api.BaseDto;
+import cc.iotkit.model.device.message.ThingModelMessage;
+import cc.iotkit.model.product.ThingModel;
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 物模型消息
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@AutoMapper(target = ThingModelMessage.class, reverseConvertGenerate = false)
+
+public class ThingModelMessageBo extends BaseDto {
+
+
+    private String id;
+
+    private String mid;
+    @NotNull(message = "设备ID不能为空")
+    private String deviceId;
+
+    private String productKey;
+
+    private String deviceName;
+
+    /**
+     * 所属用户ID
+     */
+    private String uid;
+
+    /**
+     * 消息类型
+     * lifetime:生命周期
+     * state:状态
+     * property:属性
+     * event:事件
+     * service:服务
+     */
+    private String type;
+
+    private String identifier;
+
+    /**
+     * 消息状态码
+     */
+    private int code;
+
+    private Object data;
+
+    /**
+     * 时间戳,设备上的事件或数据产生的本地时间
+     */
+    private Long occurred;
+
+    /**
+     * 消息上报时间
+     */
+    private Long time;
+
+    public Map<String, Object> dataToMap() {
+        Map<String, Object> mapData = new HashMap<>();
+        if (data instanceof Map) {
+            ((Map<?, ?>) data).forEach((key, value) -> mapData.put(key.toString(), value));
+        }
+        return mapData;
+    }
+}

+ 53 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/vo/deviceconfig/DeviceConfigVo.java

@@ -0,0 +1,53 @@
+package cc.iotkit.manager.dto.vo.deviceconfig;
+
+import cc.iotkit.model.device.DeviceConfig;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.Date;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+
+
+@ApiModel(value = "DeviceConfigVo")
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = DeviceConfig.class)
+
+public class DeviceConfigVo implements Serializable {
+
+    private static final long serialVersionUID = -1L;
+
+    @ApiModelProperty(value = "设备配置id")
+    @ExcelProperty(value = "设备配置id")
+    private String id;
+
+    @ApiModelProperty(value = "设备配置json内容")
+    @ExcelProperty(value = "设备配置json内容")
+    private String config;
+
+    @ApiModelProperty(value = "创建时间")
+    @ExcelProperty(value = "创建时间")
+    private Long createAt;
+
+    @ApiModelProperty(value = "设备id")
+    @ExcelProperty(value = "设备id")
+    private String deviceId;
+
+    @ApiModelProperty(value = "设备名称")
+    @ExcelProperty(value = "设备名称")
+    private String deviceName;
+
+    @ApiModelProperty(value = "产品key")
+    @ExcelProperty(value = "产品key")
+    private String productKey;
+
+
+}

+ 53 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/vo/devicegroup/DeviceGroupVo.java

@@ -0,0 +1,53 @@
+package cc.iotkit.manager.dto.vo.devicegroup;
+
+import cc.iotkit.model.device.DeviceGroup;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.Date;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+
+
+@ApiModel(value = "DeviceGroupVo")
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = DeviceGroup.class)
+
+public class DeviceGroupVo implements Serializable {
+
+    private static final long serialVersionUID = -1L;
+
+    @ApiModelProperty(value = "设备组id")
+    @ExcelProperty(value = "设备组id")
+    private String id;
+
+    @ApiModelProperty(value = "创建时间")
+    @ExcelProperty(value = "创建时间")
+    private Long createAt;
+
+    @ApiModelProperty(value = "设备数量")
+    @ExcelProperty(value = "设备数量")
+    private Integer deviceQty;
+
+    @ApiModelProperty(value = "设备组名称")
+    @ExcelProperty(value = "设备组名称")
+    private String name;
+
+    @ApiModelProperty(value = "分组说明")
+    @ExcelProperty(value = "分组说明")
+    private String remark;
+
+    @ApiModelProperty(value = "所属用户")
+    @ExcelProperty(value = "所属用户")
+    private String uid;
+
+
+}

+ 77 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/dto/vo/deviceinfo/DeviceInfoVo.java

@@ -0,0 +1,77 @@
+package cc.iotkit.manager.dto.vo.deviceinfo;
+
+import cc.iotkit.model.device.DeviceInfo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.Date;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+
+
+@ApiModel(value = "DeviceInfoVo")
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = DeviceInfo.class)
+
+public class DeviceInfoVo implements Serializable {
+
+    private static final long serialVersionUID = -1L;
+
+    @ApiModelProperty(value = "")
+    @ExcelProperty(value = "")
+    private String id;
+
+    @ApiModelProperty(value = "创建时间")
+    @ExcelProperty(value = "创建时间")
+    private Long createAt;
+
+    @ApiModelProperty(value = "设备id")
+    @ExcelProperty(value = "设备id")
+    private String deviceId;
+
+    @ApiModelProperty(value = "设备名称")
+    @ExcelProperty(value = "设备名称")
+    private String deviceName;
+
+    @ApiModelProperty(value = "设备类型")
+    @ExcelProperty(value = "设备类型")
+    private String model;
+
+    @ApiModelProperty(value = "设备离线时间")
+    @ExcelProperty(value = "设备离线时间")
+    private Long offlineTime;
+
+    @ApiModelProperty(value = "设备在线时间")
+    @ExcelProperty(value = "设备在线时间")
+    private Long onlineTime;
+
+    @ApiModelProperty(value = "父级id")
+    @ExcelProperty(value = "父级id")
+    private String parentId;
+
+    @ApiModelProperty(value = "产品key")
+    @ExcelProperty(value = "产品key")
+    private String productKey;
+
+    @ApiModelProperty(value = "设备描述")
+    @ExcelProperty(value = "设备描述")
+    private String secret;
+
+    @ApiModelProperty(value = "设备状态")
+    @ExcelProperty(value = "设备状态")
+    private String state;
+
+    @ApiModelProperty(value = "用户id")
+    @ExcelProperty(value = "用户id")
+    private String uid;
+
+
+}

+ 74 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/IDeviceService.java

@@ -0,0 +1,74 @@
+package cc.iotkit.manager.service;
+
+import cc.iotkit.common.api.PageRequest;
+import cc.iotkit.common.api.Paging;
+import cc.iotkit.manager.dto.bo.device.DeviceInfoBo;
+import cc.iotkit.manager.dto.bo.device.DeviceLogQueryBo;
+import cc.iotkit.manager.dto.bo.device.DeviceQueryBo;
+import cc.iotkit.manager.dto.bo.device.DeviceTagAddBo;
+import cc.iotkit.manager.dto.bo.devicegroup.DeviceAddGroupBo;
+import cc.iotkit.manager.dto.bo.devicegroup.DeviceGroupBo;
+import cc.iotkit.manager.dto.vo.deviceconfig.DeviceConfigVo;
+import cc.iotkit.manager.dto.vo.devicegroup.DeviceGroupVo;
+import cc.iotkit.manager.dto.vo.deviceinfo.DeviceInfoVo;
+import cc.iotkit.model.device.DeviceConfig;
+import cc.iotkit.model.device.DeviceGroup;
+import cc.iotkit.model.device.DeviceInfo;
+import cc.iotkit.model.device.message.DeviceProperty;
+import cc.iotkit.model.device.message.ThingModelMessage;
+import org.springframework.web.context.request.async.DeferredResult;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author: jay
+ * @Date: 2023/5/31 11:05
+ * @Version: V1.0
+ * @Description: 设备服务接口
+ */
+public interface IDeviceService {
+    Paging<DeviceInfo> getDevices(PageRequest<DeviceQueryBo> pageRequest);
+
+    boolean addDevice(DeviceInfoBo data);
+
+    List<DeviceInfoVo> selectChildrenPageList(String deviceId);
+
+    List<Map<String, Object>> getParentDevices();
+
+    DeviceInfo getDetail(String deviceId);
+
+    DeviceInfo getByPkDn(String pk, String dn);
+
+    boolean deleteDevice(String data);
+
+    Paging<ThingModelMessage> logs(PageRequest<DeviceLogQueryBo> request);
+
+    List<DeviceProperty> getPropertyHistory(String deviceId, String name, long start, long end);
+
+    boolean unbindDevice(String data);
+
+    boolean addTag(DeviceTagAddBo bo);
+
+    boolean simulateSend(ThingModelMessage message);
+
+    DeferredResult  addConsumer(String deviceId, String clientId);
+
+    Paging<DeviceGroupVo> selectGroupPageList(PageRequest<DeviceGroupBo> pageRequest);
+
+    boolean addGroup(DeviceGroup group);
+
+    boolean updateGroup(DeviceGroupBo data);
+
+    boolean deleteGroup(String id);
+
+    boolean clearGroup(String id);
+
+    boolean addDevice2Group(DeviceAddGroupBo data);
+
+    boolean removeDevices(String group, List<String> devices);
+
+    boolean saveConfig(DeviceConfig data);
+
+    DeviceConfigVo getConfig(String deviceId);
+}

+ 397 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/DeviceServiceImpl.java

@@ -0,0 +1,397 @@
+package cc.iotkit.manager.service.impl;
+
+import cc.iotkit.common.api.PageRequest;
+import cc.iotkit.common.api.Paging;
+import cc.iotkit.common.constant.Constants;
+import cc.iotkit.common.enums.ErrCode;
+import cc.iotkit.common.exception.BizException;
+import cc.iotkit.common.satoken.utils.AuthUtil;
+import cc.iotkit.common.utils.DeviceUtil;
+import cc.iotkit.common.utils.MapstructUtils;
+import cc.iotkit.common.utils.ReflectUtil;
+import cc.iotkit.common.utils.UniqueIdUtil;
+import cc.iotkit.comps.service.DeviceBehaviourService;
+import cc.iotkit.data.manager.IDeviceConfigData;
+import cc.iotkit.data.manager.IDeviceGroupData;
+import cc.iotkit.data.manager.IDeviceInfoData;
+import cc.iotkit.data.manager.IProductData;
+import cc.iotkit.manager.dto.bo.device.DeviceInfoBo;
+import cc.iotkit.manager.dto.bo.device.DeviceLogQueryBo;
+import cc.iotkit.manager.dto.bo.device.DeviceQueryBo;
+import cc.iotkit.manager.dto.bo.device.DeviceTagAddBo;
+import cc.iotkit.manager.dto.bo.devicegroup.DeviceAddGroupBo;
+import cc.iotkit.manager.dto.bo.devicegroup.DeviceGroupBo;
+import cc.iotkit.manager.dto.vo.deviceconfig.DeviceConfigVo;
+import cc.iotkit.manager.dto.vo.devicegroup.DeviceGroupVo;
+import cc.iotkit.manager.dto.vo.deviceinfo.DeviceInfoVo;
+import cc.iotkit.manager.service.DataOwnerService;
+import cc.iotkit.manager.service.DeferredDataConsumer;
+import cc.iotkit.manager.service.DeviceService;
+import cc.iotkit.manager.service.IDeviceService;
+import cc.iotkit.model.device.DeviceConfig;
+import cc.iotkit.model.device.DeviceGroup;
+import cc.iotkit.model.device.DeviceInfo;
+import cc.iotkit.model.device.message.DeviceProperty;
+import cc.iotkit.model.device.message.ThingModelMessage;
+import cc.iotkit.model.product.Product;
+import cc.iotkit.temporal.IDevicePropertyData;
+import cc.iotkit.temporal.IThingModelMessageData;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+import org.springframework.web.context.request.async.DeferredResult;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author: jay
+ * @Date: 2023/5/31 11:06
+ * @Version: V1.0
+ * @Description: 设备服务实现
+ */
+
+@Service
+public class DeviceServiceImpl implements IDeviceService {
+
+    @Autowired
+    private DeviceService deviceService;
+
+    @Autowired
+    @Qualifier("deviceInfoDataCache")
+    private IDeviceInfoData deviceInfoData;
+    @Autowired
+    @Qualifier("productDataCache")
+    private IProductData productData;
+    @Autowired
+    private DataOwnerService dataOwnerService;
+
+    @Lazy
+    @Autowired
+    private IThingModelMessageData thingModelMessageData;
+    @Lazy
+    @Autowired
+    private IDevicePropertyData devicePropertyData;
+    @Autowired
+    private DeviceBehaviourService behaviourService;
+    @Autowired
+    DeferredDataConsumer deferredDataConsumer;
+    @Autowired
+    private IDeviceGroupData deviceGroupData;
+    @Autowired
+    private IDeviceConfigData deviceConfigData;
+
+    @Override
+    public Paging<DeviceInfo> getDevices(PageRequest<DeviceQueryBo> pageRequest) {
+        DeviceQueryBo query = pageRequest.getData();
+
+        String uid = "";
+        String subUid = "";
+        if (!AuthUtil.isAdmin()) {
+            //客户端用户使用绑定子用户查询
+            if (AuthUtil.isClientUser()) {
+                subUid = AuthUtil.getUserId();
+            } else {
+                uid = AuthUtil.getUserId();
+            }
+        }
+
+        String pk = query.getProductKey();
+        //关键字查询
+        String keyword = query.getKeyword();
+        String group = query.getGroup();
+        String state = query.getState();
+
+        return deviceInfoData.findByConditions(uid, subUid, pk, group,
+                state, keyword, pageRequest.getPageNum(), pageRequest.getPageSize());
+    }
+
+    @Override
+    public boolean addDevice(DeviceInfoBo deviceInfo) {
+
+        String productKey = deviceInfo.getProductKey();
+        String deviceName = deviceInfo.getDeviceName();
+        String parentId = deviceInfo.getParentId();
+
+        Product product = productData.findById(productKey);
+        if (product == null) {
+            throw new BizException(ErrCode.PRODUCT_NOT_FOUND);
+        }
+
+        //生成设备密钥
+        String chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
+        int maxPos = chars.length();
+        StringBuilder secret = new StringBuilder();
+        for (var i = 0; i < 16; i++) {
+            secret.append(chars.charAt((int) Math.floor(Math.random() * maxPos)));
+        }
+
+        DeviceInfo device = new DeviceInfo();
+        device.setId(DeviceUtil.newDeviceId(deviceName));
+        device.setUid(product.getUid());
+        device.setDeviceId(device.getId());
+        device.setProductKey(productKey);
+        device.setDeviceName(deviceName);
+        device.setSecret(secret.toString());
+        device.setState(new DeviceInfo.State(false, null, null));
+        device.setCreateAt(System.currentTimeMillis());
+        if (StringUtils.isNotBlank(parentId)) {
+            device.setParentId(parentId);
+        }
+        deviceInfoData.save(device);
+        return true;
+    }
+
+    @Override
+    public List<DeviceInfoVo> selectChildrenPageList(String deviceId) {
+        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
+        if (deviceInfo == null) {
+            throw new BizException(ErrCode.DEVICE_NOT_FOUND);
+        }
+
+        dataOwnerService.checkOwner(deviceInfo);
+        return MapstructUtils.convert(deviceInfoData.findByParentId(deviceId), DeviceInfoVo.class);
+    }
+
+    @Override
+    public List<Map<String, Object>> getParentDevices() {
+        String uid = "";
+        if (!AuthUtil.isAdmin()) {
+            uid = AuthUtil.getUserId();
+        }
+        return deviceInfoData.findByProductNodeType(uid);
+    }
+
+    @Override
+    public DeviceInfo getDetail(String deviceId) {
+        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
+        dataOwnerService.checkOwner(deviceInfo);
+        deviceInfo.setProperty(deviceInfoData.getProperties(deviceId));
+        return deviceInfo;
+    }
+
+    @Override
+    public DeviceInfo getByPkDn(String pk, String dn) {
+        return dataOwnerService.checkOwner(
+                deviceInfoData.findByProductKeyAndDeviceName(pk, dn));
+    }
+
+    @Override
+    public boolean deleteDevice(String deviceId) {
+
+        deviceId = getDetail(deviceId).getDeviceId();
+        deviceInfoData.deleteById(deviceId);
+        return true;
+    }
+
+    @Override
+    public Paging<ThingModelMessage> logs(PageRequest<DeviceLogQueryBo> request) {
+        DeviceLogQueryBo data = request.getData();
+        return thingModelMessageData.findByTypeAndIdentifier(data.getDeviceId(), data.getType(), data.getIdentifier(), request.getPageNum(), request.getPageSize());
+
+    }
+
+    @Override
+    public List<DeviceProperty> getPropertyHistory(String deviceId, String name, long start, long end) {
+        return devicePropertyData.findDevicePropertyHistory(deviceId, name, start, end);
+    }
+
+    @Override
+    public boolean unbindDevice(String deviceId) {
+
+        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
+        dataOwnerService.checkOwner(deviceInfo);
+        deviceService.unbindDevice(deviceId);
+        return false;
+    }
+
+    @Override
+    public boolean addTag(DeviceTagAddBo bo) {
+        String deviceId = bo.getDeviceId();
+        DeviceInfo device = deviceInfoData.findByDeviceId(deviceId);
+        dataOwnerService.checkOwner(device);
+        deviceInfoData.updateTag(deviceId, bo.to(DeviceInfo.Tag.class));
+        return false;
+    }
+
+    @Override
+    public boolean simulateSend(ThingModelMessage message) {
+        DeviceInfo device = deviceInfoData.findByDeviceId(message.getDeviceId());
+        dataOwnerService.checkOwner(device);
+
+        message.setMid(UniqueIdUtil.newRequestId());
+        message.setOccurred(System.currentTimeMillis());
+        message.setTime(System.currentTimeMillis());
+        behaviourService.reportMessage(message);
+        return false;
+    }
+
+    @Override
+    public DeferredResult addConsumer(String deviceId, String clientId) {
+
+        DeferredResult<ThingModelMessage> result = new DeferredResult<>(0L);
+        String uid = AuthUtil.getUserId();
+        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
+        dataOwnerService.checkOwner(deviceInfo);
+
+        //按用户+客户端ID订阅
+        return deferredDataConsumer.newConsumer(uid + clientId,
+                Constants.HTTP_CONSUMER_DEVICE_INFO_TOPIC + deviceId);
+    }
+
+    @Override
+    public Paging<DeviceGroupVo> selectGroupPageList(PageRequest<DeviceGroupBo> pageRequest) {
+        DeviceGroupBo data = pageRequest.getData();
+        return deviceGroupData.findByNameLike(data.getName(), pageRequest.getPageNum(), pageRequest.getPageSize()).to(DeviceGroupVo.class);
+    }
+
+    @Override
+    public boolean addGroup(DeviceGroup group) {
+        group.setUid(AuthUtil.getUserId());
+        if (deviceGroupData.findById(group.getId()) != null) {
+            throw new BizException(ErrCode.GROUP_ALREADY);
+        }
+        deviceGroupData.save(group);
+        return true;
+    }
+
+    @Override
+    public boolean updateGroup(DeviceGroupBo bo) {
+        DeviceGroup group = bo.to(DeviceGroup.class);
+        DeviceGroup dbGroup = deviceGroupData.findById(group.getId());
+        if (dbGroup == null) {
+            throw new BizException(ErrCode.GROUP_NOT_FOUND);
+        }
+        dataOwnerService.checkOwner(dbGroup);
+        ReflectUtil.copyNoNulls(group, dbGroup);
+
+        deviceGroupData.save(dbGroup);
+        //更新设备中的组信息
+        deviceInfoData.updateGroup(dbGroup.getId(), new DeviceInfo.Group(dbGroup.getId(), dbGroup.getName()));
+        return true;
+    }
+
+    @Override
+    public boolean deleteGroup(String id) {
+        DeviceGroup group = deviceGroupData.findById(id);
+        if (group == null) {
+            throw new BizException(ErrCode.GROUP_NOT_FOUND);
+        }
+        dataOwnerService.checkOwner(group);
+        //删除分组
+        deviceGroupData.deleteById(id);
+
+        //移除设备信息中的分组
+        deviceInfoData.removeGroup(group.getId());
+        return true;
+    }
+
+    @Override
+    public boolean clearGroup(String id) {
+        DeviceGroup group = deviceGroupData.findById(id);
+        if (group == null) {
+            throw new BizException(ErrCode.GROUP_NOT_FOUND);
+        }
+        dataOwnerService.checkOwner(group);
+
+        //设备数量清零
+        group.setDeviceQty(0);
+        deviceGroupData.save(group);
+
+        //移除设备信息中的分组
+        deviceInfoData.removeGroup(group.getId());
+        return true;
+    }
+
+    @Override
+    public boolean addDevice2Group(DeviceAddGroupBo data) {
+
+        String group = data.getGroup();
+        List<String> devices = data.getDevices();
+        DeviceGroup deviceGroup = deviceGroupData.findById(group);
+        if (deviceGroup == null) {
+            throw new BizException(ErrCode.GROUP_NOT_FOUND);
+        }
+        dataOwnerService.checkOwner(deviceGroup);
+
+        for (String device : devices) {
+            DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(device);
+            if (deviceInfo == null) {
+                continue;
+            }
+
+            dataOwnerService.checkOwner(deviceInfo);
+            //添加设备到组
+            deviceInfoData.addToGroup(device, new DeviceInfo.Group(group, deviceGroup.getName()));
+        }
+        //统计组下设备数量
+        long qty = deviceInfoData.countByGroupId(group);
+        //更新组信息
+        deviceGroup.setDeviceQty((int) qty);
+        deviceGroupData.save(deviceGroup);
+        return true;
+    }
+
+    @Override
+    public boolean removeDevices(String group, List<String> devices) {
+
+        DeviceGroup deviceGroup = deviceGroupData.findById(group);
+        if (deviceGroup == null) {
+            throw new BizException(ErrCode.GROUP_NOT_FOUND);
+        }
+        dataOwnerService.checkOwner(deviceGroup);
+
+        for (String device : devices) {
+            DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(device);
+            if (deviceInfo == null) {
+                continue;
+            }
+
+            dataOwnerService.checkOwner(deviceInfo);
+            //删除设备所在组
+            deviceInfoData.removeGroup(device, group);
+        }
+        //统计组下设备数量
+        long qty = deviceInfoData.countByGroupId(group);
+        //更新组信息
+        deviceGroup.setDeviceQty((int) qty);
+        deviceGroupData.save(deviceGroup);
+        return true;
+    }
+
+    @Override
+    public boolean saveConfig(DeviceConfig data) {
+        String deviceId = data.getDeviceId();
+        String config = data.getConfig();
+        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
+        dataOwnerService.checkOwner(deviceInfo);
+
+        DeviceConfig deviceConfig = deviceConfigData.findByDeviceId(deviceId);
+        if (deviceConfig == null) {
+            deviceConfig = DeviceConfig.builder()
+                    .deviceId(deviceId)
+                    .deviceName(deviceInfo.getDeviceName())
+                    .productKey(deviceInfo.getProductKey())
+                    .config(config)
+                    .createAt(System.currentTimeMillis())
+                    .build();
+        } else {
+            deviceConfig.setConfig(config);
+        }
+
+        deviceConfigData.save(deviceConfig);
+        return false;
+    }
+
+    @Override
+    public DeviceConfigVo getConfig(String deviceId) {
+        DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(deviceId);
+        dataOwnerService.checkOwner(deviceInfo);
+        return MapstructUtils.convert(deviceConfigData.findByDeviceId(deviceId), DeviceConfigVo.class);
+
+    }
+
+
+}