Files
HC_APTBS/ViewModels/PumpControlViewModel.cs
LucianoDev 827b811b39 feat: developer tools page, auto-test orchestrator, BIP display, tests redesign
Bundles several feature streams that have been iterating on the working tree:

- Developer Tools page (Debug-only via DEVELOPER_TOOLS symbol): hosts the
  identification card, manual KWP write + transaction log, ROM/EEPROM dump
  card with progress banner and completion message, persisted custom-commands
  library, persisted EEPROM passwords library. New service primitives:
  IKwpService.SendRawCustomAsync / ReadEepromAsync / ReadRomEepromAsync.
  Persistence mirrors the Clients XML pattern in two new files
  (custom_commands.xml, eeprom_passwords.xml).
- Auto-test orchestrator (IAutoTestOrchestrator + AutoTestState): linear
  K-Line read -> unlock -> bench-on -> test sequence with snackbar UI and
  progress dialog VM, gated on dashboard alarms.
- BIP-STATUS display: BipDisplayViewModel + BipDisplayView, RAM read at
  0x0106 via IKwpService.ReadBipStatusAsync; status definitions in
  BipStatusDefinition.
- Tests page redesign: TestSectionCard + PhaseTileView replacing the old
  TestPlanView/TestRunningView/TestDoneView/TestPreconditionsView/
  TestSectionView controls and their VMs.
- Pump command sliders: Fluent thick-track style with overhang thumb,
  click-anywhere-and-drag, mouse-wheel adjustment.
- Window startup: app.manifest declares PerMonitorV2 DPI awareness,
  MainWindow installs a WM_GETMINMAXINFO hook in OnSourceInitialized and
  maximizes there (after the hook is in place) so the app fits the work
  area exactly on any display configuration.
- Misc: PercentToPixelsConverter, seed_aliases.py one-shot pump-alias
  importer, tools/Import-BipStatus.ps1, kline_eeprom_spec.md and
  dump-functions reference docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 13:59:50 +02:00

158 lines
6.6 KiB
C#

using CommunityToolkit.Mvvm.ComponentModel;
using HC_APTBS.Models;
using HC_APTBS.Services;
namespace HC_APTBS.ViewModels
{
/// <summary>
/// ViewModel for the three manual pump control sliders: FBKW (advance), ME (quantity),
/// and PreIn (pre-injection quantity). Each slider change calls
/// <see cref="IBenchService.SetPumpControlValue"/> to update the CAN bus.
/// </summary>
public sealed partial class PumpControlViewModel : ObservableObject
{
private readonly IBenchService _bench;
/// <summary>
/// When true, suppress forwarding slider changes to the bench service.
/// Used during programmatic updates to avoid re-entrant CAN sends.
/// </summary>
private bool _suppressSend;
// ── FBKW (Advance Control) ───────────────────────────────────────────────
/// <summary>Current FBKW slider value.</summary>
[ObservableProperty] private double _fbkwValue;
/// <summary>FBKW slider minimum.</summary>
[ObservableProperty] private double _fbkwMin;
/// <summary>FBKW slider maximum.</summary>
[ObservableProperty] private double _fbkwMax = 100;
/// <summary>FBKW slider tick frequency / step.</summary>
[ObservableProperty] private double _fbkwStep = 10;
// ── ME (Quantity Control) ─────────────────────────────────────────────────
/// <summary>Current ME slider value.</summary>
[ObservableProperty] private double _meValue;
/// <summary>ME slider minimum.</summary>
[ObservableProperty] private double _meMin;
/// <summary>ME slider maximum.</summary>
[ObservableProperty] private double _meMax = 100;
/// <summary>ME slider tick frequency / step.</summary>
[ObservableProperty] private double _meStep = 10;
// ── PreIn (Pre-injection Quantity) ────────────────────────────────────────
/// <summary>Current PreIn slider value.</summary>
[ObservableProperty] private double _preInValue;
/// <summary>PreIn slider minimum.</summary>
[ObservableProperty] private double _preInMin;
/// <summary>PreIn slider maximum.</summary>
[ObservableProperty] private double _preInMax = 100;
/// <summary>PreIn slider tick frequency / step.</summary>
[ObservableProperty] private double _preInStep = 10;
// ── Visibility / enablement ───────────────────────────────────────────────
/// <summary>True when the current pump supports pre-injection.</summary>
[ObservableProperty] private bool _isPreInAvailable;
/// <summary>True when a pump is selected and CAN is connected.</summary>
[ObservableProperty] private bool _isEnabled;
// ── Constructor ───────────────────────────────────────────────────────────
/// <summary>Creates the ViewModel wired to the bench service for CAN output.</summary>
public PumpControlViewModel(IBenchService bench)
{
_bench = bench;
}
// ── Property-changed callbacks → CAN send ─────────────────────────────────
partial void OnFbkwValueChanged(double value)
{
if (!_suppressSend)
_bench.SetPumpControlValue(PumpParameterNames.Fbkw, value);
}
partial void OnMeValueChanged(double value)
{
if (!_suppressSend)
_bench.SetPumpControlValue(PumpParameterNames.Me, value);
}
partial void OnPreInValueChanged(double value)
{
if (!_suppressSend)
_bench.SetPumpControlValue(PumpParameterNames.PreIn, value);
}
// ── Public API ────────────────────────────────────────────────────────────
/// <summary>
/// Called when the test executor sets a pump parameter value.
/// Auto-expands slider min/max if the value exceeds the current range.
/// Must be called on the UI thread.
/// </summary>
public void SetValueFromTest(string paramName, double value)
{
_suppressSend = true;
try
{
switch (paramName)
{
case PumpParameterNames.Me:
if (value > MeMax) MeMax = value;
else if (value < MeMin) MeMin = value;
MeValue = value;
break;
case PumpParameterNames.Fbkw:
if (value > FbkwMax) FbkwMax = value;
else if (value < FbkwMin) FbkwMin = value;
FbkwValue = value;
break;
case PumpParameterNames.PreIn:
if (value > PreInMax) PreInMax = value;
else if (value < PreInMin) PreInMin = value;
PreInValue = value;
break;
}
}
finally
{
_suppressSend = false;
}
}
/// <summary>Resets all slider values to zero and restores default min/max/step.</summary>
public void Reset()
{
// Min/Max/Step must be reset BEFORE Value: WPF's Slider coerces Value into
// [Minimum, Maximum]. If a previous test auto-expanded MeMin above 0 (or the
// operator widened it via the settings popup), assigning Value=0 first would
// be silently clamped to the stale Min, and the slider would stay stuck there.
_suppressSend = true;
try
{
FbkwMin = 0; FbkwMax = 100; FbkwStep = 10; FbkwValue = 0;
MeMin = 0; MeMax = 100; MeStep = 10; MeValue = 0;
PreInMin = 0; PreInMax = 100; PreInStep = 10; PreInValue = 0;
}
finally
{
_suppressSend = false;
}
}
}
}