更新20260612
This commit is contained in:
@@ -99,9 +99,10 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
private const ushort PressureCoefficientRegister = 1378;
|
||||
private const ushort PressureDisplayRegister = 1388;
|
||||
private const double TenthsRegisterScale = 10.0;
|
||||
private const int MaxTorqueSampleCount = 120;
|
||||
private const int MaxTorqueSampleCount = 300;
|
||||
private const double MinimumTorqueChangeThreshold = 0.05;
|
||||
private const string TorqueUnit = "mN.m";
|
||||
private static readonly TimeSpan RealtimeRefreshInterval = TimeSpan.FromMilliseconds(100);
|
||||
private static readonly TimeSpan SnapshotInterval = TimeSpan.FromSeconds(5);
|
||||
private static readonly TimeSpan NoLoadCaptureDuration = TimeSpan.FromSeconds(3);
|
||||
private static readonly TimeSpan SpeedTorqueStartConfirmationTimeout = TimeSpan.FromSeconds(5);
|
||||
@@ -305,7 +306,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
|
||||
_realtimeTimer = new DispatcherTimer
|
||||
{
|
||||
Interval = TimeSpan.FromMilliseconds(500)
|
||||
Interval = RealtimeRefreshInterval
|
||||
};
|
||||
_realtimeTimer.Tick += RealtimeTimer_Tick;
|
||||
_realtimeTimer.Start();
|
||||
@@ -747,8 +748,11 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
try
|
||||
{
|
||||
PlcConnectionConfig config = _parameterConfig.ToPlcConnectionConfig();
|
||||
IReadOnlyDictionary<ushort, float> values = await _plcRegisterService.ReadFloatValuesAsync(config, RealtimeRegisterAddresses);
|
||||
IReadOnlyDictionary<ushort, bool> coilValues = await _plcCoilService.ReadCoilValuesAsync(config, RealtimeCoilAddresses);
|
||||
Task<IReadOnlyDictionary<ushort, float>> registerReadTask =
|
||||
_plcRegisterService.ReadFloatValuesAsync(config, RealtimeRegisterAddresses);
|
||||
Task<IReadOnlyDictionary<ushort, bool>> coilReadTask =
|
||||
_plcCoilService.ReadCoilValuesAsync(config, RealtimeCoilAddresses);
|
||||
IReadOnlyDictionary<ushort, float> values = await registerReadTask;
|
||||
|
||||
double dialIndicator = ReadFloatValue(values, DialIndicatorRegister, "千分表显示");
|
||||
double axialForce = ReadFloatValue(values, AxialForceDisplayRegister, "轴向力显示");
|
||||
@@ -771,24 +775,24 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
_realtimeTorque = realtimeTorque;
|
||||
_realtimeSpeed = realtimeSpeed;
|
||||
AppendTorqueSample(GetScaledTorque(), _realtimeSpeed, DateTime.Now);
|
||||
ApplyResetCoilValues(coilValues);
|
||||
bool isVentValveOpen = ReadCoilValue(coilValues, VentValveCoil);
|
||||
VentValveButtonText = isVentValveOpen ? "关闭气阀" : "通气阀";
|
||||
if (_isSpeedTorqueRunning && !isVentValveOpen)
|
||||
{
|
||||
Log.Error("转速/扭矩测试运行中检测到通气阀关闭,M{VentValveCoil}=0,立即停止测试", VentValveCoil);
|
||||
await AutoStopSpeedTorqueAsync("状态:通气阀关闭保护,已停止");
|
||||
}
|
||||
|
||||
CaptureRealtimeSample(dialIndicator, coilValues);
|
||||
FinalizeNoLoadSpeedRunIfDue();
|
||||
QueueSnapshotIfDue();
|
||||
|
||||
if (_isDisplacementRunning)
|
||||
{
|
||||
_maxDisplacement = Math.Max(_maxDisplacement, Math.Abs(_relativeDisplacement));
|
||||
}
|
||||
|
||||
UpdateDisplacementDisplay();
|
||||
UpdateSpeedTorqueDisplay();
|
||||
UpdateNoLoadSpeedDisplay();
|
||||
|
||||
IReadOnlyDictionary<ushort, bool> coilValues = await coilReadTask;
|
||||
ApplyResetCoilValues(coilValues);
|
||||
bool isVentValveOpen = ReadCoilValue(coilValues, VentValveCoil);
|
||||
VentValveButtonText = isVentValveOpen ? "关闭气阀" : "通气阀";
|
||||
|
||||
CaptureRealtimeSample(dialIndicator, coilValues);
|
||||
FinalizeNoLoadSpeedRunIfDue();
|
||||
QueueSnapshotIfDue();
|
||||
|
||||
if (_isDisplacementRunning && ReadCoilValue(coilValues, AxialDoneCoil))
|
||||
{
|
||||
StopDisplacementTest("状态:已完成");
|
||||
@@ -814,9 +818,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
await StopSpeedTorqueTestAsync("状态:已完成");
|
||||
}
|
||||
|
||||
UpdateDisplacementDisplay();
|
||||
UpdateSpeedTorqueDisplay();
|
||||
UpdateNoLoadSpeedDisplay();
|
||||
await AutoStopIfSetpointReachedAsync();
|
||||
await AutoStopIfSpeedTorqueProtectionReachedAsync();
|
||||
|
||||
@@ -2188,52 +2189,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
await MoveSpeedTorqueDisplacementAsync();
|
||||
}
|
||||
|
||||
private async Task<bool> WriteAndVerifyVentValveStateAsync(bool targetState, string reason)
|
||||
{
|
||||
try
|
||||
{
|
||||
PlcConnectionConfig config = _parameterConfig.ToPlcConnectionConfig();
|
||||
await _plcCoilService.WriteCoilAsync(config, VentValveCoil, targetState);
|
||||
await Task.Delay(100);
|
||||
|
||||
IReadOnlyDictionary<ushort, bool> values = await _plcCoilService.ReadCoilValuesAsync(
|
||||
config,
|
||||
[VentValveCoil, SpeedTorqueEnabledCoil]);
|
||||
bool actualState = ReadCoilValue(values, VentValveCoil);
|
||||
bool speedTorqueEnabled = ReadCoilValue(values, SpeedTorqueEnabledCoil);
|
||||
if (actualState != targetState)
|
||||
{
|
||||
StatusText = targetState
|
||||
? "通气阀未能保持开启,已阻止测试启动。"
|
||||
: "通气阀未能关闭,请检查 PLC 状态。";
|
||||
Log.Error(
|
||||
"PLC通气阀状态校验失败:原因 {Reason},要求 M{VentValveCoil}={Expected},实际 {Actual},扭矩使能 M{EnabledCoil}={Enabled}",
|
||||
reason,
|
||||
VentValveCoil,
|
||||
targetState ? 1 : 0,
|
||||
actualState ? 1 : 0,
|
||||
SpeedTorqueEnabledCoil,
|
||||
speedTorqueEnabled ? 1 : 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.Information(
|
||||
"PLC通气阀状态校验成功:原因 {Reason},M{VentValveCoil}={Value},扭矩使能 M{EnabledCoil}={Enabled}",
|
||||
reason,
|
||||
VentValveCoil,
|
||||
actualState ? 1 : 0,
|
||||
SpeedTorqueEnabledCoil,
|
||||
speedTorqueEnabled ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusText = $"PLC 通气阀状态确认失败:{OperatorMessageFormatter.FromException(ex)}";
|
||||
Log.Error(ex, "PLC通气阀状态确认失败:原因 {Reason},M{VentValveCoil}", reason, VentValveCoil);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void QueueFloatTestPageInputWrite(TestPageInputParameter parameter, ushort registerAddress, string fieldName, string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
@@ -2473,15 +2428,9 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
SpeedTorqueTestButtonText = "启动中";
|
||||
StatusText = "转速/扭矩测试启动中...";
|
||||
|
||||
if (!await WriteAndVerifyVentValveStateAsync(true, "转速/扭矩测试启动前"))
|
||||
{
|
||||
SpeedTorqueTestButtonText = "测试";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await PulsePlcAsync(SpeedTorqueStartCoil, "转速/扭矩测试"))
|
||||
{
|
||||
await AbortSpeedTorqueStartupAsync("M80 启动指令失败,已停止并关闭通气阀。", "M80启动指令失败");
|
||||
await AbortSpeedTorqueStartupAsync("M80 启动指令失败,已停止测试。", "M80启动指令失败");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2489,13 +2438,13 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
StatusText = "转速/扭矩测试启动指令已发送,正在确认 PLC 扭矩使能。";
|
||||
if (!await WaitForSpeedTorqueStartAsync())
|
||||
{
|
||||
await AbortSpeedTorqueStartupAsync("PLC 未进入扭矩测试运行状态,已停止并关闭通气阀。", "启动状态确认失败");
|
||||
await AbortSpeedTorqueStartupAsync("PLC 未进入扭矩测试运行状态,已停止测试。", "启动状态确认失败");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryGetRealtimeSpeed(out _) || !TryGetRealtimeTorque(out _))
|
||||
{
|
||||
await AbortSpeedTorqueStartupAsync("实时数据无效,已停止测试并关闭通气阀。", "启动数据无效");
|
||||
await AbortSpeedTorqueStartupAsync("实时数据无效,已停止测试。", "启动数据无效");
|
||||
UpdateSpeedTorqueDisplay();
|
||||
return;
|
||||
}
|
||||
@@ -2515,11 +2464,11 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
AppendTorqueSample(GetScaledTorque(), _realtimeSpeed, _speedTorqueStartedAt.Value);
|
||||
_maxSpeedTorqueDisplacement = Math.Max(_maxSpeedTorqueDisplacement, Math.Abs(_speedTorqueDisplacement));
|
||||
UpdateSpeedTorqueDisplay();
|
||||
StatusText = "转速/扭矩测试已启动,通气阀与扭矩使能状态正常。";
|
||||
StatusText = "转速/扭矩测试已启动,通气阀由手动按钮独立控制。";
|
||||
Log.Information(
|
||||
"转速/扭矩测试已启动,通气阀 M{VentValveCoil}=1,启动 M{StartCoil}已触发,起始转速 {Speed},起始扭矩 {Torque},起始位移 {Displacement}",
|
||||
VentValveCoil,
|
||||
"转速/扭矩测试已启动,启动 M{StartCoil}已触发,通气阀 M{VentValveCoil}保持手动控制,起始转速 {Speed},起始扭矩 {Torque},起始位移 {Displacement}",
|
||||
SpeedTorqueStartCoil,
|
||||
VentValveCoil,
|
||||
_realtimeSpeed,
|
||||
GetScaledTorque(),
|
||||
_speedTorqueDisplacement);
|
||||
@@ -2529,7 +2478,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
private async Task<bool> WaitForSpeedTorqueStartAsync()
|
||||
{
|
||||
DateTime deadline = DateTime.Now.Add(SpeedTorqueStartConfirmationTimeout);
|
||||
bool lastVentValveOpen = false;
|
||||
bool lastEnabled = false;
|
||||
bool lastDone = false;
|
||||
bool hasReadState = false;
|
||||
@@ -2541,30 +2489,15 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
{
|
||||
IReadOnlyDictionary<ushort, bool> values = await _plcCoilService.ReadCoilValuesAsync(
|
||||
_parameterConfig.ToPlcConnectionConfig(),
|
||||
[VentValveCoil, SpeedTorqueEnabledCoil, SpeedTorqueDoneCoil]);
|
||||
lastVentValveOpen = ReadCoilValue(values, VentValveCoil);
|
||||
[SpeedTorqueEnabledCoil, SpeedTorqueDoneCoil]);
|
||||
lastEnabled = ReadCoilValue(values, SpeedTorqueEnabledCoil);
|
||||
lastDone = ReadCoilValue(values, SpeedTorqueDoneCoil);
|
||||
hasReadState = true;
|
||||
|
||||
if (!lastVentValveOpen)
|
||||
{
|
||||
StatusText = "M80 启动后通气阀 M6 未保持开启,已阻止测试运行。";
|
||||
Log.Error(
|
||||
"转速/扭矩启动状态确认失败:M80后通气阀关闭,M{VentValveCoil}=0,M{EnabledCoil}={Enabled},M{DoneCoil}={Done}",
|
||||
VentValveCoil,
|
||||
SpeedTorqueEnabledCoil,
|
||||
lastEnabled ? 1 : 0,
|
||||
SpeedTorqueDoneCoil,
|
||||
lastDone ? 1 : 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lastEnabled && !lastDone)
|
||||
{
|
||||
Log.Information(
|
||||
"转速/扭矩启动状态确认成功:M{VentValveCoil}=1,M{EnabledCoil}=1,M{DoneCoil}=0",
|
||||
VentValveCoil,
|
||||
"转速/扭矩启动状态确认成功:M{EnabledCoil}=1,M{DoneCoil}=0,通气阀保持手动控制",
|
||||
SpeedTorqueEnabledCoil,
|
||||
SpeedTorqueDoneCoil);
|
||||
return true;
|
||||
@@ -2577,8 +2510,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
hasLoggedReadFailure = true;
|
||||
Log.Warning(
|
||||
ex,
|
||||
"转速/扭矩启动状态读取失败,继续等待 M{VentValveCoil}/M{EnabledCoil}/M{DoneCoil}",
|
||||
VentValveCoil,
|
||||
"转速/扭矩启动状态读取失败,继续等待 M{EnabledCoil}/M{DoneCoil}",
|
||||
SpeedTorqueEnabledCoil,
|
||||
SpeedTorqueDoneCoil);
|
||||
}
|
||||
@@ -2589,11 +2521,9 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
|
||||
StatusText = "M80 启动后 PLC 未确认扭矩使能,已阻止测试运行。";
|
||||
Log.Error(
|
||||
"转速/扭矩启动状态确认超时:等待 {TimeoutSeconds} 秒,已读取状态 {HasReadState},最后 M{VentValveCoil}={VentValveOpen},M{EnabledCoil}={Enabled},M{DoneCoil}={Done}",
|
||||
"转速/扭矩启动状态确认超时:等待 {TimeoutSeconds} 秒,已读取状态 {HasReadState},最后 M{EnabledCoil}={Enabled},M{DoneCoil}={Done}",
|
||||
SpeedTorqueStartConfirmationTimeout.TotalSeconds,
|
||||
hasReadState,
|
||||
VentValveCoil,
|
||||
lastVentValveOpen ? 1 : 0,
|
||||
SpeedTorqueEnabledCoil,
|
||||
lastEnabled ? 1 : 0,
|
||||
SpeedTorqueDoneCoil,
|
||||
@@ -2604,19 +2534,16 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
private async Task AbortSpeedTorqueStartupAsync(string status, string reason)
|
||||
{
|
||||
bool stopSent = await PulsePlcAsync(SpeedTorqueStopCoil, $"转速/扭矩{reason}停止");
|
||||
bool ventClosed = await WriteAndVerifyVentValveStateAsync(false, $"转速/扭矩{reason}");
|
||||
_isSpeedTorqueRunning = false;
|
||||
_isSpeedTorqueCompletionArmed = false;
|
||||
_hasLoggedStaleSpeedTorqueDone = false;
|
||||
SpeedTorqueTestButtonText = "测试";
|
||||
StatusText = status;
|
||||
Log.Error(
|
||||
"转速/扭矩启动已中止:原因 {Reason},M{StopCoil}停止指令成功 {StopSent},M{VentValveCoil}关闭确认成功 {VentClosed}",
|
||||
"转速/扭矩启动已中止:原因 {Reason},M{StopCoil}停止指令成功 {StopSent},通气阀保持手动控制",
|
||||
reason,
|
||||
SpeedTorqueStopCoil,
|
||||
stopSent,
|
||||
VentValveCoil,
|
||||
ventClosed);
|
||||
stopSent);
|
||||
}
|
||||
|
||||
private async Task StopSpeedTorqueAsync()
|
||||
@@ -2670,7 +2597,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
_hasShownSpeedTorqueEndWarnings = false;
|
||||
ClearTorqueSamples();
|
||||
UpdateSpeedTorqueDisplay();
|
||||
await WriteAndVerifyVentValveStateAsync(false, "转速/扭矩复位");
|
||||
Log.Information("转速/扭矩复位完成,零点 {ZeroPosition}", _speedTorqueZero);
|
||||
}
|
||||
finally
|
||||
@@ -2691,7 +2617,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
|
||||
IReadOnlyDictionary<ushort, bool> values = await _plcCoilService.ReadCoilValuesAsync(
|
||||
config,
|
||||
[VentValveCoil, SpeedTorqueEnabledCoil]);
|
||||
[VentValveCoil]);
|
||||
bool actualState = ReadCoilValue(values, VentValveCoil);
|
||||
if (actualState != targetState)
|
||||
{
|
||||
@@ -2700,25 +2626,21 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
: "通气阀未能关闭,请检查 PLC 状态。";
|
||||
StatusText = error;
|
||||
Log.Warning(
|
||||
"通气阀切换失败:目标 {Target},实际 {Actual},M{VentValveCoil}={ActualState},扭矩使能 M{EnabledCoil}={Enabled}",
|
||||
"通气阀手动切换失败:目标 {Target},实际 {Actual},M{VentValveCoil}={ActualState}",
|
||||
targetState ? "开启" : "关闭",
|
||||
actualState ? "开启" : "关闭",
|
||||
VentValveCoil,
|
||||
actualState ? 1 : 0,
|
||||
SpeedTorqueEnabledCoil,
|
||||
ReadCoilValue(values, SpeedTorqueEnabledCoil) ? 1 : 0);
|
||||
actualState ? 1 : 0);
|
||||
return;
|
||||
}
|
||||
|
||||
VentValveButtonText = actualState ? "关闭气阀" : "通气阀";
|
||||
StatusText = actualState ? "通气阀已开启。" : "通气阀已关闭。";
|
||||
Log.Information(
|
||||
"通气阀切换成功:目标 {Target},M{VentValveCoil}={State},扭矩使能 M{EnabledCoil}={Enabled}",
|
||||
"通气阀手动切换成功:目标 {Target},M{VentValveCoil}={State}",
|
||||
targetState ? "开启" : "关闭",
|
||||
VentValveCoil,
|
||||
actualState ? 1 : 0,
|
||||
SpeedTorqueEnabledCoil,
|
||||
ReadCoilValue(values, SpeedTorqueEnabledCoil) ? 1 : 0);
|
||||
actualState ? 1 : 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -3201,7 +3123,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
_isSpeedTorqueCompletionArmed = false;
|
||||
_hasLoggedStaleSpeedTorqueDone = false;
|
||||
SpeedTorqueTestButtonText = "测试";
|
||||
await WriteAndVerifyVentValveStateAsync(false, "转速/扭矩测试结束数据无效");
|
||||
UpdateSpeedTorqueDisplay();
|
||||
return;
|
||||
}
|
||||
@@ -3218,11 +3139,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
FinalizeSpeedTorqueRun(status);
|
||||
PersistCurrentPayloadSnapshot("转速/扭矩测试停止");
|
||||
UpdateSpeedTorqueDisplay();
|
||||
Log.Information("转速/扭矩测试停止:{Status},最终位移 {FinalDisplacement},最终转速 {FinalSpeed},最终扭矩 {FinalTorque}", status, _finalSpeedTorqueDisplacement, _finalSpeed, _finalTorque);
|
||||
if (!await WriteAndVerifyVentValveStateAsync(false, "转速/扭矩测试结束"))
|
||||
{
|
||||
StatusText = "测试已停止,但通气阀关闭状态未确认,请检查设备。";
|
||||
}
|
||||
Log.Information("转速/扭矩测试停止:{Status},最终位移 {FinalDisplacement},最终转速 {FinalSpeed},最终扭矩 {FinalTorque},通气阀保持手动控制", status, _finalSpeedTorqueDisplacement, _finalSpeed, _finalTorque);
|
||||
|
||||
await ShowSpeedTorqueEndWarningsAsync();
|
||||
}
|
||||
@@ -3367,20 +3284,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
return;
|
||||
}
|
||||
|
||||
double holdTimeSeconds = _parameterConfig.TorqueHoldTime;
|
||||
if (holdTimeSeconds <= 0)
|
||||
{
|
||||
UpdateTorqueCurveStatus();
|
||||
return;
|
||||
}
|
||||
|
||||
double elapsedSeconds = Math.Max(0, (sampledAt - _speedTorqueStartedAt.Value).TotalSeconds);
|
||||
if (elapsedSeconds > holdTimeSeconds)
|
||||
{
|
||||
UpdateTorqueCurveStatus();
|
||||
return;
|
||||
}
|
||||
|
||||
TorqueSamples.Add(new TorqueSamplePayload
|
||||
{
|
||||
ElapsedSeconds = elapsedSeconds,
|
||||
@@ -3394,8 +3298,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
{
|
||||
TorqueSamples.RemoveAt(0);
|
||||
}
|
||||
|
||||
UpdateTorqueCurveStatus();
|
||||
}
|
||||
|
||||
private void ClearTorqueSamples()
|
||||
@@ -3407,14 +3309,11 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
|
||||
private void UpdateTorqueCurveStatus()
|
||||
{
|
||||
if (_isSpeedTorqueRunning && _parameterConfig.TorqueHoldTime > 0 && TorqueSamples.Count > 0)
|
||||
if (_isSpeedTorqueRunning && TorqueSamples.Count > 0)
|
||||
{
|
||||
double elapsed = TorqueSamples[^1].ElapsedSeconds;
|
||||
if (elapsed < _parameterConfig.TorqueHoldTime)
|
||||
{
|
||||
TorqueCurveStatusText = $"保持时间曲线:采集中 {FormatConfigNumber(elapsed)} / {FormatConfigNumber(_parameterConfig.TorqueHoldTime)} s";
|
||||
return;
|
||||
}
|
||||
TorqueCurveStatusText = $"实时曲线:采集中 {FormatConfigNumber(elapsed)} s;X轴转速 / Y轴扭矩";
|
||||
return;
|
||||
}
|
||||
|
||||
TorqueCurvePayload curve = CreateTorqueCurvePayload();
|
||||
@@ -3540,12 +3439,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
|
||||
private int GetTorqueSampleLimit()
|
||||
{
|
||||
if (_parameterConfig.TorqueHoldTime <= 0)
|
||||
{
|
||||
return MaxTorqueSampleCount;
|
||||
}
|
||||
|
||||
return Math.Max(MaxTorqueSampleCount, (int)Math.Ceiling(_parameterConfig.TorqueHoldTime * 2.5) + 4);
|
||||
return MaxTorqueSampleCount;
|
||||
}
|
||||
|
||||
private void CaptureRealtimeSample(double dialIndicator, IReadOnlyDictionary<ushort, bool> coilValues)
|
||||
@@ -3637,6 +3531,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
}
|
||||
|
||||
AppendLatestSample(_activeSpeedTorqueRun);
|
||||
_cachedTorqueCurve = CreateTorqueCurvePayload(_activeSpeedTorqueRun);
|
||||
_activeSpeedTorqueRun.CompletedAt = DateTime.Now;
|
||||
_activeSpeedTorqueRun.CompletionStatus = status;
|
||||
_activeSpeedTorqueRun.FinalDisplacementMm = _finalSpeedTorqueDisplacement ?? _speedTorqueDisplacement;
|
||||
|
||||
@@ -93,10 +93,17 @@ public sealed class ModbusTcpPlcCoilService : IPlcCoilService, IPlcRegisterServi
|
||||
return new Dictionary<ushort, float>();
|
||||
}
|
||||
|
||||
IReadOnlyList<RegisterReadGroup> groups = CreateRegisterReadGroups(registerAddresses);
|
||||
Task<ushort[]>[] readTasks = groups
|
||||
.Select(group => ReadHoldingRegistersAsync(config, group.StartAddress, group.RegisterCount, cancellationToken))
|
||||
.ToArray();
|
||||
ushort[][] groupRegisters = await Task.WhenAll(readTasks);
|
||||
|
||||
var values = new Dictionary<ushort, float>();
|
||||
foreach (RegisterReadGroup group in CreateRegisterReadGroups(registerAddresses))
|
||||
for (int groupIndex = 0; groupIndex < groups.Count; groupIndex++)
|
||||
{
|
||||
ushort[] registers = await ReadHoldingRegistersAsync(config, group.StartAddress, group.RegisterCount, cancellationToken);
|
||||
RegisterReadGroup group = groups[groupIndex];
|
||||
ushort[] registers = groupRegisters[groupIndex];
|
||||
foreach (ushort address in group.FloatAddresses)
|
||||
{
|
||||
int offset = address - group.StartAddress;
|
||||
|
||||
Reference in New Issue
Block a user