Files
HC_APTBS/ViewModels/DfiManageViewModel.cs
2026-04-11 12:45:18 +02:00

179 lines
7.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Threading.Tasks;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using HC_APTBS.Services;
namespace HC_APTBS.ViewModels
{
/// <summary>
/// ViewModel for the DFIManageDisplay user control.
///
/// <para>
/// Exposes the current DFI (injection timing offset) value, a slider for manual
/// adjustment, KWP version selection, and commands to read and write DFI via K-Line.
/// Auto-mode is respected by the bench service when executing a DFI test phase.
/// </para>
/// </summary>
public sealed partial class DfiManageViewModel : ObservableObject
{
// ── Services ──────────────────────────────────────────────────────────────
private readonly IKwpService _kwp;
private readonly IConfigurationService _config;
private const string LogId = "DfiManageViewModel";
// ── Constructor ───────────────────────────────────────────────────────────
/// <summary>Initialises the ViewModel with the required services.</summary>
public DfiManageViewModel(IKwpService kwpService, IConfigurationService configService)
{
_kwp = kwpService;
_config = configService;
}
// ── DFI display ───────────────────────────────────────────────────────────
/// <summary>Current DFI value read from the ECU (displayed in the label).</summary>
[ObservableProperty] private double _currentDfi;
/// <summary>
/// Slider position in integer hundredths of a DFI unit (range 300 to 300).
/// Divide by 100 to get the actual DFI value.
/// </summary>
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(SliderDfiValue))]
private int _sliderRaw;
/// <summary>The DFI value represented by the current slider position.</summary>
public double SliderDfiValue => Math.Round(SliderRaw / 100.0, 2);
// ── Options ───────────────────────────────────────────────────────────────
/// <summary>
/// KWP protocol version index (0, 1, or 2) used when writing DFI.
/// Corresponds to the three known VP44 authentication variants.
/// </summary>
[ObservableProperty] private int _versionIndex = 1;
/// <summary>
/// When <see langword="true"/> the bench service may perform automatic DFI
/// correction during test phases; when <see langword="false"/> it skips them.
/// </summary>
[ObservableProperty] private bool _isAutoMode = true;
// ── Operation state ───────────────────────────────────────────────────────
/// <summary>True while a read or write K-Line operation is in progress.</summary>
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(ReadDfiCommand))]
[NotifyCanExecuteChangedFor(nameof(WriteDfiCommand))]
private bool _isBusy;
/// <summary>Progress percentage (0100) for the current K-Line operation.</summary>
[ObservableProperty] private int _progressPercent;
/// <summary>Verbose status message for the current K-Line operation.</summary>
[ObservableProperty] private string _progressMessage = string.Empty;
// ── Public API ────────────────────────────────────────────────────────────
/// <summary>
/// Sets the displayed DFI value and repositions the slider to match.
/// Safe to call from any thread.
/// </summary>
public void SetDfi(double dfi)
{
double rounded = Math.Round(dfi, 2);
Application.Current.Dispatcher.Invoke(() =>
{
CurrentDfi = rounded;
SliderRaw = (int)(rounded * 100);
});
}
// ── Commands ──────────────────────────────────────────────────────────────
/// <summary>Reads the current DFI value from the ECU over K-Line.</summary>
[RelayCommand(CanExecute = nameof(CanOperate))]
private async Task ReadDfiAsync()
{
string? port = _kwp.DetectKLinePort();
if (string.IsNullOrEmpty(port))
{
MessageBox.Show("K-Line device not found. Check that the FTDI adapter is connected.",
"K-Line Error", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
IsBusy = true;
_kwp.ProgressChanged += OnProgress;
try
{
string dfiStr = await _kwp.ReadDfiAsync(port);
if (double.TryParse(dfiStr,
System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture,
out double val))
SetDfi(val);
}
finally
{
_kwp.ProgressChanged -= OnProgress;
IsBusy = false;
ProgressPercent = 0;
ProgressMessage = string.Empty;
}
}
/// <summary>Writes the slider DFI value to the ECU and reads back the result.</summary>
[RelayCommand(CanExecute = nameof(CanOperate))]
private async Task WriteDfiAsync()
{
string? port = _kwp.DetectKLinePort();
if (string.IsNullOrEmpty(port))
{
MessageBox.Show("K-Line device not found. Check that the FTDI adapter is connected.",
"K-Line Error", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
float value = (float)SliderDfiValue;
int version = VersionIndex;
IsBusy = true;
_kwp.ProgressChanged += OnProgress;
try
{
string dfiStr = await _kwp.WriteDfiAsync(port, value, version);
if (double.TryParse(dfiStr,
System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture,
out double val))
SetDfi(val);
}
finally
{
_kwp.ProgressChanged -= OnProgress;
IsBusy = false;
ProgressPercent = 0;
ProgressMessage = string.Empty;
}
}
private bool CanOperate() => !IsBusy;
// ── Helpers ───────────────────────────────────────────────────────────────
private void OnProgress(int pct, string msg)
{
Application.Current.Dispatcher.Invoke(() =>
{
ProgressPercent = pct;
ProgressMessage = msg;
});
}
}
}