Files
HC_APTBS/ViewModels/StatusDisplayViewModel.cs
LucianoDev 4891eb6812 feat: redesign bench calibration (factor/offset), add Ttank/P2 displays, fix sensor calibration
- Replace P1-P6 rational transfer function with factor/offset model for bench params
- Add explicit rx/tx direction flags in bench XML configuration
- Add T.Tank (BenchTemp) and P2 (AnalogSensor2) to temperature/pressure display
- Apply SensorConfiguration calibration to pressure channels, fix empty sensors.xml fallback
- Add live value labels to flowmeter charts
- Hide pump live values and PSG encoder standalone label
- Add K-Line connection state model, improve KWP service and status displays
- Restructure .claude/skills into subdirectory format

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 21:25:30 +02:00

136 lines
5.4 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.Collections;
using System.Collections.ObjectModel;
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>
/// 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);
}
}
/// <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}";
}
}
}
}