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.Reflection;
using System.Speech.Synthesis;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using Tools = SWRIS.Extensions.Tools;
namespace SWRIS
{
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : WindowX, IComponentConnector
{
// 屏幕比例阈值
private const double ASPECT_RATIO_THRESHOLD = 1.5; // 大于此值视为宽屏(16:9),小于此值视为方屏(4:3)
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();
Application.Current.MainWindow = this;
App.TcpServer.ClientConnected += TcpServer_ClientConnected;
App.TcpServer.ClientDisconnected += TcpServer_ClientDisconnected;
App.TcpServer.LiveStreamReceived += TcpServer_LiveStreamReceived;
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 async void TcpServer_LiveStreamReceived(object sender, LiveStreamReceivedEventArgs e)
{
var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress);
if (equipmentData != null)
{
if (equipmentData.DetectionData?.DetectionNo == equipmentData.DetectionNo)
{
equipmentData.ClearData();
}
await Task.Run(() =>
{
equipmentData.Chart?.AddDataPoints((equipmentData.AbsolutePosition, e.LiveStream), equipmentData.InUseSensor);
equipmentData.AddLiveStream(e.LiveStream);
});
}
}
///
/// 接收心跳数据
///
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);
}
}
///
/// 显示调试信息
///
/// 调试信息
/// IP地址
/// 序列号
public void DebugMessageShow(string message, string ipAddress, string serialNo)
{
if (App.Config.ShowDebugMessage)
{
var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => (!serialNo.IsNullOrEmpty() && c.SerialNo == serialNo) || c.IpAddress == ipAddress);
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;
}
}
///
/// 标定限位状态更改
///
[Obfuscation(Feature = "virtualization", Exclude = false)]
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(limit.SwitchIndex, (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.SpatialNormal;
Application.Current.Dispatcher.Invoke(() =>
{
NoticeBox.Show("自动检测恢复", "通知", MessageBoxIcon.Success, true, 3000);
});
}
else if (equipmentData.RunningStatus.HasFlag(RunningStatus.PreCalibration))
{
equipmentData.RunningStatus = RunningStatus.SpatialNormal;
}
}
}
///
/// 接收故障数据
///
private void TcpServer_FaultDataReceived(object sender, FaultDataReceivedEventArgs e)
{
var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress);
equipmentData?.AddFault(e.FaultData);
}
///
/// 接收实时数据
///
[Obfuscation(Feature = "virtualization", Exclude = false)]
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);
}
}
///
/// 客户端连接成功
///
[Obfuscation(Feature = "virtualization", Exclude = false)]
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.SpatialNormal)
{
equipmentData.RunningStatus |= RunningStatus.SpatialNormal;
}
}
}
///
/// 客户端连接断开
///
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}");
}
}
}
///
/// 接受检测结果原始数据
///
[Obfuscation(Feature = "virtualization", Exclude = false)]
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"; // 替换为您的网页地址
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();
if (currentPage.Title == "RealTimePage")
{
if (currentPage.DataContext is RealTimeViewModel realTimeView)
{
realTimeView.AddRecord(simpleRecord);
}
}
}
});
}
private void WindowX_Loaded(object sender, RoutedEventArgs e)
{
AdjustViewboxStretch();
NavigateToPage("Home");
// 在程序启动时开启一个后台线程,每隔15秒检测一次
Task.Run(async () =>
{
bool lastIpOk = true;
bool lastPortOk = true;
while (true)
{
bool ipOk = Tools.CheckIpAddressExists(App.Config.IpAddress);
bool portOk = !Tools.CheckPortInUse(App.Config.Port);
// IP异常
if (!ipOk)
{
NoticeBox.Show($"当前在用网卡的IP地址中没有发现[{App.Config.IpAddress}],请检查网络配置。",
"警告", MessageBoxIcon.Warning, true, 5000);
}
// IP从异常恢复正常
else if (!lastIpOk && ipOk)
{
if (!HasConnectedDevice())
{
NoticeBox.Show($"IP地址[{App.Config.IpAddress}]已恢复,5秒后将自动重启程序", "提示", MessageBoxIcon.Info, true, 5000);
if (HasConnectedDevice())
{
NoticeBox.Show($"检测到有设备处于连接状态,已取消自动重启", "提示", MessageBoxIcon.Info, true, 5000);
}
else
{
await RestartApplication();
}
}
}
// 端口异常
if (!portOk)
{
NoticeBox.Show("当前配置的端口已被占用,请更换端口或关闭占用该端口的程序。",
"警告", MessageBoxIcon.Warning, true, 5000);
}
// 端口从异常恢复正常
else if (!lastPortOk && portOk)
{
if (!HasConnectedDevice())
{
NoticeBox.Show($"端口[{App.Config.Port}]已释放,5秒后将自动重启程序", "提示", MessageBoxIcon.Info, true, 5000);
if (HasConnectedDevice())
{
NoticeBox.Show($"检测到有设备处于连接状态,已取消自动重启", "提示", MessageBoxIcon.Info, true, 5000);
}
else
{
await RestartApplication();
}
}
}
lastIpOk = ipOk;
lastPortOk = portOk;
await Task.Delay(15000); // 每15秒检测一次
}
});
}
private async Task RestartApplication(int delay = 5000)
{
await Task.Delay(delay);
Application.Current.Dispatcher.Invoke(() =>
{
App.RestartApplication();
});
}
///
/// 检查是否有设备处于连接状态
///
private bool HasConnectedDevice()
{
return App.DataCenter.Equipments.Any(e => e.IsConnect);
}
public void NavigatePage(Uri uri)
{
Main_Frame.NavigationService.Navigate(uri);
}
private void NavigateToPage(object pageName)
{
switch (pageName)
{
case "Home":
MainView.CurrentPage = "Home";
Main_Frame.NavigationService.Navigate(new Uri($"Pages/RealTime/RealTimePage.xaml", uriKind: UriKind.Relative));
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());
}
}
private void AdjustViewboxStretch()
{
var screen = System.Windows.Forms.Screen.FromHandle(
new System.Windows.Interop.WindowInteropHelper(this).Handle);
double aspectRatio = (double)screen.Bounds.Width / screen.Bounds.Height;
RootGrid.Height = aspectRatio <= ASPECT_RATIO_THRESHOLD ? 1440 : 1080;
}
}
}