|
|
@@ -19,6 +19,7 @@ using System.Threading.Tasks;
|
|
|
using System.Windows;
|
|
|
using System.Windows.Controls;
|
|
|
using System.Windows.Markup;
|
|
|
+using System.Windows.Threading;
|
|
|
using Tools = SWRIS.Extensions.Tools;
|
|
|
namespace SWRIS
|
|
|
{
|
|
|
@@ -29,7 +30,10 @@ namespace SWRIS
|
|
|
{
|
|
|
// 屏幕比例阈值
|
|
|
private const double ASPECT_RATIO_THRESHOLD = 1.5; // 大于此值视为宽屏(16:9),小于此值视为方屏(4:3)
|
|
|
+ // 预状态(PreStop/PreRunning/PreCalibration)等待设备确认的超时阈值
|
|
|
+ private static readonly long PreStatusTimeoutTicks = TimeSpan.FromSeconds(10).Ticks;
|
|
|
private readonly SpeechSynthesizer speech;
|
|
|
+ private readonly DispatcherTimer _preStatusTimer;
|
|
|
public MainViewModel MainView { get; set; }
|
|
|
|
|
|
private readonly IRecordRepository _recordRepository;
|
|
|
@@ -57,6 +61,7 @@ namespace SWRIS
|
|
|
App.TcpServer.DetectionRawDataReceived += TcpServer_DetectionRawDataReceived;
|
|
|
App.TcpServer.DetectionRawDataResultReceived += TcpServer_DetectionRawDataResultReceived;
|
|
|
App.TcpServer.DetectionStatusResultReceived += TcpServer_DetectionStatusResultReceived;
|
|
|
+ App.TcpServer.SetAbsolutePositionDataReceived += TcpServer_SetAbsolutePositionDataReceived;
|
|
|
App.TcpServer.DebugMessageReceived += TcpServer_DebugMessageReceived;
|
|
|
App.TcpServer.HeartbeatReceived += TcpServer_HeartbeatReceived;
|
|
|
App.TcpServer.UpgradedRequestResultReceived += TcpServer_UpgradedRequestResultReceived;
|
|
|
@@ -65,9 +70,32 @@ namespace SWRIS
|
|
|
|
|
|
App.TcpServer.Start();
|
|
|
|
|
|
+ // 周期性检查预状态(PreStop/PreRunning/PreCalibration)是否超时未获设备确认,超时则回退
|
|
|
+ _preStatusTimer = new DispatcherTimer
|
|
|
+ {
|
|
|
+ Interval = TimeSpan.FromSeconds(2)
|
|
|
+ };
|
|
|
+ _preStatusTimer.Tick += PreStatusTimer_Tick;
|
|
|
+ _preStatusTimer.Start();
|
|
|
+
|
|
|
DataContext = MainView;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 预状态超时检查:设备长时间未确认命令(检测状态结果),清除预状态位,回退为设备实际状态
|
|
|
+ /// </summary>
|
|
|
+ private void PreStatusTimer_Tick(object sender, EventArgs e)
|
|
|
+ {
|
|
|
+ foreach (var equipmentData in App.DataCenter.Equipments)
|
|
|
+ {
|
|
|
+ if (equipmentData.PreStatusTimestamp != 0 &&
|
|
|
+ DateTime.UtcNow.Ticks - equipmentData.PreStatusTimestamp > PreStatusTimeoutTicks)
|
|
|
+ {
|
|
|
+ equipmentData.ClearAllPreStatus();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private async void TcpServer_LiveStreamReceived(object sender, LiveStreamReceivedEventArgs e)
|
|
|
{
|
|
|
var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress);
|
|
|
@@ -155,8 +183,8 @@ namespace SWRIS
|
|
|
if (limitData.State == LimitState.AtLimit)
|
|
|
{
|
|
|
limit.State = LimitState.AtLimit;
|
|
|
- // 当前运行状态添加预标定状态
|
|
|
- equipment.RunningStatus |= RunningStatus.PreCalibration;
|
|
|
+ // 当前运行状态添加预标定状态并记录挂起时间,超时未确认时由定时器回退
|
|
|
+ equipment.MarkPreStatus(RunningStatus.PreCalibration);
|
|
|
if (App.TcpServer.SendRealTimeAbsolutePositionData(limit.SwitchIndex, (float)limitData.Position, equipment.SerialNo, equipment.ClientSocket))
|
|
|
{
|
|
|
DebugMessageShow($"{limitData.Name}标定成功", equipment.IpAddress, equipment.SerialNo);
|
|
|
@@ -198,7 +226,7 @@ namespace SWRIS
|
|
|
|
|
|
}
|
|
|
/// <summary>
|
|
|
- /// 接收检测状态开关结果
|
|
|
+ /// 接收检测状态开关结果(0x06 应答):确认 PreStop/PreRunning 预状态
|
|
|
/// </summary>
|
|
|
private void TcpServer_DetectionStatusResultReceived(object sender, DetectionStatusResultReceivedEventArgs e)
|
|
|
{
|
|
|
@@ -207,23 +235,35 @@ namespace SWRIS
|
|
|
{
|
|
|
if (equipmentData.RunningStatus.HasFlag(RunningStatus.PreStop))
|
|
|
{
|
|
|
- equipmentData.RunningStatus = RunningStatus.Stopped;
|
|
|
- Application.Current.Dispatcher.Invoke(() =>
|
|
|
- {
|
|
|
- NoticeBox.Show("自动检测停止", "通知", MessageBoxIcon.Warning, true, 3000);
|
|
|
- });
|
|
|
+ // 按位合并,保留报警/故障等其他状态位
|
|
|
+ equipmentData.ConfirmPreStatus(RunningStatus.PreStop, RunningStatus.Stopped);
|
|
|
+ DebugMessageShow("自动检测停止", e.IpAddress, equipmentData.SerialNo);
|
|
|
}
|
|
|
else if (equipmentData.RunningStatus.HasFlag(RunningStatus.PreRunning))
|
|
|
{
|
|
|
- equipmentData.RunningStatus = RunningStatus.SpatialNormal;
|
|
|
- Application.Current.Dispatcher.Invoke(() =>
|
|
|
- {
|
|
|
- NoticeBox.Show("自动检测恢复", "通知", MessageBoxIcon.Success, true, 3000);
|
|
|
- });
|
|
|
+ // 用启动命令时记录的请求模式恢复检测形式(时域/空域),避免使用切换前的旧模式位
|
|
|
+ var mode = equipmentData.PreStatusRunningMode == RunningStatus.TemporalNormal
|
|
|
+ ? RunningStatus.TemporalNormal : RunningStatus.SpatialNormal;
|
|
|
+ var modeName = mode == RunningStatus.TemporalNormal ? "时域检测" : "空域检测";
|
|
|
+ equipmentData.ConfirmPreStatus(RunningStatus.PreRunning, mode);
|
|
|
+ DebugMessageShow($"自动检测开始,检测形式:{modeName}", e.IpAddress, equipmentData.SerialNo);
|
|
|
}
|
|
|
- else if (equipmentData.RunningStatus.HasFlag(RunningStatus.PreCalibration))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 接收设置实时位置(标定)应答(0x15):确认 PreCalibration 预状态
|
|
|
+ /// </summary>
|
|
|
+ private void TcpServer_SetAbsolutePositionDataReceived(object sender, SetAbsolutePositionDataReceivedEventArgs e)
|
|
|
+ {
|
|
|
+ var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == e.IpAddress);
|
|
|
+ if (equipmentData != null && e.SetAbsolutePositionData != null)
|
|
|
+ {
|
|
|
+ // 标定命令已获得设备应答(无论成败均视为确认),清除预标定位;
|
|
|
+ // 若还有其他挂起的预状态位则保留其超时时间戳
|
|
|
+ equipmentData.RunningStatus &= ~RunningStatus.PreCalibration;
|
|
|
+ if ((equipmentData.RunningStatus & (RunningStatus.PreStop | RunningStatus.PreRunning | RunningStatus.PreCalibration)) == 0)
|
|
|
{
|
|
|
- equipmentData.RunningStatus = RunningStatus.SpatialNormal;
|
|
|
+ equipmentData.PreStatusTimestamp = 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -246,9 +286,33 @@ namespace SWRIS
|
|
|
{
|
|
|
equipmentData.Speed = Math.Round(e.RealTimeData.Speed * 60, 2);
|
|
|
equipmentData.Position = e.RealTimeData.Position;
|
|
|
- equipmentData.RunningStatus = e.RealTimeData.Status;
|
|
|
+ var preStatusMask = RunningStatus.PreStop | RunningStatus.PreRunning | RunningStatus.PreCalibration;
|
|
|
+ // 设备实时状态已带预状态位 => 设备已确认命令并进入预状态,清除本地挂起时间戳,预状态以设备状态为准
|
|
|
+ if ((e.RealTimeData.Status & preStatusMask) != 0)
|
|
|
+ {
|
|
|
+ equipmentData.PreStatusTimestamp = 0;
|
|
|
+ equipmentData.RunningStatus = e.RealTimeData.Status;
|
|
|
+ }
|
|
|
+ else if (equipmentData.PreStatusTimestamp != 0)
|
|
|
+ {
|
|
|
+ // 存在待设备确认的预状态且设备尚未确认:保留本地挂起的预状态位,等待确认或超时回退
|
|
|
+ var pendingFlags = equipmentData.RunningStatus & preStatusMask;
|
|
|
+ equipmentData.RunningStatus = e.RealTimeData.Status | pendingFlags;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 无挂起预状态:0x0B 只更新设备实际状态位
|
|
|
+ equipmentData.RunningStatus = e.RealTimeData.Status;
|
|
|
+ }
|
|
|
equipmentData.AbsolutePosition = e.RealTimeData.AbsolutePosition;
|
|
|
- equipmentData.LiftHeight = (equipmentData.RopeLength - equipmentData.AbsolutePosition) / equipmentData.LiftHightRatio;
|
|
|
+ if (equipmentData.RunningStatus == RunningStatus.SpatialNormal)
|
|
|
+ {
|
|
|
+ equipmentData.LiftHeight = (equipmentData.RopeLength - equipmentData.AbsolutePosition) / equipmentData.LiftHightRatio;
|
|
|
+ }
|
|
|
+ else if (equipmentData.LiftHeight != 0)
|
|
|
+ {
|
|
|
+ equipmentData.LiftHeight = 0;
|
|
|
+ }
|
|
|
equipmentData.Direction = equipmentData.Speed > 0 ? DirectionState.Forward :
|
|
|
(equipmentData.Speed == 0f ? DirectionState.Stoped : DirectionState.Reverse);
|
|
|
equipmentData.AddSpeedData(equipmentData.Speed);
|
|
|
@@ -295,6 +359,8 @@ namespace SWRIS
|
|
|
equipmentData.AbsolutePosition = 0;
|
|
|
equipmentData.Position = 0;
|
|
|
equipmentData.Direction = DirectionState.Stoped;
|
|
|
+ // 断线时清除挂起的预状态位,避免重连后残留影响状态判断
|
|
|
+ equipmentData.ClearAllPreStatus();
|
|
|
}
|
|
|
}
|
|
|
/// <summary>
|