Commit 05eb745f2a7e84d2cbb0d51991b97ea064e4be04
1 parent
bfbc352a
feat(iot):【网关设备:67%】整体初步实现(优化部分代码)
Showing
6 changed files
with
99 additions
and
21 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java
| @@ -262,4 +262,20 @@ public class JsonUtils { | @@ -262,4 +262,20 @@ public class JsonUtils { | ||
| 262 | return objectMapper.convertValue(obj, typeReference); | 262 | return objectMapper.convertValue(obj, typeReference); |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | + /** | ||
| 266 | + * 将 Object 转换为 List 类型 | ||
| 267 | + * <p> | ||
| 268 | + * 避免先转 jsonString 再 parseArray 的性能损耗 | ||
| 269 | + * | ||
| 270 | + * @param obj 源对象(可以是 List、数组等) | ||
| 271 | + * @param clazz 目标元素类型 | ||
| 272 | + * @return 转换后的 List | ||
| 273 | + */ | ||
| 274 | + public static <T> List<T> convertList(Object obj, Class<T> clazz) { | ||
| 275 | + if (obj == null) { | ||
| 276 | + return new ArrayList<>(); | ||
| 277 | + } | ||
| 278 | + return objectMapper.convertValue(obj, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)); | ||
| 279 | + } | ||
| 280 | + | ||
| 265 | } | 281 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java
| @@ -72,7 +72,7 @@ public class IotDeviceController { | @@ -72,7 +72,7 @@ public class IotDeviceController { | ||
| 72 | @Operation(summary = "解绑子设备与网关") | 72 | @Operation(summary = "解绑子设备与网关") |
| 73 | @PreAuthorize("@ss.hasPermission('iot:device:update')") | 73 | @PreAuthorize("@ss.hasPermission('iot:device:update')") |
| 74 | public CommonResult<Boolean> unbindDeviceGateway(@Valid @RequestBody IotDeviceUnbindGatewayReqVO reqVO) { | 74 | public CommonResult<Boolean> unbindDeviceGateway(@Valid @RequestBody IotDeviceUnbindGatewayReqVO reqVO) { |
| 75 | - deviceService.unbindDeviceGateway(reqVO.getIds()); | 75 | + deviceService.unbindDeviceGateway(reqVO.getIds(), reqVO.getGatewayId()); |
| 76 | return success(true); | 76 | return success(true); |
| 77 | } | 77 | } |
| 78 | 78 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceUnbindGatewayReqVO.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; | ||
| 2 | 2 | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import jakarta.validation.constraints.NotEmpty; | 4 | import jakarta.validation.constraints.NotEmpty; |
| 5 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | import lombok.Data; | 6 | import lombok.Data; |
| 6 | 7 | ||
| 7 | import java.util.Set; | 8 | import java.util.Set; |
| @@ -14,4 +15,8 @@ public class IotDeviceUnbindGatewayReqVO { | @@ -14,4 +15,8 @@ public class IotDeviceUnbindGatewayReqVO { | ||
| 14 | @NotEmpty(message = "子设备编号列表不能为空") | 15 | @NotEmpty(message = "子设备编号列表不能为空") |
| 15 | private Set<Long> ids; | 16 | private Set<Long> ids; |
| 16 | 17 | ||
| 18 | + @Schema(description = "网关设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 19 | + @NotNull(message = "网关设备编号不能为空") | ||
| 20 | + private Long gatewayId; | ||
| 21 | + | ||
| 17 | } | 22 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/IotDeviceMapper.java
| @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePa | @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePa | ||
| 8 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; | 8 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 9 | import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; | 9 | import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; |
| 10 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 10 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| 11 | +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | ||
| 11 | import jakarta.annotation.Nullable; | 12 | import jakarta.annotation.Nullable; |
| 12 | import org.apache.ibatis.annotations.Mapper; | 13 | import org.apache.ibatis.annotations.Mapper; |
| 13 | 14 | ||
| @@ -159,4 +160,16 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> { | @@ -159,4 +160,16 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> { | ||
| 159 | .orderByDesc(IotDeviceDO::getId)); | 160 | .orderByDesc(IotDeviceDO::getId)); |
| 160 | } | 161 | } |
| 161 | 162 | ||
| 163 | + /** | ||
| 164 | + * 批量更新设备的网关编号 | ||
| 165 | + * | ||
| 166 | + * @param ids 设备编号列表 | ||
| 167 | + * @param gatewayId 网关设备编号(可以为 null,表示解绑) | ||
| 168 | + */ | ||
| 169 | + default void updateGatewayIdBatch(Collection<Long> ids, Long gatewayId) { | ||
| 170 | + update(null, new LambdaUpdateWrapper<IotDeviceDO>() | ||
| 171 | + .set(IotDeviceDO::getGatewayId, gatewayId) | ||
| 172 | + .in(IotDeviceDO::getId, ids)); | ||
| 173 | + } | ||
| 174 | + | ||
| 162 | } | 175 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
| @@ -305,9 +305,10 @@ public interface IotDeviceService { | @@ -305,9 +305,10 @@ public interface IotDeviceService { | ||
| 305 | /** | 305 | /** |
| 306 | * 解绑子设备与网关 | 306 | * 解绑子设备与网关 |
| 307 | * | 307 | * |
| 308 | - * @param ids 子设备编号列表 | 308 | + * @param ids 子设备编号列表 |
| 309 | + * @param gatewayId 网关设备编号 | ||
| 309 | */ | 310 | */ |
| 310 | - void unbindDeviceGateway(Collection<Long> ids); | 311 | + void unbindDeviceGateway(Collection<Long> ids, Long gatewayId); |
| 311 | 312 | ||
| 312 | /** | 313 | /** |
| 313 | * 获取未绑定网关的子设备分页 | 314 | * 获取未绑定网关的子设备分页 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
| @@ -14,12 +14,14 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | @@ -14,12 +14,14 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | ||
| 14 | import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | 14 | import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; |
| 15 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; | 15 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; |
| 16 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO; | 16 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO; |
| 17 | +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; | ||
| 17 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum; | 18 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum; |
| 18 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | 19 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 19 | import cn.iocoder.yudao.module.iot.core.topic.IotDeviceIdentity; | 20 | import cn.iocoder.yudao.module.iot.core.topic.IotDeviceIdentity; |
| 20 | import cn.iocoder.yudao.module.iot.core.topic.auth.IotSubDeviceRegisterReqDTO; | 21 | import cn.iocoder.yudao.module.iot.core.topic.auth.IotSubDeviceRegisterReqDTO; |
| 21 | import cn.iocoder.yudao.module.iot.core.topic.auth.IotSubDeviceRegisterRespDTO; | 22 | import cn.iocoder.yudao.module.iot.core.topic.auth.IotSubDeviceRegisterRespDTO; |
| 22 | import cn.iocoder.yudao.module.iot.core.topic.topo.IotDeviceTopoAddReqDTO; | 23 | import cn.iocoder.yudao.module.iot.core.topic.topo.IotDeviceTopoAddReqDTO; |
| 24 | +import cn.iocoder.yudao.module.iot.core.topic.topo.IotDeviceTopoChangeReqDTO; | ||
| 23 | import cn.iocoder.yudao.module.iot.core.topic.topo.IotDeviceTopoDeleteReqDTO; | 25 | import cn.iocoder.yudao.module.iot.core.topic.topo.IotDeviceTopoDeleteReqDTO; |
| 24 | import cn.iocoder.yudao.module.iot.core.topic.topo.IotDeviceTopoGetRespDTO; | 26 | import cn.iocoder.yudao.module.iot.core.topic.topo.IotDeviceTopoGetRespDTO; |
| 25 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils; | 27 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils; |
| @@ -29,6 +31,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; | @@ -29,6 +31,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; | ||
| 29 | import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper; | 31 | import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper; |
| 30 | import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; | 32 | import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; |
| 31 | import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; | 33 | import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; |
| 34 | +import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService; | ||
| 32 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; | 35 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; |
| 33 | import jakarta.annotation.Resource; | 36 | import jakarta.annotation.Resource; |
| 34 | import jakarta.validation.ConstraintViolationException; | 37 | import jakarta.validation.ConstraintViolationException; |
| @@ -49,6 +52,7 @@ import java.util.*; | @@ -49,6 +52,7 @@ import java.util.*; | ||
| 49 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 52 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 50 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 53 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| 51 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; | 54 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; |
| 55 | +import static java.util.Collections.singletonList; | ||
| 52 | 56 | ||
| 53 | /** | 57 | /** |
| 54 | * IoT 设备 Service 实现类 | 58 | * IoT 设备 Service 实现类 |
| @@ -69,6 +73,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -69,6 +73,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 69 | @Resource | 73 | @Resource |
| 70 | @Lazy // 延迟加载,解决循环依赖 | 74 | @Lazy // 延迟加载,解决循环依赖 |
| 71 | private IotDeviceGroupService deviceGroupService; | 75 | private IotDeviceGroupService deviceGroupService; |
| 76 | + @Resource | ||
| 77 | + @Lazy // 延迟加载,解决循环依赖 | ||
| 78 | + private IotDeviceMessageService deviceMessageService; | ||
| 72 | 79 | ||
| 73 | @Override | 80 | @Override |
| 74 | public Long createDevice(IotDeviceSaveReqVO createReqVO) { | 81 | public Long createDevice(IotDeviceSaveReqVO createReqVO) { |
| @@ -590,7 +597,8 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -590,7 +597,8 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 590 | // 3. 清空对应缓存 | 597 | // 3. 清空对应缓存 |
| 591 | deleteDeviceCache(devices); | 598 | deleteDeviceCache(devices); |
| 592 | 599 | ||
| 593 | - // TODO @AI:需要下发网关设备,让其建立拓扑关系吗?(增加) | 600 | + // 4. 下发网关设备拓扑变更通知(增加) |
| 601 | + sendTopoChangeNotify(gatewayId, IotDeviceTopoChangeReqDTO.STATUS_CREATE, devices); | ||
| 594 | } | 602 | } |
| 595 | 603 | ||
| 596 | private void checkSubDeviceCanBind(IotDeviceDO device, Long gatewayId) { | 604 | private void checkSubDeviceCanBind(IotDeviceDO device, Long gatewayId) { |
| @@ -604,30 +612,25 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -604,30 +612,25 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 604 | 612 | ||
| 605 | @Override | 613 | @Override |
| 606 | @Transactional(rollbackFor = Exception.class) | 614 | @Transactional(rollbackFor = Exception.class) |
| 607 | - public void unbindDeviceGateway(Collection<Long> ids) { | 615 | + public void unbindDeviceGateway(Collection<Long> ids, Long gatewayId) { |
| 608 | // 1. 校验设备存在 | 616 | // 1. 校验设备存在 |
| 609 | if (CollUtil.isEmpty(ids)) { | 617 | if (CollUtil.isEmpty(ids)) { |
| 610 | return; | 618 | return; |
| 611 | } | 619 | } |
| 612 | List<IotDeviceDO> devices = deviceMapper.selectByIds(ids); | 620 | List<IotDeviceDO> devices = deviceMapper.selectByIds(ids); |
| 613 | - if (CollUtil.isNotEmpty(devices)) { | 621 | + devices.removeIf(device -> device.getGatewayId() == null); |
| 622 | + if (CollUtil.isEmpty(devices)) { | ||
| 614 | return; | 623 | return; |
| 615 | } | 624 | } |
| 616 | 625 | ||
| 617 | // 2. 批量更新数据库(将 gatewayId 设置为 null) | 626 | // 2. 批量更新数据库(将 gatewayId 设置为 null) |
| 618 | - // TODO @AI:需要搞个方法,专门批量更新某个字段为 null。 | ||
| 619 | - List<IotDeviceDO> updateList = devices.stream() | ||
| 620 | - .filter(device -> device.getGatewayId() != null) | ||
| 621 | - .map(device -> new IotDeviceDO().setId(device.getId()).setGatewayId(null)) | ||
| 622 | - .toList(); | ||
| 623 | - if (CollUtil.isNotEmpty(updateList)) { | ||
| 624 | - deviceMapper.updateBatch(updateList); | ||
| 625 | - } | 627 | + deviceMapper.updateGatewayIdBatch(convertList(devices, IotDeviceDO::getId), null); |
| 626 | 628 | ||
| 627 | // 3. 清空对应缓存 | 629 | // 3. 清空对应缓存 |
| 628 | deleteDeviceCache(devices); | 630 | deleteDeviceCache(devices); |
| 629 | 631 | ||
| 630 | - // TODO @AI:需要下发网关设备,让其建立拓扑关系吗?(减少) | 632 | + // 4. 下发网关设备拓扑变更通知(删除) |
| 633 | + sendTopoChangeNotify(gatewayId, IotDeviceTopoChangeReqDTO.STATUS_DELETE, devices); | ||
| 631 | } | 634 | } |
| 632 | 635 | ||
| 633 | @Override | 636 | @Override |
| @@ -742,9 +745,8 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -742,9 +745,8 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 742 | subDeviceIdentity.getProductKey(), subDeviceIdentity.getDeviceName()); | 745 | subDeviceIdentity.getProductKey(), subDeviceIdentity.getDeviceName()); |
| 743 | } | 746 | } |
| 744 | 747 | ||
| 745 | - // 2. 更新数据库 | ||
| 746 | - // TODO @AI:直接调用更新方法; | ||
| 747 | -// unbindDeviceGateway(Collections.singletonList(subDevice.getId())); | 748 | + // 2. 更新数据库(将 gatewayId 设置为 null) |
| 749 | + deviceMapper.updateGatewayIdBatch(singletonList(subDevice.getId()), null); | ||
| 748 | log.info("[deleteDeviceTopo][网关({}/{}) 解绑子设备({}/{})]", | 750 | log.info("[deleteDeviceTopo][网关({}/{}) 解绑子设备({}/{})]", |
| 749 | gatewayDevice.getProductKey(), gatewayDevice.getDeviceName(), | 751 | gatewayDevice.getProductKey(), gatewayDevice.getDeviceName(), |
| 750 | subDevice.getProductKey(), subDevice.getDeviceName()); | 752 | subDevice.getProductKey(), subDevice.getDeviceName()); |
| @@ -782,8 +784,7 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -782,8 +784,7 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 782 | if (!(message.getParams() instanceof List)) { | 784 | if (!(message.getParams() instanceof List)) { |
| 783 | throw exception(DEVICE_SUB_REGISTER_PARAMS_INVALID); | 785 | throw exception(DEVICE_SUB_REGISTER_PARAMS_INVALID); |
| 784 | } | 786 | } |
| 785 | - // TODO @AI:这个要不也弄到 JsonUtils 里面去?感觉类似 convertObject 呀。 | ||
| 786 | - List<IotSubDeviceRegisterReqDTO> paramsList = JsonUtils.parseArray(JsonUtils.toJsonString(message.getParams()), | 787 | + List<IotSubDeviceRegisterReqDTO> paramsList = JsonUtils.convertList(message.getParams(), |
| 787 | IotSubDeviceRegisterReqDTO.class); | 788 | IotSubDeviceRegisterReqDTO.class); |
| 788 | if (CollUtil.isEmpty(paramsList)) { | 789 | if (CollUtil.isEmpty(paramsList)) { |
| 789 | throw exception(DEVICE_SUB_REGISTER_PARAMS_INVALID); | 790 | throw exception(DEVICE_SUB_REGISTER_PARAMS_INVALID); |
| @@ -817,9 +818,13 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -817,9 +818,13 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 817 | throw exception(DEVICE_SUB_REGISTER_PRODUCT_NOT_GATEWAY_SUB, params.getProductKey()); | 818 | throw exception(DEVICE_SUB_REGISTER_PRODUCT_NOT_GATEWAY_SUB, params.getProductKey()); |
| 818 | } | 819 | } |
| 819 | // 1.3 查找设备是否已存在 | 820 | // 1.3 查找设备是否已存在 |
| 820 | - // TODO @AI:存在的时候,必须父设备是自己,才返回,否则抛出业务异常; | ||
| 821 | IotDeviceDO existDevice = getSelf().getDeviceFromCache(params.getProductKey(), params.getDeviceName()); | 821 | IotDeviceDO existDevice = getSelf().getDeviceFromCache(params.getProductKey(), params.getDeviceName()); |
| 822 | if (existDevice != null) { | 822 | if (existDevice != null) { |
| 823 | + // 校验是否绑定到当前网关 | ||
| 824 | + if (ObjUtil.notEqual(existDevice.getGatewayId(), gatewayDevice.getId())) { | ||
| 825 | + throw exception(DEVICE_GATEWAY_BINDTO_EXISTS, | ||
| 826 | + existDevice.getProductKey(), existDevice.getDeviceName()); | ||
| 827 | + } | ||
| 823 | // 已存在则返回设备信息 | 828 | // 已存在则返回设备信息 |
| 824 | return existDevice; | 829 | return existDevice; |
| 825 | } | 830 | } |
| @@ -840,4 +845,42 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -840,4 +845,42 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 840 | return SpringUtil.getBean(getClass()); | 845 | return SpringUtil.getBean(getClass()); |
| 841 | } | 846 | } |
| 842 | 847 | ||
| 848 | + /** | ||
| 849 | + * 发送拓扑变更通知给网关设备 | ||
| 850 | + * | ||
| 851 | + * @param gatewayId 网关设备编号 | ||
| 852 | + * @param status 变更状态(0-创建, 1-删除) | ||
| 853 | + * @param subDevices 子设备列表 | ||
| 854 | + * @see <a href="https://help.aliyun.com/zh/marketplace/notify-gateway-topology-changes">阿里云 - 通知网关拓扑关系变化</a> | ||
| 855 | + */ | ||
| 856 | + private void sendTopoChangeNotify(Long gatewayId, Integer status, List<IotDeviceDO> subDevices) { | ||
| 857 | + if (CollUtil.isEmpty(subDevices)) { | ||
| 858 | + return; | ||
| 859 | + } | ||
| 860 | + // 1. 获取网关设备 | ||
| 861 | + IotDeviceDO gatewayDevice = deviceMapper.selectById(gatewayId); | ||
| 862 | + if (gatewayDevice == null) { | ||
| 863 | + log.warn("[sendTopoChangeNotify][网关设备({}) 不存在,无法发送拓扑变更通知]", gatewayId); | ||
| 864 | + return; | ||
| 865 | + } | ||
| 866 | + | ||
| 867 | + try { | ||
| 868 | + // 2.1 构建拓扑变更通知消息 | ||
| 869 | + List<IotDeviceIdentity> subList = convertList(subDevices, subDevice -> | ||
| 870 | + new IotDeviceIdentity(subDevice.getProductKey(), subDevice.getDeviceName())); | ||
| 871 | + IotDeviceTopoChangeReqDTO params = new IotDeviceTopoChangeReqDTO(status, subList); | ||
| 872 | + IotDeviceMessage notifyMessage = IotDeviceMessage.requestOf( | ||
| 873 | + IotDeviceMessageMethodEnum.TOPO_CHANGE.getMethod(), params); | ||
| 874 | + | ||
| 875 | + // 2.2 发送消息 | ||
| 876 | + deviceMessageService.sendDeviceMessage(notifyMessage, gatewayDevice); | ||
| 877 | + log.info("[sendTopoChangeNotify][网关({}/{}) 发送拓扑变更通知成功,status={}, subDevices={}]", | ||
| 878 | + gatewayDevice.getProductKey(), gatewayDevice.getDeviceName(), | ||
| 879 | + status, subList); | ||
| 880 | + } catch (Exception ex) { | ||
| 881 | + log.error("[sendTopoChangeNotify][网关({}/{}) 发送拓扑变更通知失败,status={}]", | ||
| 882 | + gatewayDevice.getProductKey(), gatewayDevice.getDeviceName(), status, ex); | ||
| 883 | + } | ||
| 884 | + } | ||
| 885 | + | ||
| 843 | } | 886 | } |