DeviceStatusCheckTask.java 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. package com.hfln.device.application.task;
  2. import com.hfln.device.domain.entity.Device;
  3. import com.hfln.device.domain.gateway.DeviceGateway;
  4. import com.hfln.device.domain.gateway.MqttGateway;
  5. import com.hfln.device.domain.service.DeviceManagerService;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.scheduling.annotation.Scheduled;
  9. import org.springframework.stereotype.Component;
  10. import java.util.Collection;
  11. import java.util.Collections;
  12. import java.util.ArrayList;
  13. import java.util.List;
  14. /**
  15. * 设备状态检查任务
  16. * 参考Python版本的check_dev_keepalive和check_dev_alarm_ack功能
  17. */
  18. @Component
  19. @Slf4j
  20. public class DeviceStatusCheckTask {
  21. @Autowired
  22. private DeviceManagerService deviceManagerService;
  23. @Autowired
  24. private DeviceGateway deviceGateway;
  25. @Autowired
  26. private MqttGateway mqttGateway;
  27. /**
  28. * 检查设备保活状态 (参考Python版本的check_dev_keepalive函数)
  29. * 每30秒执行一次
  30. */
  31. @Scheduled(fixedRate = 30000) // 30秒检查一次
  32. public void checkDeviceKeepAlive() {
  33. try {
  34. long currentTime = System.currentTimeMillis();
  35. Collection<Device> deviceCollection = deviceManagerService.getAllDevicesFromCache();
  36. List<Device> allDevices = new ArrayList<>(deviceCollection);
  37. for (Device device : allDevices) {
  38. // 检查在线设备是否超时
  39. if (Integer.valueOf(1).equals(device.getOnline()) && device.isExpired(currentTime)) {
  40. log.info("设备保活超时,设置为离线: deviceId={}, lastKeepAlive={}, currentTime={}",
  41. device.getDevId(), device.getKeepaliveTime(), currentTime);
  42. // 设置设备离线
  43. device.updateOnlineStatus(0);
  44. // 更新数据库在线状态
  45. deviceGateway.updateDeviceOnlineStatus(device.getDevId(), 0);
  46. // 更新设备缓存
  47. deviceManagerService.updateDeviceInCache(device);
  48. // 发送设备状态更新消息
  49. mqttGateway.sendDeviceStatusMessage(device);
  50. }
  51. }
  52. } catch (Exception e) {
  53. log.error("检查设备保活状态异常", e);
  54. }
  55. }
  56. /**
  57. * 检查设备告警确认状态 (参考Python版本的check_dev_alarm_ack函数)
  58. * 每分钟执行一次
  59. */
  60. @Scheduled(fixedRate = 60000) // 60秒检查一次
  61. public void checkDeviceAlarmAck() {
  62. try {
  63. long currentTime = System.currentTimeMillis();
  64. Collection<Device> deviceCollection = deviceManagerService.getAllDevicesFromCache();
  65. List<Device> allDevices = new ArrayList<>(deviceCollection);
  66. for (Device device : allDevices) {
  67. // 检查告警确认是否超时
  68. if (device.shouldClearAlarmAck(currentTime)) {
  69. log.info("告警确认超时,清除确认状态: deviceId={}, currentTime={}",
  70. device.getDevId(), currentTime);
  71. // 清除告警确认状态
  72. device.clearAlarmAck();
  73. // 更新设备缓存
  74. deviceManagerService.updateDeviceInCache(device);
  75. }
  76. }
  77. } catch (Exception e) {
  78. log.error("检查设备告警确认状态异常", e);
  79. }
  80. }
  81. /**
  82. * 检查所有设备停留时间 (参考Python版本的check_all_dev_stay_time函数)
  83. * 每30秒执行一次
  84. */
  85. @Scheduled(fixedRate = 30000) // 30秒检查一次
  86. public void checkAllDeviceStayTime() {
  87. try {
  88. long currentTime = System.currentTimeMillis();
  89. Collection<Device> deviceCollection = deviceManagerService.getAllDevicesFromCache();
  90. List<Device> allDevices = new ArrayList<>(deviceCollection);
  91. for (Device device : allDevices) {
  92. // 检查停留时间
  93. Device.StayTimeRecord stayRecord = device.checkStayTime(currentTime);
  94. if (stayRecord != null) {
  95. log.info("检测到停留事件: deviceId={}, stayTime={}秒",
  96. device.getDevId(), stayRecord.getStayTime() / 1000);
  97. // 记录停留时间到数据库
  98. recordStayTime(stayRecord);
  99. // 如果需要告警,创建滞留告警
  100. if (stayRecord.isNeedAlarm()) {
  101. createRetentionAlarm(stayRecord);
  102. }
  103. // 更新设备缓存
  104. deviceManagerService.updateDeviceInCache(device);
  105. }
  106. }
  107. } catch (Exception e) {
  108. log.error("检查设备停留时间异常", e);
  109. }
  110. }
  111. /**
  112. * 检查所有设备告警计划 (参考Python版本的check_all_dev_alarm_plan函数)
  113. * 每分钟执行一次
  114. */
  115. @Scheduled(fixedRate = 60000) // 60秒检查一次
  116. public void checkAllDeviceAlarmPlan() {
  117. try {
  118. Collection<Device> deviceCollection = deviceManagerService.getAllDevicesFromCache();
  119. List<Device> allDevices = new ArrayList<>(deviceCollection);
  120. for (Device device : allDevices) {
  121. // 检查设备的告警计划
  122. device.checkAlarmPlans();
  123. // 更新设备缓存
  124. deviceManagerService.updateDeviceInCache(device);
  125. }
  126. } catch (Exception e) {
  127. log.error("检查设备告警计划异常", e);
  128. }
  129. }
  130. /**
  131. * 记录停留时间到数据库
  132. */
  133. private void recordStayTime(Device.StayTimeRecord stayRecord) {
  134. try {
  135. // 格式化停留时间
  136. long stayTimeSeconds = stayRecord.getStayTime() / 1000;
  137. long hours = stayTimeSeconds / 3600;
  138. long minutes = (stayTimeSeconds % 3600) / 60;
  139. long seconds = stayTimeSeconds % 60;
  140. String stayTimeStr = String.format("%d时%d分%d秒", hours, minutes, seconds);
  141. // 调用网关记录停留时间
  142. deviceGateway.recordDeviceStayTime(
  143. stayRecord.getDevId(),
  144. stayRecord.getEnterTime(),
  145. stayRecord.getLeaveTime(),
  146. stayTimeStr
  147. );
  148. } catch (Exception e) {
  149. log.error("记录停留时间异常: deviceId={}", stayRecord.getDevId(), e);
  150. }
  151. }
  152. /**
  153. * 创建滞留告警
  154. */
  155. private void createRetentionAlarm(Device.StayTimeRecord stayRecord) {
  156. try {
  157. long currentTime = System.currentTimeMillis();
  158. // 调用网关记录滞留告警
  159. deviceGateway.recordDeviceRetentionAlarm(
  160. stayRecord.getDevId(),
  161. currentTime,
  162. stayRecord.getAlarmType(),
  163. stayRecord.getAlarmDescription()
  164. );
  165. // 发送告警事件消息
  166. mqttGateway.sendAlarmEventMessage(
  167. stayRecord.getDevId(),
  168. stayRecord.getAlarmDescription(),
  169. "alarm_event",
  170. 0 // 表ID,这里用0表示新插入的记录
  171. );
  172. log.info("创建滞留告警: deviceId={}, alarmType={}",
  173. stayRecord.getDevId(), stayRecord.getAlarmType());
  174. } catch (Exception e) {
  175. log.error("创建滞留告警异常: deviceId={}", stayRecord.getDevId(), e);
  176. }
  177. }
  178. }