EquipmentStatusApiServiceImpl.java 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package com.zksy.api.service.impl;
  2. import static com.zksy.common.utils.CollectionSideEffects.*;
  3. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  4. import com.zksy.api.domain.EquipmentBase;
  5. import com.zksy.api.domain.EquipmentStatus;
  6. import com.zksy.api.domain.AlarmData;
  7. import com.zksy.api.event.DeviceStatusChangePublisher;
  8. import com.zksy.api.service.CollectionAlarmWriter;
  9. import com.zksy.api.mapper.EquipmentBaseApiMapper;
  10. import com.zksy.api.mapper.EquipmentStatusApiMapper;
  11. import com.zksy.api.service.EquipmentStatusApiService;
  12. import lombok.extern.slf4j.Slf4j;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.stereotype.Service;
  15. import org.springframework.transaction.annotation.Transactional;
  16. import org.springframework.transaction.support.TransactionSynchronization;
  17. import org.springframework.transaction.support.TransactionSynchronizationManager;
  18. import java.time.LocalDateTime;
  19. import java.util.Objects;
  20. /**
  21. * 设备报警状态服务实现
  22. * 根据设备编码更新 equipment_status 表的报警状态
  23. */
  24. @Slf4j
  25. @Service
  26. public class EquipmentStatusApiServiceImpl implements EquipmentStatusApiService {
  27. @Autowired
  28. private EquipmentBaseApiMapper equipmentBaseApiMapper;
  29. @Autowired
  30. private EquipmentStatusApiMapper equipmentStatusApiMapper;
  31. @Autowired
  32. private DeviceStatusChangePublisher deviceStatusChangePublisher;
  33. @Autowired
  34. private CollectionAlarmWriter collectionAlarmWriter;
  35. @Override
  36. @Transactional
  37. public boolean updateAlarmStatus(String deviceCode, Integer alarmStatus) {
  38. if (deviceCode == null || deviceCode.isEmpty()) {
  39. log.warn("更新设备报警状态失败:deviceCode为空");
  40. return false;
  41. }
  42. // 1. 根据设备编码查询设备基础信息,获取 equipmentId
  43. EquipmentBase equipmentBase = equipmentBaseApiMapper.selectOne(
  44. new LambdaQueryWrapper<EquipmentBase>()
  45. .eq(EquipmentBase::getEquipmentCode, deviceCode)
  46. .last("LIMIT 1"));
  47. if (equipmentBase == null) {
  48. log.warn("更新设备报警状态失败:未找到设备编码对应的设备信息,deviceCode={}", deviceCode);
  49. return false;
  50. }
  51. String equipmentId = equipmentBase.getEquipmentId();
  52. // 2. 查询是否已有状态记录
  53. EquipmentStatus existingStatus = equipmentStatusApiMapper.selectOne(
  54. new LambdaQueryWrapper<EquipmentStatus>()
  55. .eq(EquipmentStatus::getEquipmentId, equipmentId));
  56. if (existingStatus != null) {
  57. Integer previousAlarmStatus = existingStatus.getAlarmStatus();
  58. // 更新已有记录
  59. existingStatus.setAlarmStatus(alarmStatus);
  60. existingStatus.setStatusUpdateTime(LocalDateTime.now());
  61. int affected = equipmentStatusApiMapper.updateById(existingStatus);
  62. if (affected <= 0) {
  63. return false;
  64. }
  65. log.info("更新设备报警状态成功: deviceCode={}, equipmentId={}, alarmStatus={}",
  66. deviceCode, equipmentId, alarmStatus);
  67. if (!Objects.equals(previousAlarmStatus, alarmStatus)) {
  68. deviceStatusChangePublisher.publishAfterCommit(deviceCode, equipmentId,
  69. existingStatus.getCurrentStatus(), existingStatus.getAlarmStatus(),
  70. existingStatus.getOnlineStatus(), "zk-api:updateAlarmStatus");
  71. }
  72. } else {
  73. // 不存在则创建新记录
  74. EquipmentStatus newStatus = new EquipmentStatus();
  75. newStatus.setEquipmentId(equipmentId);
  76. newStatus.setAlarmStatus(alarmStatus);
  77. newStatus.setCurrentStatus(1); // 默认在用
  78. newStatus.setOnlineStatus(1); // 默认在线
  79. newStatus.setStatusUpdateTime(LocalDateTime.now());
  80. newStatus.setCreateTime(LocalDateTime.now());
  81. int affected = equipmentStatusApiMapper.insert(newStatus);
  82. if (affected <= 0) {
  83. return false;
  84. }
  85. log.info("创建设备报警状态记录成功: deviceCode={}, equipmentId={}, alarmStatus={}",
  86. deviceCode, equipmentId, alarmStatus);
  87. deviceStatusChangePublisher.publishAfterCommit(deviceCode, equipmentId,
  88. newStatus.getCurrentStatus(), newStatus.getAlarmStatus(),
  89. newStatus.getOnlineStatus(), "zk-api:updateAlarmStatus");
  90. }
  91. return true;
  92. }
  93. @Override
  94. @Transactional
  95. public boolean updateOnlineStatus(String deviceCode, Integer onlineStatus) {
  96. if (deviceCode == null || deviceCode.isEmpty()) {
  97. log.warn("更新设备在线状态失败:deviceCode为空");
  98. return false;
  99. }
  100. EquipmentBase equipmentBase = equipmentBaseApiMapper.selectOne(
  101. new LambdaQueryWrapper<EquipmentBase>()
  102. .eq(EquipmentBase::getEquipmentCode, deviceCode)
  103. .last("LIMIT 1"));
  104. if (equipmentBase == null) {
  105. log.warn("更新设备在线状态失败:未找到设备编码对应的设备信息,deviceCode={}", deviceCode);
  106. return false;
  107. }
  108. String equipmentId = equipmentBase.getEquipmentId();
  109. EquipmentStatus existingStatus = equipmentStatusApiMapper.selectOne(
  110. new LambdaQueryWrapper<EquipmentStatus>()
  111. .eq(EquipmentStatus::getEquipmentId, equipmentId));
  112. if (existingStatus != null) {
  113. Integer previousOnlineStatus = existingStatus.getOnlineStatus();
  114. existingStatus.setOnlineStatus(onlineStatus);
  115. existingStatus.setStatusUpdateTime(LocalDateTime.now());
  116. int affected = equipmentStatusApiMapper.updateById(existingStatus);
  117. if (affected <= 0) {
  118. return false;
  119. }
  120. log.info("更新设备在线状态成功: deviceCode={}, equipmentId={}, onlineStatus={}",
  121. deviceCode, equipmentId, onlineStatus);
  122. if (!Objects.equals(previousOnlineStatus, onlineStatus)) {
  123. deviceStatusChangePublisher.publishAfterCommit(deviceCode, equipmentId,
  124. existingStatus.getCurrentStatus(), existingStatus.getAlarmStatus(),
  125. existingStatus.getOnlineStatus(), "zk-api:updateOnlineStatus");
  126. }
  127. // 设备由在线转为离线时,新增离线报警记录
  128. if (previousOnlineStatus != null && previousOnlineStatus == 1 && onlineStatus == 0) {
  129. saveOfflineAlarmAfterCommit(deviceCode);
  130. }
  131. // 收到有效数据重新上线后,自动处理对应的离线告警;恢复失败不影响在线状态和后续采集。
  132. if (previousOnlineStatus != null && previousOnlineStatus == 0 && onlineStatus == 1) {
  133. recoverOfflineAlarmAfterCommit(deviceCode);
  134. }
  135. } else {
  136. EquipmentStatus newStatus = new EquipmentStatus();
  137. newStatus.setEquipmentId(equipmentId);
  138. newStatus.setOnlineStatus(onlineStatus);
  139. newStatus.setAlarmStatus(0);
  140. newStatus.setCurrentStatus(1);
  141. newStatus.setStatusUpdateTime(LocalDateTime.now());
  142. newStatus.setCreateTime(LocalDateTime.now());
  143. int affected = equipmentStatusApiMapper.insert(newStatus);
  144. if (affected <= 0) {
  145. return false;
  146. }
  147. log.info("创建设备在线状态记录成功: deviceCode={}, equipmentId={}, onlineStatus={}",
  148. deviceCode, equipmentId, onlineStatus);
  149. deviceStatusChangePublisher.publishAfterCommit(deviceCode, equipmentId,
  150. newStatus.getCurrentStatus(), newStatus.getAlarmStatus(),
  151. newStatus.getOnlineStatus(), "zk-api:updateOnlineStatus");
  152. }
  153. return true;
  154. }
  155. /**
  156. * 新增设备离线报警记录
  157. */
  158. private void saveOfflineAlarmAfterCommit(String deviceCode) {
  159. if (TransactionSynchronizationManager.isSynchronizationActive()) {
  160. TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  161. @Override
  162. public void afterCommit() {
  163. run(deviceCode, "离线报警独立事务", () -> saveOfflineAlarm(deviceCode));
  164. }
  165. });
  166. } else {
  167. run(deviceCode, "离线报警", () -> saveOfflineAlarm(deviceCode));
  168. }
  169. }
  170. private void saveOfflineAlarm(String deviceCode) {
  171. AlarmData alarmData = new AlarmData();
  172. alarmData.setDeviceCode(deviceCode);
  173. alarmData.setWarningCode("OFFLINE");
  174. alarmData.setAlarmLevel(4);
  175. alarmData.setAlarmStatus(0);
  176. alarmData.setCreateTime(LocalDateTime.now());
  177. alarmData.setCreateTime(LocalDateTime.now());
  178. if (collectionAlarmWriter.saveOrUpdateUnhandled(alarmData)) {
  179. log.info("设备离线报警数据入库成功: deviceCode={}, alarmId={}", deviceCode, alarmData.getId());
  180. }
  181. }
  182. private void recoverOfflineAlarmAfterCommit(String deviceCode) {
  183. if (TransactionSynchronizationManager.isSynchronizationActive()) {
  184. TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  185. @Override
  186. public void afterCommit() {
  187. run(deviceCode, "离线告警恢复独立事务", () ->
  188. collectionAlarmWriter.markRecovered(deviceCode, "OFFLINE"));
  189. }
  190. });
  191. } else {
  192. run(deviceCode, "离线告警恢复", () ->
  193. collectionAlarmWriter.markRecovered(deviceCode, "OFFLINE"));
  194. }
  195. }
  196. }