Commit eb74f753a8e514c04581f3ca259bc59c60acdbb9

Authored by YunaiV
1 parent 7fe4dd23

【功能新增】IoT:增加 IotDeviceOnlineMessageConsumer,处理设备自动上线

yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageIdentifierEnum.java
@@ -15,7 +15,9 @@ public enum IotDeviceMessageIdentifierEnum { @@ -15,7 +15,9 @@ public enum IotDeviceMessageIdentifierEnum {
15 PROPERTY_REPORT("report"), 15 PROPERTY_REPORT("report"),
16 16
17 STATE_ONLINE("online"), 17 STATE_ONLINE("online"),
18 - STATE_OFFLINE("offline"); 18 + STATE_OFFLINE("offline"),
  19 +
  20 + SERVICE_REPLY_SUFFIX("_reply");
19 21
20 22
21 /** 23 /**
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageTypeEnum.java
@@ -15,7 +15,8 @@ public enum IotDeviceMessageTypeEnum implements ArrayValuable<String> { @@ -15,7 +15,8 @@ public enum IotDeviceMessageTypeEnum implements ArrayValuable<String> {
15 15
16 STATE("state"), // 设备状态 16 STATE("state"), // 设备状态
17 PROPERTY("property"), // 设备属性 17 PROPERTY("property"), // 设备属性
18 - EVENT("event"); // 设备事件 18 + EVENT("event"), // 设备事件
  19 + SERVICE("service"); // 设备服务
19 20
20 public static final String[] ARRAYS = Arrays.stream(values()).map(IotDeviceMessageTypeEnum::getType).toArray(String[]::new); 21 public static final String[] ARRAYS = Arrays.stream(values()).map(IotDeviceMessageTypeEnum::getType).toArray(String[]::new);
21 22
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceStateEnum.java
@@ -35,4 +35,8 @@ public enum IotDeviceStateEnum implements ArrayValuable<Integer> { @@ -35,4 +35,8 @@ public enum IotDeviceStateEnum implements ArrayValuable<Integer> {
35 return ARRAYS; 35 return ARRAYS;
36 } 36 }
37 37
  38 + public static boolean isOnline(Integer state) {
  39 + return ONLINE.getState().equals(state);
  40 + }
  41 +
38 } 42 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/job/device/IotDeviceOfflineCheckJob.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.job.device;
  2 +
  3 +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
  4 +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
  5 +import org.springframework.stereotype.Component;
  6 +
  7 +// TODO @芋艿:待实现
  8 +/**
  9 + * IoT 设备离线检查 Job
  10 + *
  11 + * 检测逻辑:设备最后一条 {@link cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage} 消息超过一定时间,则认为设备离线
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Component
  16 +public class IotDeviceOfflineCheckJob implements JobHandler {
  17 +
  18 + @Override
  19 + @TenantJob
  20 + public String execute(String param) {
  21 + return "";
  22 + }
  23 +
  24 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceOnlineMessageConsumer.java 0 → 100644
  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.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.upstream.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 +}
0 \ No newline at end of file 86 \ No newline at end of file