425 lines
11 KiB
C#
425 lines
11 KiB
C#
using System.ComponentModel;
|
|
using System.Globalization;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace DentistryHandpieces;
|
|
|
|
public enum ErrorMode
|
|
{
|
|
Absolute,
|
|
Percent
|
|
}
|
|
|
|
public enum PlcFloatWordOrder
|
|
{
|
|
LowWordFirst,
|
|
HighWordFirst
|
|
}
|
|
|
|
public sealed class TestPointRow : INotifyPropertyChanged
|
|
{
|
|
private string _measuredText = string.Empty;
|
|
private string _note = string.Empty;
|
|
|
|
public TestPointRow(string projectName, double target, string unit, double tolerance, ErrorMode errorMode)
|
|
{
|
|
ProjectName = projectName;
|
|
Target = target;
|
|
Unit = unit;
|
|
Tolerance = tolerance;
|
|
ErrorMode = errorMode;
|
|
}
|
|
|
|
public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
|
public string ProjectName { get; }
|
|
|
|
public double Target { get; }
|
|
|
|
public string Unit { get; }
|
|
|
|
public double Tolerance { get; }
|
|
|
|
public ErrorMode ErrorMode { get; }
|
|
|
|
public string TargetText => $"{FormatNumber(Target)} {Unit}";
|
|
|
|
public string MeasuredText
|
|
{
|
|
get => _measuredText;
|
|
set
|
|
{
|
|
if (_measuredText == value)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_measuredText = value;
|
|
OnPropertyChanged();
|
|
OnPropertyChanged(nameof(AllowedRangeText));
|
|
OnPropertyChanged(nameof(ResultText));
|
|
}
|
|
}
|
|
|
|
public string AllowedRangeText
|
|
{
|
|
get
|
|
{
|
|
(double lower, double upper) = GetAllowedRange();
|
|
return $"{FormatNumber(lower)} - {FormatNumber(upper)} {Unit}";
|
|
}
|
|
}
|
|
|
|
public string ToleranceText => ErrorMode == ErrorMode.Absolute
|
|
? $"±{FormatNumber(Tolerance)} {Unit}"
|
|
: $"±{Tolerance:P0}";
|
|
|
|
public string ResultText
|
|
{
|
|
get
|
|
{
|
|
if (!TryGetMeasuredValue(out double measured))
|
|
{
|
|
return "待输入";
|
|
}
|
|
|
|
(double lower, double upper) = GetAllowedRange();
|
|
return measured >= lower && measured <= upper ? "合格" : "不合格";
|
|
}
|
|
}
|
|
|
|
public string Note
|
|
{
|
|
get => _note;
|
|
set
|
|
{
|
|
if (_note == value)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_note = value;
|
|
OnPropertyChanged();
|
|
}
|
|
}
|
|
|
|
public PointPayload ToPayload()
|
|
{
|
|
return new PointPayload
|
|
{
|
|
ProjectName = ProjectName,
|
|
Target = Target,
|
|
Unit = Unit,
|
|
TargetText = TargetText,
|
|
MeasuredText = MeasuredText,
|
|
AllowedRangeText = AllowedRangeText,
|
|
ToleranceText = ToleranceText,
|
|
Result = ResultText,
|
|
Note = Note
|
|
};
|
|
}
|
|
|
|
private (double Lower, double Upper) GetAllowedRange()
|
|
{
|
|
double delta = ErrorMode == ErrorMode.Absolute ? Tolerance : Target * Tolerance;
|
|
return (Target - delta, Target + delta);
|
|
}
|
|
|
|
private bool TryGetMeasuredValue(out double measured)
|
|
{
|
|
return double.TryParse(MeasuredText, NumberStyles.Float, CultureInfo.CurrentCulture, out measured)
|
|
|| double.TryParse(MeasuredText, NumberStyles.Float, CultureInfo.InvariantCulture, out measured);
|
|
}
|
|
|
|
private static string FormatNumber(double value)
|
|
{
|
|
return value.ToString("0.####", CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
|
{
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
}
|
|
}
|
|
|
|
public sealed class AcceptancePayload
|
|
{
|
|
public int SchemaVersion { get; init; } = 2;
|
|
|
|
public string SessionId { get; init; } = string.Empty;
|
|
|
|
public DateTime CreatedAt { get; init; }
|
|
|
|
public DateTime LastUpdatedAt { get; init; }
|
|
|
|
public string SampleCode { get; init; } = string.Empty;
|
|
|
|
public string OperatorName { get; init; } = string.Empty;
|
|
|
|
public string OverallResult { get; init; } = string.Empty;
|
|
|
|
public TestParameterConfig ParameterSnapshot { get; init; } = TestParameterConfig.CreateDefault();
|
|
|
|
public List<ProjectPayload> Projects { get; init; } = [];
|
|
|
|
public List<TestRunPayload> Runs { get; init; } = [];
|
|
}
|
|
|
|
public sealed class ProjectPayload
|
|
{
|
|
public string Name { get; init; } = string.Empty;
|
|
|
|
public string Requirement { get; init; } = string.Empty;
|
|
|
|
public string Result { get; init; } = string.Empty;
|
|
|
|
public List<PointPayload> Points { get; init; } = [];
|
|
|
|
public TorqueCurvePayload? TorqueCurve { get; init; }
|
|
}
|
|
|
|
public sealed class PointPayload
|
|
{
|
|
public string ProjectName { get; init; } = string.Empty;
|
|
|
|
public double Target { get; init; }
|
|
|
|
public string Unit { get; init; } = string.Empty;
|
|
|
|
public string TargetText { get; init; } = string.Empty;
|
|
|
|
public string MeasuredText { get; init; } = string.Empty;
|
|
|
|
public string AllowedRangeText { get; init; } = string.Empty;
|
|
|
|
public string ToleranceText { get; init; } = string.Empty;
|
|
|
|
public string Result { get; init; } = string.Empty;
|
|
|
|
public string Note { get; init; } = string.Empty;
|
|
}
|
|
|
|
public sealed class TorqueSamplePayload
|
|
{
|
|
public double ElapsedSeconds { get; init; }
|
|
|
|
public double SpeedRpm { get; init; }
|
|
|
|
public double TorqueMilliNewtonMeters { get; init; }
|
|
}
|
|
|
|
public sealed class TorqueCurvePayload
|
|
{
|
|
public double HoldTimeSeconds { get; init; }
|
|
|
|
public double ChangeThresholdMilliNewtonMeters { get; init; }
|
|
|
|
public double SpeedChangeThresholdRpm { get; init; }
|
|
|
|
public double MinTorqueMilliNewtonMeters { get; init; }
|
|
|
|
public double MaxTorqueMilliNewtonMeters { get; init; }
|
|
|
|
public double AverageTorqueMilliNewtonMeters { get; init; }
|
|
|
|
public double FluctuationMilliNewtonMeters { get; init; }
|
|
|
|
public double MinSpeedRpm { get; init; }
|
|
|
|
public double MaxSpeedRpm { get; init; }
|
|
|
|
public double AverageSpeedRpm { get; init; }
|
|
|
|
public double SpeedFluctuationRpm { get; init; }
|
|
|
|
public string Result { get; init; } = string.Empty;
|
|
|
|
public List<TorqueSamplePayload> Samples { get; init; } = [];
|
|
}
|
|
|
|
public sealed class TestRunPayload
|
|
{
|
|
public string RunId { get; init; } = string.Empty;
|
|
|
|
public string TestType { get; init; } = string.Empty;
|
|
|
|
public DateTime StartedAt { get; init; }
|
|
|
|
public DateTime? CompletedAt { get; set; }
|
|
|
|
public string CompletionStatus { get; set; } = "测试中";
|
|
|
|
public TestParameterConfig ParameterSnapshot { get; init; } = TestParameterConfig.CreateDefault();
|
|
|
|
public double? FinalDisplacementMm { get; set; }
|
|
|
|
public double? FinalAxialForceN { get; set; }
|
|
|
|
public double? FinalSpeedRpm { get; set; }
|
|
|
|
public double? FinalTorqueMilliNewtonMeters { get; set; }
|
|
|
|
public double? NoLoadSpeedRpm { get; set; }
|
|
|
|
public double? NoLoadSpeedErrorRatePercent { get; set; }
|
|
|
|
public List<RealtimeSamplePayload> Samples { get; init; } = [];
|
|
}
|
|
|
|
public sealed class RealtimeSamplePayload
|
|
{
|
|
public long Sequence { get; init; }
|
|
|
|
public DateTime SampledAt { get; init; }
|
|
|
|
public double DialIndicatorMm { get; init; }
|
|
|
|
public double RelativeDisplacementMm { get; init; }
|
|
|
|
public double AxialAxisPositionMm { get; init; }
|
|
|
|
public double AxialSampleStartMm { get; init; }
|
|
|
|
public double AxialSampleEndMm { get; init; }
|
|
|
|
public double AxialSampleDifferenceMm { get; init; }
|
|
|
|
public double AxialForceN { get; init; }
|
|
|
|
public double SpeedTorqueAxisPositionMm { get; init; }
|
|
|
|
public double SpeedTorqueDisplacementMm { get; init; }
|
|
|
|
public double SpeedTorquePeakTorqueMilliNewtonMeters { get; init; }
|
|
|
|
public double RealtimeTorqueMilliNewtonMeters { get; init; }
|
|
|
|
public double RealtimeSpeedRpm { get; init; }
|
|
|
|
public double RealtimePressureMpa { get; init; }
|
|
|
|
public double NoLoadSpeedRpm { get; init; }
|
|
|
|
public double NoLoadSpeedErrorRatePercent { get; init; }
|
|
|
|
public bool SpeedTorqueDone { get; init; }
|
|
|
|
public bool SpeedTorqueResetEnabled { get; init; }
|
|
|
|
public bool SpeedTorqueResetDone { get; init; }
|
|
|
|
public bool AxialResetEnabled { get; init; }
|
|
|
|
public bool AxialResetDone { get; init; }
|
|
}
|
|
|
|
public sealed class TestParameterConfig
|
|
{
|
|
public double AxialDisplacementLimit { get; init; }
|
|
|
|
public double AxialSpeed { get; init; }
|
|
|
|
public double AxialManualDisplacement { get; init; }
|
|
|
|
public double AxialForceLowerLimit { get; init; }
|
|
|
|
public double AxialForceUpperLimit { get; init; }
|
|
|
|
public double AxialForceCoefficient { get; init; }
|
|
|
|
public double AxialForceSetpoint { get; init; }
|
|
|
|
public double AxialJumpForceSetpoint { get; init; }
|
|
|
|
public bool UseAxialPullForceSetpoint { get; init; }
|
|
|
|
public double AxialForceProtection { get; init; }
|
|
|
|
public double AxialForceHoldTime { get; init; }
|
|
|
|
public double SpeedTorqueDisplacementLimit { get; init; }
|
|
|
|
public double SpeedTorqueSpeed { get; init; }
|
|
|
|
public double SpeedTorqueManualDisplacement { get; init; }
|
|
|
|
public double TorqueCoefficient { get; init; }
|
|
|
|
public double TorqueProtection { get; init; }
|
|
|
|
public double HoldTorque { get; init; }
|
|
|
|
public double TorqueHoldTime { get; init; }
|
|
|
|
public double SpeedCoefficient { get; init; }
|
|
|
|
public double SpeedStopThreshold { get; init; }
|
|
|
|
public double PressureCoefficient { get; init; }
|
|
|
|
public double LoadSpeedSetting { get; init; }
|
|
|
|
public double NoLoadSpeedSetting { get; init; }
|
|
|
|
public string PlcIpAddress { get; init; } = "192.168.1.10";
|
|
|
|
public int PlcPort { get; init; } = 502;
|
|
|
|
public int PlcUnitId { get; init; } = 1;
|
|
|
|
public int PlcPulseMilliseconds { get; init; } = 200;
|
|
|
|
public int PlcTimeoutMilliseconds { get; init; } = 2000;
|
|
|
|
public PlcFloatWordOrder FloatWordOrder { get; init; } = PlcFloatWordOrder.LowWordFirst;
|
|
|
|
public PlcConnectionConfig ToPlcConnectionConfig()
|
|
{
|
|
return new PlcConnectionConfig
|
|
{
|
|
IpAddress = string.IsNullOrWhiteSpace(PlcIpAddress) ? "192.168.1.10" : PlcIpAddress,
|
|
Port = PlcPort > 0 ? PlcPort : 502,
|
|
UnitId = PlcUnitId is >= 0 and <= byte.MaxValue ? (byte)PlcUnitId : (byte)1,
|
|
PulseMilliseconds = PlcPulseMilliseconds > 0 ? PlcPulseMilliseconds : 200,
|
|
TimeoutMilliseconds = PlcTimeoutMilliseconds > 0 ? PlcTimeoutMilliseconds : 2000,
|
|
FloatWordOrder = FloatWordOrder
|
|
};
|
|
}
|
|
|
|
public static TestParameterConfig CreateDefault()
|
|
{
|
|
return new TestParameterConfig
|
|
{
|
|
AxialDisplacementLimit = 0,
|
|
AxialSpeed = 10,
|
|
AxialManualDisplacement = 0,
|
|
AxialForceLowerLimit = 0,
|
|
AxialForceUpperLimit = 0,
|
|
AxialForceCoefficient = 1,
|
|
AxialForceSetpoint = 0,
|
|
AxialJumpForceSetpoint = 0,
|
|
UseAxialPullForceSetpoint = false,
|
|
AxialForceProtection = 50,
|
|
AxialForceHoldTime = 0,
|
|
SpeedTorqueDisplacementLimit = 0,
|
|
SpeedTorqueSpeed = 10,
|
|
SpeedTorqueManualDisplacement = 0,
|
|
TorqueCoefficient = 1,
|
|
TorqueProtection = 0,
|
|
HoldTorque = 0,
|
|
TorqueHoldTime = 0,
|
|
SpeedCoefficient = 1,
|
|
SpeedStopThreshold = 0,
|
|
PressureCoefficient = 1,
|
|
LoadSpeedSetting = 0,
|
|
NoLoadSpeedSetting = 0,
|
|
PlcIpAddress = "192.168.1.10",
|
|
PlcPort = 502,
|
|
PlcUnitId = 1,
|
|
PlcPulseMilliseconds = 200,
|
|
PlcTimeoutMilliseconds = 2000,
|
|
FloatWordOrder = PlcFloatWordOrder.LowWordFirst
|
|
};
|
|
}
|
|
}
|