From ab73d00299e09ceb2caae73a751437c0baad284f Mon Sep 17 00:00:00 2001 From: tianyongbao Date: Sun, 8 Mar 2026 13:54:28 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=80=BB=E8=BE=91=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../intc/iot/handler/DeviceDataHandler.java | 98 ++++++++++++++++++- .../service/impl/AmqpMessageHandlerImpl.java | 21 ++-- 2 files changed, 109 insertions(+), 10 deletions(-) diff --git a/intc-modules/intc-iot/src/main/java/com/intc/iot/handler/DeviceDataHandler.java b/intc-modules/intc-iot/src/main/java/com/intc/iot/handler/DeviceDataHandler.java index 3f6346e..e717d28 100644 --- a/intc-modules/intc-iot/src/main/java/com/intc/iot/handler/DeviceDataHandler.java +++ b/intc-modules/intc-iot/src/main/java/com/intc/iot/handler/DeviceDataHandler.java @@ -115,12 +115,14 @@ public class DeviceDataHandler { private static final int WARN_TYPE_DISSOLVED_OXYGEN = 2; // 溶解氧 private static final int WARN_TYPE_TEMPERATURE = 2; // 温度 private static final int WARN_TYPE_BATTERY = 2; // 电池电量 + private static final int WARN_TYPE_OFFLINE = 5; // 设备离线 /** * 告警类型名称 */ private static final String ALARM_TYPE_DISSOLVED_OXYGEN = "溶解氧"; - private static final String ALARM_TYPE_TEMPERATURE = "温度"; + private static final String ALARM_TYPE_TEMPERATURE_HIGH = "温度过高"; + private static final String ALARM_TYPE_TEMPERATURE_LOW = "温度过低"; private static final String ALARM_TYPE_BATTERY = "电池电量"; /** @@ -380,7 +382,7 @@ public class DeviceDataHandler { alarmMessage.append(message).append("; "); warnList.add(createMessageWarn(deviceId, userId, pondName, - ALARM_TYPE_TEMPERATURE, WARN_TYPE_TEMPERATURE, message)); + ALARM_TYPE_TEMPERATURE_LOW, WARN_TYPE_TEMPERATURE, message)); hasAlarm = true; } else if (tempWarnUpper != null && temperature > tempWarnUpper) { String message = String.format("水温过高: %.2f °C (最高: %.2f)", @@ -388,7 +390,7 @@ public class DeviceDataHandler { alarmMessage.append(message).append("; "); warnList.add(createMessageWarn(deviceId, userId, pondName, - ALARM_TYPE_TEMPERATURE, WARN_TYPE_TEMPERATURE, message)); + ALARM_TYPE_TEMPERATURE_HIGH, WARN_TYPE_TEMPERATURE, message)); hasAlarm = true; } } @@ -588,6 +590,96 @@ public class DeviceDataHandler { } } + /** + * 处理设备离线告警 + * 当设备离线时,查询设备信息并发送语音通知 + * + * @param deviceName 设备名称(serialNum) + */ + public void handleDeviceOffline(String deviceName) { + try { + Device device = deviceMapper.selectOne( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(Device::getSerialNum, deviceName) + .last("LIMIT 1") + ); + + if (device == null) { + log.debug("[离线告警] 设备不存在,跳过: {}", deviceName); + return; + } + + Long deviceId = device.getId(); + Long userId = device.getUserId(); + + if (userId == null) { + log.debug("[离线告警] 设备未绑定用户,跳过: {}", deviceName); + return; + } + + // 查询手机号 + AquUser aquUser = aquUserMapper.selectById(userId); + if (aquUser == null || StrUtil.isBlank(aquUser.getMobilePhone())) { + log.warn("[离线告警] 用户手机号不存在,跳过: {}", deviceName); + return; + } + String mobilePhone = aquUser.getMobilePhone(); + + // 检查告警间隔(防止频繁通知) + LocalDateTime intervalTime = LocalDateTime.now().minusMinutes(ALARM_NOTIFICATION_INTERVAL); + long recentCount = warnCallNoticeMapper.selectCount( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(AquWarnCallNotice::getDeviceId, deviceId) + .ge(AquWarnCallNotice::getCallTime, intervalTime) + ); + if (recentCount > 0) { + log.debug("[离线告警] {}分钟内已通知,跳过: {}", ALARM_NOTIFICATION_INTERVAL, deviceName); + return; + } + + // 查询塘口名称 + String pondName = deviceName; + if (device.getPondId() != null) { + Pond pond = pondMapper.selectById(device.getPondId()); + if (pond != null) { + pondName = pond.getPondName(); + } + } + + // 写入告警消息 + String warnMsg = "设备离线"; + MessageWarn warn = createMessageWarn(deviceId, userId, pondName, + "设备离线", WARN_TYPE_OFFLINE, warnMsg); + messageWarnMapper.insert(warn); + + // 创建通知记录 + AquWarnCallNotice callNotice = new AquWarnCallNotice(); + callNotice.setUserId(userId); + callNotice.setMobilePhone(mobilePhone); + callNotice.setDeviceId(deviceId); + callNotice.setPondName(pondName); + callNotice.setCallTime(LocalDateTime.now()); + callNotice.setCallStatus(CALL_STATUS_NO_CALL); + warnCallNoticeMapper.insert(callNotice); + + // 保存关联记录 + if (warn.getId() != null) { + AquMapMessageWarnCallNotice mapRecord = new AquMapMessageWarnCallNotice(); + mapRecord.setMessageWarnId(warn.getId()); + mapRecord.setCallNoticeId(callNotice.getId()); + mapMessageWarnCallNoticeMapper.insert(mapRecord); + } + + // 发送语音通知 + sendVoiceNotification(callNotice, device.getDeviceName() != null ? device.getDeviceName() : deviceName, warnMsg); + + log.info("[离线告警] 已触发通知 - 设备: {}, 手机: {}", deviceName, mobilePhone); + + } catch (Exception e) { + log.error("[离线告警] 处理失败: {}", e.getMessage(), e); + } + } + /** * 触发设备故障告警 * 针对设备事件(error)的紧急告警 diff --git a/intc-modules/intc-iot/src/main/java/com/intc/iot/service/impl/AmqpMessageHandlerImpl.java b/intc-modules/intc-iot/src/main/java/com/intc/iot/service/impl/AmqpMessageHandlerImpl.java index d054cb1..3eda2a1 100644 --- a/intc-modules/intc-iot/src/main/java/com/intc/iot/service/impl/AmqpMessageHandlerImpl.java +++ b/intc-modules/intc-iot/src/main/java/com/intc/iot/service/impl/AmqpMessageHandlerImpl.java @@ -241,10 +241,12 @@ public class AmqpMessageHandlerImpl implements AmqpMessageHandler { private void handleStatusMessage(JSONObject json) { String deviceName = json.getStr("deviceName"); String status = json.getStr("status"); - + log.debug("设备状态: {} - {}", deviceName, status); - - // TODO: 更新设备状态 + + if ("offline".equals(status) && deviceDataHandler != null && deviceName != null) { + deviceDataHandler.handleDeviceOffline(deviceName); + } } /** @@ -253,11 +255,16 @@ public class AmqpMessageHandlerImpl implements AmqpMessageHandler { private void handleLifeCycleMessage(JSONObject json) { String deviceName = json.getStr("deviceName"); String action = json.getStr("action"); - + // 先尝试 status 字段(部分消息格式用 status 而非 action) + if (action == null) { + action = json.getStr("status"); + } + log.debug("设备{}: {}", "online".equals(action) ? "上线" : "下线", deviceName); - - // action: "online" 或 "offline" - // TODO: 更新设备在线状态 + + if ("offline".equals(action) && deviceDataHandler != null && deviceName != null) { + deviceDataHandler.handleDeviceOffline(deviceName); + } } }