Commit 5db1c5116c338653d7e97555ddbb0e70a8651299

Authored by YunaiV
1 parent 56b2b540

refactor(iot): 对齐设备影子代码风格

yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceShadowController.java
... ... @@ -57,31 +57,23 @@ public class IotDeviceShadowController {
57 57 public CommonResult<IotDeviceShadowRespVO> getDeviceShadow(@RequestParam("deviceId") Long deviceId) {
58 58 IotDeviceDO device = deviceService.validateDeviceExists(deviceId);
59 59 IotDeviceShadowDO shadow = deviceShadowService.getOrCreateShadow(device);
60   -
  60 + // 拼接 VO
61 61 List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductIdAndType(
62 62 device.getProductId(), IotThingModelTypeEnum.PROPERTY.getType());
63 63 Map<String, Object> desired = shadow.getDesired() != null ? shadow.getDesired() : MapUtil.empty();
64 64 Map<String, Object> reported = shadow.getReported() != null ? shadow.getReported() : MapUtil.empty();
65 65 Map<String, Object> metadata = shadow.getMetadata() != null ? shadow.getMetadata() : MapUtil.empty();
66   - // 拼接 VO
67 66 List<IotDeviceShadowPropertyRespVO> properties = convertList(thingModels, thingModel -> {
68 67 ThingModelProperty prop = thingModel.getProperty();
69 68 Assert.notNull(prop, "属性不能为空");
70   - return new IotDeviceShadowPropertyRespVO()
71   - .setIdentifier(thingModel.getIdentifier()).setName(thingModel.getName())
72   - .setDataType(prop.getDataType()).setDataSpecs(prop.getDataSpecs())
73   - .setDataSpecsList(prop.getDataSpecsList())
74   - .setDesiredValue(desired.get(thingModel.getIdentifier()))
75   - .setReportedValue(reported.get(thingModel.getIdentifier()))
  69 + return new IotDeviceShadowPropertyRespVO().setIdentifier(thingModel.getIdentifier()).setName(thingModel.getName())
  70 + .setDataType(prop.getDataType()).setDataSpecs(prop.getDataSpecs()).setDataSpecsList(prop.getDataSpecsList())
  71 + .setDesiredValue(desired.get(thingModel.getIdentifier())).setReportedValue(reported.get(thingModel.getIdentifier()))
76 72 .setDesiredTime(IotDeviceShadowProtocolUtils.getDesiredTimestamp(metadata, thingModel.getIdentifier()))
77 73 .setReportedTime(IotDeviceShadowProtocolUtils.getReportedTimestamp(metadata, thingModel.getIdentifier()));
78 74 });
79   -
80 75 IotDeviceShadowRespVO respVO = BeanUtils.toBean(shadow, IotDeviceShadowRespVO.class)
81   - .setProperties(properties)
82   - .setDesired(desired)
83   - .setReported(reported)
84   - .setMetadata(metadata);
  76 + .setProperties(properties).setDesired(desired).setReported(reported).setMetadata(metadata);
85 77 return success(respVO);
86 78 }
87 79  
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/shadow/IotDeviceShadowRespVO.java
... ... @@ -21,7 +21,7 @@ public class IotDeviceShadowRespVO {
21 21 @Schema(description = "最后更新时间(epoch 秒)", example = "1469564576")
22 22 private Long shadowTime;
23 23  
24   - @Schema(description = "是否启用", example = "0")
  24 + @Schema(description = "影子状态", example = "0")
25 25 private Integer status;
26 26  
27 27 @Schema(description = "属性对比列表")
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceShadowDO.java
... ... @@ -34,6 +34,8 @@ public class IotDeviceShadowDO extends TenantBaseDO {
34 34 private Long id;
35 35 /**
36 36 * 设备编号
  37 + * <p>
  38 + * 关联 {@link IotDeviceDO#getId()}
37 39 */
38 40 private Long deviceId;
39 41 /**
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/shadow/IotDeviceShadowServiceImpl.java
... ... @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.service.device.shadow;
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.date.DateUtil;
5 5 import cn.hutool.core.lang.Assert;
  6 +import cn.hutool.core.map.MapUtil;
6 7 import cn.hutool.core.util.ObjUtil;
7 8 import cn.hutool.core.util.StrUtil;
8 9 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
... ... @@ -96,6 +97,14 @@ public class IotDeviceShadowServiceImpl implements IotDeviceShadowService {
96 97 }
97 98 }
98 99  
  100 + /**
  101 + * 处理设备影子上行:解析 params,并按内层 method 分发到 get、update
  102 + * <p>
  103 + * 影子未启用时,直接忽略,不回复
  104 + *
  105 + * @param device 设备
  106 + * @param message 上行消息
  107 + */
99 108 private void handleDeviceShadowUpdate0(IotDeviceDO device, IotDeviceMessage message) {
100 109 // 1.1 解析请求:params 结构为 { method, state: { reported }, version }
101 110 IotDeviceShadowUpdateReqDTO reqDTO = JsonUtils.convertObject(message.getParams(),
... ... @@ -125,6 +134,14 @@ public class IotDeviceShadowServiceImpl implements IotDeviceShadowService {
125 134 shadow.getVersion());
126 135 }
127 136  
  137 + /**
  138 + * 处理设备上报的 update:version 为 -1 时清空影子,否则合并 reported,并回复新版本
  139 + *
  140 + * @param device 设备
  141 + * @param message 上行消息
  142 + * @param reqDTO 上行 params
  143 + * @param shadow DB 中的当前影子,用于错误回复时携带版本
  144 + */
128 145 private void handleReportedUpdate(IotDeviceDO device, IotDeviceMessage message,
129 146 IotDeviceShadowUpdateReqDTO reqDTO, IotDeviceShadowDO shadow) {
130 147 // 1. version 为 -1 时,清空影子,无需 state
... ... @@ -269,13 +286,14 @@ public class IotDeviceShadowServiceImpl implements IotDeviceShadowService {
269 286 }
270 287  
271 288 // 2.1 合并属性,并校验属性数
272   - Map<String, Object> state = mergeMap(desired ? latest.getDesired() : latest.getReported(), values);
  289 + Map<String, Object> state = new HashMap<>(MapUtil.emptyIfNull(desired ? latest.getDesired() : latest.getReported()));
  290 + state.putAll(values);
273 291 if (state.size() > MAX_PROPERTY_COUNT) {
274 292 throw exception(DEVICE_SHADOW_PROPERTY_COUNT_EXCEEDED);
275 293 }
276 294 // 2.2 记录属性的更新时间
277 295 long now = DateUtil.currentSeconds();
278   - Map<String, Object> metadata = mergeMap(latest.getMetadata(), null);
  296 + Map<String, Object> metadata = new HashMap<>(MapUtil.emptyIfNull(latest.getMetadata()));
279 297 if (desired) {
280 298 IotDeviceShadowProtocolUtils.putDesiredTimestamps(metadata, values.keySet(), now);
281 299 } else {
... ... @@ -338,6 +356,9 @@ public class IotDeviceShadowServiceImpl implements IotDeviceShadowService {
338 356 });
339 357 }
340 358  
  359 + /**
  360 + * 回复全量影子:设备 get 请求的回复,或 desired 更新后的主动推送(requestId 为空)
  361 + */
341 362 private void sendShadowGetReply(IotDeviceDO device, String serverId, String requestId, IotDeviceShadowDO shadow) {
342 363 sendShadowReply(device, serverId, requestId, SUCCESS.getCode(), SUCCESS.getMsg(),
343 364 IotDeviceShadowProtocolUtils.buildGetData(shadow.getDesired(), shadow.getReported(),
... ... @@ -381,12 +402,4 @@ public class IotDeviceShadowServiceImpl implements IotDeviceShadowService {
381 402 }
382 403 }
383 404  
384   - private static Map<String, Object> mergeMap(Map<String, Object> oldMap, Map<String, Object> newMap) {
385   - Map<String, Object> result = oldMap != null ? new HashMap<>(oldMap) : new HashMap<>();
386   - if (CollUtil.isNotEmpty(newMap)) {
387   - result.putAll(newMap);
388   - }
389   - return result;
390   - }
391   -
392 405 }
... ...
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/util/IotDeviceShadowProtocolUtils.java
1 1 package cn.iocoder.yudao.module.iot.core.util;
2 2  
3 3 import cn.hutool.core.map.MapUtil;
  4 +import lombok.experimental.UtilityClass;
4 5  
5 6 import java.util.HashMap;
6 7 import java.util.Map;
... ... @@ -13,11 +14,9 @@ import java.util.Set;
13 14 *
14 15 * @author 芋道源码
15 16 */
  17 +@UtilityClass
16 18 public final class IotDeviceShadowProtocolUtils {
17 19  
18   - private IotDeviceShadowProtocolUtils() {
19   - }
20   -
21 20 // ========== 内层 method(上行 params.method) ==========
22 21  
23 22 public static final String INNER_METHOD_GET = "get";
... ...