using SWRIS.Controls;
using SWRIS.Dtos;
using SWRIS.Enums;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Windows;
namespace SWRIS.Models
{
public class EquipmentDataModel : INotifyPropertyChanged
{
private int ropeNumber;
private string ropeName;
private int trolleyId;
private string ipAddress;
private string serialNo;
private bool isConnect = false;
private bool isDataActive = false;
private int sensorCount = 4;
private double liftHightRatio = 1;
private double ropeLength = 100f; // 默认长度为100米
private RunningStatus runningStatus = RunningStatus.Stopped;
private DirectionState direction;
private FaultType? faultType;
private double speed;
private double position;
private double absolutePosition;
private double liftHeight;
private double maxDamageValue;
private double avgDamageValue;
private int damageCount;
private int mildCount;
private int lightCount;
private int moderateCount;
private int severeCount;
private int criticalCount;
private int extremeCount;
private DetectionDataModel detectionData;
private RiskLevel riskLevel = RiskLevel.Normal;
private Socket clientSocket;
private double samplingStep;
private DebugMessageModel debugMessage = new DebugMessageModel(string.Empty);
private bool isAlerting = false;
private bool isSpeedStable = true;
private double variationThreshold = 0.25;
private bool isHeartbeatReceived;
private uint detectionNo;
private bool disableAlarm;
private int[] inUseSensor = new int[] { 1, 2, 3, 4 };
private RealTimeLineChart chart;
///
/// 钢丝绳绳号
///
public int RopeNumber
{
get => ropeNumber;
set { ropeNumber = value; OnPropertyChanged(nameof(RopeNumber)); }
}
///
/// 钢丝绳名称
///
public string RopeName
{
get => ropeName;
set { ropeName = value; OnPropertyChanged(nameof(RopeName)); }
}
///
/// 小车Id
///
public int TrolleyId
{
get => trolleyId;
set { trolleyId = value; OnPropertyChanged(nameof(TrolleyId)); }
}
///
/// 设备Ip地址
///
public string IpAddress
{
get => ipAddress;
set { ipAddress = value; OnPropertyChanged(nameof(IpAddress)); }
}
///
/// 设备序列号
///
public string SerialNo
{
get => serialNo;
set { serialNo = value; OnPropertyChanged(nameof(SerialNo)); }
}
///
/// 连接状态
///
public bool IsConnect
{
get => isConnect;
set { isConnect = value; OnPropertyChanged(nameof(IsConnect)); }
}
///
/// 数据激活状态:最近有正常数据收发。
/// 用于在心跳缺失但数据仍在上报时,区分链路真实静默与被误判离线。
///
public bool IsDataActive
{
get => isDataActive;
set { isDataActive = value; OnPropertyChanged(nameof(IsDataActive)); }
}
///
/// 传感器数量
///
public int SensorCount
{
get => sensorCount;
set { sensorCount = value; OnPropertyChanged(nameof(SensorCount)); }
}
///
/// 钢丝绳绳长
///
public double RopeLength
{
get => ropeLength;
set { ropeLength = value; OnPropertyChanged(nameof(RopeLength)); }
}
public double LiftHightRatio
{
get => liftHightRatio;
set { liftHightRatio = value; OnPropertyChanged(nameof(LiftHightRatio)); }
}
///
/// 采样步长
///
public double SamplingStep
{
get => samplingStep;
set { samplingStep = value; OnPropertyChanged(nameof(SamplingStep)); }
}
///
/// 运行状态
///
public RunningStatus RunningStatus
{
get => runningStatus;
set { runningStatus = value; OnPropertyChanged(nameof(RunningStatus)); }
}
///
/// 预状态挂起时间戳(UtcNow.Ticks),0 表示无挂起的预状态
///
public long PreStatusTimestamp { get; set; }
///
/// 预运行请求的检测模式(TemporalNormal=时域,SpatialNormal=空域),用于 0x06 应答确认时恢复正确模式
///
public RunningStatus PreStatusRunningMode { get; set; }
///
/// 标记预状态位并记录挂起时间戳(本地先行、等待设备确认)
///
public void MarkPreStatus(RunningStatus flag)
{
RunningStatus |= flag;
PreStatusTimestamp = DateTime.UtcNow.Ticks;
}
///
/// 标记预运行状态并记录本次请求的检测模式(时域/空域),清除旧模式位避免切换时残留
///
public void MarkPreRunning(RunningStatus mode)
{
RunningStatus = (RunningStatus & ~(RunningStatus.SpatialNormal | RunningStatus.TemporalNormal)) | mode | RunningStatus.PreRunning;
PreStatusRunningMode = mode;
PreStatusTimestamp = DateTime.UtcNow.Ticks;
}
///
/// 设备已确认命令:按位清除对应预状态位并合并实际状态,保留报警/故障等其他状态位
///
public void ConfirmPreStatus(RunningStatus preFlag, RunningStatus actualStatus)
{
RunningStatus = (RunningStatus & ~preFlag) | actualStatus;
if (preFlag == RunningStatus.PreRunning)
{
PreStatusRunningMode = 0;
}
// 仅当没有其他挂起的预状态位时才清零挂起时间戳,避免影响其他预状态的超时判断
if ((RunningStatus & (RunningStatus.PreStop | RunningStatus.PreRunning | RunningStatus.PreCalibration)) == 0)
{
PreStatusTimestamp = 0;
}
}
///
/// 清除所有挂起的预状态位(用于断线、超时等场景)
///
public void ClearAllPreStatus()
{
RunningStatus &= ~(RunningStatus.PreStop | RunningStatus.PreRunning | RunningStatus.PreCalibration);
PreStatusRunningMode = 0;
PreStatusTimestamp = 0;
}
///
/// 运行方向
///
public DirectionState Direction
{
get => direction;
set { direction = value; OnPropertyChanged(nameof(Direction)); }
}
///
/// 故障类型
///
public FaultType? FaultType
{
get => faultType;
set { faultType = value; OnPropertyChanged(nameof(FaultType)); }
}
///
/// 速度
///
public double Speed
{
get => speed;
set { speed = value; OnPropertyChanged(nameof(Speed)); }
}
///
/// 速度变化率阈值
///
public double VariationThreshold
{
get => variationThreshold;
set { variationThreshold = value; OnPropertyChanged(nameof(VariationThreshold)); }
}
///
/// 速度是否稳定
///
public bool IsSpeedStable
{
get => isSpeedStable;
set { isSpeedStable = value; OnPropertyChanged(nameof(IsSpeedStable)); }
}
///
/// 位置
///
public double Position
{
get => position;
set { position = value; OnPropertyChanged(nameof(Position)); }
}
///
/// 绝对位置
///
public double AbsolutePosition
{
get => absolutePosition;
set { absolutePosition = value; OnPropertyChanged(nameof(AbsolutePosition)); }
}
///
/// 起升高度
///
public double LiftHeight
{
get => liftHeight;
set { liftHeight = value; OnPropertyChanged(nameof(LiftHeight)); }
}
///
/// 健康程度
///
public RiskLevel RiskLevel
{
get => riskLevel;
set { riskLevel = value; OnPropertyChanged(nameof(RiskLevel)); }
}
///
/// 平均损伤值
///
public double AvgDamageValue
{
get => avgDamageValue;
set { avgDamageValue = value; OnPropertyChanged(nameof(AvgDamageValue)); }
}
///
/// 最大损伤值
///
public double MaxDamageValue
{
get => maxDamageValue;
set { maxDamageValue = value; OnPropertyChanged(nameof(MaxDamageValue)); }
}
///
/// 损伤报警数量
///
public int DamageCount
{
get => damageCount;
set { damageCount = value; OnPropertyChanged(nameof(DamageCount)); }
}
///
/// 轻微损伤数量
///
public int MildCount
{
get => mildCount;
set { mildCount = value; OnPropertyChanged(nameof(MildCount)); }
}
///
/// 轻度损伤数量
///
public int LightCount
{
get => lightCount;
set { lightCount = value; OnPropertyChanged(nameof(LightCount)); }
}
///
/// 中度损伤数量
///
public int ModerateCount
{
get => moderateCount;
set { moderateCount = value; OnPropertyChanged(nameof(ModerateCount)); }
}
///
/// 较重损伤数量
///
public int SevereCount
{
get => severeCount;
set { severeCount = value; OnPropertyChanged(nameof(SevereCount)); }
}
///
/// 严重损伤数量
///
public int CriticalCount
{
get => criticalCount;
set { criticalCount = value; OnPropertyChanged(nameof(CriticalCount)); }
}
///
/// 超限损伤数量
///
public int ExtremeCount
{
get => extremeCount;
set { extremeCount = value; OnPropertyChanged(nameof(ExtremeCount)); }
}
///
/// 最后一次的检测数据
///
public DetectionDataModel DetectionData
{
get => detectionData;
set { detectionData = value; OnPropertyChanged(nameof(DetectionData)); }
}
///
/// 调试信息
///
public DebugMessageModel DebugMessage
{
get => debugMessage;
set { debugMessage = value; OnPropertyChanged(nameof(DebugMessage)); }
}
///
/// TCP 客户端
///
public Socket ClientSocket
{
get => clientSocket;
set { clientSocket = value; OnPropertyChanged(nameof(ClientSocket)); }
}
///
/// 是否报警中
///
public bool IsAlerting
{
get => isAlerting;
set { isAlerting = value; OnPropertyChanged(nameof(IsAlerting)); }
}
public bool IsHeartbeatReceived
{
get => isHeartbeatReceived;
set
{
isHeartbeatReceived = value;
OnPropertyChanged(nameof(IsHeartbeatReceived));
if (value)
{
// 延迟一段时间后重置,以便动画可以重复触发
Task.Delay(600).ContinueWith(_ =>
{
Application.Current.Dispatcher.Invoke(() =>
{
IsHeartbeatReceived = false;
});
});
}
}
}
///
/// 检测编号
///
public uint DetectionNo
{
get => detectionNo;
set { detectionNo = value; OnPropertyChanged(nameof(DetectionNo)); }
}
///
/// 禁用报警
///
public bool DisableAlarm
{
get => disableAlarm;
set { disableAlarm = value; OnPropertyChanged(nameof(DisableAlarm)); }
}
///
/// 在用传感器
///
public int[] InUseSensor
{
get => inUseSensor;
set { inUseSensor = value; OnPropertyChanged(nameof(InUseSensor)); }
}
public RealTimeLineChart Chart
{
get => chart;
set
{
chart = value;
}
}
public ObservableCollection Faults { get; set; } = new ObservableCollection();
public ObservableCollection Alarms { get; set; } = new ObservableCollection();
public ObservableCollection Limits { get; set; } = new ObservableCollection();
public Queue RecentSpeeds { get; internal set; } = new Queue();
private readonly object _liveStreamLock = new object();
public Queue LiveStreams { get; internal set; } = new Queue();
public ObservableCollection LiveStreamValues { get; set; } = new ObservableCollection();
public void AddLiveStream(LiveStreamDataModel liveStream)
{
if (liveStream?.Data == null || liveStream.Data.Length == 0)
return;
lock (_liveStreamLock)
{
// 新数据到来时清空之前的实时流数据
LiveStreams.Clear();
int sensorCount = liveStream.SensorCount;
int sampleCount = liveStream.Data.Length;
// 本次与上次接收的时间间隔对应的采样点数量(每50ms 1个点)
int targetCount = Math.Max(1, liveStream.SampleInterval / 50);
int actualCount = Math.Min(targetCount, sampleCount);
// 从 sampleCount 个采样点中平均抽取 actualCount 个点
for (int i = 0; i < actualCount; i++)
{
int sourceIndex = actualCount == 1
? 0
: (int)Math.Round((double)i * (sampleCount - 1) / (actualCount - 1));
var point = new int[sensorCount];
for (int s = 0; s < sensorCount; s++)
{
point[s] = liveStream.Data[sourceIndex][s];
}
LiveStreams.Enqueue(point);
}
}
}
///
/// 从实时流队列取出并移除一项(取出即移出)
///
public bool TryDequeueLiveStream(out int[] sample)
{
lock (_liveStreamLock)
{
if (LiveStreams.Count > 0)
{
sample = LiveStreams.Dequeue();
return true;
}
}
sample = null;
return false;
}
public void AddFault(FaultDataModel fault)
{
if (fault == null)
return;
// 无故障(HasFault 为 false):取消对应的故障(含编码器故障)
if (!fault.HasFault)
{
RemoveFault(fault.FaultType);
return;
}
// 有故障:查找同类型的已有故障
var existingFault = Faults.FirstOrDefault(c => c.FaultType == fault.FaultType);
if (existingFault == null)
{
// 无同类型故障,直接添加
Faults.Add(fault);
AddFaultMessage(fault);
return;
}
// 已有同类型故障:判断故障传感器是否一致
if (!existingFault.FaultySensors.SequenceEqual(fault.FaultySensors))
{
// 故障传感器不一致,更新为最新的故障信息
existingFault.FaultCode = fault.FaultCode;
UpdateFaultMessage(fault.FaultType, fault.FaultCode);
}
// 传感器一致则忽略,不重复添加
}
///
/// 取消指定类型的故障(含编码器故障)
///
private void RemoveFault(FaultType faultType)
{
var existing = Faults.FirstOrDefault(c => c.FaultType == faultType);
if (existing != null)
{
Faults.Remove(existing);
}
var message = App.DataCenter.Messages.FirstOrDefault(m => m.RopeName == RopeName);
if (message != null)
{
Application.Current.Dispatcher.Invoke(() =>
{
message.Messages.RemoveAll(c => c.FaultType == faultType);
});
}
}
///
/// 添加故障到消息中心
///
private void AddFaultMessage(FaultDataModel fault)
{
var message = App.DataCenter.Messages.FirstOrDefault(m => m.RopeName == RopeName);
if (message == null)
{
Application.Current.Dispatcher.Invoke(() =>
{
App.DataCenter.Messages.Add(new FaultsMessageDto
{
RopeName = RopeName,
Messages = new List { fault }
});
});
}
else
{
Application.Current.Dispatcher.Invoke(() =>
{
message.Messages.Add(fault);
});
}
}
///
/// 更新消息中心中指定类型的故障码
///
private void UpdateFaultMessage(FaultType faultType, int faultCode)
{
var message = App.DataCenter.Messages.FirstOrDefault(m => m.RopeName == RopeName);
if (message != null)
{
Application.Current.Dispatcher.Invoke(() =>
{
var msgFault = message.Messages.FirstOrDefault(c => c.FaultType == faultType);
if (msgFault != null)
{
msgFault.FaultCode = faultCode;
}
});
}
}
public void AddSpeedData(double speed)
{
// 更新数据窗口
RecentSpeeds.Enqueue(speed);
if (RecentSpeeds.Count > 3)
RecentSpeeds.Dequeue();
if (RecentSpeeds.Count < 2)
return;
double avgSpeed = RecentSpeeds.Average();
if (avgSpeed == 0)
{
IsSpeedStable = true;
return;
}
// 计算当前速度相对于平均值的偏差
bool _isStable = (Math.Abs(speed - avgSpeed) / avgSpeed) <= VariationThreshold;
if (IsSpeedStable != _isStable)
{
IsSpeedStable = _isStable;
}
}
public void AddAlarm(AlarmDataModel alarm)
{
DamageCount++;
MaxDamageValue = alarm.DamageValue > MaxDamageValue ? alarm.DamageValue : MaxDamageValue;
AvgDamageValue = (AvgDamageValue * (DamageCount - 1) + alarm.DamageValue) / DamageCount;
switch (alarm.DamageLevel)
{
case DamageLevel.Mild:
MildCount++;
break;
case DamageLevel.Light:
LightCount++;
break;
case DamageLevel.Moderate:
ModerateCount++;
break;
case DamageLevel.Severe:
SevereCount++;
break;
case DamageLevel.Critical:
CriticalCount++;
break;
case DamageLevel.ExceededLimit:
ExtremeCount++;
break;
}
Alarms.Add(alarm);
RiskLevel = Alarms.Any() ? (RiskLevel)Alarms.Max(c => (int)c.DamageLevel) : RiskLevel.Normal;
IsAlerting = true;
Task.Run(() =>
{
Task.Delay(3000).Wait();
IsAlerting = false;
});
}
public void ClearData()
{
Speed = 0;
MaxDamageValue = 0;
AvgDamageValue = 0;
DamageCount = 0;
MildCount = 0;
LightCount = 0;
ModerateCount = 0;
SevereCount = 0;
CriticalCount = 0;
ExtremeCount = 0;
RiskLevel = RiskLevel.Normal;
DetectionNo += 1;
Application.Current.Dispatcher.Invoke(() => Alarms.Clear());
Task.Run(async () =>
{
// 持续监控直到条件满足
while (DetectionData?.RawDataReceiving == true)
{
await Task.Delay(100); // 避免CPU占用过高
}
// 条件满足时执行
DetectionData = null;
});
}
public event PropertyChangedEventHandler PropertyChanged;
protected internal virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}