using Panuon.WPF.UI; using SWRIS.Core; using SWRIS.Dtos; using SWRIS.Enums; using SWRIS.Events; using SWRIS.Extensions; using SWRIS.Models; using SWRIS.Models.ViewModel; using SWRIS.Pages; using SWRIS.Repository; using System; using System.ComponentModel; using System.IO; using System.Linq; using System.Speech.Synthesis; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Markup; namespace SWRIS { /// /// MainWindow.xaml 的交互逻辑 /// public partial class MainWindow : WindowX, IComponentConnector { private readonly SpeechSynthesizer speech; public MainViewModel MainView { get; set; } private readonly IRecordRepository _recordRepository; private readonly IAlarmRepository _alarmRepository; public MainWindow() { InitializeComponent(); _recordRepository = new RecordRepository(); _alarmRepository = new AlarmRepository(); speech = new SpeechSynthesizer() { Rate = 1, Volume = 100 }; MainView = new MainViewModel() { AppName = App.Config.AppName, Version = App.Config.Version, Copyright = App.Config.Copyright, SwitchInstances = App.Config.SwitchInstances }; Application.Current.MainWindow = this; App.TcpServer.ClientConnected += TcpServer_ClientConnected; App.TcpServer.ClientDisconnected += TcpServer_ClientDisconnected; App.TcpServer.AlarmDataReceived += TcpServer_AlarmDataReceived; App.TcpServer.DetectionDataReceived += TcpServer_DetectionDataReceived; App.TcpServer.RealTimeDataReceived += TcpServer_RealTimeDataReceived; App.TcpServer.FaultDataReceived += TcpServer_FaultDataReceived; App.TcpServer.DetectionRawDataReceived += TcpServer_DetectionRawDataReceived; App.TcpServer.DetectionRawDataResultReceived += TcpServer_DetectionRawDataResultReceived; App.TcpServer.DetectionStatusResultReceived += TcpServer_DetectionStatusResultReceived; App.TcpServer.DebugMessageReceived += TcpServer_DebugMessageReceived; App.TcpServer.HeartbeatReceived += TcpServer_HeartbeatReceived; App.TcpServer.UpgradedRequestResultReceived += TcpServer_UpgradedRequestResultReceived; App.Calibration.ConnectionStateChanged += Calibration_ConnectionStateChanged; App.Calibration.LimitStateChanged += Calibration_LimitStateChanged; App.TcpServer.Start(); DataContext = MainView; } /// /// 接收心跳数据 /// private void TcpServer_HeartbeatReceived(object sender, HeartbeatReceviedEventArgs e) { var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); if (equipmentData != null) { equipmentData.IsHeartbeatReceived = true; } } /// /// 接收调试信息 /// private void TcpServer_DebugMessageReceived(object sender, DebugMessageReceivedEventArgs e) { if (e.IpAddress.IsNullOrEmpty() && e.SerialNo.IsNullOrEmpty()) { DebugMessageShow(e.Message); } else { DebugMessageShow(e.Message, e.IpAddress, e.SerialNo); } } public void DebugMessageShow(string message, string ipAddress, string serialNo) { if (App.Config.ShowDebugMessage) { var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == ipAddress || (serialNo != null && c.SerialNo == serialNo)); if (equipmentData != null) { equipmentData.DebugMessage.DateTime = DateTime.Now; equipmentData.DebugMessage.Message = message; } } } public void DebugMessageShow(string message) { if (App.Config.ShowDebugMessage) { MainView.DebugMessage.DateTime = DateTime.Now; MainView.DebugMessage.Message = message; } } /// /// 标定限位状态更改 /// private void Calibration_LimitStateChanged(object sender, LimitData limitData) { foreach (var equipment in App.DataCenter.Equipments) { foreach (var limit in equipment.Limits) { if (limit.Name == limitData.Name && limit.IsEnable) { if (limitData.State == LimitState.AtLimit) { limit.State = LimitState.AtLimit; // 当前运行状态添加预标定状态 equipment.RunningStatus |= RunningStatus.PreCalibration; if (App.TcpServer.SendRealTimeAbsolutePositionData((float)limitData.Position, equipment.SerialNo, equipment.ClientSocket)) { DebugMessageShow($"{limitData.Name}标定成功", equipment.IpAddress, equipment.SerialNo); } } else if (limitData.State == LimitState.NotInLimit) { limit.State = LimitState.NotInLimit; } } } } } /// /// 标定模块连接状态更改 /// private void Calibration_ConnectionStateChanged(object sender, bool isConnect) { foreach (var equipment in App.DataCenter.Equipments) { foreach (var limit in equipment.Limits) { if (isConnect) { if (limit.State == LimitState.Offline) { limit.State = LimitState.NotInLimit; } } else { if (limit.State != LimitState.Offline) { limit.State = LimitState.Offline; } } } } } /// /// 接收检测状态开关结果 /// private void TcpServer_DetectionStatusResultReceived(object sender, DetectionStatusResultReceivedEventArgs e) { var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); if (equipmentData != null) { if (equipmentData.RunningStatus.HasFlag(RunningStatus.PreStop)) { equipmentData.RunningStatus = RunningStatus.Stopped; Application.Current.Dispatcher.Invoke(() => { NoticeBox.Show("自动检测停止", "通知", MessageBoxIcon.Warning, true, 3000); }); } else if (equipmentData.RunningStatus.HasFlag(RunningStatus.PreRunning)) { equipmentData.RunningStatus = RunningStatus.TemporalNormal; Application.Current.Dispatcher.Invoke(() => { NoticeBox.Show("自动检测恢复", "通知", MessageBoxIcon.Success, true, 3000); }); } else if (equipmentData.RunningStatus.HasFlag(RunningStatus.PreCalibration)) { equipmentData.RunningStatus = RunningStatus.TemporalNormal; } } } /// /// 接收故障数据 /// private void TcpServer_FaultDataReceived(object sender, FaultDataReceivedEventArgs e) { var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); equipmentData?.Faults.Add(e.FaultData); } /// /// 接收实时数据 /// private void TcpServer_RealTimeDataReceived(object sender, RealTimeDataReceivedEventArgs e) { var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); if (equipmentData != null) { equipmentData.Speed = Math.Round(e.RealTimeData.Speed * 60, 2); equipmentData.Position = e.RealTimeData.Position; equipmentData.RunningStatus = e.RealTimeData.Status; equipmentData.AbsolutePosition = e.RealTimeData.AbsolutePosition; equipmentData.LiftHeight = (equipmentData.RopeLength - equipmentData.AbsolutePosition) / equipmentData.LiftHightRatio; equipmentData.Direction = equipmentData.Speed > 0 ? DirectionState.Forward : (equipmentData.Speed == 0f ? DirectionState.Stoped : DirectionState.Reverse); equipmentData.AddSpeedData(equipmentData.Speed); } } /// /// 客户端连接成功 /// private void TcpServer_ClientConnected(object sender, ClientConnectedEventArgs e) { var equipment = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); if (equipment == null) { LogHelper.Error($"未找到设备,IP地址:{e.IpAddress}"); return; } var server = (TcpServerFrame)sender; server.SendTurnLiveStreamData(true, equipment.SerialNo, e.ClientSocket); Thread.Sleep(20); server.SendSetClockData(DateTime.Now.DateTimeToTimestamp(), equipment.SerialNo, e.ClientSocket); var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); if (equipmentData != null) { equipmentData.IsConnect = true; equipmentData.ClientSocket = e.ClientSocket; if (equipmentData.RunningStatus != RunningStatus.TemporalNormal) { equipmentData.RunningStatus |= RunningStatus.TemporalNormal; } } } /// /// 客户端连接断开 /// private void TcpServer_ClientDisconnected(object sender, ClientDisconnectedEventArgs e) { var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); if (equipmentData != null) { equipmentData.IsConnect = false; equipmentData.ClientSocket = null; equipmentData.Speed = 0; equipmentData.AbsolutePosition = 0; equipmentData.Position = 0; equipmentData.Direction = DirectionState.Stoped; } } /// /// 接收检测结果 /// private void TcpServer_DetectionDataReceived(object sender, DetectionDataReceivedEventArgs e) { var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); if (equipmentData != null) { e.DetectionData.DetectionNo = equipmentData.DetectionNo; equipmentData.DetectionData = e.DetectionData; } } /// /// 接检测原始数据结果 /// private void TcpServer_DetectionRawDataResultReceived(object sender, DetectionRawDataResultReceivedEventArgs e) { var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); if (equipmentData != null) { // 处理检测原始结果数据 if (e.DetectionRawResultData.Code == 0) { if (equipmentData.DetectionData != null) { equipmentData.DetectionData.RawResultData = e.DetectionRawResultData; } } else { LogHelper.Error($"获取检测原始数据失败,错误码:{e.DetectionRawResultData.Code}"); } } } /// /// 接受检测结果原始数据 /// private async void TcpServer_DetectionRawDataReceived(object sender, DetectionRawDataReceivedEventArgs e) { var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); if (equipmentData != null) { if (equipmentData.DisableAlarm) { DebugMessageShow($"获取检测结果原始数据结束", equipmentData.IpAddress, equipmentData.SerialNo); return; } await Task.Run(() => { if (equipmentData.DetectionData != null && equipmentData.DetectionData.RawResultData != null) { DebugMessageShow($"数据接收:{e.DetectionRawData.PacketNumber}/{e.DetectionRawData.TotalPackets}", equipmentData.IpAddress, equipmentData.SerialNo); if (e.DetectionRawData.PacketNumber == 1) { equipmentData.DetectionData.RawDataReceiving = true; equipmentData.DetectionData.RawData = new MemoryStream(); equipmentData.DetectionData.RawData.Write(e.DetectionRawData.Data, 0, e.DetectionRawData.Data.Length); } else if (e.DetectionRawData.PacketNumber <= e.DetectionRawData.TotalPackets) { // 添加原始数据到检测数据中 equipmentData.DetectionData.RawData.Write(e.DetectionRawData.Data, 0, e.DetectionRawData.Data.Length); // 如果是最后一包数据,处理检测数据 if (e.DetectionRawData.PacketNumber == e.DetectionRawData.TotalPackets) { // 生成数据文件路径 (string absolutePath, string relativePath) = DatFileHandler.GetDatFilePath(equipmentData.SerialNo); // 处理检测数据逻辑 var record = new RecordDto { RopeName = equipmentData.RopeName, RopeNumber = equipmentData.RopeNumber, StartPoint = equipmentData.DetectionData.StartPoint, EndPoint = equipmentData.DetectionData.EndPoint, DetectedSpeed = equipmentData.DetectionData.DetectedSpeed, DetectionLength = equipmentData.DetectionData.DetectionLength, StartTime = equipmentData.DetectionData.StartTime.TimestampToDateTime(), EndTime = equipmentData.DetectionData.EndTime.TimestampToDateTime(), SensorCount = equipmentData.DetectionData.RawResultData.SensorCount, SamplingStep = equipmentData.DetectionData.RawResultData.SamplingStep, DataFilePath = relativePath, InUseSensors = string.Join(",", equipmentData.InUseSensor) }; foreach (var damage in equipmentData.DetectionData.Damages) { var alarmCount = _alarmRepository.AddAlarm(new AlarmDataModel { DamageLevel = damage.DamageLevel, DamagePosition = damage.DamagePoint, DamageValue = damage.DamageValue, RopeNumber = equipmentData.RopeNumber }, AlarmSourceType.Detection, App.Config.DamageExtent); if (alarmCount >= App.Config.AlarmValidCount) { record.Damages.Add(new DamageDto { DamageLevel = damage.DamageLevel, DamagePoint = damage.DamagePoint, DamageValue = damage.DamageValue, }); record.DamageCount++; //纠正健康度 以客户端上传的损伤数据 重新计算 if ((int)record.RiskLevel < (int)damage.DamageLevel) { record.RiskLevel = (RiskLevel)damage.DamageLevel; } } } equipmentData.RiskLevel = record.RiskLevel; if (record.DamageCount > 0) { int? recordId = _recordRepository.CreateRecord(record); if (recordId.HasValue) { record.Id = recordId.Value; AddRecordToPageRecords(record); if (!DatFileHandler.CreateDatFile(absolutePath, equipmentData.DetectionData.RawData)) { LogHelper.Error($"创建检测数据文件失败,路径:{absolutePath}"); } DebugMessageShow($"检测数据记录成功", equipmentData.IpAddress, equipmentData.SerialNo); if ((int)record.RiskLevel >= (int)App.Config.SoundRiskLevel) { Application.Current.Dispatcher.Invoke(() => { speech.SpeakAsync($"{equipmentData.RopeName},检测到{record.DamageCount}处损伤"); }); } } else { LogHelper.Error("检测数据记录失败"); } } else { DebugMessageShow($"检测完成,未发现损伤,本次检测不做记录。", equipmentData.IpAddress, equipmentData.SerialNo); } equipmentData.DetectionData.RawDataReceiving = false; } } } }); } } /// /// 接收报警数据 /// private void TcpServer_AlarmDataReceived(object sender, AlarmDataReceivedEventArgs e) { var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress); if (equipmentData != null && equipmentData.IsSpeedStable && !equipmentData.DisableAlarm) { Dispatcher.InvokeAsync(() => { e.AlarmData.RopeNumber = equipmentData.RopeNumber; var alarmCount = _alarmRepository.AddAlarm(e.AlarmData, AlarmSourceType.RealTime, App.Config.DamageExtent); if (alarmCount >= App.Config.AlarmValidCount) { equipmentData.AddAlarm(e.AlarmData); } }); } } private void TcpServer_UpgradedRequestResultReceived(object sender, UpgradedResultReceivedEventArgs e) { Dispatcher.InvokeAsync(async () => { if (e.Code == 0) { await Task.Delay(2000); string url = $"http://192.168.1.200"; // 替换为您的网页地址 Extensions.Tools.OpenUrl(url); } }); } public void AddRecordToPageRecords(RecordDto record) { Application.Current.Dispatcher.Invoke(() => { if (main_frame.Content is Page currentPage && currentPage != null) { var simpleRecord = record.ToSimpleRecordDto(); switch (currentPage.Title) { case "OneRopePage": if (currentPage.DataContext is OneRopeViewModel oneRopeView) { oneRopeView.AddRecord(simpleRecord); } break; case "TwoRopesPage": if (currentPage.DataContext is TwoRopesViewModel twoRopesView) { twoRopesView.AddRecord(simpleRecord); } break; case "ThreeRopesPage": if (currentPage.DataContext is ThreeRopesViewModel threeRopesView) { threeRopesView.AddRecord(simpleRecord); } break; case "FourRopesPage": if (currentPage.DataContext is FourRopesViewModel fourRopesView) { fourRopesView.AddRecord(simpleRecord); } break; } } }); } private void WindowX_Loaded(object sender, RoutedEventArgs e) { NavigateToPage("Home"); } public void NavigatePage(Uri uri) { main_frame.NavigationService.Navigate(uri); } private void NavigateToPage(object pageName) { switch (pageName) { case "Home": MainView.CurrentPage = "Home"; int equipmentCount = App.Config.Equipments.Count; switch (equipmentCount) { case 1: main_frame.NavigationService.Navigate(new Uri($"Pages/RealTime/OneRopePage.xaml", uriKind: UriKind.Relative)); break; case 2: main_frame.NavigationService.Navigate(new Uri($"Pages/RealTime/TwoRopesPage.xaml", uriKind: UriKind.Relative)); break; case 3: main_frame.NavigationService.Navigate(new Uri($"Pages/RealTime/ThreeRopesPage.xaml", uriKind: UriKind.Relative)); break; case 4: main_frame.NavigationService.Navigate(new Uri($"Pages/RealTime/FourRopesPage.xaml", uriKind: UriKind.Relative)); break; } break; case "Record": MainView.CurrentPage = "Record"; main_frame.NavigationService.Navigate(new Uri($"Pages/RecordPage.xaml", uriKind: UriKind.Relative)); break; } } private void Menu_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (sender is TextBlock menuItem) { CleanNavigation(main_frame); NavigateToPage(menuItem?.Tag); } } private void CleanNavigation(Frame frame) { while (frame.CanGoBack) frame.RemoveBackEntry(); } private void StackPanel_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (e.ClickCount == 2) { Left = 0; Top = 0; } } private void Setting_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { SettingDialog settingDialog = new SettingDialog(); if (settingDialog.ShowDialog(true) == true) { if (settingDialog.IsAutoStart) { App.RestartApplication(); } } } private void Window_Closing(object sender, CancelEventArgs e) { App.TcpServer?.Dispose(); speech?.Dispose(); } private void Minimize_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { WindowState = WindowState.Minimized; } private void Close_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { var result = MessageBoxX.Show(this, "退出后将无法进行实时检测,是否确认退出程序?", "警告", MessageBoxButton.YesNo, MessageBoxIcon.Warning, DefaultButton.YesOK); if (result == MessageBoxResult.Yes) { Close(); } } private void SwitchToInstance_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (sender is Border instanceBorder && instanceBorder.Tag != null) { App.SwitchToExistingInstance(instanceBorder.Tag.ToString()); } } } }