Commit 0bb01eaeeb1c7431b981f14484a79c95ed69ae7c

Authored by YunaiV
1 parent ac624b74

feat:【IoT 物联网】消息下行时,增加 serverId 的接入

Showing 51 changed files with 624 additions and 822 deletions
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/IotDeviceUpstreamApi.java
@@ -18,59 +18,6 @@ public interface IotDeviceUpstreamApi { @@ -18,59 +18,6 @@ public interface IotDeviceUpstreamApi {
18 18
19 String PREFIX = ApiConstants.PREFIX + "/device/upstream"; 19 String PREFIX = ApiConstants.PREFIX + "/device/upstream";
20 20
21 - // ========== 设备相关 ==========  
22 -  
23 - /**  
24 - * 更新设备状态  
25 - *  
26 - * @param updateReqDTO 更新设备状态 DTO  
27 - */  
28 - @PostMapping(PREFIX + "/update-state")  
29 - CommonResult<Boolean> updateDeviceState(@Valid @RequestBody IotDeviceStateUpdateReqDTO updateReqDTO);  
30 -  
31 - /**  
32 - * 上报设备属性数据  
33 - *  
34 - * @param reportReqDTO 上报设备属性数据 DTO  
35 - */  
36 - @PostMapping(PREFIX + "/report-property")  
37 - CommonResult<Boolean> reportDeviceProperty(@Valid @RequestBody IotDevicePropertyReportReqDTO reportReqDTO);  
38 -  
39 - /**  
40 - * 上报设备事件数据  
41 - *  
42 - * @param reportReqDTO 设备事件  
43 - */  
44 - @PostMapping(PREFIX + "/report-event")  
45 - CommonResult<Boolean> reportDeviceEvent(@Valid @RequestBody IotDeviceEventReportReqDTO reportReqDTO);  
46 -  
47 - // TODO @芋艿:这个需要 plugins 接入下  
48 - /**  
49 - * 注册设备  
50 - *  
51 - * @param registerReqDTO 注册设备 DTO  
52 - */  
53 - @PostMapping(PREFIX + "/register")  
54 - CommonResult<Boolean> registerDevice(@Valid @RequestBody IotDeviceRegisterReqDTO registerReqDTO);  
55 -  
56 - // TODO @芋艿:这个需要 plugins 接入下  
57 - /**  
58 - * 注册子设备  
59 - *  
60 - * @param registerReqDTO 注册子设备 DTO  
61 - */  
62 - @PostMapping(PREFIX + "/register-sub")  
63 - CommonResult<Boolean> registerSubDevice(@Valid @RequestBody IotDeviceRegisterSubReqDTO registerReqDTO);  
64 -  
65 - // TODO @芋艿:这个需要 plugins 接入下  
66 - /**  
67 - * 注册设备拓扑  
68 - *  
69 - * @param addReqDTO 注册设备拓扑 DTO  
70 - */  
71 - @PostMapping(PREFIX + "/add-topology")  
72 - CommonResult<Boolean> addDeviceTopology(@Valid @RequestBody IotDeviceTopologyAddReqDTO addReqDTO);  
73 -  
74 // TODO @芋艿:考虑 http 认证 21 // TODO @芋艿:考虑 http 认证
75 /** 22 /**
76 * 认证 Emqx 连接 23 * 认证 Emqx 连接
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceStateUpdateReqDTO.java deleted
1 -package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;  
2 -  
3 -import cn.iocoder.yudao.framework.common.validation.InEnum;  
4 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;  
5 -import jakarta.validation.constraints.NotNull;  
6 -import lombok.Data;  
7 -  
8 -/**  
9 - * IoT 设备【状态】更新 Request DTO  
10 - *  
11 - * @author 芋道源码  
12 - */  
13 -@Data  
14 -public class IotDeviceStateUpdateReqDTO extends IotDeviceUpstreamAbstractReqDTO {  
15 -  
16 - /**  
17 - * 设备状态  
18 - */  
19 - @NotNull(message = "设备状态不能为空")  
20 - @InEnum(IotDeviceStateEnum.class) // 只使用:在线、离线  
21 - private Integer state;  
22 -  
23 -}  
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
@@ -30,7 +30,7 @@ public interface ErrorCodeConstants { @@ -30,7 +30,7 @@ public interface ErrorCodeConstants {
30 ErrorCode DEVICE_GATEWAY_NOT_EXISTS = new ErrorCode(1_050_003_004, "网关设备不存在"); 30 ErrorCode DEVICE_GATEWAY_NOT_EXISTS = new ErrorCode(1_050_003_004, "网关设备不存在");
31 ErrorCode DEVICE_NOT_GATEWAY = new ErrorCode(1_050_003_005, "设备不是网关设备"); 31 ErrorCode DEVICE_NOT_GATEWAY = new ErrorCode(1_050_003_005, "设备不是网关设备");
32 ErrorCode DEVICE_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_050_003_006, "导入设备数据不能为空!"); 32 ErrorCode DEVICE_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_050_003_006, "导入设备数据不能为空!");
33 - ErrorCode DEVICE_DOWNSTREAM_FAILED = new ErrorCode(1_050_003_007, "执行失败,原因:{}"); 33 + ErrorCode DEVICE_DOWNSTREAM_FAILED_SERVER_ID_NULL = new ErrorCode(1_050_003_007, "下行设备消息失败,原因:设备未连接网关");
34 34
35 // ========== 产品分类 1-050-004-000 ========== 35 // ========== 产品分类 1-050-004-000 ==========
36 ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_004_000, "产品分类不存在"); 36 ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_004_000, "产品分类不存在");
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/IoTDeviceUpstreamApiImpl.java
@@ -21,44 +21,6 @@ public class IoTDeviceUpstreamApiImpl implements IotDeviceUpstreamApi { @@ -21,44 +21,6 @@ public class IoTDeviceUpstreamApiImpl implements IotDeviceUpstreamApi {
21 @Resource 21 @Resource
22 private IotDeviceUpstreamService deviceUpstreamService; 22 private IotDeviceUpstreamService deviceUpstreamService;
23 23
24 - // ========== 设备相关 ==========  
25 -  
26 - @Override  
27 - public CommonResult<Boolean> updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {  
28 - deviceUpstreamService.updateDeviceState(updateReqDTO);  
29 - return success(true);  
30 - }  
31 -  
32 - @Override  
33 - public CommonResult<Boolean> reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) {  
34 - deviceUpstreamService.reportDeviceProperty(reportReqDTO);  
35 - return success(true);  
36 - }  
37 -  
38 - @Override  
39 - public CommonResult<Boolean> reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) {  
40 - deviceUpstreamService.reportDeviceEvent(reportReqDTO);  
41 - return success(true);  
42 - }  
43 -  
44 - @Override  
45 - public CommonResult<Boolean> registerDevice(IotDeviceRegisterReqDTO registerReqDTO) {  
46 - deviceUpstreamService.registerDevice(registerReqDTO);  
47 - return success(true);  
48 - }  
49 -  
50 - @Override  
51 - public CommonResult<Boolean> registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO) {  
52 - deviceUpstreamService.registerSubDevice(registerReqDTO);  
53 - return success(true);  
54 - }  
55 -  
56 - @Override  
57 - public CommonResult<Boolean> addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO) {  
58 - deviceUpstreamService.addDeviceTopology(addReqDTO);  
59 - return success(true);  
60 - }  
61 -  
62 @Override 24 @Override
63 public CommonResult<Boolean> authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) { 25 public CommonResult<Boolean> authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) {
64 boolean result = deviceUpstreamService.authenticateEmqxConnection(authReqDTO); 26 boolean result = deviceUpstreamService.authenticateEmqxConnection(authReqDTO);
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDevicePageReqVO.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageParam; 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; 5 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
6 import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; 6 import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum;
7 import io.swagger.v3.oas.annotations.media.Schema; 7 import io.swagger.v3.oas.annotations.media.Schema;
8 import lombok.Data; 8 import lombok.Data;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/IotStatisticsController.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryRespVO; 4 import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryRespVO;
5 import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsReqVO; 5 import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsReqVO;
6 import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsSummaryRespVO; 6 import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsSummaryRespVO;
7 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; 7 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
8 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 8 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
9 import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService; 9 import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService;
10 import cn.iocoder.yudao.module.iot.service.product.IotProductCategoryService; 10 import cn.iocoder.yudao.module.iot.service.product.IotProductCategoryService;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDO.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.mybatis.core.type.LongSetTypeHandler; @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.mybatis.core.type.LongSetTypeHandler;
4 import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; 4 import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
5 import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaFirmwareDO; 5 import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
6 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
7 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; 7 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
8 import com.baomidou.mybatisplus.annotation.KeySequence; 8 import com.baomidou.mybatisplus.annotation.KeySequence;
9 import com.baomidou.mybatisplus.annotation.TableField; 9 import com.baomidou.mybatisplus.annotation.TableField;
10 import com.baomidou.mybatisplus.annotation.TableId; 10 import com.baomidou.mybatisplus.annotation.TableId;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotAlertRecordDO.java
1 package cn.iocoder.yudao.module.iot.dal.dataobject.rule; 1 package cn.iocoder.yudao.module.iot.dal.dataobject.rule;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 5 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
5 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
6 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
7 import com.baomidou.mybatisplus.annotation.KeySequence; 7 import com.baomidou.mybatisplus.annotation.KeySequence;
8 import com.baomidou.mybatisplus.annotation.TableField; 8 import com.baomidou.mybatisplus.annotation.TableField;
9 import com.baomidou.mybatisplus.annotation.TableName; 9 import com.baomidou.mybatisplus.annotation.TableName;
10 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; 10 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
11 -import lombok.*; 11 +import lombok.AllArgsConstructor;
  12 +import lombok.Builder;
  13 +import lombok.Data;
  14 +import lombok.NoArgsConstructor;
12 15
13 /** 16 /**
14 * IoT 告警记录 DO 17 * IoT 告警记录 DO
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java
@@ -145,7 +145,7 @@ public class IotRuleSceneDO extends TenantBaseDO { @@ -145,7 +145,7 @@ public class IotRuleSceneDO extends TenantBaseDO {
145 public static class TriggerConditionParameter { 145 public static class TriggerConditionParameter {
146 146
147 // TODO @芋艿: identifier0 存事件和服务的 identifier 属性的情况 identifier0 就为 null 解决前端回显问题 147 // TODO @芋艿: identifier0 存事件和服务的 identifier 属性的情况 identifier0 就为 null 解决前端回显问题
148 - // TODO @haohao:可以根据 TriggerCondition.type 判断,是服务、还是事件、还是属性么? 148 + // TODO @puhui999:可以根据 TriggerCondition.type 判断,是服务、还是事件、还是属性么?
149 /** 149 /**
150 * 标识符(事件、服务) 150 * 标识符(事件、服务)
151 * 151 *
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java
@@ -19,11 +19,10 @@ public interface RedisKeyConstants { @@ -19,11 +19,10 @@ public interface RedisKeyConstants {
19 */ 19 */
20 String DEVICE_PROPERTY = "iot:device_property:%s"; 20 String DEVICE_PROPERTY = "iot:device_property:%s";
21 21
22 - // TODO @芋艿:弱化 deviceKey;使用 product_key + device_name 替代  
23 /** 22 /**
24 * 设备的最后上报时间,采用 ZSET 结构 23 * 设备的最后上报时间,采用 ZSET 结构
25 * 24 *
26 - * KEY 格式:{deviceKey} 25 + * KEY 格式:{productKey},${deviceName}
27 * SCORE:上报时间 26 * SCORE:上报时间
28 */ 27 */
29 String DEVICE_REPORT_TIMES = "iot:device_report_times"; 28 String DEVICE_REPORT_TIMES = "iot:device_report_times";
@@ -44,4 +43,13 @@ public interface RedisKeyConstants { @@ -44,4 +43,13 @@ public interface RedisKeyConstants {
44 */ 43 */
45 String THING_MODEL_LIST = "iot:thing_model_list"; 44 String THING_MODEL_LIST = "iot:thing_model_list";
46 45
  46 + /**
  47 + * 设备关联的网关 serverId 缓存,采用 HASH 结构
  48 + *
  49 + * KEY 格式:device_server_id
  50 + * HASH KEY:{productKey},{deviceName}
  51 + * VALUE 数据类型:String serverId
  52 + */
  53 + String DEVICE_SERVER_ID = "iot:device_server_id";
  54 +
47 } 55 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/device/DeviceReportTimeRedisDAO.java
1 package cn.iocoder.yudao.module.iot.dal.redis.device; 1 package cn.iocoder.yudao.module.iot.dal.redis.device;
2 2
3 import cn.hutool.core.date.LocalDateTimeUtil; 3 import cn.hutool.core.date.LocalDateTimeUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4 import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; 6 import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants;
5 import jakarta.annotation.Resource; 7 import jakarta.annotation.Resource;
6 import org.springframework.data.redis.core.StringRedisTemplate; 8 import org.springframework.data.redis.core.StringRedisTemplate;
@@ -20,14 +22,17 @@ public class DeviceReportTimeRedisDAO { @@ -20,14 +22,17 @@ public class DeviceReportTimeRedisDAO {
20 @Resource 22 @Resource
21 private StringRedisTemplate stringRedisTemplate; 23 private StringRedisTemplate stringRedisTemplate;
22 24
23 - public void update(String deviceKey, LocalDateTime reportTime) {  
24 - stringRedisTemplate.opsForZSet().add(RedisKeyConstants.DEVICE_REPORT_TIMES, deviceKey, 25 + public void update(String productKey, String deviceName, LocalDateTime reportTime) {
  26 + String value = productKey + StrUtil.COMMA + deviceName; // 使用 , 分隔
  27 + stringRedisTemplate.opsForZSet().add(RedisKeyConstants.DEVICE_REPORT_TIMES, value,
25 LocalDateTimeUtil.toEpochMilli(reportTime)); 28 LocalDateTimeUtil.toEpochMilli(reportTime));
26 } 29 }
27 30
28 - public Set<String> range(LocalDateTime maxReportTime) {  
29 - return stringRedisTemplate.opsForZSet().rangeByScore(RedisKeyConstants.DEVICE_REPORT_TIMES, 0, 31 + public Set<String[]> range(LocalDateTime maxReportTime) {
  32 + Set<String> values = stringRedisTemplate.opsForZSet().rangeByScore(RedisKeyConstants.DEVICE_REPORT_TIMES, 0,
30 LocalDateTimeUtil.toEpochMilli(maxReportTime)); 33 LocalDateTimeUtil.toEpochMilli(maxReportTime));
  34 + return CollectionUtils.convertSet(values,
  35 + value -> value.split(StrUtil.COMMA)); // 使用, 分隔
31 } 36 }
32 37
33 } 38 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/device/DeviceServerIdRedisDAO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.dal.redis.device;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants;
  5 +import jakarta.annotation.Resource;
  6 +import org.springframework.data.redis.core.StringRedisTemplate;
  7 +import org.springframework.stereotype.Repository;
  8 +
  9 +/**
  10 + * 设备关联的网关 serverId 的 Redis DAO
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Repository
  15 +public class DeviceServerIdRedisDAO {
  16 +
  17 + @Resource
  18 + private StringRedisTemplate stringRedisTemplate;
  19 +
  20 + /**
  21 + * 更新设备关联的网关 serverId
  22 + *
  23 + * @param productKey 产品标识
  24 + * @param deviceName 设备名称
  25 + * @param serverId 网关 serverId
  26 + */
  27 + public void update(String productKey, String deviceName, String serverId) {
  28 + String hashKey = buildHashKey(productKey, deviceName);
  29 + stringRedisTemplate.opsForHash().put(RedisKeyConstants.DEVICE_SERVER_ID, hashKey, serverId);
  30 + }
  31 +
  32 + /**
  33 + * 获得设备关联的网关 serverId
  34 + *
  35 + * @param productKey 产品标识
  36 + * @param deviceName 设备名称
  37 + * @return 网关 serverId
  38 + */
  39 + public String get(String productKey, String deviceName) {
  40 + String hashKey = buildHashKey(productKey, deviceName);
  41 + Object value = stringRedisTemplate.opsForHash().get(RedisKeyConstants.DEVICE_SERVER_ID, hashKey);
  42 + return value != null ? (String) value : null;
  43 + }
  44 +
  45 + /**
  46 + * 删除设备关联的网关 serverId
  47 + *
  48 + * @param productKey 产品标识
  49 + * @param deviceName 设备名称
  50 + */
  51 + public void delete(String productKey, String deviceName) {
  52 + String hashKey = buildHashKey(productKey, deviceName);
  53 + stringRedisTemplate.opsForHash().delete(RedisKeyConstants.DEVICE_SERVER_ID, hashKey);
  54 + }
  55 +
  56 + /**
  57 + * 构建 HASH KEY
  58 + *
  59 + * @param productKey 产品标识
  60 + * @param deviceName 设备名称
  61 + * @return HASH KEY
  62 + */
  63 + private String buildHashKey(String productKey, String deviceName) {
  64 + return productKey + StrUtil.COMMA + deviceName;
  65 + }
  66 +
  67 +}
0 \ No newline at end of file 68 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/job/device/IotDeviceOfflineCheckJob.java
1 package cn.iocoder.yudao.module.iot.job.device; 1 package cn.iocoder.yudao.module.iot.job.device;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.util.IdUtil; 4 +import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; 6 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
7 import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; 7 import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
8 -import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO; 8 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
  9 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  10 +import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
9 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 11 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
10 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;  
11 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 12 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
12 import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService; 13 import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
13 -import cn.iocoder.yudao.module.iot.service.device.control.IotDeviceUpstreamService;  
14 import jakarta.annotation.Resource; 14 import jakarta.annotation.Resource;
15 import org.springframework.stereotype.Component; 15 import org.springframework.stereotype.Component;
16 16
@@ -20,10 +20,12 @@ import java.util.Collections; @@ -20,10 +20,12 @@ import java.util.Collections;
20 import java.util.List; 20 import java.util.List;
21 import java.util.Set; 21 import java.util.Set;
22 22
  23 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  24 +
23 /** 25 /**
24 * IoT 设备离线检查 Job 26 * IoT 设备离线检查 Job
25 * 27 *
26 - * 检测逻辑:设备最后一条 {@link cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage} 消息超过一定时间,则认为设备离线 28 + * 检测逻辑:设备最后一条 {@link IotDeviceMessage} 消息超过一定时间,则认为设备离线
27 * 29 *
28 * @author 芋道源码 30 * @author 芋道源码
29 */ 31 */
@@ -41,8 +43,9 @@ public class IotDeviceOfflineCheckJob implements JobHandler { @@ -41,8 +43,9 @@ public class IotDeviceOfflineCheckJob implements JobHandler {
41 private IotDeviceService deviceService; 43 private IotDeviceService deviceService;
42 @Resource 44 @Resource
43 private IotDevicePropertyService devicePropertyService; 45 private IotDevicePropertyService devicePropertyService;
  46 +
44 @Resource 47 @Resource
45 - private IotDeviceUpstreamService deviceUpstreamService; 48 + private IotDeviceMessageProducer deviceMessageProducer;
46 49
47 @Override 50 @Override
48 @TenantJob 51 @TenantJob
@@ -52,22 +55,22 @@ public class IotDeviceOfflineCheckJob implements JobHandler { @@ -52,22 +55,22 @@ public class IotDeviceOfflineCheckJob implements JobHandler {
52 if (CollUtil.isEmpty(devices)) { 55 if (CollUtil.isEmpty(devices)) {
53 return JsonUtils.toJsonString(Collections.emptyList()); 56 return JsonUtils.toJsonString(Collections.emptyList());
54 } 57 }
55 - // 1.2 获取超时的 deviceKey 集合  
56 - Set<String> timeoutDeviceKeys = devicePropertyService.getDeviceKeysByReportTime( 58 + // 1.2 获取超时的设备集合
  59 + Set<String[]> timeoutDevices = devicePropertyService.getProductKeyDeviceNameListByReportTime(
57 LocalDateTime.now().minus(OFFLINE_TIMEOUT)); 60 LocalDateTime.now().minus(OFFLINE_TIMEOUT));
  61 + Set<String> timeoutDevices2 = convertSet(timeoutDevices, item -> item[0] + StrUtil.COMMA + item[1]);
58 62
59 // 2. 下线设备 63 // 2. 下线设备
60 - List<String> offlineDeviceKeys = CollUtil.newArrayList(); 64 + List<String[]> offlineDeviceKeys = CollUtil.newArrayList();
61 for (IotDeviceDO device : devices) { 65 for (IotDeviceDO device : devices) {
62 - if (!timeoutDeviceKeys.contains(device.getDeviceKey())) { 66 + String timeoutDeviceKey = device.getProductKey() + StrUtil.COMMA + device.getDeviceName();
  67 + if (!timeoutDevices2.contains(timeoutDeviceKey)) {
63 continue; 68 continue;
64 } 69 }
65 - offlineDeviceKeys.add(device.getDeviceKey()); 70 + offlineDeviceKeys.add(new String[]{device.getProductKey(), device.getDeviceName()});
66 // 为什么不直接更新状态呢?因为通过 IotDeviceMessage 可以经过一系列的处理,例如说记录日志等等 71 // 为什么不直接更新状态呢?因为通过 IotDeviceMessage 可以经过一系列的处理,例如说记录日志等等
67 - deviceUpstreamService.updateDeviceState(((IotDeviceStateUpdateReqDTO)  
68 - new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()).setReportTime(LocalDateTime.now())  
69 - .setProductKey(device.getProductKey()).setDeviceName(device.getDeviceName()))  
70 - .setState((IotDeviceStateEnum.OFFLINE.getState()))); 72 + deviceMessageProducer.sendDeviceMessage(IotDeviceMessage.of(device.getProductKey(), device.getDeviceName())
  73 + .ofStateOffline());
71 } 74 }
72 return JsonUtils.toJsonString(offlineDeviceKeys); 75 return JsonUtils.toJsonString(offlineDeviceKeys);
73 } 76 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageSubscriber.java
@@ -10,7 +10,7 @@ import lombok.extern.slf4j.Slf4j; @@ -10,7 +10,7 @@ import lombok.extern.slf4j.Slf4j;
10 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
11 11
12 /** 12 /**
13 - * 针对 {@link IotDeviceMessage} 的消费者,记录设备日志 13 + * 针对 {@link IotDeviceMessage} 的消费者:记录设备日志
14 * 14 *
15 * @author 芋道源码 15 * @author 芋道源码
16 */ 16 */
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceOnlineMessageConsumer.java deleted
1 -package cn.iocoder.yudao.module.iot.mq.consumer.device;  
2 -  
3 -import cn.hutool.core.util.IdUtil;  
4 -import cn.hutool.core.util.StrUtil;  
5 -import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO;  
6 -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;  
7 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;  
8 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;  
9 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;  
10 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
11 -import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;  
12 -import cn.iocoder.yudao.module.iot.service.device.control.IotDeviceUpstreamService;  
13 -import jakarta.annotation.Resource;  
14 -import lombok.extern.slf4j.Slf4j;  
15 -import org.springframework.context.event.EventListener;  
16 -import org.springframework.scheduling.annotation.Async;  
17 -import org.springframework.stereotype.Component;  
18 -  
19 -import java.time.LocalDateTime;  
20 -import java.util.Objects;  
21 -  
22 -/**  
23 - * 针对 {@link IotDeviceMessage} 的消费者,将离线的设备,自动标记为上线  
24 - *  
25 - * 注意:只有设备上行消息,才会触发该逻辑  
26 - *  
27 - * @author 芋道源码  
28 - */  
29 -@Component  
30 -@Slf4j  
31 -public class IotDeviceOnlineMessageConsumer {  
32 -  
33 - @Resource  
34 - private IotDeviceService deviceService;  
35 -  
36 - @Resource  
37 - private IotDeviceUpstreamService deviceUpstreamService;  
38 -  
39 - @EventListener  
40 - @Async  
41 - public void onMessage(IotDeviceMessage message) {  
42 - // 1.1 只处理上行消息。因为,只有设备上行的消息,才会触发设备上线的逻辑  
43 - if (!isUpstreamMessage(message)) {  
44 - return;  
45 - }  
46 - // 1.2 如果设备已在线,则不做处理  
47 - log.info("[onMessage][消息内容({})]", message);  
48 - IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceNameFromCache(  
49 - message.getProductKey(), message.getDeviceName());  
50 - if (device == null) {  
51 - log.error("[onMessage][消息({}) 对应的设备部存在]", message);  
52 - return;  
53 - }  
54 - if (IotDeviceStateEnum.isOnline(device.getState())) {  
55 - return;  
56 - }  
57 -  
58 - // 2. 标记设备为在线  
59 - // 为什么不直接更新状态呢?因为通过 IotDeviceMessage 可以经过一系列的处理,例如说记录日志等等  
60 - deviceUpstreamService.updateDeviceState(((IotDeviceStateUpdateReqDTO)  
61 - new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()).setReportTime(LocalDateTime.now())  
62 - .setProductKey(device.getProductKey()).setDeviceName(device.getDeviceName()))  
63 - .setState((IotDeviceStateEnum.ONLINE.getState())));  
64 - }  
65 -  
66 - private boolean isUpstreamMessage(IotDeviceMessage message) {  
67 - // 设备属性  
68 - if (Objects.equals(message.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType())  
69 - && Objects.equals(message.getIdentifier(), IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier())) {  
70 - return true;  
71 - }  
72 - // 设备事件  
73 - if (Objects.equals(message.getType(), IotDeviceMessageTypeEnum.EVENT.getType())) {  
74 - return true;  
75 - }  
76 - // 设备服务  
77 - // noinspection RedundantIfStatement  
78 - if (Objects.equals(message.getType(), IotDeviceMessageTypeEnum.SERVICE.getType())  
79 - && !StrUtil.endWith(message.getIdentifier(), IotDeviceMessageIdentifierEnum.SERVICE_REPLY_SUFFIX.getIdentifier())) {  
80 - return true;  
81 - }  
82 - return false;  
83 - }  
84 -  
85 -}  
86 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDevicePropertyMessageConsumer.java
1 package cn.iocoder.yudao.module.iot.mq.consumer.device; 1 package cn.iocoder.yudao.module.iot.mq.consumer.device;
2 2
3 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
  4 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum; 5 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
5 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum; 6 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
6 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
7 import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService; 7 import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
8 import lombok.extern.slf4j.Slf4j; 8 import lombok.extern.slf4j.Slf4j;
9 import org.springframework.context.event.EventListener; 9 import org.springframework.context.event.EventListener;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceStateMessageSubscriber.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.mq.consumer.device;
  2 +
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
  5 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageIdentifierEnum;
  6 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageTypeEnum;
  7 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
  8 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
  9 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
  10 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  11 +import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
  12 +import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
  13 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
  14 +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
  15 +import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
  16 +import jakarta.annotation.PostConstruct;
  17 +import jakarta.annotation.Resource;
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.springframework.stereotype.Component;
  20 +
  21 +import java.time.LocalDateTime;
  22 +import java.util.Objects;
  23 +
  24 +/**
  25 + * 针对 {@link IotDeviceMessage} 的消费者:记录设备状态
  26 + *
  27 + * 特殊:如果是离线的设备,将自动上线
  28 + *
  29 + * @author 芋道源码
  30 + */
  31 +@Component
  32 +@Slf4j
  33 +public class IotDeviceStateMessageSubscriber implements IotMessageSubscriber<IotDeviceMessage> {
  34 +
  35 + @Resource
  36 + private IotDeviceService deviceService;
  37 + @Resource
  38 + private IotDevicePropertyService devicePropertyService;
  39 +
  40 + @Resource
  41 + private IotMessageBus messageBus;
  42 + @Resource
  43 + private IotDeviceMessageProducer deviceMessageProducer;
  44 +
  45 + @PostConstruct
  46 + public void init() {
  47 + messageBus.register(this);
  48 + }
  49 +
  50 + @Override
  51 + public String getTopic() {
  52 + return IotDeviceMessage.MESSAGE_BUS_DEVICE_MESSAGE_TOPIC;
  53 + }
  54 +
  55 + @Override
  56 + public String getGroup() {
  57 + return "iot_device_state_consumer";
  58 + }
  59 +
  60 + @Override
  61 + public void onMessage(IotDeviceMessage message) {
  62 + // 1.1 只处理上行消息,或者是 STATE 相关的消息
  63 + if (!IotDeviceMessageUtils.isUpstreamMessage(message)
  64 + && ObjectUtil.notEqual(message.getType(), IotDeviceMessageTypeEnum.STATE.getType())) {
  65 + return;
  66 + }
  67 + // 1.2 校验设备是否存在
  68 + IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceNameFromCache(
  69 + message.getProductKey(), message.getDeviceName());
  70 + if (device == null) {
  71 + log.error("[onMessage][消息({}) 对应的设备部存在]", message);
  72 + return;
  73 + }
  74 +
  75 + // 2. 处理消息
  76 + TenantUtils.execute(device.getTenantId(), () -> onMessage(message, device));
  77 + }
  78 +
  79 + private void onMessage(IotDeviceMessage message, IotDeviceDO device) {
  80 + // 更新设备的最后时间
  81 + devicePropertyService.updateDeviceReportTime(device.getProductKey(), device.getDeviceName(), LocalDateTime.now());
  82 +
  83 + // 情况一:STATE 相关的消息
  84 + if (Objects.equals(message.getType(), IotDeviceMessageTypeEnum.STATE.getType())) {
  85 + if (Objects.equals(message.getIdentifier(), IotDeviceMessageIdentifierEnum.STATE_ONLINE.getIdentifier())) {
  86 + deviceService.updateDeviceState(device.getId(), IotDeviceStateEnum.ONLINE.getState());
  87 + devicePropertyService.updateDeviceServerId(device.getProductKey(), device.getDeviceName(), message.getServerId());
  88 + } else {
  89 + deviceService.updateDeviceState(device.getId(), IotDeviceStateEnum.OFFLINE.getState());
  90 + devicePropertyService.deleteDeviceServerId(device.getProductKey(), device.getDeviceName());
  91 + }
  92 + // TODO 芋艿:子设备的关联
  93 + return;
  94 + }
  95 +
  96 + // 情况二:非 STATE 相关的消息
  97 + devicePropertyService.updateDeviceServerId(device.getProductKey(), device.getDeviceName(), message.getServerId());
  98 + // 特殊:设备非在线时,主动标记设备为在线
  99 + // 为什么不直接更新状态呢?因为通过 IotDeviceMessage 可以经过一系列的处理,例如说记录日志等等
  100 + if (ObjectUtil.notEqual(device.getState(), IotDeviceStateEnum.ONLINE.getState())) {
  101 + deviceMessageProducer.sendDeviceMessage(IotDeviceMessage.of(message.getProductKey(), message.getDeviceName())
  102 + .ofStateOnline());
  103 + }
  104 + }
  105 +
  106 +}
0 \ No newline at end of file 107 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/rule/IotRuleSceneMessageHandler.java
1 package cn.iocoder.yudao.module.iot.mq.consumer.rule; 1 package cn.iocoder.yudao.module.iot.mq.consumer.rule;
2 2
3 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 3 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 import cn.iocoder.yudao.module.iot.service.rule.IotRuleSceneService; 4 import cn.iocoder.yudao.module.iot.service.rule.IotRuleSceneService;
5 import jakarta.annotation.Resource; 5 import jakarta.annotation.Resource;
6 import lombok.extern.slf4j.Slf4j; 6 import lombok.extern.slf4j.Slf4j;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/message/IotDeviceMessage.java deleted
1 -package cn.iocoder.yudao.module.iot.mq.message;  
2 -  
3 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;  
4 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;  
5 -import lombok.AllArgsConstructor;  
6 -import lombok.Builder;  
7 -import lombok.Data;  
8 -import lombok.NoArgsConstructor;  
9 -  
10 -import java.time.LocalDateTime;  
11 -  
12 -// TODO @芋艿:参考阿里云的物模型,优化 IoT 上下行消息的设计,尽量保持一致(渐进式,不要一口气)!  
13 -/**  
14 - * IoT 设备消息  
15 - */  
16 -@Data  
17 -@NoArgsConstructor  
18 -@AllArgsConstructor  
19 -@Builder  
20 -@Deprecated  
21 -public class IotDeviceMessage {  
22 -  
23 - /**  
24 - * 请求编号  
25 - */  
26 - private String requestId;  
27 -  
28 - /**  
29 - * 设备信息  
30 - */  
31 - private String productKey;  
32 - /**  
33 - * 设备名称  
34 - */  
35 - private String deviceName;  
36 - /**  
37 - * 设备标识  
38 - */  
39 - private String deviceKey;  
40 -  
41 - /**  
42 - * 消息类型  
43 - *  
44 - * 枚举 {@link IotDeviceMessageTypeEnum}  
45 - */  
46 - private String type;  
47 - /**  
48 - * 标识符  
49 - *  
50 - * 枚举 {@link IotDeviceMessageIdentifierEnum}  
51 - */  
52 - private String identifier;  
53 -  
54 - /**  
55 - * 请求参数  
56 - *  
57 - * 例如说:属性上报的 properties、事件上报的 params  
58 - */  
59 - private Object data;  
60 - /**  
61 - * 响应码  
62 - *  
63 - * 目前只有 server 下行消息给 device 设备时,才会有响应码  
64 - */  
65 - private Integer code;  
66 -  
67 - /**  
68 - * 上报时间  
69 - */  
70 - private LocalDateTime reportTime;  
71 -  
72 - /**  
73 - * 租户编号  
74 - */  
75 - private Long tenantId;  
76 -  
77 -}  
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/producer/device/IotDeviceProducer.java deleted
1 -package cn.iocoder.yudao.module.iot.mq.producer.device;  
2 -  
3 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
4 -import jakarta.annotation.Resource;  
5 -import lombok.extern.slf4j.Slf4j;  
6 -import org.springframework.context.ApplicationContext;  
7 -import org.springframework.stereotype.Component;  
8 -  
9 -/**  
10 - * IoT 设备相关消息的 Producer  
11 - *  
12 - * @author alwayssuper  
13 - * @since 2024/12/17 16:35  
14 - */  
15 -@Slf4j  
16 -@Component  
17 -public class IotDeviceProducer {  
18 -  
19 - @Resource  
20 - private ApplicationContext applicationContext;  
21 -  
22 - /**  
23 - * 发送 {@link IotDeviceMessage} 消息  
24 - *  
25 - * @param thingModelMessage 物模型消息  
26 - */  
27 - public void sendDeviceMessage(IotDeviceMessage thingModelMessage) {  
28 - applicationContext.publishEvent(thingModelMessage);  
29 - }  
30 -  
31 -}  
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/producer/package-info.java
1 /** 1 /**
2 - * TODO 芋艿:临时占位 2 + * 消息队列的生产者
3 */ 3 */
4 -package cn.iocoder.yudao.module.iot.mq.producer;  
5 \ No newline at end of file 4 \ No newline at end of file
  5 +package cn.iocoder.yudao.module.iot.mq.producer;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.service.device; @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.service.device;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; 4 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*;
5 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 5 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
6 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; 6 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
7 import jakarta.validation.Valid; 7 import jakarta.validation.Valid;
8 import jakarta.validation.constraints.NotEmpty; 8 import jakarta.validation.constraints.NotEmpty;
9 9
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
@@ -17,7 +17,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO; @@ -17,7 +17,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO;
17 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 17 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
18 import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper; 18 import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper;
19 import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; 19 import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants;
20 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; 20 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
21 import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; 21 import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum;
22 import cn.iocoder.yudao.module.iot.service.product.IotProductService; 22 import cn.iocoder.yudao.module.iot.service.product.IotProductService;
23 import cn.iocoder.yudao.module.iot.util.MqttSignUtils; 23 import cn.iocoder.yudao.module.iot.util.MqttSignUtils;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamService.java
1 package cn.iocoder.yudao.module.iot.service.device.control; 1 package cn.iocoder.yudao.module.iot.service.device.control;
2 2
3 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO; 3 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
4 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 4 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
5 import jakarta.validation.Valid; 5 import jakarta.validation.Valid;
6 6
7 /** 7 /**
8 * IoT 设备下行 Service 接口 8 * IoT 设备下行 Service 接口
9 * 9 *
10 - * 目的:服务端 -> 插件 -> 设备 10 + * 目的:服务端 -> 网关 -> 设备
11 * 11 *
12 * @author 芋道源码 12 * @author 芋道源码
13 */ 13 */
@@ -17,7 +17,7 @@ public interface IotDeviceDownstreamService { @@ -17,7 +17,7 @@ public interface IotDeviceDownstreamService {
17 * 设备下行,可用于设备模拟 17 * 设备下行,可用于设备模拟
18 * 18 *
19 * @param downstreamReqVO 设备下行请求 VO 19 * @param downstreamReqVO 设备下行请求 VO
20 - * @return 下发消息 20 + * @return 下行消息
21 */ 21 */
22 IotDeviceMessage downstreamDevice(@Valid IotDeviceDownstreamReqVO downstreamReqVO); 22 IotDeviceMessage downstreamDevice(@Valid IotDeviceDownstreamReqVO downstreamReqVO);
23 23
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamServiceImpl.java
1 package cn.iocoder.yudao.module.iot.service.device.control; 1 package cn.iocoder.yudao.module.iot.service.device.control;
2 2
3 -import cn.hutool.core.lang.Assert; 3 +import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.framework.common.exception.ServiceException; 4 import cn.iocoder.yudao.framework.common.exception.ServiceException;
5 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
6 -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;  
7 -import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceConfigSetReqDTO;  
8 -import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceOtaUpgradeReqDTO;  
9 -import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;  
10 -import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;  
11 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO; 5 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
  6 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
12 import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; 7 import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
13 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
14 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum; 9 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
15 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum; 10 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
16 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
17 -import cn.iocoder.yudao.module.iot.mq.producer.device.IotDeviceProducer;  
18 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 11 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
  12 +import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
19 import jakarta.annotation.Resource; 13 import jakarta.annotation.Resource;
20 import lombok.extern.slf4j.Slf4j; 14 import lombok.extern.slf4j.Slf4j;
21 import org.springframework.stereotype.Service; 15 import org.springframework.stereotype.Service;
22 import org.springframework.validation.annotation.Validated; 16 import org.springframework.validation.annotation.Validated;
23 17
24 -import java.time.LocalDateTime;  
25 -import java.util.List;  
26 import java.util.Map; 18 import java.util.Map;
27 import java.util.Objects; 19 import java.util.Objects;
28 20
29 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; 21 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 22 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
31 -import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_DOWNSTREAM_FAILED; 23 +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_DOWNSTREAM_FAILED_SERVER_ID_NULL;
32 24
33 /** 25 /**
34 * IoT 设备下行 Service 实现类 26 * IoT 设备下行 Service 实现类
@@ -42,255 +34,234 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic @@ -42,255 +34,234 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
42 34
43 @Resource 35 @Resource
44 private IotDeviceService deviceService; 36 private IotDeviceService deviceService;
45 -  
46 @Resource 37 @Resource
47 - private IotDeviceProducer deviceProducer; 38 + private IotDevicePropertyService devicePropertyService;
  39 +
48 @Resource 40 @Resource
49 private IotDeviceMessageProducer deviceMessageProducer; 41 private IotDeviceMessageProducer deviceMessageProducer;
50 42
51 @Override 43 @Override
52 public IotDeviceMessage downstreamDevice(IotDeviceDownstreamReqVO downstreamReqVO) { 44 public IotDeviceMessage downstreamDevice(IotDeviceDownstreamReqVO downstreamReqVO) {
53 - // 校验设备是否存在 45 + // 1. 校验设备是否存在
54 IotDeviceDO device = deviceService.validateDeviceExists(downstreamReqVO.getId()); 46 IotDeviceDO device = deviceService.validateDeviceExists(downstreamReqVO.getId());
55 - // TODO @芋艿:离线设备,不允许推送  
56 // TODO 芋艿:父设备的处理 47 // TODO 芋艿:父设备的处理
57 IotDeviceDO parentDevice = null; 48 IotDeviceDO parentDevice = null;
58 49
  50 + // 2. 构建消息
  51 + IotDeviceMessage message = buildDownstreamDeviceMessage(downstreamReqVO, device, parentDevice);
  52 +
  53 + // 3.1 发送给网关
  54 + String serverId = devicePropertyService.getDeviceServerId(message.getProductKey(), message.getDeviceName());
  55 + if (StrUtil.isEmpty(serverId)) {
  56 + throw exception(DEVICE_DOWNSTREAM_FAILED_SERVER_ID_NULL);
  57 + }
  58 + deviceMessageProducer.sendGatewayDeviceMessage(serverId, message);
  59 +
  60 + // 3.2 发送给服务器(用于设备日志等的记录)
  61 + deviceMessageProducer.sendDeviceMessage(message);
  62 + return message;
  63 + }
  64 +
  65 + @SuppressWarnings("unchecked")
  66 + private IotDeviceMessage buildDownstreamDeviceMessage(IotDeviceDownstreamReqVO downstreamReqVO,
  67 + IotDeviceDO device, IotDeviceDO parentDevice) {
  68 + IotDeviceMessage message = IotDeviceMessage.of(getProductKey(device, parentDevice),
  69 + getDeviceName(device, parentDevice));
59 // 服务调用 70 // 服务调用
60 if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.SERVICE.getType())) { 71 if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.SERVICE.getType())) {
61 - return invokeDeviceService(downstreamReqVO, device, parentDevice); 72 + // TODO @芋艿:待实现
  73 +// return invokeDeviceService(downstreamReqVO, device, parentDevice);
62 } 74 }
63 // 属性相关 75 // 属性相关
64 if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType())) { 76 if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType())) {
65 // 属性设置 77 // 属性设置
66 if (Objects.equals(downstreamReqVO.getIdentifier(), 78 if (Objects.equals(downstreamReqVO.getIdentifier(),
67 IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier())) { 79 IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier())) {
68 - return setDeviceProperty(downstreamReqVO, device, parentDevice); 80 + if (!(downstreamReqVO.getData() instanceof Map<?, ?>)) {
  81 + throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 Map 类型");
  82 + }
  83 + return message.ofPropertySet((Map<String, Object>) downstreamReqVO.getData());
69 } 84 }
70 - // 属性设置 85 + // 属性获取
71 if (Objects.equals(downstreamReqVO.getIdentifier(), 86 if (Objects.equals(downstreamReqVO.getIdentifier(),
72 IotDeviceMessageIdentifierEnum.PROPERTY_GET.getIdentifier())) { 87 IotDeviceMessageIdentifierEnum.PROPERTY_GET.getIdentifier())) {
73 - return getDeviceProperty(downstreamReqVO, device, parentDevice); 88 + // TODO @芋艿:待实现
  89 +// return getDeviceProperty(downstreamReqVO, device, parentDevice);
74 } 90 }
75 } 91 }
76 // 配置下发 92 // 配置下发
77 if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.CONFIG.getType()) 93 if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.CONFIG.getType())
78 && Objects.equals(downstreamReqVO.getIdentifier(), 94 && Objects.equals(downstreamReqVO.getIdentifier(),
79 - IotDeviceMessageIdentifierEnum.CONFIG_SET.getIdentifier())) {  
80 - return setDeviceConfig(downstreamReqVO, device, parentDevice); 95 + IotDeviceMessageIdentifierEnum.CONFIG_SET.getIdentifier())) {
  96 + // TODO @芋艿:待实现
  97 +// return setDeviceConfig(downstreamReqVO, device, parentDevice);
81 } 98 }
82 // OTA 升级 99 // OTA 升级
83 if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.OTA.getType())) { 100 if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.OTA.getType())) {
84 - return otaUpgrade(downstreamReqVO, device, parentDevice); 101 + // TODO @芋艿:待实现
  102 +// return otaUpgrade(downstreamReqVO, device, parentDevice);
85 } 103 }
86 // TODO @芋艿:取消设备的网关的时,要不要下发 REGISTER_UNREGISTER_SUB ? 104 // TODO @芋艿:取消设备的网关的时,要不要下发 REGISTER_UNREGISTER_SUB ?
87 throw new IllegalArgumentException("不支持的下行消息类型:" + downstreamReqVO); 105 throw new IllegalArgumentException("不支持的下行消息类型:" + downstreamReqVO);
88 } 106 }
89 107
90 - /**  
91 - * 调用设备服务  
92 - *  
93 - * @param downstreamReqVO 下行请求  
94 - * @param device 设备  
95 - * @param parentDevice 父设备  
96 - * @return 下发消息  
97 - */  
98 - @SuppressWarnings("unchecked")  
99 - private IotDeviceMessage invokeDeviceService(IotDeviceDownstreamReqVO downstreamReqVO,  
100 - IotDeviceDO device, IotDeviceDO parentDevice) {  
101 - // 1. 参数校验  
102 - if (!(downstreamReqVO.getData() instanceof Map<?, ?>)) {  
103 - throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 Map 类型");  
104 - }  
105 - // TODO @super:【可优化】过滤掉不合法的服务 108 +// /**
  109 +// * 调用设备服务
  110 +// *
  111 +// * @param downstreamReqVO 下行请求
  112 +// * @param device 设备
  113 +// * @param parentDevice 父设备
  114 +// * @return 下发消息
  115 +// */
  116 +// @SuppressWarnings("unchecked")
  117 +// private IotDeviceMessage invokeDeviceService(IotDeviceDownstreamReqVO downstreamReqVO,
  118 +// IotDeviceDO device, IotDeviceDO parentDevice) {
  119 +// // 1. 参数校验
  120 +// if (!(downstreamReqVO.getData() instanceof Map<?, ?>)) {
  121 +// throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 Map 类型");
  122 +// }
  123 +// // TODO @super:【可优化】过滤掉不合法的服务
  124 +//
  125 +// // 2. 发送请求
  126 +// String url = String.format("sys/%s/%s/thing/service/%s",
  127 +// getProductKey(device, parentDevice), getDeviceName(device, parentDevice),
  128 +// downstreamReqVO.getIdentifier());
  129 +// IotDeviceServiceInvokeReqDTO reqDTO = new IotDeviceServiceInvokeReqDTO()
  130 +// .setParams((Map<String, Object>) downstreamReqVO.getData());
  131 +//// CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);
  132 +// CommonResult<Boolean> result = null;
  133 +//
  134 +// // 3. 发送设备消息
  135 +// IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())
  136 +// .setType(IotDeviceMessageTypeEnum.SERVICE.getType()).setIdentifier(reqDTO.getIdentifier())
  137 +// .setData(reqDTO.getParams());
  138 +// sendDeviceMessage(message, device, result.getCode());
  139 +//
  140 +// // 4. 如果不成功,抛出异常,提示用户
  141 +// if (result.isError()) {
  142 +// log.error("[invokeDeviceService][设备({})服务调用失败,请求参数:({}),响应结果:({})]",
  143 +// device.getDeviceKey(), reqDTO, result);
  144 +// throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());
  145 +// }
  146 +// return message;
  147 +// }
106 148
107 - // 2. 发送请求  
108 - String url = String.format("sys/%s/%s/thing/service/%s",  
109 - getProductKey(device, parentDevice), getDeviceName(device, parentDevice),  
110 - downstreamReqVO.getIdentifier());  
111 - IotDeviceServiceInvokeReqDTO reqDTO = new IotDeviceServiceInvokeReqDTO()  
112 - .setParams((Map<String, Object>) downstreamReqVO.getData());  
113 -// CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);  
114 - CommonResult<Boolean> result = null; 149 +// /**
  150 +// * 获取设备属性
  151 +// *
  152 +// * @param downstreamReqVO 下行请求
  153 +// * @param device 设备
  154 +// * @param parentDevice 父设备
  155 +// * @return 下发消息
  156 +// */
  157 +// @SuppressWarnings("unchecked")
  158 +// private IotDeviceMessage getDeviceProperty(IotDeviceDownstreamReqVO downstreamReqVO,
  159 +// IotDeviceDO device, IotDeviceDO parentDevice) {
  160 +// // 1. 参数校验
  161 +// if (!(downstreamReqVO.getData() instanceof List<?>)) {
  162 +// throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 List 类型");
  163 +// }
  164 +// // TODO @super:【可优化】过滤掉不合法的属性
  165 +//
  166 +// // 2. 发送请求
  167 +// String url = String.format("sys/%s/%s/thing/service/property/get",
  168 +// getProductKey(device, parentDevice), getDeviceName(device, parentDevice));
  169 +// IotDevicePropertyGetReqDTO reqDTO = new IotDevicePropertyGetReqDTO()
  170 +// .setIdentifiers((List<String>) downstreamReqVO.getData());
  171 +//// CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);
  172 +// CommonResult<Boolean> result = null;
  173 +//
  174 +// // 3. 发送设备消息
  175 +// IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())
  176 +// .setType(IotDeviceMessageTypeEnum.PROPERTY.getType())
  177 +// .setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier())
  178 +// .setData(reqDTO.getIdentifiers());
  179 +// sendDeviceMessage(message, device, result.getCode());
  180 +//
  181 +// // 4. 如果不成功,抛出异常,提示用户
  182 +// if (result.isError()) {
  183 +// log.error("[getDeviceProperty][设备({})属性获取失败,请求参数:({}),响应结果:({})]",
  184 +// device.getDeviceKey(), reqDTO, result);
  185 +// throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());
  186 +// }
  187 +// return message;
  188 +// }
115 189
116 - // 3. 发送设备消息  
117 - IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())  
118 - .setType(IotDeviceMessageTypeEnum.SERVICE.getType()).setIdentifier(reqDTO.getIdentifier())  
119 - .setData(reqDTO.getParams());  
120 - sendDeviceMessage(message, device, result.getCode()); 190 +// /**
  191 +// * 设置设备配置
  192 +// *
  193 +// * @param downstreamReqVO 下行请求
  194 +// * @param device 设备
  195 +// * @param parentDevice 父设备
  196 +// * @return 下发消息
  197 +// */
  198 +// @SuppressWarnings({ "unchecked", "unused" })
  199 +// private IotDeviceMessage setDeviceConfig(IotDeviceDownstreamReqVO downstreamReqVO,
  200 +// IotDeviceDO device, IotDeviceDO parentDevice) {
  201 +// // 1. 参数转换,无需校验
  202 +// Map<String, Object> config = JsonUtils.parseObject(device.getConfig(), Map.class);
  203 +//
  204 +// // 2. 发送请求
  205 +// String url = String.format("sys/%s/%s/thing/service/config/set",
  206 +// getProductKey(device, parentDevice), getDeviceName(device, parentDevice));
  207 +// IotDeviceConfigSetReqDTO reqDTO = new IotDeviceConfigSetReqDTO()
  208 +// .setConfig(config);
  209 +//// CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);
  210 +// CommonResult<Boolean> result = null;
  211 +//
  212 +// // 3. 发送设备消息
  213 +// IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())
  214 +// .setType(IotDeviceMessageTypeEnum.CONFIG.getType())
  215 +// .setIdentifier(IotDeviceMessageIdentifierEnum.CONFIG_SET.getIdentifier())
  216 +// .setData(reqDTO.getConfig());
  217 +// sendDeviceMessage(message, device, result.getCode());
  218 +//
  219 +// // 4. 如果不成功,抛出异常,提示用户
  220 +// if (result.isError()) {
  221 +// log.error("[setDeviceConfig][设备({})配置下发失败,请求参数:({}),响应结果:({})]",
  222 +// device.getDeviceKey(), reqDTO, result);
  223 +// throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());
  224 +// }
  225 +// return message;
  226 +// }
121 227
122 - // 4. 如果不成功,抛出异常,提示用户  
123 - if (result.isError()) {  
124 - log.error("[invokeDeviceService][设备({})服务调用失败,请求参数:({}),响应结果:({})]",  
125 - device.getDeviceKey(), reqDTO, result);  
126 - throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());  
127 - }  
128 - return message;  
129 - }  
130 -  
131 - /**  
132 - * 设置设备属性  
133 - *  
134 - * @param downstreamReqVO 下行请求  
135 - * @param device 设备  
136 - * @param parentDevice 父设备  
137 - * @return 下发消息  
138 - */  
139 - @SuppressWarnings("unchecked")  
140 - private IotDeviceMessage setDeviceProperty(IotDeviceDownstreamReqVO downstreamReqVO,  
141 - IotDeviceDO device, IotDeviceDO parentDevice) {  
142 - // 1. 参数校验  
143 - if (!(downstreamReqVO.getData() instanceof Map<?, ?>)) {  
144 - throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 Map 类型");  
145 - }  
146 - // TODO @super:【可优化】过滤掉不合法的属性  
147 -  
148 - // 2. 发送请求  
149 - cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage message = cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage  
150 - .of(getProductKey(device, parentDevice), getDeviceName(device, parentDevice));  
151 - String serverId = "192_168_64_1_8092";  
152 - deviceMessageProducer.sendGatewayDeviceMessage(serverId, message);  
153 - deviceMessageProducer.sendDeviceMessage(message);  
154 - // TODO @芋艿:后续可以清理掉  
155 - return null;  
156 - }  
157 -  
158 - /**  
159 - * 获取设备属性  
160 - *  
161 - * @param downstreamReqVO 下行请求  
162 - * @param device 设备  
163 - * @param parentDevice 父设备  
164 - * @return 下发消息  
165 - */  
166 - @SuppressWarnings("unchecked")  
167 - private IotDeviceMessage getDeviceProperty(IotDeviceDownstreamReqVO downstreamReqVO,  
168 - IotDeviceDO device, IotDeviceDO parentDevice) {  
169 - // 1. 参数校验  
170 - if (!(downstreamReqVO.getData() instanceof List<?>)) {  
171 - throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 List 类型");  
172 - }  
173 - // TODO @super:【可优化】过滤掉不合法的属性  
174 -  
175 - // 2. 发送请求  
176 - String url = String.format("sys/%s/%s/thing/service/property/get",  
177 - getProductKey(device, parentDevice), getDeviceName(device, parentDevice));  
178 - IotDevicePropertyGetReqDTO reqDTO = new IotDevicePropertyGetReqDTO()  
179 - .setIdentifiers((List<String>) downstreamReqVO.getData());  
180 -// CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);  
181 - CommonResult<Boolean> result = null;  
182 -  
183 - // 3. 发送设备消息  
184 - IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())  
185 - .setType(IotDeviceMessageTypeEnum.PROPERTY.getType())  
186 - .setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier())  
187 - .setData(reqDTO.getIdentifiers());  
188 - sendDeviceMessage(message, device, result.getCode());  
189 -  
190 - // 4. 如果不成功,抛出异常,提示用户  
191 - if (result.isError()) {  
192 - log.error("[getDeviceProperty][设备({})属性获取失败,请求参数:({}),响应结果:({})]",  
193 - device.getDeviceKey(), reqDTO, result);  
194 - throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());  
195 - }  
196 - return message;  
197 - }  
198 -  
199 - /**  
200 - * 设置设备配置  
201 - *  
202 - * @param downstreamReqVO 下行请求  
203 - * @param device 设备  
204 - * @param parentDevice 父设备  
205 - * @return 下发消息  
206 - */  
207 - @SuppressWarnings({ "unchecked", "unused" })  
208 - private IotDeviceMessage setDeviceConfig(IotDeviceDownstreamReqVO downstreamReqVO,  
209 - IotDeviceDO device, IotDeviceDO parentDevice) {  
210 - // 1. 参数转换,无需校验  
211 - Map<String, Object> config = JsonUtils.parseObject(device.getConfig(), Map.class);  
212 -  
213 - // 2. 发送请求  
214 - String url = String.format("sys/%s/%s/thing/service/config/set",  
215 - getProductKey(device, parentDevice), getDeviceName(device, parentDevice));  
216 - IotDeviceConfigSetReqDTO reqDTO = new IotDeviceConfigSetReqDTO()  
217 - .setConfig(config);  
218 -// CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);  
219 - CommonResult<Boolean> result = null;  
220 -  
221 - // 3. 发送设备消息  
222 - IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())  
223 - .setType(IotDeviceMessageTypeEnum.CONFIG.getType())  
224 - .setIdentifier(IotDeviceMessageIdentifierEnum.CONFIG_SET.getIdentifier())  
225 - .setData(reqDTO.getConfig());  
226 - sendDeviceMessage(message, device, result.getCode());  
227 -  
228 - // 4. 如果不成功,抛出异常,提示用户  
229 - if (result.isError()) {  
230 - log.error("[setDeviceConfig][设备({})配置下发失败,请求参数:({}),响应结果:({})]",  
231 - device.getDeviceKey(), reqDTO, result);  
232 - throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());  
233 - }  
234 - return message;  
235 - }  
236 -  
237 - /**  
238 - * 设备 OTA 升级  
239 - *  
240 - * @param downstreamReqVO 下行请求  
241 - * @param device 设备  
242 - * @param parentDevice 父设备  
243 - * @return 下发消息  
244 - */  
245 - private IotDeviceMessage otaUpgrade(IotDeviceDownstreamReqVO downstreamReqVO,  
246 - IotDeviceDO device, IotDeviceDO parentDevice) {  
247 - // 1. 参数校验  
248 - if (!(downstreamReqVO.getData() instanceof Map<?, ?> data)) {  
249 - throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 Map 类型");  
250 - }  
251 -  
252 - // 2. 发送请求  
253 - String url = String.format("ota/%s/%s/upgrade",  
254 - getProductKey(device, parentDevice), getDeviceName(device, parentDevice));  
255 - IotDeviceOtaUpgradeReqDTO reqDTO = IotDeviceOtaUpgradeReqDTO.build(data);  
256 -// CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);  
257 - CommonResult<Boolean> result = null;  
258 -  
259 - // 3. 发送设备消息  
260 - IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())  
261 - .setType(IotDeviceMessageTypeEnum.OTA.getType())  
262 - .setIdentifier(IotDeviceMessageIdentifierEnum.OTA_UPGRADE.getIdentifier())  
263 - .setData(downstreamReqVO.getData());  
264 - sendDeviceMessage(message, device, result.getCode());  
265 -  
266 - // 4. 如果不成功,抛出异常,提示用户  
267 - if (result.isError()) {  
268 - log.error("[otaUpgrade][设备({}) OTA 升级失败,请求参数:({}),响应结果:({})]",  
269 - device.getDeviceKey(), reqDTO, result);  
270 - throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());  
271 - }  
272 - return message;  
273 - }  
274 -  
275 - private void sendDeviceMessage(IotDeviceMessage message, IotDeviceDO device, Integer code) {  
276 - // 1. 完善消息  
277 - message.setProductKey(device.getProductKey()).setDeviceName(device.getDeviceName())  
278 - .setDeviceKey(device.getDeviceKey())  
279 - .setTenantId(device.getTenantId());  
280 - Assert.notNull(message.getRequestId(), "requestId 不能为空");  
281 - if (message.getReportTime() == null) {  
282 - message.setReportTime(LocalDateTime.now());  
283 - }  
284 - message.setCode(code);  
285 -  
286 - // 2. 发送消息  
287 - try {  
288 - deviceProducer.sendDeviceMessage(message);  
289 - log.info("[sendDeviceMessage][message({}) 发送消息成功]", message);  
290 - } catch (Exception e) {  
291 - log.error("[sendDeviceMessage][message({}) 发送消息失败]", message, e);  
292 - }  
293 - } 228 +// /**
  229 +// * 设备 OTA 升级
  230 +// *
  231 +// * @param downstreamReqVO 下行请求
  232 +// * @param device 设备
  233 +// * @param parentDevice 父设备
  234 +// * @return 下发消息
  235 +// */
  236 +// private IotDeviceMessage otaUpgrade(IotDeviceDownstreamReqVO downstreamReqVO,
  237 +// IotDeviceDO device, IotDeviceDO parentDevice) {
  238 +// // 1. 参数校验
  239 +// if (!(downstreamReqVO.getData() instanceof Map<?, ?> data)) {
  240 +// throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 Map 类型");
  241 +// }
  242 +//
  243 +// // 2. 发送请求
  244 +// String url = String.format("ota/%s/%s/upgrade",
  245 +// getProductKey(device, parentDevice), getDeviceName(device, parentDevice));
  246 +// IotDeviceOtaUpgradeReqDTO reqDTO = IotDeviceOtaUpgradeReqDTO.build(data);
  247 +//// CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);
  248 +// CommonResult<Boolean> result = null;
  249 +//
  250 +// // 3. 发送设备消息
  251 +// IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())
  252 +// .setType(IotDeviceMessageTypeEnum.OTA.getType())
  253 +// .setIdentifier(IotDeviceMessageIdentifierEnum.OTA_UPGRADE.getIdentifier())
  254 +// .setData(downstreamReqVO.getData());
  255 +// sendDeviceMessage(message, device, result.getCode());
  256 +//
  257 +// // 4. 如果不成功,抛出异常,提示用户
  258 +// if (result.isError()) {
  259 +// log.error("[otaUpgrade][设备({}) OTA 升级失败,请求参数:({}),响应结果:({})]",
  260 +// device.getDeviceKey(), reqDTO, result);
  261 +// throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());
  262 +// }
  263 +// return message;
  264 +// }
294 265
295 private String getDeviceName(IotDeviceDO device, IotDeviceDO parentDevice) { 266 private String getDeviceName(IotDeviceDO device, IotDeviceDO parentDevice) {
296 return parentDevice != null ? parentDevice.getDeviceName() : device.getDeviceName(); 267 return parentDevice != null ? parentDevice.getDeviceName() : device.getDeviceName();
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceUpstreamService.java
@@ -7,7 +7,7 @@ import jakarta.validation.Valid; @@ -7,7 +7,7 @@ import jakarta.validation.Valid;
7 /** 7 /**
8 * IoT 设备上行 Service 接口 8 * IoT 设备上行 Service 接口
9 * 9 *
10 - * 目的:设备 -> 插件 -> 服务端 10 + * 目的:设备 -> 网关 -> 服务端
11 * 11 *
12 * @author 芋道源码 12 * @author 芋道源码
13 */ 13 */
@@ -20,47 +20,33 @@ public interface IotDeviceUpstreamService { @@ -20,47 +20,33 @@ public interface IotDeviceUpstreamService {
20 */ 20 */
21 void upstreamDevice(@Valid IotDeviceUpstreamReqVO simulatorReqVO); 21 void upstreamDevice(@Valid IotDeviceUpstreamReqVO simulatorReqVO);
22 22
23 - /**  
24 - * 更新设备状态  
25 - *  
26 - * @param updateReqDTO 更新设备状态 DTO  
27 - */  
28 - void updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO);  
29 -  
30 - /**  
31 - * 上报设备属性数据  
32 - *  
33 - * @param reportReqDTO 上报设备属性数据 DTO  
34 - */  
35 - void reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO);  
36 -  
37 - /**  
38 - * 上报设备事件数据  
39 - *  
40 - * @param reportReqDTO 设备事件  
41 - */  
42 - void reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO);  
43 -  
44 - /**  
45 - * 注册设备  
46 - *  
47 - * @param registerReqDTO 注册设备 DTO  
48 - */  
49 - void registerDevice(IotDeviceRegisterReqDTO registerReqDTO);  
50 -  
51 - /**  
52 - * 注册子设备  
53 - *  
54 - * @param registerReqDTO 注册子设备 DTO  
55 - */  
56 - void registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO);  
57 -  
58 - /**  
59 - * 添加设备拓扑  
60 - *  
61 - * @param addReqDTO 添加设备拓扑 DTO  
62 - */  
63 - void addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO); 23 +// /**
  24 +// * 上报设备事件数据
  25 +// *
  26 +// * @param reportReqDTO 设备事件
  27 +// */
  28 +// void reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO);
  29 +//
  30 +// /**
  31 +// * 注册设备
  32 +// *
  33 +// * @param registerReqDTO 注册设备 DTO
  34 +// */
  35 +// void registerDevice(IotDeviceRegisterReqDTO registerReqDTO);
  36 +//
  37 +// /**
  38 +// * 注册子设备
  39 +// *
  40 +// * @param registerReqDTO 注册子设备 DTO
  41 +// */
  42 +// void registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO);
  43 +//
  44 +// /**
  45 +// * 添加设备拓扑
  46 +// *
  47 +// * @param addReqDTO 添加设备拓扑 DTO
  48 +// */
  49 +// void addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO);
64 50
65 /** 51 /**
66 * Emqx 连接认证 52 * Emqx 连接认证
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceUpstreamServiceImpl.java
1 package cn.iocoder.yudao.module.iot.service.device.control; 1 package cn.iocoder.yudao.module.iot.service.device.control;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.lang.Assert;  
5 import cn.hutool.core.util.IdUtil; 4 import cn.hutool.core.util.IdUtil;
6 import cn.hutool.core.util.ObjUtil; 5 import cn.hutool.core.util.ObjUtil;
7 import cn.hutool.core.util.StrUtil; 6 import cn.hutool.core.util.StrUtil;
8 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;  
9 -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;  
10 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; 7 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
11 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.*; 8 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.*;
12 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceUpstreamReqVO; 9 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceUpstreamReqVO;
13 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 10 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
14 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;  
15 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum; 11 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
16 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;  
17 import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; 12 import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum;
18 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
19 -import cn.iocoder.yudao.module.iot.mq.producer.device.IotDeviceProducer;  
20 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 13 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
21 import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService; 14 import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
22 import cn.iocoder.yudao.module.iot.util.MqttSignUtils; 15 import cn.iocoder.yudao.module.iot.util.MqttSignUtils;
@@ -45,9 +38,7 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { @@ -45,9 +38,7 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
45 @Resource 38 @Resource
46 private IotDevicePropertyService devicePropertyService; 39 private IotDevicePropertyService devicePropertyService;
47 40
48 - @Resource  
49 - private IotDeviceProducer deviceProducer;  
50 - 41 + // TODO @芋艿:需要重新实现下;
51 @Override 42 @Override
52 @SuppressWarnings("unchecked") 43 @SuppressWarnings("unchecked")
53 public void upstreamDevice(IotDeviceUpstreamReqVO simulatorReqVO) { 44 public void upstreamDevice(IotDeviceUpstreamReqVO simulatorReqVO) {
@@ -74,53 +65,13 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { @@ -74,53 +65,13 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
74 } 65 }
75 // 2.3 情况三:状态变更 66 // 2.3 情况三:状态变更
76 if (Objects.equals(simulatorReqVO.getType(), IotDeviceMessageTypeEnum.STATE.getType())) { 67 if (Objects.equals(simulatorReqVO.getType(), IotDeviceMessageTypeEnum.STATE.getType())) {
77 - updateDeviceState(((IotDeviceStateUpdateReqDTO) new IotDeviceStateUpdateReqDTO()  
78 - .setRequestId(IdUtil.fastSimpleUUID()).setReportTime(LocalDateTime.now())  
79 - .setProductKey(device.getProductKey()).setDeviceName(device.getDeviceName()))  
80 - .setState((Integer) simulatorReqVO.getData())); 68 + // TODO @芋艿:这里未搞完
81 return; 69 return;
82 } 70 }
83 throw new IllegalArgumentException("未知的类型:" + simulatorReqVO.getType()); 71 throw new IllegalArgumentException("未知的类型:" + simulatorReqVO.getType());
84 } 72 }
85 73
86 - @Override  
87 - public void updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {  
88 - Assert.isTrue(ObjectUtils.equalsAny(updateReqDTO.getState(),  
89 - IotDeviceStateEnum.ONLINE.getState(), IotDeviceStateEnum.OFFLINE.getState()),  
90 - "状态不合法");  
91 - // 1.1 获得设备  
92 - log.info("[updateDeviceState][更新设备状态: {}]", updateReqDTO);  
93 - IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceNameFromCache(  
94 - updateReqDTO.getProductKey(), updateReqDTO.getDeviceName());  
95 - if (device == null) {  
96 - log.error("[updateDeviceState][设备({}/{}) 不存在]",  
97 - updateReqDTO.getProductKey(), updateReqDTO.getDeviceName());  
98 - return;  
99 - }  
100 - TenantUtils.execute(device.getTenantId(), () -> {  
101 - // 1.2 记录设备的最后时间  
102 - updateDeviceLastTime(device, updateReqDTO);  
103 - // 1.3 当前状态一致,不处理  
104 - if (Objects.equals(device.getState(), updateReqDTO.getState())) {  
105 - return;  
106 - }  
107 -  
108 - // 2. 更新设备状态  
109 - deviceService.updateDeviceState(device.getId(), updateReqDTO.getState());  
110 -  
111 - // 3. TODO 芋艿:子设备的关联  
112 -  
113 - // 4. 发送设备消息  
114 - IotDeviceMessage message = BeanUtils.toBean(updateReqDTO, IotDeviceMessage.class)  
115 - .setType(IotDeviceMessageTypeEnum.STATE.getType())  
116 - .setIdentifier(ObjUtil.equals(updateReqDTO.getState(), IotDeviceStateEnum.ONLINE.getState())  
117 - ? IotDeviceMessageIdentifierEnum.STATE_ONLINE.getIdentifier()  
118 - : IotDeviceMessageIdentifierEnum.STATE_OFFLINE.getIdentifier());  
119 - sendDeviceMessage(message, device);  
120 - });  
121 - }  
122 -  
123 - @Override 74 +// @Override TODO 芋艿:待重新实现
124 public void reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) { 75 public void reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) {
125 // 1.1 获得设备 76 // 1.1 获得设备
126 log.info("[reportDeviceProperty][上报设备属性: {}]", reportReqDTO); 77 log.info("[reportDeviceProperty][上报设备属性: {}]", reportReqDTO);
@@ -131,18 +82,16 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { @@ -131,18 +82,16 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
131 reportReqDTO.getProductKey(), reportReqDTO.getDeviceName()); 82 reportReqDTO.getProductKey(), reportReqDTO.getDeviceName());
132 return; 83 return;
133 } 84 }
134 - // 1.2 记录设备的最后时间  
135 - updateDeviceLastTime(device, reportReqDTO);  
136 85
137 // 2. 发送设备消息 86 // 2. 发送设备消息
138 - IotDeviceMessage message = BeanUtils.toBean(reportReqDTO, IotDeviceMessage.class)  
139 - .setType(IotDeviceMessageTypeEnum.PROPERTY.getType())  
140 - .setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier())  
141 - .setData(reportReqDTO.getProperties());  
142 - sendDeviceMessage(message, device); 87 +// IotDeviceMessage message = BeanUtils.toBean(reportReqDTO, IotDeviceMessage.class)
  88 +// .setType(IotDeviceMessageTypeEnum.PROPERTY.getType())
  89 +// .setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier())
  90 +// .setData(reportReqDTO.getProperties());
  91 +// sendDeviceMessage(message, device);
143 } 92 }
144 93
145 - @Override 94 + // @Override TODO 芋艿:待重新实现
146 public void reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) { 95 public void reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) {
147 // 1.1 获得设备 96 // 1.1 获得设备
148 log.info("[reportDeviceEvent][上报设备事件: {}]", reportReqDTO); 97 log.info("[reportDeviceEvent][上报设备事件: {}]", reportReqDTO);
@@ -153,18 +102,16 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { @@ -153,18 +102,16 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
153 reportReqDTO.getProductKey(), reportReqDTO.getDeviceName()); 102 reportReqDTO.getProductKey(), reportReqDTO.getDeviceName());
154 return; 103 return;
155 } 104 }
156 - // 1.2 记录设备的最后时间  
157 - updateDeviceLastTime(device, reportReqDTO);  
158 105
159 // 2. 发送设备消息 106 // 2. 发送设备消息
160 - IotDeviceMessage message = BeanUtils.toBean(reportReqDTO, IotDeviceMessage.class)  
161 - .setType(IotDeviceMessageTypeEnum.EVENT.getType())  
162 - .setIdentifier(reportReqDTO.getIdentifier())  
163 - .setData(reportReqDTO.getParams());  
164 - sendDeviceMessage(message, device); 107 +// IotDeviceMessage message = BeanUtils.toBean(reportReqDTO, IotDeviceMessage.class)
  108 +// .setType(IotDeviceMessageTypeEnum.EVENT.getType())
  109 +// .setIdentifier(reportReqDTO.getIdentifier())
  110 +// .setData(reportReqDTO.getParams());
  111 +// sendDeviceMessage(message, device);
165 } 112 }
166 113
167 - @Override 114 + // @Override TODO 芋艿:待重新实现
168 public void registerDevice(IotDeviceRegisterReqDTO registerReqDTO) { 115 public void registerDevice(IotDeviceRegisterReqDTO registerReqDTO) {
169 log.info("[registerDevice][注册设备: {}]", registerReqDTO); 116 log.info("[registerDevice][注册设备: {}]", registerReqDTO);
170 registerDevice0(registerReqDTO.getProductKey(), registerReqDTO.getDeviceName(), null, registerReqDTO); 117 registerDevice0(registerReqDTO.getProductKey(), registerReqDTO.getDeviceName(), null, registerReqDTO);
@@ -186,18 +133,18 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { @@ -186,18 +133,18 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
186 registerReqDTO, productKey, device, gatewayId); 133 registerReqDTO, productKey, device, gatewayId);
187 } 134 }
188 // 1.2 记录设备的最后时间 135 // 1.2 记录设备的最后时间
189 - updateDeviceLastTime(device, registerReqDTO); 136 +// updateDeviceLastTime(device, registerReqDTO);
190 137
191 // 2. 发送设备消息 138 // 2. 发送设备消息
192 if (registerNew) { 139 if (registerNew) {
193 - IotDeviceMessage message = BeanUtils.toBean(registerReqDTO, IotDeviceMessage.class)  
194 - .setType(IotDeviceMessageTypeEnum.REGISTER.getType())  
195 - .setIdentifier(IotDeviceMessageIdentifierEnum.REGISTER_REGISTER.getIdentifier());  
196 - sendDeviceMessage(message, device); 140 +// IotDeviceMessage message = BeanUtils.toBean(registerReqDTO, IotDeviceMessage.class)
  141 +// .setType(IotDeviceMessageTypeEnum.REGISTER.getType())
  142 +// .setIdentifier(IotDeviceMessageIdentifierEnum.REGISTER_REGISTER.getIdentifier());
  143 +// sendDeviceMessage(message, device);
197 } 144 }
198 } 145 }
199 146
200 - @Override 147 + // @Override TODO 芋艿:待重新实现
201 public void registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO) { 148 public void registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO) {
202 // 1.1 注册子设备 149 // 1.1 注册子设备
203 log.info("[registerSubDevice][注册子设备: {}]", registerReqDTO); 150 log.info("[registerSubDevice][注册子设备: {}]", registerReqDTO);
@@ -214,7 +161,7 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { @@ -214,7 +161,7 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
214 return; 161 return;
215 } 162 }
216 // 1.2 记录设备的最后时间 163 // 1.2 记录设备的最后时间
217 - updateDeviceLastTime(device, registerReqDTO); 164 +// updateDeviceLastTime(device, registerReqDTO);
218 165
219 // 2. 处理子设备 166 // 2. 处理子设备
220 if (CollUtil.isNotEmpty(registerReqDTO.getParams())) { 167 if (CollUtil.isNotEmpty(registerReqDTO.getParams())) {
@@ -224,14 +171,14 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { @@ -224,14 +171,14 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
224 } 171 }
225 172
226 // 3. 发送设备消息 173 // 3. 发送设备消息
227 - IotDeviceMessage message = BeanUtils.toBean(registerReqDTO, IotDeviceMessage.class)  
228 - .setType(IotDeviceMessageTypeEnum.REGISTER.getType())  
229 - .setIdentifier(IotDeviceMessageIdentifierEnum.REGISTER_REGISTER_SUB.getIdentifier())  
230 - .setData(registerReqDTO.getParams());  
231 - sendDeviceMessage(message, device); 174 +// IotDeviceMessage message = BeanUtils.toBean(registerReqDTO, IotDeviceMessage.class)
  175 +// .setType(IotDeviceMessageTypeEnum.REGISTER.getType())
  176 +// .setIdentifier(IotDeviceMessageIdentifierEnum.REGISTER_REGISTER_SUB.getIdentifier())
  177 +// .setData(registerReqDTO.getParams());
  178 +// sendDeviceMessage(message, device);
232 } 179 }
233 180
234 - @Override 181 + // @Override TODO 芋艿:待重新实现
235 public void addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO) { 182 public void addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO) {
236 // 1.1 获得设备 183 // 1.1 获得设备
237 log.info("[addDeviceTopology][添加设备拓扑: {}]", addReqDTO); 184 log.info("[addDeviceTopology][添加设备拓扑: {}]", addReqDTO);
@@ -247,8 +194,6 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { @@ -247,8 +194,6 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
247 addReqDTO.getProductKey(), addReqDTO.getDeviceName(), device); 194 addReqDTO.getProductKey(), addReqDTO.getDeviceName(), device);
248 return; 195 return;
249 } 196 }
250 - // 1.2 记录设备的最后时间  
251 - updateDeviceLastTime(device, addReqDTO);  
252 197
253 // 2. 处理拓扑 198 // 2. 处理拓扑
254 if (CollUtil.isNotEmpty(addReqDTO.getParams())) { 199 if (CollUtil.isNotEmpty(addReqDTO.getParams())) {
@@ -270,11 +215,11 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { @@ -270,11 +215,11 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
270 } 215 }
271 216
272 // 3. 发送设备消息 217 // 3. 发送设备消息
273 - IotDeviceMessage message = BeanUtils.toBean(addReqDTO, IotDeviceMessage.class)  
274 - .setType(IotDeviceMessageTypeEnum.TOPOLOGY.getType())  
275 - .setIdentifier(IotDeviceMessageIdentifierEnum.TOPOLOGY_ADD.getIdentifier())  
276 - .setData(addReqDTO.getParams());  
277 - sendDeviceMessage(message, device); 218 +// IotDeviceMessage message = BeanUtils.toBean(addReqDTO, IotDeviceMessage.class)
  219 +// .setType(IotDeviceMessageTypeEnum.TOPOLOGY.getType())
  220 +// .setIdentifier(IotDeviceMessageIdentifierEnum.TOPOLOGY_ADD.getIdentifier())
  221 +// .setData(addReqDTO.getParams());
  222 +// sendDeviceMessage(message, device);
278 } 223 }
279 224
280 // TODO @芋艿:后续需要考虑,http 的认证 225 // TODO @芋艿:后续需要考虑,http 的认证
@@ -310,33 +255,4 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { @@ -310,33 +255,4 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService {
310 return false; 255 return false;
311 } 256 }
312 257
313 - private void updateDeviceLastTime(IotDeviceDO device, IotDeviceUpstreamAbstractReqDTO reqDTO) {  
314 - // 1. 【异步】记录设备与插件实例的映射  
315 -// pluginInstanceService.updateDevicePluginInstanceProcessIdAsync(device.getDeviceKey(), reqDTO.getProcessId());  
316 - // TODO @芋艿:需要单独补充下;  
317 -  
318 - // 2. 【异步】更新设备的最后时间  
319 - devicePropertyService.updateDeviceReportTimeAsync(device.getDeviceKey(), LocalDateTime.now());  
320 - }  
321 -  
322 - private void sendDeviceMessage(IotDeviceMessage message, IotDeviceDO device) {  
323 - // 1. 完善消息  
324 - message.setDeviceKey(device.getDeviceKey())  
325 - .setTenantId(device.getTenantId());  
326 - if (StrUtil.isEmpty(message.getRequestId())) {  
327 - message.setRequestId(IdUtil.fastSimpleUUID());  
328 - }  
329 - if (message.getReportTime() == null) {  
330 - message.setReportTime(LocalDateTime.now());  
331 - }  
332 -  
333 - // 2. 发送消息  
334 - try {  
335 - deviceProducer.sendDeviceMessage(message);  
336 - log.info("[sendDeviceMessage][message({}) 发送消息成功]", message);  
337 - } catch (Exception e) {  
338 - log.error("[sendDeviceMessage][message({}) 发送消息失败]", message, e);  
339 - }  
340 - }  
341 -  
342 } 258 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyService.java
@@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.service.device.data; @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.service.device.data;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryPageReqVO; 4 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryPageReqVO;
5 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO; 5 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO;
  6 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
6 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
7 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
8 import jakarta.validation.Valid; 8 import jakarta.validation.Valid;
9 9
10 import java.time.LocalDateTime; 10 import java.time.LocalDateTime;
@@ -56,16 +56,43 @@ public interface IotDevicePropertyService { @@ -56,16 +56,43 @@ public interface IotDevicePropertyService {
56 * 获得最后上报时间小于指定时间的设备标识 56 * 获得最后上报时间小于指定时间的设备标识
57 * 57 *
58 * @param maxReportTime 最大上报时间 58 * @param maxReportTime 最大上报时间
59 - * @return 设备标识列表 59 + * @return [productKey, deviceName] 列表
60 */ 60 */
61 - Set<String> getDeviceKeysByReportTime(LocalDateTime maxReportTime); 61 + Set<String[]> getProductKeyDeviceNameListByReportTime(LocalDateTime maxReportTime);
62 62
63 /** 63 /**
64 - * 异步更新设备上报时间 64 + * 更新设备上报时间
65 * 65 *
66 - * @param deviceKey 设备标识 66 + * @param productKey 产品标识
  67 + * @param deviceName 设备名称
67 * @param reportTime 上报时间 68 * @param reportTime 上报时间
68 */ 69 */
69 - void updateDeviceReportTimeAsync(String deviceKey, LocalDateTime reportTime); 70 + void updateDeviceReportTime(String productKey, String deviceName, LocalDateTime reportTime);
  71 +
  72 + /**
  73 + * 更新设备关联的网关 serverId
  74 + *
  75 + * @param productKey 产品标识
  76 + * @param deviceName 设备名称
  77 + * @param serverId 网关 serverId
  78 + */
  79 + void updateDeviceServerId(String productKey, String deviceName, String serverId);
  80 +
  81 + /**
  82 + * 删除设备关联的网关 serverId
  83 + *
  84 + * @param productKey 产品标识
  85 + * @param deviceName 设备名称
  86 + */
  87 + void deleteDeviceServerId(String productKey, String deviceName);
  88 +
  89 + /**
  90 + * 获得设备关联的网关 serverId
  91 + *
  92 + * @param productKey 产品标识
  93 + * @param deviceName 设备名称
  94 + * @return 网关 serverId
  95 + */
  96 + String getDeviceServerId(String productKey, String deviceName);
70 97
71 } 98 }
72 \ No newline at end of file 99 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyServiceImpl.java
@@ -9,17 +9,18 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; @@ -9,17 +9,18 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
9 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryPageReqVO; 9 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryPageReqVO;
10 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO; 10 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO;
11 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs; 11 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs;
  12 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
12 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 13 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
13 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; 14 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
14 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 15 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
15 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; 16 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
16 import cn.iocoder.yudao.module.iot.dal.redis.device.DevicePropertyRedisDAO; 17 import cn.iocoder.yudao.module.iot.dal.redis.device.DevicePropertyRedisDAO;
17 import cn.iocoder.yudao.module.iot.dal.redis.device.DeviceReportTimeRedisDAO; 18 import cn.iocoder.yudao.module.iot.dal.redis.device.DeviceReportTimeRedisDAO;
  19 +import cn.iocoder.yudao.module.iot.dal.redis.device.DeviceServerIdRedisDAO;
18 import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyMapper; 20 import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyMapper;
19 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; 21 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum;
20 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; 22 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
21 import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField; 23 import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField;
22 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
23 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 24 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
24 import cn.iocoder.yudao.module.iot.service.product.IotProductService; 25 import cn.iocoder.yudao.module.iot.service.product.IotProductService;
25 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; 26 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
@@ -27,7 +28,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage; @@ -27,7 +28,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
27 import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 28 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
28 import jakarta.annotation.Resource; 29 import jakarta.annotation.Resource;
29 import lombok.extern.slf4j.Slf4j; 30 import lombok.extern.slf4j.Slf4j;
30 -import org.springframework.scheduling.annotation.Async;  
31 import org.springframework.stereotype.Service; 31 import org.springframework.stereotype.Service;
32 32
33 import java.time.LocalDateTime; 33 import java.time.LocalDateTime;
@@ -70,6 +70,8 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { @@ -70,6 +70,8 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
70 private DevicePropertyRedisDAO deviceDataRedisDAO; 70 private DevicePropertyRedisDAO deviceDataRedisDAO;
71 @Resource 71 @Resource
72 private DeviceReportTimeRedisDAO deviceReportTimeRedisDAO; 72 private DeviceReportTimeRedisDAO deviceReportTimeRedisDAO;
  73 + @Resource
  74 + private DeviceServerIdRedisDAO deviceServerIdRedisDAO;
73 75
74 @Resource 76 @Resource
75 private IotDevicePropertyMapper devicePropertyMapper; 77 private IotDevicePropertyMapper devicePropertyMapper;
@@ -153,7 +155,8 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { @@ -153,7 +155,8 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
153 LocalDateTimeUtil.toEpochMilli(message.getReportTime())); 155 LocalDateTimeUtil.toEpochMilli(message.getReportTime()));
154 156
155 // 3.2 保存设备属性【日志】 157 // 3.2 保存设备属性【日志】
156 - deviceDataRedisDAO.putAll(message.getDeviceKey(), convertMap(properties.entrySet(), Map.Entry::getKey, 158 + // TODO @芋艿:这里要调整下;
  159 + deviceDataRedisDAO.putAll(device.getDeviceKey(), convertMap(properties.entrySet(), Map.Entry::getKey,
157 entry -> IotDevicePropertyDO.builder().value(entry.getValue()).updateTime(message.getReportTime()).build())); 160 entry -> IotDevicePropertyDO.builder().value(entry.getValue()).updateTime(message.getReportTime()).build()));
158 } 161 }
159 162
@@ -187,14 +190,31 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { @@ -187,14 +190,31 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
187 // ========== 设备时间相关操作 ========== 190 // ========== 设备时间相关操作 ==========
188 191
189 @Override 192 @Override
190 - public Set<String> getDeviceKeysByReportTime(LocalDateTime maxReportTime) { 193 + public Set<String[]> getProductKeyDeviceNameListByReportTime(LocalDateTime maxReportTime) {
191 return deviceReportTimeRedisDAO.range(maxReportTime); 194 return deviceReportTimeRedisDAO.range(maxReportTime);
192 } 195 }
193 196
194 @Override 197 @Override
195 - @Async  
196 - public void updateDeviceReportTimeAsync(String deviceKey, LocalDateTime reportTime) {  
197 - deviceReportTimeRedisDAO.update(deviceKey, reportTime); 198 + public void updateDeviceReportTime(String productKey, String deviceName, LocalDateTime reportTime) {
  199 + deviceReportTimeRedisDAO.update(productKey, deviceName, reportTime);
  200 + }
  201 +
  202 + @Override
  203 + public void updateDeviceServerId(String productKey, String deviceName, String serverId) {
  204 + if (StrUtil.isEmpty(serverId)) {
  205 + return;
  206 + }
  207 + deviceServerIdRedisDAO.update(productKey, deviceName, serverId);
  208 + }
  209 +
  210 + @Override
  211 + public void deleteDeviceServerId(String productKey, String deviceName) {
  212 + deviceServerIdRedisDAO.delete(productKey, deviceName);
  213 + }
  214 +
  215 + @Override
  216 + public String getDeviceServerId(String productKey, String deviceName) {
  217 + return deviceServerIdRedisDAO.get(productKey, deviceName);
198 } 218 }
199 219
200 } 220 }
201 \ No newline at end of file 221 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneService.java
@@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.iot.service.rule; @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.iot.service.rule;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO; 4 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO;
5 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO; 5 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
  6 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
7 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum; 8 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
8 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
9 import jakarta.validation.Valid; 9 import jakarta.validation.Valid;
10 10
11 import java.util.List; 11 import java.util.List;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java
@@ -17,6 +17,7 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; @@ -17,6 +17,7 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
17 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; 17 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
18 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO; 18 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO;
19 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO; 19 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
  20 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
20 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 21 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
21 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper; 22 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper;
22 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum; 23 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
@@ -26,7 +27,6 @@ import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerConditionParame @@ -26,7 +27,6 @@ import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerConditionParame
26 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum; 27 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
27 import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager; 28 import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager;
28 import cn.iocoder.yudao.module.iot.job.rule.IotRuleSceneJob; 29 import cn.iocoder.yudao.module.iot.job.rule.IotRuleSceneJob;
29 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
30 import cn.iocoder.yudao.module.iot.service.rule.action.IotRuleSceneAction; 30 import cn.iocoder.yudao.module.iot.service.rule.action.IotRuleSceneAction;
31 import jakarta.annotation.Resource; 31 import jakarta.annotation.Resource;
32 import lombok.SneakyThrows; 32 import lombok.SneakyThrows;
@@ -240,16 +240,17 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -240,16 +240,17 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
240 240
241 @Override 241 @Override
242 public void executeRuleSceneByDevice(IotDeviceMessage message) { 242 public void executeRuleSceneByDevice(IotDeviceMessage message) {
243 - TenantUtils.execute(message.getTenantId(), () -> {  
244 - // 1. 获得设备匹配的规则场景  
245 - List<IotRuleSceneDO> ruleScenes = getMatchedRuleSceneListByMessage(message);  
246 - if (CollUtil.isEmpty(ruleScenes)) {  
247 - return;  
248 - }  
249 -  
250 - // 2. 执行规则场景  
251 - executeRuleSceneAction(message, ruleScenes);  
252 - }); 243 + // TODO @芋艿:这里的 tenantId,通过设备获取;
  244 +// TenantUtils.execute(message.getTenantId(), () -> {
  245 +// // 1. 获得设备匹配的规则场景
  246 +// List<IotRuleSceneDO> ruleScenes = getMatchedRuleSceneListByMessage(message);
  247 +// if (CollUtil.isEmpty(ruleScenes)) {
  248 +// return;
  249 +// }
  250 +//
  251 +// // 2. 执行规则场景
  252 +// executeRuleSceneAction(message, ruleScenes);
  253 +// });
253 } 254 }
254 255
255 @Override 256 @Override
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAction.java
1 package cn.iocoder.yudao.module.iot.service.rule.action; 1 package cn.iocoder.yudao.module.iot.service.rule.action;
2 2
  3 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 4 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
4 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 5 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
5 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
6 6
7 import javax.annotation.Nullable; 7 import javax.annotation.Nullable;
8 8
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAlertAction.java
1 package cn.iocoder.yudao.module.iot.service.rule.action; 1 package cn.iocoder.yudao.module.iot.service.rule.action;
2 2
  3 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 4 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
4 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 5 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
5 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
6 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
7 7
8 import javax.annotation.Nullable; 8 import javax.annotation.Nullable;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java
@@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.iot.service.rule.action; @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.iot.service.rule.action;
2 2
3 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  5 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
5 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
7 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 8 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
8 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
9 import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService; 9 import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService;
10 import cn.iocoder.yudao.module.iot.service.rule.action.databridge.IotDataBridgeExecute; 10 import cn.iocoder.yudao.module.iot.service.rule.action.databridge.IotDataBridgeExecute;
11 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDeviceControlAction.java
@@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.iot.service.rule.action; @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.iot.service.rule.action;
2 2
3 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
4 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO; 4 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
  5 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
5 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
7 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 8 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
8 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
9 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 9 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
10 import cn.iocoder.yudao.module.iot.service.device.control.IotDeviceDownstreamService; 10 import cn.iocoder.yudao.module.iot.service.device.control.IotDeviceDownstreamService;
11 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/AbstractCacheableDataBridgeExecute.java
1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge; 1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
3 import cn.hutool.core.util.ObjUtil; 3 import cn.hutool.core.util.ObjUtil;
  4 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 5 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
5 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
6 import com.google.common.cache.CacheBuilder; 6 import com.google.common.cache.CacheBuilder;
7 import com.google.common.cache.CacheLoader; 7 import com.google.common.cache.CacheLoader;
8 import com.google.common.cache.LoadingCache; 8 import com.google.common.cache.LoadingCache;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotDataBridgeExecute.java
1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge; 1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
  3 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 4 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
4 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
5 -  
6 5
7 /** 6 /**
8 * IoT 数据桥梁的执行器 execute 接口 7 * IoT 数据桥梁的执行器 execute 接口
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotHttpDataBridgeExecute.java
@@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil; @@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.framework.common.util.http.HttpUtils; 4 import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeHttpConfig; 6 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeHttpConfig;
  7 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
7 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum; 8 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
8 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
9 import jakarta.annotation.Resource; 9 import jakarta.annotation.Resource;
10 import lombok.extern.slf4j.Slf4j; 10 import lombok.extern.slf4j.Slf4j;
11 import org.springframework.http.*; 11 import org.springframework.http.*;
@@ -16,8 +16,6 @@ import org.springframework.web.util.UriComponentsBuilder; @@ -16,8 +16,6 @@ import org.springframework.web.util.UriComponentsBuilder;
16 import java.util.HashMap; 16 import java.util.HashMap;
17 import java.util.Map; 17 import java.util.Map;
18 18
19 -import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;  
20 -  
21 /** 19 /**
22 * Http 的 {@link IotDataBridgeExecute} 实现类 20 * Http 的 {@link IotDataBridgeExecute} 实现类
23 * 21 *
@@ -48,7 +46,8 @@ public class IotHttpDataBridgeExecute implements IotDataBridgeExecute&lt;IotDataBri @@ -48,7 +46,8 @@ public class IotHttpDataBridgeExecute implements IotDataBridgeExecute&lt;IotDataBri
48 if (CollUtil.isNotEmpty(config.getHeaders())) { 46 if (CollUtil.isNotEmpty(config.getHeaders())) {
49 config.getHeaders().putAll(config.getHeaders()); 47 config.getHeaders().putAll(config.getHeaders());
50 } 48 }
51 - headers.add(HEADER_TENANT_ID, message.getTenantId().toString()); 49 + // TODO @puhui999:@yunai:可能需要通过设备查询到租户,然后 set
  50 +// headers.add(HEADER_TENANT_ID, message.getTenantId().toString());
52 // 1.2 构建 URL 51 // 1.2 构建 URL
53 UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(config.getUrl()); 52 UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(config.getUrl());
54 if (CollUtil.isNotEmpty(config.getQuery())) { 53 if (CollUtil.isNotEmpty(config.getQuery())) {
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotKafkaMQDataBridgeExecute.java
1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge; 1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
3 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeKafkaMQConfig; 3 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeKafkaMQConfig;
  4 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum; 5 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
5 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
6 import lombok.extern.slf4j.Slf4j; 6 import lombok.extern.slf4j.Slf4j;
7 import org.apache.kafka.clients.producer.ProducerConfig; 7 import org.apache.kafka.clients.producer.ProducerConfig;
8 import org.apache.kafka.common.serialization.StringSerializer; 8 import org.apache.kafka.common.serialization.StringSerializer;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRabbitMQDataBridgeExecute.java
1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge; 1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
3 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRabbitMQConfig; 3 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRabbitMQConfig;
  4 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum; 5 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
5 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
6 import com.rabbitmq.client.Channel; 6 import com.rabbitmq.client.Channel;
7 import com.rabbitmq.client.Connection; 7 import com.rabbitmq.client.Connection;
8 import com.rabbitmq.client.ConnectionFactory; 8 import com.rabbitmq.client.ConnectionFactory;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamDataBridgeExecute.java
@@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action.databridge; @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
3 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRedisStreamConfig; 4 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRedisStreamConfig;
  5 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
5 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum; 6 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
6 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
7 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
8 import org.redisson.Redisson; 8 import org.redisson.Redisson;
9 import org.redisson.api.RedissonClient; 9 import org.redisson.api.RedissonClient;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRocketMQDataBridgeExecute.java
1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge; 1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
3 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRocketMQConfig; 3 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRocketMQConfig;
  4 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum; 5 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
5 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
6 import lombok.extern.slf4j.Slf4j; 6 import lombok.extern.slf4j.Slf4j;
7 import org.apache.rocketmq.client.producer.DefaultMQProducer; 7 import org.apache.rocketmq.client.producer.DefaultMQProducer;
8 import org.apache.rocketmq.client.producer.SendResult; 8 import org.apache.rocketmq.client.producer.SendResult;
yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotDataBridgeExecuteTest.java
@@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action.databridge; @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
3 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; 3 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.*; 4 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.*;
  5 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
5 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
6 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;  
7 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
8 import org.junit.jupiter.api.BeforeEach; 8 import org.junit.jupiter.api.BeforeEach;
9 import org.junit.jupiter.api.Disabled; 9 import org.junit.jupiter.api.Disabled;
@@ -41,8 +41,8 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest { @@ -41,8 +41,8 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest {
41 @BeforeEach 41 @BeforeEach
42 public void setUp() { 42 public void setUp() {
43 // 创建共享的测试消息 43 // 创建共享的测试消息
44 - message = IotDeviceMessage.builder().requestId("TEST-001").reportTime(LocalDateTime.now()).tenantId(1L)  
45 - .productKey("testProduct").deviceName("testDevice").deviceKey("testDeviceKey") 44 + message = IotDeviceMessage.builder().messageId("TEST-001").reportTime(LocalDateTime.now())
  45 + .productKey("testProduct").deviceName("testDevice")
46 .type("property").identifier("temperature").data("{\"value\": 60}") 46 .type("property").identifier("temperature").data("{\"value\": 60}")
47 .build(); 47 .build();
48 } 48 }
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceStateEnum.java renamed to yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/enums/IotDeviceStateEnum.java
1 -package cn.iocoder.yudao.module.iot.enums.device; 1 +package cn.iocoder.yudao.module.iot.core.enums;
2 2
3 import cn.iocoder.yudao.framework.common.core.ArrayValuable; 3 import cn.iocoder.yudao.framework.common.core.ArrayValuable;
4 import lombok.Getter; 4 import lombok.Getter;
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/mq/message/IotDeviceMessage.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.core.mq.message; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.core.mq.message;
2 2
3 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageIdentifierEnum; 3 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageIdentifierEnum;
4 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageTypeEnum; 4 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageTypeEnum;
5 -import cn.iocoder.yudao.module.iot.core.util.IotCoreUtils; 5 +import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
6 import lombok.AllArgsConstructor; 6 import lombok.AllArgsConstructor;
7 import lombok.Builder; 7 import lombok.Builder;
8 import lombok.Data; 8 import lombok.Data;
@@ -79,7 +79,7 @@ public class IotDeviceMessage { @@ -79,7 +79,7 @@ public class IotDeviceMessage {
79 private LocalDateTime reportTime; 79 private LocalDateTime reportTime;
80 80
81 /** 81 /**
82 - * 服务编号,该消息由哪个消息发送 82 + * 服务编号,该消息由哪个 server 服务进行消费
83 */ 83 */
84 private String serverId; 84 private String serverId;
85 85
@@ -97,6 +97,18 @@ public class IotDeviceMessage { @@ -97,6 +97,18 @@ public class IotDeviceMessage {
97 return this; 97 return this;
98 } 98 }
99 99
  100 + public IotDeviceMessage ofStateOnline() {
  101 + this.setType(IotDeviceMessageTypeEnum.STATE.getType());
  102 + this.setIdentifier(IotDeviceMessageIdentifierEnum.STATE_ONLINE.getIdentifier());
  103 + return this;
  104 + }
  105 +
  106 + public IotDeviceMessage ofStateOffline() {
  107 + this.setType(IotDeviceMessageTypeEnum.STATE.getType());
  108 + this.setIdentifier(IotDeviceMessageIdentifierEnum.STATE_OFFLINE.getIdentifier());
  109 + return this;
  110 + }
  111 +
100 public static IotDeviceMessage of(String productKey, String deviceName) { 112 public static IotDeviceMessage of(String productKey, String deviceName) {
101 return of(productKey, deviceName, 113 return of(productKey, deviceName,
102 null, null); 114 null, null);
@@ -113,17 +125,11 @@ public class IotDeviceMessage { @@ -113,17 +125,11 @@ public class IotDeviceMessage {
113 if (reportTime == null) { 125 if (reportTime == null) {
114 reportTime = LocalDateTime.now(); 126 reportTime = LocalDateTime.now();
115 } 127 }
116 - String messageId = IotCoreUtils.generateMessageId(); 128 + String messageId = IotDeviceMessageUtils.generateMessageId();
117 return IotDeviceMessage.builder() 129 return IotDeviceMessage.builder()
118 .messageId(messageId).reportTime(reportTime) 130 .messageId(messageId).reportTime(reportTime)
119 .productKey(productKey).deviceName(deviceName) 131 .productKey(productKey).deviceName(deviceName)
120 .serverId(serverId).build(); 132 .serverId(serverId).build();
121 } 133 }
122 134
123 - // ========== Topic 相关 ==========  
124 -  
125 - public static String buildMessageBusGatewayDeviceMessageTopic(String serverId) {  
126 - return String.format(MESSAGE_BUS_GATEWAY_DEVICE_MESSAGE_TOPIC, serverId);  
127 - }  
128 -  
129 } 135 }
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/mq/producer/IotDeviceMessageProducer.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.core.mq.producer; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.core.mq.producer;
2 2
3 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; 3 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
4 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 4 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  5 +import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
5 import lombok.RequiredArgsConstructor; 6 import lombok.RequiredArgsConstructor;
6 7
7 /** 8 /**
@@ -30,7 +31,7 @@ public class IotDeviceMessageProducer { @@ -30,7 +31,7 @@ public class IotDeviceMessageProducer {
30 * @param message 设备消息 31 * @param message 设备消息
31 */ 32 */
32 public void sendGatewayDeviceMessage(String serverId, Object message) { 33 public void sendGatewayDeviceMessage(String serverId, Object message) {
33 - messageBus.post(IotDeviceMessage.buildMessageBusGatewayDeviceMessageTopic(serverId), message); 34 + messageBus.post(IotDeviceMessageUtils.buildMessageBusGatewayDeviceMessageTopic(serverId), message);
34 } 35 }
35 36
36 } 37 }
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/util/IotCoreUtils.java renamed to yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/util/IotDeviceMessageUtils.java
1 package cn.iocoder.yudao.module.iot.core.util; 1 package cn.iocoder.yudao.module.iot.core.util;
2 2
3 import cn.hutool.core.util.IdUtil; 3 import cn.hutool.core.util.IdUtil;
  4 +import cn.hutool.core.util.StrUtil;
4 import cn.hutool.system.SystemUtil; 5 import cn.hutool.system.SystemUtil;
  6 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
5 7
6 /** 8 /**
7 - * IoT 核心模块的工具类 9 + * IoT 设备消息的工具类
8 * 10 *
9 * @author 芋道源码 11 * @author 芋道源码
10 */ 12 */
11 -public class IotCoreUtils { 13 +public class IotDeviceMessageUtils {
  14 +
  15 + // ========== Message 相关 ==========
  16 +
  17 + public static String generateMessageId() {
  18 + return IdUtil.fastSimpleUUID();
  19 + }
  20 +
  21 + /**
  22 + * 是否是上行消息:由设备发送
  23 + *
  24 + * @param message 消息
  25 + * @return 是否
  26 + */
  27 + public static boolean isUpstreamMessage(IotDeviceMessage message) {
  28 + return StrUtil.isNotEmpty(message.getServerId());
  29 + }
  30 +
  31 + // ========== Topic 相关 ==========
  32 +
  33 + public static String buildMessageBusGatewayDeviceMessageTopic(String serverId) {
  34 + return String.format(IotDeviceMessage.MESSAGE_BUS_GATEWAY_DEVICE_MESSAGE_TOPIC, serverId);
  35 + }
12 36
13 /** 37 /**
14 * 生成服务器编号 38 * 生成服务器编号
@@ -22,8 +46,4 @@ public class IotCoreUtils { @@ -22,8 +46,4 @@ public class IotCoreUtils {
22 return serverId.replaceAll("\\.", "_"); 46 return serverId.replaceAll("\\.", "_");
23 } 47 }
24 48
25 - public static String generateMessageId() {  
26 - return IdUtil.fastSimpleUUID();  
27 - }  
28 -  
29 } 49 }
30 \ No newline at end of file 50 \ No newline at end of file
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpDownstreamSubscriber.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.gateway.protocol.http; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.gateway.protocol.http;
3 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; 3 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
4 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber; 4 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  6 +import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
6 import jakarta.annotation.PostConstruct; 7 import jakarta.annotation.PostConstruct;
7 import lombok.RequiredArgsConstructor; 8 import lombok.RequiredArgsConstructor;
8 import lombok.extern.slf4j.Slf4j; 9 import lombok.extern.slf4j.Slf4j;
@@ -27,7 +28,7 @@ public class IotHttpDownstreamSubscriber implements IotMessageSubscriber&lt;IotDevi @@ -27,7 +28,7 @@ public class IotHttpDownstreamSubscriber implements IotMessageSubscriber&lt;IotDevi
27 28
28 @Override 29 @Override
29 public String getTopic() { 30 public String getTopic() {
30 - return IotDeviceMessage.buildMessageBusGatewayDeviceMessageTopic(protocol.getServerId()); 31 + return IotDeviceMessageUtils.buildMessageBusGatewayDeviceMessageTopic(protocol.getServerId());
31 } 32 }
32 33
33 @Override 34 @Override
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpUpstreamProtocol.java
1 package cn.iocoder.yudao.module.iot.gateway.protocol.http; 1 package cn.iocoder.yudao.module.iot.gateway.protocol.http;
2 2
3 import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; 3 import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
4 -import cn.iocoder.yudao.module.iot.core.util.IotCoreUtils; 4 +import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
5 import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties; 5 import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties;
6 import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpUpstreamHandler; 6 import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpUpstreamHandler;
7 import io.vertx.core.AbstractVerticle; 7 import io.vertx.core.AbstractVerticle;
@@ -70,7 +70,7 @@ public class IotHttpUpstreamProtocol extends AbstractVerticle { @@ -70,7 +70,7 @@ public class IotHttpUpstreamProtocol extends AbstractVerticle {
70 } 70 }
71 71
72 public String getServerId() { 72 public String getServerId() {
73 - return IotCoreUtils.generateServerId(httpProperties.getServerPort()); 73 + return IotDeviceMessageUtils.generateServerId(httpProperties.getServerPort());
74 } 74 }
75 75
76 } 76 }
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/upstream/IotDeviceUpstreamClient.java
@@ -19,38 +19,8 @@ public class IotDeviceUpstreamClient implements IotDeviceUpstreamApi { @@ -19,38 +19,8 @@ public class IotDeviceUpstreamClient implements IotDeviceUpstreamApi {
19 private IotDeviceUpstreamApi deviceUpstreamApi; 19 private IotDeviceUpstreamApi deviceUpstreamApi;
20 20
21 @Override 21 @Override
22 - public CommonResult<Boolean> updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {  
23 - return deviceUpstreamApi.updateDeviceState(updateReqDTO);  
24 - }  
25 -  
26 - @Override  
27 - public CommonResult<Boolean> reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) {  
28 - return deviceUpstreamApi.reportDeviceEvent(reportReqDTO);  
29 - }  
30 -  
31 - @Override  
32 - public CommonResult<Boolean> registerDevice(IotDeviceRegisterReqDTO registerReqDTO) {  
33 - return deviceUpstreamApi.registerDevice(registerReqDTO);  
34 - }  
35 -  
36 - @Override  
37 - public CommonResult<Boolean> registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO) {  
38 - return deviceUpstreamApi.registerSubDevice(registerReqDTO);  
39 - }  
40 -  
41 - @Override  
42 - public CommonResult<Boolean> addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO) {  
43 - return deviceUpstreamApi.addDeviceTopology(addReqDTO);  
44 - }  
45 -  
46 - @Override  
47 public CommonResult<Boolean> authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) { 22 public CommonResult<Boolean> authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) {
48 return deviceUpstreamApi.authenticateEmqxConnection(authReqDTO); 23 return deviceUpstreamApi.authenticateEmqxConnection(authReqDTO);
49 } 24 }
50 25
51 - @Override  
52 - public CommonResult<Boolean> reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) {  
53 - return deviceUpstreamApi.reportDeviceProperty(reportReqDTO);  
54 - }  
55 -  
56 } 26 }
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/router/IotDeviceWebhookVertxHandler.java
@@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil; @@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; 5 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
6 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO; 6 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO;
7 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; 7 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
8 import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils; 8 import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils;
9 import io.vertx.core.Handler; 9 import io.vertx.core.Handler;
10 import io.vertx.core.json.JsonObject; 10 import io.vertx.core.json.JsonObject;