更新20260602
This commit is contained in:
@@ -5,12 +5,17 @@ using Avalonia.Data.Core.Plugins;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModels;
|
||||
using Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Views;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
private static bool exceptionHandlersRegistered;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
@@ -18,6 +23,8 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
RegisterExceptionHandlers();
|
||||
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
desktop.MainWindow = new MainWindow
|
||||
@@ -28,5 +35,33 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
|
||||
private static void RegisterExceptionHandlers()
|
||||
{
|
||||
if (exceptionHandlersRegistered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
|
||||
{
|
||||
if (args.ExceptionObject is Exception exception)
|
||||
{
|
||||
Log.Fatal(exception, "捕获到 AppDomain 未处理异常,IsTerminating={IsTerminating}", args.IsTerminating);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("捕获到 AppDomain 未处理异常:{ExceptionObject}", args.ExceptionObject);
|
||||
}
|
||||
};
|
||||
|
||||
TaskScheduler.UnobservedTaskException += (_, args) =>
|
||||
{
|
||||
Log.Error(args.Exception, "捕获到未观察的后台任务异常");
|
||||
args.SetObserved();
|
||||
};
|
||||
|
||||
exceptionHandlersRegistered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,8 @@
|
||||
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
|
||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.4" />
|
||||
<PackageReference Include="NModbus" Version="3.0.83" />
|
||||
<PackageReference Include="Serilog" Version="4.3.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
<PackageReference Include="SukiUI" Version="6.0.2" />
|
||||
<PackageReference Include="System.IO.Ports" Version="10.0.8" />
|
||||
<PackageReference Include="Tmds.DBus.Protocol" Version="0.94.1" />
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Models
|
||||
{
|
||||
public sealed record AdcZeroCalibration(
|
||||
int NormalPressureZero,
|
||||
int FrictionZero1,
|
||||
int FrictionZero2);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Models
|
||||
{
|
||||
public sealed record PlcDeviceParameters(
|
||||
double ManualSpeed,
|
||||
double ManualDisplacement,
|
||||
double TestSpeed);
|
||||
}
|
||||
@@ -1,18 +1,35 @@
|
||||
using Avalonia;
|
||||
using Avalonia;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance
|
||||
{
|
||||
internal sealed class Program
|
||||
{
|
||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||
// yet and stuff might break.
|
||||
[STAThread]
|
||||
public static void Main(string[] args) => BuildAvaloniaApp()
|
||||
.StartWithClassicDesktopLifetime(args);
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
ConfigureLogging();
|
||||
|
||||
try
|
||||
{
|
||||
Log.Information("鞋类整鞋防滑性能试验程序启动");
|
||||
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
||||
return 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, "程序发生致命异常并退出");
|
||||
return 1;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Log.Information("鞋类整鞋防滑性能试验程序退出");
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
}
|
||||
|
||||
// Avalonia configuration, don't remove; also used by visual designer.
|
||||
public static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
@@ -21,5 +38,27 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance
|
||||
#endif
|
||||
.WithInterFont()
|
||||
.LogToTrace();
|
||||
|
||||
private static void ConfigureLogging()
|
||||
{
|
||||
var logDirectory = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"FootwearSlipResistance",
|
||||
"Logs");
|
||||
Directory.CreateDirectory(logDirectory);
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.MinimumLevel.Debug()
|
||||
.WriteTo.File(
|
||||
Path.Combine(logDirectory, "app-.log"),
|
||||
rollingInterval: RollingInterval.Day,
|
||||
retainedFileCountLimit: 30,
|
||||
fileSizeLimitBytes: 20 * 1024 * 1024,
|
||||
rollOnFileSizeLimit: true,
|
||||
shared: true,
|
||||
flushToDiskInterval: TimeSpan.FromSeconds(1),
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
|
||||
.CreateLogger();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using DocumentFormat.OpenXml;
|
||||
using DocumentFormat.OpenXml.Packaging;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Models;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
@@ -28,6 +29,13 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
: report.TestNumber);
|
||||
var path = Path.Combine(directory, $"{safeNumber}_防滑性能测试报告.xlsx");
|
||||
|
||||
Log.Information(
|
||||
"开始导出防滑性能 Excel:TestNumber={TestNumber}, ResultCount={ResultCount}, PointCount={PointCount}, Path={Path}",
|
||||
report.TestNumber,
|
||||
report.Results.Count,
|
||||
report.Points.Count,
|
||||
path);
|
||||
|
||||
using var document = SpreadsheetDocument.Create(path, SpreadsheetDocumentType.Workbook);
|
||||
var workbookPart = document.AddWorkbookPart();
|
||||
workbookPart.Workbook = new Workbook();
|
||||
@@ -38,6 +46,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
AddDataSheet(workbookPart, sheets, 3, report.Points);
|
||||
|
||||
workbookPart.Workbook.Save();
|
||||
Log.Information("防滑性能 Excel 导出完成:Path={Path}", path);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Models;
|
||||
using NModbus;
|
||||
using NModbus.IO;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO.Ports;
|
||||
@@ -37,10 +38,16 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
private IModbusSerialMaster? adcMaster;
|
||||
private DeviceSettings settings = new("0.00", "0.00", "0.30", "0", "0.00", "0", "0.00", "0", "0.00", "COM7", "COM8", 115200);
|
||||
private SlipDeviceSnapshot snapshot = SlipDeviceSnapshot.Offline();
|
||||
private DateTime lastAdcErrorLoggedAt = DateTime.MinValue;
|
||||
private DateTime lastPlcErrorLoggedAt = DateTime.MinValue;
|
||||
|
||||
private double verticalLoadN;
|
||||
private double horizontalFrictionN;
|
||||
private double displacementMm;
|
||||
private int pressureRawValue;
|
||||
private int frictionRawValue1;
|
||||
private int frictionRawValue2;
|
||||
private bool hasAdcRawValues;
|
||||
private bool isTestRunning;
|
||||
private bool isResetting;
|
||||
private bool isConnected;
|
||||
@@ -64,6 +71,13 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
|
||||
try
|
||||
{
|
||||
Log.Information(
|
||||
"启动防滑测试设备连接:PLC={PlcPort}, ADC={AdcPort}, BaudRate={BaudRate}, SlaveId={SlaveId}",
|
||||
settings.PlcPortName,
|
||||
settings.AdcPortName,
|
||||
settings.BaudRate,
|
||||
SlaveId);
|
||||
|
||||
plcPort = CreatePort(settings.PlcPortName, settings.BaudRate);
|
||||
adcPort = CreatePort(settings.AdcPortName, settings.BaudRate);
|
||||
plcPort.Open();
|
||||
@@ -79,9 +93,16 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
SetConnected(true, string.Empty);
|
||||
adcTask = Task.Run(() => PollAdc(token), token);
|
||||
plcTask = Task.Run(() => PollPlc(token), token);
|
||||
Log.Information("防滑测试设备连接成功,ADC/PLC 轮询已启动");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(
|
||||
ex,
|
||||
"防滑测试设备连接失败:PLC={PlcPort}, ADC={AdcPort}, BaudRate={BaudRate}",
|
||||
settings.PlcPortName,
|
||||
settings.AdcPortName,
|
||||
settings.BaudRate);
|
||||
SetConnected(false, ex.Message);
|
||||
Stop();
|
||||
}
|
||||
@@ -90,6 +111,14 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
public void UpdateSettings(DeviceSettings deviceSettings)
|
||||
{
|
||||
settings = deviceSettings;
|
||||
Log.Debug(
|
||||
"设备设置已更新:PLC={PlcPort}, ADC={AdcPort}, BaudRate={BaudRate}, TestSpeed={TestSpeed}, ManualSpeed={ManualSpeed}, ManualDisplacement={ManualDisplacement}",
|
||||
settings.PlcPortName,
|
||||
settings.AdcPortName,
|
||||
settings.BaudRate,
|
||||
settings.TestSpeed,
|
||||
settings.ManualSpeed,
|
||||
settings.ManualDisplacement);
|
||||
}
|
||||
|
||||
public Task PulseStartTestAsync() => PulseCoilAsync(StartTestCoil);
|
||||
@@ -120,8 +149,50 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
|
||||
public Task WriteManualDisplacementAsync(double value) => WriteFloatRegisterAsync(ManualDisplacementRegister, value);
|
||||
|
||||
public Task<PlcDeviceParameters> ReadDeviceParametersAsync() =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
var master = plcMaster ?? throw new InvalidOperationException("PLC 未连接");
|
||||
var manualSpeedWords = master.ReadHoldingRegisters(SlaveId, ManualSpeedRegister, 2);
|
||||
var manualDisplacementWords = master.ReadHoldingRegisters(SlaveId, ManualDisplacementRegister, 2);
|
||||
var testSpeedWords = master.ReadHoldingRegisters(SlaveId, TestSpeedRegister, 2);
|
||||
var parameters = new PlcDeviceParameters(
|
||||
UshortToFloat(manualSpeedWords[1], manualSpeedWords[0]),
|
||||
UshortToFloat(manualDisplacementWords[1], manualDisplacementWords[0]),
|
||||
UshortToFloat(testSpeedWords[1], testSpeedWords[0]));
|
||||
|
||||
Log.Information(
|
||||
"读取 PLC 参数完成:D{ManualSpeedRegister}={ManualSpeed:F3}, D{ManualDisplacementRegister}={ManualDisplacement:F3}, D{TestSpeedRegister}={TestSpeed:F3}",
|
||||
ManualSpeedRegister,
|
||||
parameters.ManualSpeed,
|
||||
ManualDisplacementRegister,
|
||||
parameters.ManualDisplacement,
|
||||
TestSpeedRegister,
|
||||
parameters.TestSpeed);
|
||||
return parameters;
|
||||
});
|
||||
|
||||
public AdcZeroCalibration CaptureCurrentAdcZero()
|
||||
{
|
||||
lock (sync)
|
||||
{
|
||||
if (!hasAdcRawValues)
|
||||
{
|
||||
throw new InvalidOperationException("ADC 尚未读取到有效原始数据");
|
||||
}
|
||||
|
||||
Log.Information(
|
||||
"采集 ADC 零点:NormalPressureZero={NormalPressureZero}, FrictionZero1={FrictionZero1}, FrictionZero2={FrictionZero2}",
|
||||
pressureRawValue,
|
||||
frictionRawValue1,
|
||||
frictionRawValue2);
|
||||
return new AdcZeroCalibration(pressureRawValue, frictionRawValue1, frictionRawValue2);
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Log.Information("停止防滑测试设备连接与轮询");
|
||||
cancellationTokenSource?.Cancel();
|
||||
|
||||
try
|
||||
@@ -209,6 +280,10 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
|
||||
lock (sync)
|
||||
{
|
||||
pressureRawValue = pressureRaw;
|
||||
frictionRawValue1 = friction1Raw;
|
||||
frictionRawValue2 = friction2Raw;
|
||||
hasAdcRawValues = true;
|
||||
verticalLoadN = pressure;
|
||||
horizontalFrictionN = friction;
|
||||
lastError = string.Empty;
|
||||
@@ -220,6 +295,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogPollingError("ADC", ex, ref lastAdcErrorLoggedAt);
|
||||
SetConnected(false, ex.Message);
|
||||
Thread.Sleep(250);
|
||||
}
|
||||
@@ -255,6 +331,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogPollingError("PLC", ex, ref lastPlcErrorLoggedAt);
|
||||
SetConnected(false, ex.Message);
|
||||
Thread.Sleep(250);
|
||||
}
|
||||
@@ -263,6 +340,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
|
||||
private async Task PulseCoilAsync(ushort coil)
|
||||
{
|
||||
Log.Information("发送 PLC 脉冲线圈:M{Coil}", coil);
|
||||
await WriteCoilAsync(coil, true);
|
||||
await Task.Delay(80);
|
||||
await WriteCoilAsync(coil, false);
|
||||
@@ -274,6 +352,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
var master = plcMaster ?? throw new InvalidOperationException("PLC 未连接");
|
||||
var current = master.ReadCoils(SlaveId, coil, 1)[0];
|
||||
master.WriteSingleCoil(SlaveId, coil, !current);
|
||||
Log.Information("切换 PLC 线圈:M{Coil}, Before={Before}, After={After}", coil, current, !current);
|
||||
});
|
||||
|
||||
private Task WriteCoilAsync(ushort coil, bool value) =>
|
||||
@@ -281,6 +360,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
{
|
||||
var master = plcMaster ?? throw new InvalidOperationException("PLC 未连接");
|
||||
master.WriteSingleCoil(SlaveId, coil, value);
|
||||
Log.Debug("写入 PLC 线圈:M{Coil}={Value}", coil, value);
|
||||
});
|
||||
|
||||
private Task WriteFloatRegisterAsync(ushort register, double value) =>
|
||||
@@ -288,8 +368,27 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
{
|
||||
var master = plcMaster ?? throw new InvalidOperationException("PLC 未连接");
|
||||
master.WriteMultipleRegisters(SlaveId, register, SplitFloatToUShortArray((float)value));
|
||||
Log.Information("写入 PLC 浮点寄存器:D{Register}={Value:F3}", register, value);
|
||||
});
|
||||
|
||||
private void LogPollingError(string source, Exception exception, ref DateTime lastLoggedAt)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
if (now - lastLoggedAt < TimeSpan.FromSeconds(5))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lastLoggedAt = now;
|
||||
Log.Error(
|
||||
exception,
|
||||
"{Source} 轮询失败:PLC={PlcPort}, ADC={AdcPort}, BaudRate={BaudRate}",
|
||||
source,
|
||||
settings.PlcPortName,
|
||||
settings.AdcPortName,
|
||||
settings.BaudRate);
|
||||
}
|
||||
|
||||
private void SetConnected(bool connected, string error)
|
||||
{
|
||||
lock (sync)
|
||||
|
||||
@@ -7,6 +7,7 @@ using LiveChartsCore;
|
||||
using LiveChartsCore.Defaults;
|
||||
using LiveChartsCore.SkiaSharpView;
|
||||
using LiveChartsCore.SkiaSharpView.Painting;
|
||||
using Serilog;
|
||||
using SkiaSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -215,6 +216,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
|
||||
public MainWindowViewModel()
|
||||
{
|
||||
Log.Information("初始化主页面 ViewModel");
|
||||
Series =
|
||||
[
|
||||
CreateLineSeries("垂直压力(N)", verticalLoadPoints, "#DC2626", 0, 0.65),
|
||||
@@ -226,6 +228,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
LoadDeviceSettings();
|
||||
UpdateTargetLoad();
|
||||
deviceService.Start(CurrentSettings());
|
||||
_ = LoadPlcParametersAsync();
|
||||
|
||||
refreshTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(33) };
|
||||
refreshTimer.Tick += (_, _) => RefreshFromDevice();
|
||||
@@ -263,6 +266,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
var points = currentRun.Count > 0 ? currentRun.ToList() : lastCompletedRun;
|
||||
if (points.Count == 0)
|
||||
{
|
||||
Log.Warning("请求导出 Excel 时没有可导出的实时采样数据:TestNumber={TestNumber}", TestNumber);
|
||||
CurrentStatus = "没有可导出的实时采样数据,请先完成一次测试";
|
||||
return;
|
||||
}
|
||||
@@ -292,6 +296,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Excel 导出失败:TestNumber={TestNumber}, PointCount={PointCount}", TestNumber, points.Count);
|
||||
CurrentStatus = $"Excel 导出失败:{ex.Message}";
|
||||
}
|
||||
}
|
||||
@@ -336,6 +341,41 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
deviceService.UpdateSettings(CurrentSettings());
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void CalibrateNormalPressureZero()
|
||||
{
|
||||
try
|
||||
{
|
||||
var zero = deviceService.CaptureCurrentAdcZero();
|
||||
NormalPressureZero = zero.NormalPressureZero.ToString(CultureInfo.InvariantCulture);
|
||||
SaveAndApplySettings();
|
||||
CurrentStatus = "正压力零点已按当前 ADC 原始值采集";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "正压力零点采集失败");
|
||||
CurrentStatus = $"正压力零点采集失败:{ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void CalibrateFrictionZero()
|
||||
{
|
||||
try
|
||||
{
|
||||
var zero = deviceService.CaptureCurrentAdcZero();
|
||||
FrictionZero1 = zero.FrictionZero1.ToString(CultureInfo.InvariantCulture);
|
||||
FrictionZero2 = zero.FrictionZero2.ToString(CultureInfo.InvariantCulture);
|
||||
SaveAndApplySettings();
|
||||
CurrentStatus = "摩擦零点已按当前 ADC 原始值采集";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "摩擦零点采集失败");
|
||||
CurrentStatus = $"摩擦零点采集失败:{ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnUploadProgressChanged(int value) => OnPropertyChanged(nameof(UploadProgressText));
|
||||
|
||||
partial void OnManualSpeedChanged(string value)
|
||||
@@ -434,6 +474,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
runStopwatch.Restart();
|
||||
UploadProgress = 0;
|
||||
CurrentStatus = "测试运行:按标准采集垂直载荷、摩擦力、位移与摩擦系数";
|
||||
Log.Information("测试开始:TestNumber={TestNumber}, TargetLoad={TargetLoad}, TestSpeed={TestSpeed}", TestNumber, TargetLoadText, TestSpeedText);
|
||||
}
|
||||
|
||||
private void RecordPoint(SlipDeviceSnapshot device)
|
||||
@@ -466,6 +507,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
runStopwatch.Stop();
|
||||
if (currentRun.Count < 3)
|
||||
{
|
||||
Log.Warning("测试停止但采样点不足:TestNumber={TestNumber}, PointCount={PointCount}", TestNumber, currentRun.Count);
|
||||
CurrentStatus = "测试已停止,但有效采样点不足,未生成结果";
|
||||
return;
|
||||
}
|
||||
@@ -503,6 +545,13 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
CurrentStatus = verdict == "有效"
|
||||
? "测试完成:已按标准生成静/动摩擦系数"
|
||||
: "测试完成:最近三次结果差异超过 10%,建议重新测试";
|
||||
Log.Information(
|
||||
"测试完成:TestNumber={TestNumber}, PointCount={PointCount}, StaticCoefficient={StaticCoefficient:F3}, DynamicCoefficient={DynamicCoefficient:F3}, Verdict={Verdict}",
|
||||
TestNumber,
|
||||
currentRun.Count,
|
||||
staticCoefficientValue,
|
||||
dynamicCoefficientValue,
|
||||
verdict);
|
||||
}
|
||||
|
||||
private bool NeedsRetest(double staticCoefficientValue, double dynamicCoefficientValue)
|
||||
@@ -571,6 +620,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "设备指令失败:{SuccessMessage}", successMessage);
|
||||
CurrentStatus = $"设备指令失败:{ex.Message}";
|
||||
}
|
||||
}
|
||||
@@ -591,6 +641,25 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
deviceService.UpdateSettings(CurrentSettings());
|
||||
}
|
||||
|
||||
private async Task LoadPlcParametersAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var parameters = await deviceService.ReadDeviceParametersAsync();
|
||||
isLoadingDeviceSettings = true;
|
||||
ManualSpeed = parameters.ManualSpeed.ToString("F2", CultureInfo.InvariantCulture);
|
||||
ManualDisplacement = parameters.ManualDisplacement.ToString("F2", CultureInfo.InvariantCulture);
|
||||
TestSpeed = parameters.TestSpeed.ToString("F2", CultureInfo.InvariantCulture);
|
||||
isLoadingDeviceSettings = false;
|
||||
SaveAndApplySettings();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
isLoadingDeviceSettings = false;
|
||||
Log.Warning(ex, "启动时读取 PLC 参数失败,将使用本地保存的设备设置");
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadDeviceSettings()
|
||||
{
|
||||
if (!File.Exists(DeviceSettingsPath))
|
||||
@@ -621,8 +690,9 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
AdcPortName = settings.AdcPortName ?? AdcPortName;
|
||||
BaudRate = settings.BaudRate > 0 ? settings.BaudRate : BaudRate;
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "读取设备设置失败:Path={Path}", DeviceSettingsPath);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -643,8 +713,9 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
var json = JsonSerializer.Serialize(CurrentSettings(), new JsonSerializerOptions { WriteIndented = true });
|
||||
File.WriteAllText(DeviceSettingsPath, json);
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "保存设备设置失败:Path={Path}", DeviceSettingsPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -328,7 +328,7 @@
|
||||
<Button Content="复位" Classes="action" Command="{Binding ClearCommand}"/>
|
||||
<Button Grid.Column="1" Content="测试" Classes="success action" Command="{Binding StartTestCommand}"/>
|
||||
<Button Grid.Row="1" Content="停止" Classes="danger action" Command="{Binding StopTestCommand}"/>
|
||||
<Button Grid.Row="1" Grid.Column="1" Content="导出Excel" Classes="primary action" Command="{Binding ExportReportCommand}"/>
|
||||
<Button Grid.Row="1" Grid.Column="1" Content="导出报告" Classes="primary action" Command="{Binding ExportReportCommand}"/>
|
||||
</Grid>
|
||||
|
||||
<StackPanel Grid.Row="2" Spacing="8">
|
||||
@@ -432,12 +432,14 @@
|
||||
|
||||
<Label Grid.Row="6" Content="正压力零点" Classes="setting-label" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="6" Grid.Column="1" Classes="setting-value" Text="{Binding NormalPressureZero, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<Button Grid.Row="6" Grid.Column="2" Content="采零" Classes="compact" Command="{Binding CalibrateNormalPressureZeroCommand}"/>
|
||||
|
||||
<Label Grid.Row="6" Grid.Column="4" Content="正压力系数" Classes="setting-label" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="6" Grid.Column="5" Classes="setting-value" Text="{Binding NormalPressureCoefficient, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
|
||||
<Label Grid.Row="7" Content="摩擦1零点" Classes="setting-label" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="7" Grid.Column="1" Classes="setting-value" Text="{Binding FrictionZero1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<Button Grid.Row="7" Grid.Column="2" Content="摩擦采零" Classes="compact" Command="{Binding CalibrateFrictionZeroCommand}"/>
|
||||
|
||||
<Label Grid.Row="7" Grid.Column="4" Content="摩擦1系数" Classes="setting-label" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="7" Grid.Column="5" Classes="setting-value" Text="{Binding FrictionCoefficient1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
|
||||
Reference in New Issue
Block a user