765 lines
26 KiB
C#
765 lines
26 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using UnityEngine;
|
||
using System.Collections; // 确保有这个 using
|
||
|
||
|
||
public enum AlarmPriority
|
||
{
|
||
None,
|
||
Low,
|
||
Medium,
|
||
High
|
||
}
|
||
|
||
public class AlarmEvent
|
||
{
|
||
public int Id;
|
||
public AlarmPriority Priority;
|
||
public string Reason;
|
||
public DateTime Time;
|
||
}
|
||
/// <summary>
|
||
/// DCS协议报警管理器 - 统一管理所有报警功能,包括串口通信、界面显示和声音播放
|
||
/// </summary>
|
||
public class DCSAlarmManager : MonoBehaviour
|
||
{
|
||
public static DCSAlarmManager Instance { get; private set; }
|
||
|
||
// 报警事件,供UI组件订阅
|
||
public static event Action<AlarmPriority, string> OnAlarmRaised;
|
||
public static event Action OnAlarmCleared; // 所有报警消除时触发
|
||
public static event Action<bool> OnMuteStateChanged;
|
||
|
||
private ISerialCommunicationService _serialService;
|
||
private AlarmRecordPersistenceService _recordPersistence;
|
||
|
||
// 静音功能
|
||
// private bool _isMuted = false;
|
||
// private DateTime _muteEndTime = DateTime.MinValue;
|
||
|
||
// 报警记录管理
|
||
private readonly List<AlarmEvent> _alarmRecords = new List<AlarmEvent>();
|
||
private const int MAX_ALARM_RECORDS = 1000; // 最大记录数
|
||
|
||
// 10秒内报警相关
|
||
private readonly int delayTime = 10;
|
||
|
||
private bool _isPowerAlarmActive = false;
|
||
private bool _isLowBatteryAlarmActive = false;
|
||
private bool _isMediumBatteryAlarmActive = false;
|
||
|
||
private int _nextAlarmId = 1;
|
||
// public bool IsMuted
|
||
// {
|
||
// get
|
||
// {
|
||
// // 检查定时静音是否已过期
|
||
// if (_muteEndTime > DateTime.MinValue && DateTime.Now >= _muteEndTime)
|
||
// {
|
||
// _isMuted = false;
|
||
// _muteEndTime = DateTime.MinValue;
|
||
// OnMuteStateChanged?.Invoke(false);
|
||
// }
|
||
// return _isMuted;
|
||
// }
|
||
// }
|
||
|
||
// 报警代码到消息的映射
|
||
private readonly Dictionary<byte, (AlarmPriority priority, string message)> _alarmCodeMap = new()
|
||
{
|
||
{ 0x11, (AlarmPriority.Low, "电池电量低(<40%)") },
|
||
{ 0x21, (AlarmPriority.Medium, "电池电量低(<20%)") },
|
||
{ 0x31, (AlarmPriority.High, "电池电量空(<5%)") },
|
||
{ 0x32, (AlarmPriority.High, "BFI数值异常") },
|
||
{ 0x22, (AlarmPriority.Medium, "激光器温度异常") },
|
||
{ 0x33, (AlarmPriority.High, "激光器工作异常") },
|
||
{ 0x34, (AlarmPriority.High, "通信异常") },
|
||
{ 0x35, (AlarmPriority.Medium, "电池故障") },
|
||
{ 0x12, (AlarmPriority.Low, "交流电未连接") }
|
||
};
|
||
|
||
// 当前活跃的报警
|
||
private readonly HashSet<byte> _activeAlarms = new();
|
||
|
||
// 当前活跃报警的最高优先级
|
||
private AlarmPriority _currentHighestPriority = AlarmPriority.None;
|
||
|
||
// 报警发送频率限制
|
||
private readonly Dictionary<byte, DateTime> _lastAlarmSendTime = new();
|
||
private readonly Dictionary<byte, bool> _lastAlarmState = new(); // 记录上次报警状态
|
||
private const int ALARM_SEND_INTERVAL_MS = 1000; // 同一报警状态1秒内不重复发送
|
||
|
||
// 启动阶段的通讯异常检测
|
||
private bool _communicationErrorDuringStartup = false;
|
||
public bool HasCommunicationErrorDuringStartup => _communicationErrorDuringStartup;
|
||
|
||
void Awake()
|
||
{
|
||
if (Instance == null)
|
||
{
|
||
Instance = this;
|
||
|
||
DontDestroyOnLoad(gameObject);
|
||
}
|
||
else
|
||
{
|
||
Destroy(gameObject);
|
||
}
|
||
}
|
||
|
||
void Start(){
|
||
_serialService = ServiceLocator.Get<ISerialCommunicationService>();
|
||
_recordPersistence = new AlarmRecordPersistenceService();
|
||
InitializeCurrentSettings();
|
||
|
||
// 从持久化存储加载历史记录
|
||
LoadPersistedRecords();
|
||
}
|
||
|
||
|
||
private void InitializeCurrentSettings()
|
||
{
|
||
// 从配置服务加载当前阈值设置
|
||
var settingsService = ServiceLocator.Get<ISystemSettingsService>();
|
||
|
||
BFIThresholdSettings _settings = new BFIThresholdSettings
|
||
{
|
||
MinThreshold = settingsService?.BFILowThreshold ?? _bfiLowThreshold,
|
||
MaxThreshold = settingsService?.BFIHighThreshold ??_bfiHighThreshold,
|
||
// EnableLowAlarm = settingsService?.EnableBFIAlarm ?? true,
|
||
// EnableHighAlarm = settingsService?.EnableBFIAlarm ?? true,
|
||
AlarmPriority = (AlarmPriority)(settingsService?.BFIAlarmPriority ?? 2)
|
||
};
|
||
UpdateBFIThresholds(
|
||
_settings.MinThreshold,
|
||
_settings.MaxThreshold,
|
||
(int)_settings.AlarmPriority,
|
||
true
|
||
);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送报警控制命令到下位机
|
||
/// 统一协调串口命令发送、界面显示和声音播放
|
||
/// </summary>
|
||
public void SendAlarmCommand(byte alarmCode, AlarmPriority priority, bool trigger)
|
||
{
|
||
|
||
if (_serialService == null) return;
|
||
var now = DateTime.Now;
|
||
|
||
// 检查报警状态是否改变
|
||
bool stateChanged = false;
|
||
if (_lastAlarmState.TryGetValue(alarmCode, out var lastState))
|
||
{
|
||
stateChanged = (lastState != trigger);
|
||
}
|
||
else
|
||
{
|
||
stateChanged = true; // 首次发送
|
||
}
|
||
|
||
// 如果状态未改变,检查重发间隔
|
||
if (!stateChanged)
|
||
{
|
||
if (_lastAlarmSendTime.TryGetValue(alarmCode, out var lastSendTime))
|
||
{
|
||
var timeSinceLastSend = (now - lastSendTime).TotalMilliseconds;
|
||
if (timeSinceLastSend < ALARM_SEND_INTERVAL_MS)
|
||
{
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
Debug.Log($"报警重发: 代码=0x{alarmCode:X2}, 状态={trigger}, 距离上次{timeSinceLastSend/1000:F0}秒");
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.Log($"报警状态变化: 代码=0x{alarmCode:X2}, {lastState}→{trigger}");
|
||
}
|
||
|
||
try
|
||
{
|
||
// 1. 发送串口命令
|
||
byte priorityByte = priority switch
|
||
{
|
||
AlarmPriority.Low => 0,
|
||
AlarmPriority.Medium => 1,
|
||
AlarmPriority.High => 2,
|
||
_ => 1
|
||
};
|
||
|
||
byte stateByte = (byte)(trigger ? 1 : 0);
|
||
|
||
_serialService.SendAlarmCommand(alarmCode, priorityByte, stateByte);
|
||
_lastAlarmSendTime[alarmCode] = now;
|
||
_lastAlarmState[alarmCode] = trigger; // 更新状态记录
|
||
|
||
// 更新活跃报警集合
|
||
if (trigger)
|
||
{
|
||
_activeAlarms.Add(alarmCode);
|
||
}
|
||
else
|
||
{
|
||
_activeAlarms.Remove(alarmCode);
|
||
}
|
||
|
||
// 更新当前最高优先级
|
||
UpdateHighestPriority();
|
||
|
||
Debug.Log($"[报警命令] 代码=0x{alarmCode:X2}, 优先级={priority}, 状态={trigger}");
|
||
|
||
// 2. 记录报警状态变化(触发和解除都记录)
|
||
if (_alarmCodeMap.TryGetValue(alarmCode, out var alarmInfoForRecord))
|
||
{
|
||
var alarmEvent = new AlarmEvent
|
||
{
|
||
Id = _nextAlarmId++,
|
||
Priority = alarmInfoForRecord.priority,
|
||
Reason = trigger ? alarmInfoForRecord.message : $"{alarmInfoForRecord.message} (已解除)",
|
||
Time = DateTime.Now
|
||
};
|
||
|
||
// 使用持久化服务保存记录(自动去重)
|
||
if (_recordPersistence != null)
|
||
{
|
||
_recordPersistence.AddRecord(alarmEvent, alarmCode, trigger);
|
||
}
|
||
else
|
||
{
|
||
// 降级到内存存储
|
||
AddAlarmRecord(alarmEvent);
|
||
}
|
||
}
|
||
|
||
// 3. 统一触发系统报警显示和声音(仅在触发报警时)
|
||
if (trigger && _alarmCodeMap.TryGetValue(alarmCode, out var alarmInfo))
|
||
{
|
||
// 检查启动阶段的通讯异常
|
||
if (alarmCode == 0x34)
|
||
{
|
||
_communicationErrorDuringStartup = true;
|
||
Debug.LogError("[DCSAlarmManager] 通讯异常(0x34)在启动阶段被触发!");
|
||
}
|
||
|
||
TriggerSystemAlarm(alarmCode, alarmInfo.priority, alarmInfo.message);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"发送报警命令异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 统一触发系统报警(界面显示 + 声音播放)
|
||
/// 根据优先级过滤:高优先级报警时不显示中低优先级,中优先级报警时不显示低优先级
|
||
/// </summary>
|
||
private void TriggerSystemAlarm(byte alarmCode, AlarmPriority priority, string message)
|
||
{
|
||
try
|
||
{
|
||
// 检查是否应该显示此报警(优先级过滤)
|
||
if (!ShouldDisplayAlarm(priority))
|
||
{
|
||
Debug.Log($"[DCS报警管理器] 报警被优先级过滤: [{priority}] {message} (当前最高优先级: {_currentHighestPriority})");
|
||
return;
|
||
}
|
||
|
||
// 触发报警事件,UI组件和AudioService可以订阅此事件
|
||
OnAlarmRaised?.Invoke(priority, message);
|
||
|
||
Debug.Log($"[DCS报警管理器] 触发系统报警: [{priority}] {message} (代码: 0x{alarmCode:X2})");
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"触发系统报警异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据设备状态自动检查并发送报警命令
|
||
/// 统一协调报警命令发送、界面显示和声音播放
|
||
/// </summary>
|
||
public void CheckAndSendAlarms(DeviceStatusData status)
|
||
{
|
||
// 检查电源状态报警
|
||
CheckPowerAlarms(status.PowerType);
|
||
|
||
// 检查激光器状态报警
|
||
CheckLaserAlarms(status.LaserStatus);
|
||
|
||
// 检查电池电量报警(仅在使用电池供电时)
|
||
CheckBatteryAlarms(status.BatteryLevel, status.PowerType);
|
||
|
||
// 检查温度报警
|
||
CheckTemperatureAlarms(status.Temperature);
|
||
}
|
||
|
||
private IEnumerator SendLowBatteryClearAlarm(float delayInSeconds)
|
||
{
|
||
yield return new WaitForSeconds(delayInSeconds); // 等待指定秒数
|
||
SendAlarmCommand(0x11, AlarmPriority.Low, false);
|
||
// 注意:不在这里重置 _isLowBatteryAlarmActive,保持低电状态标记,
|
||
// 直到电量恢复 >40% 或切换到交流电供电时再重置,避免持续低电重复触发。
|
||
}
|
||
|
||
private IEnumerator SendMediumBatteryClearAlarm(float delayInSeconds)
|
||
{
|
||
yield return new WaitForSeconds(delayInSeconds); // 等待指定秒数
|
||
SendAlarmCommand(0x21, AlarmPriority.Medium, false);
|
||
// 同理:不在这里重置 _isMediumBatteryAlarmActive,保持中低电状态标记,
|
||
// 直到电量恢复 >20% 或切换到交流电供电时再重置。
|
||
}
|
||
|
||
private void CheckBatteryAlarms(byte batteryLevel, byte powerType)
|
||
{
|
||
// 使用交流电时忽略电池报警
|
||
if (powerType == 0) // 0=AC交流电供电
|
||
{
|
||
// 清除所有电池相关报警
|
||
if (_activeAlarms.Contains(0x31))
|
||
{
|
||
SendAlarmCommand(0x31, AlarmPriority.High, false);
|
||
Debug.Log("交流电供电,清除电池电量空报警");
|
||
}
|
||
if (_activeAlarms.Contains(0x21))
|
||
{
|
||
SendAlarmCommand(0x21, AlarmPriority.Medium, false);
|
||
Debug.Log("交流电供电,清除电池电量低报警");
|
||
}
|
||
if (_activeAlarms.Contains(0x11))
|
||
{
|
||
SendAlarmCommand(0x11, AlarmPriority.Low, false);
|
||
Debug.Log("交流电供电,清除电池电量低报警");
|
||
}
|
||
// 在交流电供电下,视为电池状态恢复,重置进入低电的状态标记,允许后续再触发。
|
||
_isLowBatteryAlarmActive = false;
|
||
_isMediumBatteryAlarmActive = false;
|
||
return; // 使用交流电时不检查电池报警
|
||
}
|
||
|
||
// 仅在使用电池供电时检查电池报警 (powerType == 1)
|
||
if (batteryLevel <= 5)
|
||
{
|
||
SendAlarmCommand(0x31, AlarmPriority.High, true);
|
||
}
|
||
else if (batteryLevel <= 20)
|
||
{
|
||
// 仅在从非中低电状态进入中低电状态时触发一次
|
||
if (!_isMediumBatteryAlarmActive)
|
||
{
|
||
_isMediumBatteryAlarmActive = true;
|
||
SendAlarmCommand(0x21, AlarmPriority.Medium, true);
|
||
StartCoroutine(SendMediumBatteryClearAlarm(delayTime));
|
||
}
|
||
}
|
||
else if (batteryLevel <= 40)
|
||
{
|
||
// 仅在从非低电状态进入低电状态时触发一次
|
||
if (!_isLowBatteryAlarmActive)
|
||
{
|
||
_isLowBatteryAlarmActive = true;
|
||
SendAlarmCommand(0x11, AlarmPriority.Low, true);
|
||
StartCoroutine(SendLowBatteryClearAlarm(delayTime));
|
||
}
|
||
}
|
||
|
||
// 清除已恢复的电池报警
|
||
if (batteryLevel > 5 && _activeAlarms.Contains(0x31))
|
||
{
|
||
SendAlarmCommand(0x31, AlarmPriority.High, false);
|
||
}
|
||
// 当电量恢复到阈值之上,清除一次性触发标记,允许后续再次进入时重新触发
|
||
if (batteryLevel > 20 && _isMediumBatteryAlarmActive)
|
||
{
|
||
_isMediumBatteryAlarmActive = false;
|
||
}
|
||
if (batteryLevel > 40 && _isLowBatteryAlarmActive)
|
||
{
|
||
_isLowBatteryAlarmActive = false;
|
||
}
|
||
}
|
||
|
||
private void CheckLaserAlarms(byte laserStatus)
|
||
{
|
||
if (laserStatus == 2) // 激光器异常
|
||
{
|
||
SendAlarmCommand(0x33, AlarmPriority.High, true);
|
||
}
|
||
else if (laserStatus != 2 && _activeAlarms.Contains(0x33)) // 激光器恢复正常
|
||
{
|
||
SendAlarmCommand(0x33, AlarmPriority.High, false);
|
||
}
|
||
}
|
||
|
||
private void CheckTemperatureAlarms(short temperature)
|
||
{
|
||
// 假设温度单位为0.1°C,正常范围20-40°C
|
||
float tempCelsius = temperature / 10.0f;
|
||
bool tempAbnormal = tempCelsius > 40;
|
||
|
||
if (tempAbnormal)
|
||
{
|
||
SendAlarmCommand(0x22, AlarmPriority.Medium, true);
|
||
}
|
||
else if (!tempAbnormal && _activeAlarms.Contains(0x22))
|
||
{
|
||
SendAlarmCommand(0x22, AlarmPriority.Medium, false);
|
||
}
|
||
}
|
||
|
||
private void CheckPowerAlarms(byte powerType)
|
||
{
|
||
if (powerType == 1)
|
||
{
|
||
// 仅在从交流电切换到电池供电的瞬间触发一次
|
||
if (!_isPowerAlarmActive)
|
||
{
|
||
_isPowerAlarmActive = true;
|
||
SendAlarmCommand(0x12, AlarmPriority.Low, true);
|
||
StartCoroutine(SendPowerClearAlarm(delayTime));
|
||
}
|
||
}
|
||
else if (powerType == 0)
|
||
{
|
||
// 交流电供电,视为恢复,允许下一次切换到电池时再触发
|
||
_isPowerAlarmActive = false;
|
||
// 如果当前仍有活动报警,立即发送清除
|
||
if (_activeAlarms.Contains(0x12))
|
||
{
|
||
SendAlarmCommand(0x12, AlarmPriority.Low, false);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
private IEnumerator SendPowerClearAlarm(float delayInSeconds)
|
||
{
|
||
yield return new WaitForSeconds(delayInSeconds); // 等待指定秒数
|
||
SendAlarmCommand(0x12, AlarmPriority.Low, false); // 恢复交流电
|
||
// 不在这里重置 _isPowerAlarmActive,保持当前供电状态标记;
|
||
// 仅当检测到实际切换回交流电(powerType==0)时再重置。
|
||
}
|
||
|
||
|
||
// BFI阈值设置
|
||
private float _bfiLowThreshold = 0f;
|
||
private float _bfiHighThreshold = 200f;
|
||
private bool _enableBFIAlarm = true;
|
||
|
||
// BFI防抖动相关
|
||
private float _bfiLastValue = 0f;
|
||
private DateTime _bfiAbnormalStartTime = DateTime.MinValue;
|
||
private const int BFI_DEBOUNCE_TIME_MS = 5000; // 5秒防抖:持续异常5秒才触发报警
|
||
|
||
/// <summary>
|
||
/// 更新BFI阈值设置
|
||
/// </summary>
|
||
public void UpdateBFIThresholds(float lowThreshold, float highThreshold, int priority, bool enabled)
|
||
{
|
||
_bfiLowThreshold = lowThreshold;
|
||
_bfiHighThreshold = highThreshold;
|
||
_enableBFIAlarm = enabled;
|
||
|
||
}
|
||
|
||
|
||
|
||
public void CheckBFIAlarm(float bfiValue)
|
||
{
|
||
if (!_enableBFIAlarm) return;
|
||
|
||
// 使用可配置的阈值范围
|
||
bool bfiAbnormal = bfiValue < _bfiLowThreshold || bfiValue > _bfiHighThreshold;
|
||
|
||
var alarmPriority = AlarmPriority.High;
|
||
|
||
if (bfiAbnormal)
|
||
{
|
||
// BFI异常
|
||
SendAlarmCommand(0x32, alarmPriority, true);
|
||
Debug.Log($"[BFI报警] 数值异常: {bfiValue:F2} (阈值范围: {_bfiLowThreshold:F1}-{_bfiHighThreshold:F1})");
|
||
}
|
||
else
|
||
{
|
||
// BFI恢复正常
|
||
if (_activeAlarms.Contains(0x32))
|
||
{
|
||
SendAlarmCommand(0x32, alarmPriority, false);
|
||
Debug.Log($"[BFI报警] 数值恢复正常: {bfiValue:F2}");
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 检查BFI数值是否异常(带防抖动)
|
||
/// 统一处理BFI报警的发送、界面显示和声音
|
||
/// 防抖动:只有持续异常5秒才触发报警,避免阈值边界频繁抖动
|
||
/// </summary>
|
||
public void CheckBFIAlarmInterval(float bfiValue)
|
||
{
|
||
if (!_enableBFIAlarm) return;
|
||
|
||
// 使用可配置的阈值范围
|
||
bool bfiAbnormal = bfiValue < _bfiLowThreshold || bfiValue > _bfiHighThreshold;
|
||
|
||
var alarmPriority = AlarmPriority.High;
|
||
|
||
if (bfiAbnormal)
|
||
{
|
||
// BFI异常
|
||
if (_bfiAbnormalStartTime == DateTime.MinValue)
|
||
{
|
||
// 第一次检测到异常,记录开始时间
|
||
_bfiAbnormalStartTime = DateTime.Now;
|
||
|
||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||
AndroidFileLogger.Instance?.LogInfo("BFI",
|
||
$"防抖:检测到异常,开始计时: BFI={bfiValue:F2} (阈值: {_bfiLowThreshold:F1}-{_bfiHighThreshold:F1})");
|
||
#endif
|
||
|
||
Debug.Log($"[BFI防抖] 检测到异常,开始计时: BFI={bfiValue:F2}");
|
||
SendAlarmCommand(0x32, alarmPriority, true);
|
||
return; // 不立即报警,等待持续异常
|
||
}
|
||
|
||
// 检查持续异常时间
|
||
var abnormalDuration = (DateTime.Now - _bfiAbnormalStartTime).TotalMilliseconds;
|
||
|
||
if (abnormalDuration >= BFI_DEBOUNCE_TIME_MS)
|
||
{
|
||
// 持续异常超过5秒,触发报警
|
||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||
AndroidFileLogger.Instance?.LogInfo("BFI",
|
||
$"防抖:持续异常{abnormalDuration:F0}ms,触发报警: BFI={bfiValue:F2}");
|
||
#endif
|
||
|
||
Debug.Log($"[BFI防抖] 持续异常{abnormalDuration:F0}ms,触发报警: BFI={bfiValue:F2}");
|
||
SendAlarmCommand(0x32, alarmPriority, true);
|
||
Debug.Log($"[BFI报警] 数值异常: {bfiValue:F2} (阈值范围: {_bfiLowThreshold:F1}-{_bfiHighThreshold:F1})");
|
||
}
|
||
else if (abnormalDuration < BFI_DEBOUNCE_TIME_MS)
|
||
{
|
||
// 仍在防抖时间内,继续等待
|
||
var remaining = BFI_DEBOUNCE_TIME_MS - abnormalDuration;
|
||
Debug.Log($"[BFI防抖] 异常持续中({abnormalDuration:F0}ms),等待{remaining:F0}ms后触发报警");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// BFI恢复正常
|
||
if (_bfiAbnormalStartTime != DateTime.MinValue)
|
||
{
|
||
// 异常时间未达到5秒就恢复了
|
||
var abnormalDuration = (DateTime.Now - _bfiAbnormalStartTime).TotalMilliseconds;
|
||
|
||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||
AndroidFileLogger.Instance?.LogInfo("BFI",
|
||
$"防抖:异常已恢复(持续{abnormalDuration:F0}ms<{BFI_DEBOUNCE_TIME_MS}ms): BFI={bfiValue:F2}");
|
||
#endif
|
||
|
||
Debug.Log($"[BFI防抖] 异常已恢复(持续{abnormalDuration:F0}ms): BFI={bfiValue:F2}");
|
||
_bfiAbnormalStartTime = DateTime.MinValue;
|
||
}
|
||
|
||
// 如果当前有激活的报警,取消报警
|
||
if (_activeAlarms.Contains(0x32))
|
||
{
|
||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||
AndroidFileLogger.Instance?.LogInfo("BFI",
|
||
$"防抖:取消报警: BFI={bfiValue:F2}");
|
||
#endif
|
||
|
||
Debug.Log($"[BFI防抖] 取消报警: BFI={bfiValue:F2}");
|
||
SendAlarmCommand(0x32, alarmPriority, false);
|
||
Debug.Log($"[BFI报警] 数值恢复正常: {bfiValue:F2}");
|
||
}
|
||
}
|
||
|
||
_bfiLastValue = bfiValue;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新当前活跃报警的最高优先级
|
||
/// </summary>
|
||
private void UpdateHighestPriority()
|
||
{
|
||
var previousPriority = _currentHighestPriority;
|
||
_currentHighestPriority = AlarmPriority.None;
|
||
|
||
foreach (var alarmCode in _activeAlarms)
|
||
{
|
||
if (_alarmCodeMap.TryGetValue(alarmCode, out var alarmInfo))
|
||
{
|
||
if (alarmInfo.priority > _currentHighestPriority)
|
||
{
|
||
_currentHighestPriority = alarmInfo.priority;
|
||
}
|
||
}
|
||
}
|
||
|
||
Debug.Log($"[DCS报警管理器] 更新最高优先级: {_currentHighestPriority}");
|
||
|
||
// 如果从有报警变为无报警,触发清除事件
|
||
if (previousPriority != AlarmPriority.None && _currentHighestPriority == AlarmPriority.None)
|
||
{
|
||
OnAlarmCleared?.Invoke();
|
||
Debug.Log("[DCS报警管理器] 所有报警已清除,触发正常状态");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断是否应该显示该优先级的报警
|
||
/// 规则:
|
||
/// - 有高优先级报警时,只显示高优先级
|
||
/// - 有中优先级报警时,只显示高、中优先级
|
||
/// - 只有低优先级报警时,显示所有报警
|
||
/// </summary>
|
||
private bool ShouldDisplayAlarm(AlarmPriority priority)
|
||
{
|
||
switch (_currentHighestPriority)
|
||
{
|
||
case AlarmPriority.High:
|
||
// 有高优先级报警时,只显示高优先级
|
||
return priority == AlarmPriority.High;
|
||
|
||
case AlarmPriority.Medium:
|
||
// 有中优先级报警时,只显示高、中优先级
|
||
return priority >= AlarmPriority.Medium;
|
||
|
||
case AlarmPriority.Low:
|
||
case AlarmPriority.None:
|
||
default:
|
||
// 只有低优先级或无报警时,显示所有报警
|
||
return true;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前活跃的报警列表
|
||
/// </summary>
|
||
public List<(byte code, string message, AlarmPriority priority)> GetActiveAlarms()
|
||
{
|
||
var result = new List<(byte, string, AlarmPriority)>();
|
||
|
||
foreach (var alarmCode in _activeAlarms)
|
||
{
|
||
if (_alarmCodeMap.TryGetValue(alarmCode, out var alarmInfo))
|
||
{
|
||
result.Add((alarmCode, alarmInfo.message, alarmInfo.priority));
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前最高优先级
|
||
/// </summary>
|
||
public AlarmPriority GetCurrentHighestPriority()
|
||
{
|
||
return _currentHighestPriority;
|
||
}
|
||
|
||
#region 报警记录管理
|
||
|
||
/// <summary>
|
||
/// 添加报警记录
|
||
/// </summary>
|
||
private void AddAlarmRecord(AlarmEvent alarmEvent)
|
||
{
|
||
_alarmRecords.Add(alarmEvent);
|
||
|
||
// 保持记录数量在限制范围内
|
||
if (_alarmRecords.Count > MAX_ALARM_RECORDS)
|
||
{
|
||
_alarmRecords.RemoveAt(0); // 移除最旧的记录
|
||
}
|
||
|
||
Debug.Log($"[DCS报警记录] 添加记录: ID={alarmEvent.Id}, {alarmEvent.Priority}, {alarmEvent.Reason}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取报警记录列表
|
||
/// </summary>
|
||
public IReadOnlyList<AlarmEvent> GetAlarmRecords(int maxCount = 1000)
|
||
{
|
||
// 优先从持久化服务读取
|
||
if (_recordPersistence != null)
|
||
{
|
||
return _recordPersistence.GetRecords(maxCount).AsReadOnly();
|
||
}
|
||
|
||
// 降级到内存存储
|
||
var count = Math.Min(maxCount, _alarmRecords.Count);
|
||
return _alarmRecords.Skip(_alarmRecords.Count - count).ToList().AsReadOnly();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除所有报警记录
|
||
/// </summary>
|
||
public void ClearAlarmRecords()
|
||
{
|
||
// 清除持久化记录
|
||
if (_recordPersistence != null)
|
||
{
|
||
_recordPersistence.ClearRecords();
|
||
}
|
||
|
||
// 清除内存记录
|
||
int clearedCount = _alarmRecords.Count;
|
||
_alarmRecords.Clear();
|
||
_nextAlarmId = 1; // 重置ID计数器
|
||
|
||
Debug.Log($"[DCS报警记录] 已清除 {clearedCount} 条记录(含持久化)");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取报警记录总数
|
||
/// </summary>
|
||
public int GetAlarmRecordCount()
|
||
{
|
||
if (_recordPersistence != null)
|
||
{
|
||
return _recordPersistence.GetRecordCount();
|
||
}
|
||
return _alarmRecords.Count;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从持久化存储加载历史记录到内存
|
||
/// </summary>
|
||
private void LoadPersistedRecords()
|
||
{
|
||
if (_recordPersistence == null) return;
|
||
|
||
var persistedRecords = _recordPersistence.GetAllRecords();
|
||
if (persistedRecords != null && persistedRecords.Count > 0)
|
||
{
|
||
_alarmRecords.Clear();
|
||
_alarmRecords.AddRange(persistedRecords);
|
||
|
||
// 更新ID计数器
|
||
if (persistedRecords.Count > 0)
|
||
{
|
||
_nextAlarmId = persistedRecords.Max(r => r.Id) + 1;
|
||
}
|
||
|
||
Debug.Log($"[DCS报警管理器] 从持久化存储加载了 {persistedRecords.Count} 条历史记录");
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
}
|