Files
HC_APTBS/ViewModels/StatusDisplayViewModel.cs
LucianoDev 70be693116 feat: redesign Pump page with Fluent card layout, bottom snackbar, and RPM chart
- Replace sub-nav + HiddenTabsTabControl with 3-column Fluent card layout:
  PumpCommandsCard (vertical ME/FBKW/PreIn sliders) + DfiCalibrationCard /
  PumpLiveDataCard (KPI tiles + RPM rolling chart + redesigned status bytes) /
  PumpIdentificationCard + DtcCard
- Add PumpTopStripView: pump selector, model badge, CAN + K-Line chips
- Move immobilizer unlock to MainWindow bottom snackbar (UnlockSnackbarView):
  auto-close on success after 3 s, persist on failure with manual Dismiss
- Redesign StatusDisplayView to 2×8 rounded 28px tiles with bit index + tooltip
- Add NullToVisibilityConverter; add SnackbarShell, PumpCard, and related styles
- Delete obsolete views: UnlockProgressDialog, UnlockPanelView,
  PumpIdentificationPanelView, PumpLiveDataView, DfiManageView,
  DtcListView, PumpControlView
- PumpPageViewModel: remove PumpSubPage enum, add RpmChart wired to Root.PumpRpm

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 14:03:47 +02:00

144 lines
5.7 KiB
C#
Raw Permalink 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.Collections;
using System.Collections.ObjectModel;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using HC_APTBS.Models;
namespace HC_APTBS.ViewModels
{
/// <summary>
/// Represents the state of a single bit indicator in the 16-bit pump status word display.
/// </summary>
public sealed class BitIndicatorViewModel : ObservableObject
{
[System.Runtime.CompilerServices.CompilerGenerated]
private string _color = "#26C200";
/// <summary>HTML hex colour for the indicator background (e.g. "#26C200" = green, "#FF1E1E" = red).</summary>
public string Color
{
get => _color;
set => SetProperty(ref _color, value);
}
[System.Runtime.CompilerServices.CompilerGenerated]
private string _description = string.Empty;
/// <summary>Tooltip / label for this bit's current state.</summary>
public string Description
{
get => _description;
set => SetProperty(ref _description, value);
}
[System.Runtime.CompilerServices.CompilerGenerated]
private bool _isActive;
/// <summary>True when this bit is set in the status word.</summary>
public bool IsActive
{
get => _isActive;
set => SetProperty(ref _isActive, value);
}
/// <summary>Zero-based bit position (015) shown as a label beneath the indicator.</summary>
public int Index { get; init; }
}
/// <summary>
/// ViewModel for the StatusDisplay user control.
///
/// <para>
/// Maintains a 16-element collection of <see cref="BitIndicatorViewModel"/> objects,
/// one per bit of the pump status word. Call <see cref="UpdateStatusWord"/> whenever
/// a new value arrives from the CAN bus.
/// </para>
/// </summary>
public sealed partial class StatusDisplayViewModel : ObservableObject
{
// ── Properties ────────────────────────────────────────────────────────────
/// <summary>Title shown above the bit display (e.g. "Table 2 Status").</summary>
[ObservableProperty] private string _title = "STATUS";
/// <summary>16 bit indicators for bits 015 of the current status word.</summary>
public ObservableCollection<BitIndicatorViewModel> Bits { get; } = new();
/// <summary>Number of bits currently active (set to 1) in the status word.</summary>
public int ActiveCount => Bits.Count(b => b.IsActive);
/// <summary>
/// Fired when a bit that is flagged as an error transitions to active.
/// The argument is the bit position (0-based).
/// </summary>
public event Action<int>? ErrorBitDetected;
// ── Constructor ───────────────────────────────────────────────────────────
/// <summary>Initialises the collection with 16 green indicator placeholders.</summary>
public StatusDisplayViewModel()
{
for (int i = 0; i < 16; i++)
Bits.Add(new BitIndicatorViewModel { Color = "#26C200", Description = $"Bit {i}", Index = i });
}
// ── Public API ────────────────────────────────────────────────────────────
/// <summary>
/// Updates all 16 bit indicators from a <see cref="PumpStatusDefinition"/> and a live value.
/// Must be called on the UI thread.
/// </summary>
/// <param name="statusDefinition">Definition describing what each bit means.</param>
/// <param name="rawValue">Integer value from the pump CAN status parameter.</param>
public void UpdateStatusWord(PumpStatusDefinition statusDefinition, int rawValue)
{
if (statusDefinition == null) return;
Title = $"Table {statusDefinition.Id} {statusDefinition.Name}";
var bits = new BitArray(new[] { rawValue });
foreach (var statusBit in statusDefinition.Bits)
{
int index = statusBit.Bit;
if (index < 0 || index >= 16) continue;
bool isSet = index < bits.Length && bits[index];
var indicator = Bits[index];
indicator.IsActive = isSet;
// Find the matching state definition and apply its colour/description.
foreach (var val in statusBit.Values)
{
int expectedState = isSet ? 1 : 0;
if (val.State == expectedState)
{
indicator.Color = "#" + val.Color;
indicator.Description = val.Description;
break;
}
}
// Notify the bench service / main VM of error bits.
if (isSet && statusBit.Enabled)
ErrorBitDetected?.Invoke(index);
}
OnPropertyChanged(nameof(ActiveCount));
}
/// <summary>Resets all indicators to the default green / inactive state.</summary>
public void Reset()
{
for (int i = 0; i < Bits.Count; i++)
{
Bits[i].IsActive = false;
Bits[i].Color = "#26C200";
Bits[i].Description = $"Bit {i}";
}
OnPropertyChanged(nameof(ActiveCount));
}
}
}