Files
HC_APTBS/docs/gap-missing-features.md
LucianoDev c617854c09 feat: implement SavePump/SaveAlarms, fix config round-trip bugs, redesign PDF reports
Config system fixes:
- Implement SavePump() — full XML serialization with insert/update by pump ID
- Add CanBusParameter.ToPumpXml() for legacy P1-P6 pump param format
- Fix LastRotationDirection never loaded in LoadSettings()
- Add SaveAlarms() to ConfigurationService and IConfigurationService
- Remove dead fields AppSettings.Clients and AppSettings.PumpIds

PDF report redesign:
- Professional layout with charts, verdict badges, and tolerance bands
- Add ReportChartRenderer (SVG) and ReportTheme styling constants
- Embed default_logo.png as fallback report logo

Documentation:
- Add gap analysis docs (config validation, ford unlock, missing features)
- Update CLAUDE.md architecture, known gaps, and debt tracking

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

6.2 KiB

Gap: Missing Features

1. Localization System (HIGH)

Problem

The old app supported runtime Spanish/English switching via R.LoadLanguage() which swapped WPF ResourceDictionary files (StringResources.xaml for Spanish, StringResourcesEN.xaml for English). The new app has AppSettings.Language ("ESP"/"ENG") persisted but NOT used — all UI strings are hardcoded in English.

Implementation approach

  1. Create Resources/StringResources.xaml (Spanish) and Resources/StringResources.en.xaml (English) with keyed sys:String entries
  2. Reference strings in XAML via {DynamicResource key} (not StaticResource — dynamic allows runtime swap)
  3. Add LanguageService or extension method that merges the correct dictionary into Application.Current.Resources
  4. Wire language toggle to AppSettings.Language change
  5. Default resource dictionary should be Spanish (the primary user base)

Scope

All user-facing text: labels, button text, dialog messages, status messages, report text, error messages. Roughly 200-300 strings.

2. User Credential Encryption (HIGH)

Problem

Users stored as plaintext user:password pairs in config.xml. Default is admin:admin. Old system used AES-256 (Rijndael CBC, PBKDF2 1000 iterations) via Encrypter.cs.

Don't re-implement the old Rijndael scheme (it used obsolete primitives and weak iteration count). Instead:

  1. Hash passwords with Rfc2898DeriveBytes using HMAC-SHA256, 600,000 iterations, random 16-byte salt
  2. Store as user:salt:hash in config.xml
  3. ValidateUser() computes hash of input password with stored salt and compares
  4. Migration: on first load of old-format user:password entries, hash them and rewrite

This is more secure than the old encrypted-but-reversible approach. Passwords become irreversible.

Files to modify

  • Models/BenchConfiguration.cs — change Users property format
  • Services/Impl/ConfigurationService.csValidateUser(), GetUsers(), UpdateUsers(), SaveSettings()

3. KlineIDs Auto-Mapping (MEDIUM)

Problem

Old system remembered K-Line ID → pump ID associations via Settings.Default.KlineIDs (comma-separated klineID:pumpID string). When a pump was connected and identified via K-Line, the system could auto-select it next time. New system has no equivalent.

Implementation

  1. Add Dictionary<string, string> KlineIdMap to AppSettings
  2. Persist as <KlineIDs>kline1:pump1,kline2:pump2</KlineIDs> in config.xml
  3. In KwpService or PumpIdentificationViewModel: after successful K-Line read, save the mapping
  4. On pump connection: look up K-Line ID in map, auto-select pump if found

4. Test Phase Timer/Countdown Display (MEDIUM)

Problem

During test execution, conditioning and measurement phases have timed durations (e.g., 10 sec conditioning, 30 sec measurement). The old system showed a visual countdown. The new system fires VerboseMessage events with text like "Conditioning: 8s remaining" but there's no dedicated countdown UI.

Implementation

  • Add countdown properties to TestDisplayViewModel: RemainingSeconds, PhaseProgress (0-1), PhaseName
  • Fire PhaseTimerTick event from BenchService with remaining seconds
  • Display as a circular progress indicator or large countdown text in TestDisplayView

5. QOver Zero-Flow Safety Check (HIGH — Safety)

Problem

The old system had a safety check: if QOver == 0 while RPM > 300 and oil pump is on, trigger emergency stop (leak/blockage detection). This is completely absent from the new codebase.

Implementation

Add to BenchService or the ViewModel's bench monitoring loop:

if (qOverValue == 0 && benchRpm > 300 && IsRelayOn(RelayNames.OilPump))
{
    EmergencyStop();
    _log.Error(LogId, "QOver zero-flow safety triggered: oil flow blocked while motor running");
}

Debounce for 2-3 seconds to avoid false positives during startup transients.

6. Alarm Bit Recording During Tests (HIGH)

Problem

PhaseDefinition has ErrorBits list and RecordErrorBit(int bit) method, but no code in BenchService ever calls it. The old system tracked which alarm bits fired during each test phase for inclusion in the report.

Implementation

In BenchService.MeasurePhaseAsync(), subscribe to alarm parameter changes. When an alarm bit transitions to active during a measurement phase, call phase.RecordErrorBit(bit). The error bits are already rendered in the PDF report (PdfService checks phase.ErrorBits).

7. Per-Sample Real-Time UI Callback (MEDIUM)

Problem

Old system fired ITestParameterListener.OnValueUpdate for every measurement sample, enabling live chart updates during test execution. New system silently collects samples with no per-sample event.

Implementation

Add an event to IBenchService:

event Action<string, double, double>? MeasurementSampled; // paramName, value, timestamp

Fire in MeasurePhaseAsync after each sample. ViewModel subscribes to update live charts.

8. Pump Parameter Zeroing Between Phases (MEDIUM)

Problem

Old system called StopPump() between phases, which zeroed ME/FBKW/PreIn values. New system calls SetRpm(0) but does NOT zero pump injection parameters. This means the pump may continue injecting fuel between phases at the previous phase's setpoint.

Implementation

Add a StopPumpParameters() method to BenchService that sets ME, FBKW, and PreIn to 0 and sends the CAN frame. Call it at the end of each phase (currently line 776 in BenchService.cs — after SetRpm(0)).

9. PDF Report Observations Section (LOW)

Problem

Old report had an "Observaciones" free-text section at the bottom. New IPdfService.GenerateReport() has no observations parameter and no observations rendering.

Implementation

  1. Add string? observations parameter to IPdfService.GenerateReport()
  2. Add a text section at the bottom of the PDF body in PdfService
  3. Add an observations text box to ReportDialog/ReportViewModel

10. PDF Auto-Open After Generation (LOW)

Problem

Old code called Process.Start(filePath) to open the generated PDF. New code returns the path but doesn't open it.

Implementation

After GenerateReport() returns the path, call Process.Start(new ProcessStartInfo(path) { UseShellExecute = true }) in the ViewModel.