DCS/ruiyiweiUX/Assets/Scripts/Services/AlarmRecordPersistenceServi...

290 lines
9.1 KiB
C#
Raw Permalink Normal View History

2026-06-09 13:59:11 +08:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using LitJson;
/// <summary>
/// 报警记录持久化数据模型
/// </summary>
[Serializable]
public class AlarmRecordData
{
public int Id;
public int Priority; // AlarmPriority枚举值
public string Reason;
public string Time; // DateTime序列化为字符串
public string AlarmCode; // 报警代码,用于去重
public bool IsTriggered; // true=报警触发, false=报警解除
public AlarmRecordData() { }
public AlarmRecordData(AlarmEvent alarmEvent, byte alarmCode, bool isTriggered)
{
Id = alarmEvent.Id;
Priority = (int)alarmEvent.Priority;
Reason = alarmEvent.Reason;
Time = alarmEvent.Time.ToString("yyyy-MM-dd HH:mm:ss");
AlarmCode = $"0x{alarmCode:X2}";
IsTriggered = isTriggered;
}
public AlarmEvent ToAlarmEvent()
{
return new AlarmEvent
{
Id = Id,
Priority = (AlarmPriority)Priority,
Reason = Reason,
Time = DateTime.TryParse(Time, out var dt) ? dt : DateTime.Now
};
}
}
/// <summary>
/// 报警记录存储容器
/// </summary>
[Serializable]
public class AlarmRecordStorage
{
public List<AlarmRecordData> Records = new List<AlarmRecordData>();
public int NextId = 1;
}
/// <summary>
/// 报警记录持久化服务
/// 负责报警记录的保存、加载和去重
/// </summary>
public class AlarmRecordPersistenceService
{
private readonly string _alarmRecordsPath;
private const int MAX_ALARM_RECORDS = 1000; // 最大记录数
private AlarmRecordStorage _storage;
// 去重窗口时间(秒)- 同一报警在此时间内不重复记录
private const int DEDUPLICATION_WINDOW_SECONDS = 60;
public AlarmRecordPersistenceService()
{
var dataPath = Application.persistentDataPath;
_alarmRecordsPath = Path.Combine(dataPath, "alarm_records.json");
LoadFromFile();
}
/// <summary>
/// 添加报警记录(带去重)
/// </summary>
/// <param name="alarmEvent">报警事件</param>
/// <param name="alarmCode">报警代码</param>
/// <param name="isTriggered">true=报警触发, false=报警解除</param>
public void AddRecord(AlarmEvent alarmEvent, byte alarmCode, bool isTriggered)
{
if (_storage == null)
{
_storage = new AlarmRecordStorage();
}
// 检查是否为重复记录
if (IsDuplicateRecord(alarmCode, alarmEvent.Reason, alarmEvent.Time, isTriggered))
{
string statusStr = isTriggered ? "触发" : "解除";
Debug.Log($"[报警记录持久化] 跳过重复记录: {alarmEvent.Reason} (代码: 0x{alarmCode:X2}, 状态: {statusStr})");
return;
}
// 创建新记录
var recordData = new AlarmRecordData(alarmEvent, alarmCode, isTriggered);
recordData.Id = _storage.NextId++;
_storage.Records.Add(recordData);
// 保持记录数量在限制范围内
if (_storage.Records.Count > MAX_ALARM_RECORDS)
{
_storage.Records.RemoveAt(0); // 移除最旧的记录
}
// 保存到文件
SaveToFile();
string statusText = isTriggered ? "触发" : "解除";
Debug.Log($"[报警记录持久化] 添加记录: ID={recordData.Id}, {alarmEvent.Priority}, {alarmEvent.Reason} [{statusText}]");
}
/// <summary>
/// 检查是否为重复记录
/// 同一报警代码、同一状态在指定时间窗口内不重复记录
/// </summary>
private bool IsDuplicateRecord(byte alarmCode, string reason, DateTime time, bool isTriggered)
{
if (_storage?.Records == null || _storage.Records.Count == 0)
return false;
string codeStr = $"0x{alarmCode:X2}";
var record = _storage.Records[ _storage.Records.Count - 1];
if (record.AlarmCode == codeStr && record.Reason == reason && record.IsTriggered == isTriggered)
{
if (DateTime.TryParse(record.Time, out var recordTime))
{
var timeDiff = (time - recordTime).TotalSeconds;
if (timeDiff < DEDUPLICATION_WINDOW_SECONDS)
{
return true;
}
}
}
// 从最新记录开始检查
// for (int i = _storage.Records.Count - 1; i >= 0; i--)
// {
// var record = _storage.Records[i];
// // 检查报警代码、原因和状态是否相同
// if (record.AlarmCode == codeStr && record.Reason == reason && record.IsTriggered == isTriggered)
// {
// // 检查时间差
// if (DateTime.TryParse(record.Time, out var recordTime))
// {
// var timeDiff = (time - recordTime).TotalSeconds;
// // 如果在去重窗口内,认为是重复记录
// if (timeDiff < DEDUPLICATION_WINDOW_SECONDS)
// {
// return true;
// }
// // 如果已经超过窗口时间,后面的记录更早,可以停止检查
// if (timeDiff > DEDUPLICATION_WINDOW_SECONDS * 2)
// {
// break;
// }
// }
// }
// }
return false;
}
/// <summary>
/// 获取报警记录列表
/// </summary>
public List<AlarmEvent> GetRecords(int maxCount = 1000)
{
if (_storage?.Records == null || _storage.Records.Count == 0)
return new List<AlarmEvent>();
var count = Math.Min(maxCount, _storage.Records.Count);
return _storage.Records
.Skip(_storage.Records.Count - count)
.Select(r => r.ToAlarmEvent())
.ToList();
}
/// <summary>
/// 获取所有报警记录
/// </summary>
public List<AlarmEvent> GetAllRecords()
{
if (_storage?.Records == null || _storage.Records.Count == 0)
return new List<AlarmEvent>();
return _storage.Records.Select(r => r.ToAlarmEvent()).ToList();
}
/// <summary>
/// 清除所有报警记录
/// </summary>
public void ClearRecords()
{
int clearedCount = _storage?.Records?.Count ?? 0;
_storage = new AlarmRecordStorage();
_storage.NextId = 1;
SaveToFile();
Debug.Log($"[报警记录持久化] 已清除 {clearedCount} 条记录");
}
/// <summary>
/// 获取报警记录总数
/// </summary>
public int GetRecordCount()
{
return _storage?.Records?.Count ?? 0;
}
/// <summary>
/// 保存到文件
/// </summary>
private void SaveToFile()
{
try
{
var json = JsonMapper.ToJson(_storage);
File.WriteAllText(_alarmRecordsPath, json);
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidFileLogger.Instance?.LogInfo("AlarmRecord",
$"报警记录已保存: {_storage.Records.Count} 条");
#endif
}
catch (Exception ex)
{
Debug.LogError($"[报警记录持久化] 保存失败: {ex.Message}");
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidFileLogger.Instance?.LogError("AlarmRecord",
$"保存失败: {ex.Message}");
#endif
}
}
/// <summary>
/// 从文件加载
/// </summary>
private void LoadFromFile()
{
try
{
if (File.Exists(_alarmRecordsPath))
{
var json = File.ReadAllText(_alarmRecordsPath);
_storage = JsonMapper.ToObject<AlarmRecordStorage>(json);
Debug.Log($"[报警记录持久化] 加载成功: {_storage.Records.Count} 条记录");
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidFileLogger.Instance?.LogInfo("AlarmRecord",
$"加载成功: {_storage.Records.Count} 条记录");
#endif
}
else
{
_storage = new AlarmRecordStorage();
Debug.Log("[报警记录持久化] 首次启动,创建新存储");
}
}
catch (Exception ex)
{
Debug.LogError($"[报警记录持久化] 加载失败: {ex.Message}");
_storage = new AlarmRecordStorage();
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidFileLogger.Instance?.LogError("AlarmRecord",
$"加载失败: {ex.Message}");
#endif
}
}
/// <summary>
/// 获取存储文件路径(用于调试)
/// </summary>
public string GetStoragePath()
{
return _alarmRecordsPath;
}
}