EquipmentDataModel.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. using ScottPlot;
  2. using SWRIS.Enums;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Collections.ObjectModel;
  6. using System.ComponentModel;
  7. using System.Linq;
  8. using System.Net.Sockets;
  9. using System.Threading.Tasks;
  10. using System.Windows;
  11. namespace SWRIS.Models
  12. {
  13. public class EquipmentDataModel : INotifyPropertyChanged
  14. {
  15. private int ropeNumber;
  16. private string ropeName;
  17. private string ipAddress;
  18. private string serialNo;
  19. private bool isConnect = false;
  20. private int sensorCount = 4;
  21. private double liftHightRatio = 1;
  22. private double ropeLength = 100f; // 默认长度为100米
  23. private RunningStatus runningStatus = RunningStatus.Stopped;
  24. private DirectionState direction;
  25. private FaultType? faultType;
  26. private double speed;
  27. private double position;
  28. private double absolutePosition;
  29. private double liftHeight;
  30. private double maxDamageValue;
  31. private double avgDamageValue;
  32. private int damageCount;
  33. private int mildCount;
  34. private int lightCount;
  35. private int moderateCount;
  36. private int severeCount;
  37. private int criticalCount;
  38. private int extremeCount;
  39. private DetectionDataModel detectionData;
  40. private RiskLevel riskLevel = RiskLevel.Normal;
  41. private Socket clientSocket;
  42. private double samplingStep;
  43. private DebugMessageModel debugMessage = new DebugMessageModel(string.Empty);
  44. private bool isAlerting = false;
  45. private bool isSpeedStable = true;
  46. private double variationThreshold = 0.25;
  47. private bool isHeartbeatReceived;
  48. private uint detectionNo;
  49. private bool disableAlarm;
  50. private int[] inUseSensor = new int[] { 1, 2, 3, 4 };
  51. /// <summary>
  52. /// 钢丝绳绳号
  53. /// </summary>
  54. public int RopeNumber
  55. {
  56. get => ropeNumber;
  57. set { ropeNumber = value; OnPropertyChanged(nameof(RopeNumber)); }
  58. }
  59. /// <summary>
  60. /// 钢丝绳名称
  61. /// </summary>
  62. public string RopeName
  63. {
  64. get => ropeName;
  65. set { ropeName = value; OnPropertyChanged(nameof(RopeName)); }
  66. }
  67. /// <summary>
  68. /// 设备Ip地址
  69. /// </summary>
  70. public string IpAddress
  71. {
  72. get => ipAddress;
  73. set { ipAddress = value; OnPropertyChanged(nameof(IpAddress)); }
  74. }
  75. /// <summary>
  76. /// 设备序列号
  77. /// </summary>
  78. public string SerialNo
  79. {
  80. get => serialNo;
  81. set { serialNo = value; OnPropertyChanged(nameof(SerialNo)); }
  82. }
  83. /// <summary>
  84. /// 连接状态
  85. /// </summary>
  86. public bool IsConnect
  87. {
  88. get => isConnect;
  89. set { isConnect = value; OnPropertyChanged(nameof(IsConnect)); }
  90. }
  91. /// <summary>
  92. /// 传感器数量
  93. /// </summary>
  94. public int SensorCount
  95. {
  96. get => sensorCount;
  97. set { sensorCount = value; OnPropertyChanged(nameof(SensorCount)); }
  98. }
  99. /// <summary>
  100. /// 钢丝绳绳长
  101. /// </summary>
  102. public double RopeLength
  103. {
  104. get => ropeLength;
  105. set { ropeLength = value; OnPropertyChanged(nameof(RopeLength)); }
  106. }
  107. public double LiftHightRatio
  108. {
  109. get => liftHightRatio;
  110. set { liftHightRatio = value; OnPropertyChanged(nameof(LiftHightRatio)); }
  111. }
  112. /// <summary>
  113. /// 采样步长
  114. /// </summary>
  115. public double SamplingStep
  116. {
  117. get => samplingStep;
  118. set { samplingStep = value; OnPropertyChanged(nameof(SamplingStep)); }
  119. }
  120. /// <summary>
  121. /// 运行状态
  122. /// </summary>
  123. public RunningStatus RunningStatus
  124. {
  125. get => runningStatus;
  126. set { runningStatus = value; OnPropertyChanged(nameof(RunningStatus)); }
  127. }
  128. /// <summary>
  129. /// 运行方向
  130. /// </summary>
  131. public DirectionState Direction
  132. {
  133. get => direction;
  134. set { direction = value; OnPropertyChanged(nameof(Direction)); }
  135. }
  136. /// <summary>
  137. /// 故障类型
  138. /// </summary>
  139. public FaultType? FaultType
  140. {
  141. get => faultType;
  142. set { faultType = value; OnPropertyChanged(nameof(FaultType)); }
  143. }
  144. /// <summary>
  145. /// 速度
  146. /// </summary>
  147. public double Speed
  148. {
  149. get => speed;
  150. set { speed = value; OnPropertyChanged(nameof(Speed)); }
  151. }
  152. /// <summary>
  153. /// 速度变化率阈值
  154. /// </summary>
  155. public double VariationThreshold
  156. {
  157. get => variationThreshold;
  158. set { variationThreshold = value; OnPropertyChanged(nameof(VariationThreshold)); }
  159. }
  160. /// <summary>
  161. /// 速度是否稳定
  162. /// </summary>
  163. public bool IsSpeedStable
  164. {
  165. get => isSpeedStable;
  166. set { isSpeedStable = value; OnPropertyChanged(nameof(IsSpeedStable)); }
  167. }
  168. /// <summary>
  169. /// 位置
  170. /// </summary>
  171. public double Position
  172. {
  173. get => position;
  174. set { position = value; OnPropertyChanged(nameof(Position)); }
  175. }
  176. /// <summary>
  177. /// 绝对位置
  178. /// </summary>
  179. public double AbsolutePosition
  180. {
  181. get => absolutePosition;
  182. set { absolutePosition = value; OnPropertyChanged(nameof(AbsolutePosition)); }
  183. }
  184. /// <summary>
  185. /// 起升高度
  186. /// </summary>
  187. public double LiftHeight
  188. {
  189. get => liftHeight;
  190. set { liftHeight = value; OnPropertyChanged(nameof(LiftHeight)); }
  191. }
  192. /// <summary>
  193. /// 健康程度
  194. /// </summary>
  195. public RiskLevel RiskLevel
  196. {
  197. get => riskLevel;
  198. set { riskLevel = value; OnPropertyChanged(nameof(RiskLevel)); }
  199. }
  200. /// <summary>
  201. /// 平均损伤值
  202. /// </summary>
  203. public double AvgDamageValue
  204. {
  205. get => avgDamageValue;
  206. set { avgDamageValue = value; OnPropertyChanged(nameof(AvgDamageValue)); }
  207. }
  208. /// <summary>
  209. /// 最大损伤值
  210. /// </summary>
  211. public double MaxDamageValue
  212. {
  213. get => maxDamageValue;
  214. set { maxDamageValue = value; OnPropertyChanged(nameof(MaxDamageValue)); }
  215. }
  216. /// <summary>
  217. /// 损伤报警数量
  218. /// </summary>
  219. public int DamageCount
  220. {
  221. get => damageCount;
  222. set { damageCount = value; OnPropertyChanged(nameof(DamageCount)); }
  223. }
  224. /// <summary>
  225. /// 轻微损伤数量
  226. /// </summary>
  227. public int MildCount
  228. {
  229. get => mildCount;
  230. set { mildCount = value; OnPropertyChanged(nameof(MildCount)); }
  231. }
  232. /// <summary>
  233. /// 轻度损伤数量
  234. /// </summary>
  235. public int LightCount
  236. {
  237. get => lightCount;
  238. set { lightCount = value; OnPropertyChanged(nameof(LightCount)); }
  239. }
  240. /// <summary>
  241. /// 中度损伤数量
  242. /// </summary>
  243. public int ModerateCount
  244. {
  245. get => moderateCount;
  246. set { moderateCount = value; OnPropertyChanged(nameof(ModerateCount)); }
  247. }
  248. /// <summary>
  249. /// 较重损伤数量
  250. /// </summary>
  251. public int SevereCount
  252. {
  253. get => severeCount;
  254. set { severeCount = value; OnPropertyChanged(nameof(SevereCount)); }
  255. }
  256. /// <summary>
  257. /// 严重损伤数量
  258. /// </summary>
  259. public int CriticalCount
  260. {
  261. get => criticalCount;
  262. set { criticalCount = value; OnPropertyChanged(nameof(CriticalCount)); }
  263. }
  264. /// <summary>
  265. /// 超限损伤数量
  266. /// </summary>
  267. public int ExtremeCount
  268. {
  269. get => extremeCount;
  270. set { extremeCount = value; OnPropertyChanged(nameof(ExtremeCount)); }
  271. }
  272. /// <summary>
  273. /// 最后一次的检测数据
  274. /// </summary>
  275. public DetectionDataModel DetectionData
  276. {
  277. get => detectionData;
  278. set { detectionData = value; OnPropertyChanged(nameof(DetectionData)); }
  279. }
  280. /// <summary>
  281. /// 调试信息
  282. /// </summary>
  283. public DebugMessageModel DebugMessage
  284. {
  285. get => debugMessage;
  286. set { debugMessage = value; OnPropertyChanged(nameof(DebugMessage)); }
  287. }
  288. /// <summary>
  289. /// TCP 客户端
  290. /// </summary>
  291. public Socket ClientSocket
  292. {
  293. get => clientSocket;
  294. set { clientSocket = value; OnPropertyChanged(nameof(ClientSocket)); }
  295. }
  296. /// <summary>
  297. /// 是否报警中
  298. /// </summary>
  299. public bool IsAlerting
  300. {
  301. get => isAlerting;
  302. set { isAlerting = value; OnPropertyChanged(nameof(IsAlerting)); }
  303. }
  304. public bool IsHeartbeatReceived
  305. {
  306. get => isHeartbeatReceived;
  307. set
  308. {
  309. isHeartbeatReceived = value;
  310. OnPropertyChanged(nameof(IsHeartbeatReceived));
  311. if (value)
  312. {
  313. // 延迟一段时间后重置,以便动画可以重复触发
  314. Task.Delay(600).ContinueWith(_ =>
  315. {
  316. Application.Current.Dispatcher.Invoke(() =>
  317. {
  318. IsHeartbeatReceived = false;
  319. });
  320. });
  321. }
  322. }
  323. }
  324. /// <summary>
  325. /// 检测编号
  326. /// </summary>
  327. public uint DetectionNo
  328. {
  329. get => detectionNo;
  330. set { detectionNo = value; OnPropertyChanged(nameof(DetectionNo)); }
  331. }
  332. /// <summary>
  333. /// 禁用报警
  334. /// </summary>
  335. public bool DisableAlarm
  336. {
  337. get => disableAlarm;
  338. set { disableAlarm = value; OnPropertyChanged(nameof(DisableAlarm)); }
  339. }
  340. /// <summary>
  341. /// 在用传感器
  342. /// </summary>
  343. public int[] InUseSensor
  344. {
  345. get => inUseSensor;
  346. set { inUseSensor = value; OnPropertyChanged(nameof(InUseSensor)); }
  347. }
  348. public ObservableCollection<AlarmDataModel> Alarms { get; set; } = new ObservableCollection<AlarmDataModel>();
  349. public ObservableCollection<FaultDataModel> Faults { get; set; } = new ObservableCollection<FaultDataModel>();
  350. public ObservableCollection<LimitModel> Limits { get; set; } = new ObservableCollection<LimitModel>();
  351. public ObservableCollection<string> Messages { get; set; } = new ObservableCollection<string>();
  352. public Coordinates[] ChartSource { get; internal set; }
  353. public Queue<double> RecentSpeeds { get; internal set; } = new Queue<double>();
  354. public void AddSpeedData(double speed)
  355. {
  356. // 更新数据窗口
  357. RecentSpeeds.Enqueue(speed);
  358. if (RecentSpeeds.Count > 3)
  359. RecentSpeeds.Dequeue();
  360. if (RecentSpeeds.Count < 2)
  361. return;
  362. double avgSpeed = RecentSpeeds.Average();
  363. if (avgSpeed == 0)
  364. {
  365. IsSpeedStable = true;
  366. return;
  367. }
  368. // 计算当前速度相对于平均值的偏差
  369. bool _isStable = (Math.Abs(speed - avgSpeed) / avgSpeed) <= VariationThreshold;
  370. if (IsSpeedStable != _isStable)
  371. {
  372. IsSpeedStable = _isStable;
  373. }
  374. }
  375. public void AddAlarm(AlarmDataModel alarm)
  376. {
  377. DamageCount++;
  378. MaxDamageValue = alarm.DamageValue > MaxDamageValue ? alarm.DamageValue : MaxDamageValue;
  379. AvgDamageValue = (AvgDamageValue * (DamageCount - 1) + alarm.DamageValue) / DamageCount;
  380. switch (alarm.DamageLevel)
  381. {
  382. case DamageLevel.Mild:
  383. MildCount++;
  384. break;
  385. case DamageLevel.Light:
  386. LightCount++;
  387. break;
  388. case DamageLevel.Moderate:
  389. ModerateCount++;
  390. break;
  391. case DamageLevel.Severe:
  392. SevereCount++;
  393. break;
  394. case DamageLevel.Critical:
  395. CriticalCount++;
  396. break;
  397. case DamageLevel.ExceededLimit:
  398. ExtremeCount++;
  399. break;
  400. }
  401. Alarms.Add(alarm);
  402. RiskLevel = Alarms.Any() ? (RiskLevel)Alarms.Max(c => (int)c.DamageLevel) : RiskLevel.Normal;
  403. IsAlerting = true;
  404. Task.Run(() =>
  405. {
  406. Task.Delay(3000).Wait();
  407. IsAlerting = false;
  408. });
  409. }
  410. public void ClearData()
  411. {
  412. Speed = 0;
  413. MaxDamageValue = 0;
  414. AvgDamageValue = 0;
  415. DamageCount = 0;
  416. MildCount = 0;
  417. LightCount = 0;
  418. ModerateCount = 0;
  419. SevereCount = 0;
  420. CriticalCount = 0;
  421. ExtremeCount = 0;
  422. ChartSource = null;
  423. RiskLevel = RiskLevel.Normal;
  424. DetectionNo += 1;
  425. Application.Current.Dispatcher.Invoke(() => Alarms.Clear());
  426. Task.Run(async () =>
  427. {
  428. // 持续监控直到条件满足
  429. while (DetectionData?.RawDataReceiving == true)
  430. {
  431. await Task.Delay(100); // 避免CPU占用过高
  432. }
  433. // 条件满足时执行
  434. DetectionData = null;
  435. });
  436. }
  437. public event PropertyChangedEventHandler PropertyChanged;
  438. protected internal virtual void OnPropertyChanged(string propertyName)
  439. {
  440. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  441. }
  442. }
  443. }