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>
This commit is contained in:
2026-04-15 15:21:22 +02:00
parent 4891eb6812
commit c617854c09
15 changed files with 1495 additions and 141 deletions

View File

@@ -0,0 +1,76 @@
# Gap: Configuration Validation & Migration
## Problem
The configuration system loads 7 XML files with no schema validation, no bounds checking, and silent error swallowing. Malformed files produce partial/default state with no user indication. There is no migration path from the old 32-CFG-file format.
## Critical Issues
### 1. SavePump() Stub
**File:** `Services/Impl/ConfigurationService.cs:191-194`
**Impact:** Pump definition edits (test phase enable/disable, parameter changes, new pumps) are lost on restart.
**Fix:** Implement full XML serialization mirroring the `LoadPump`/`ParsePumpElement` logic. Use `PumpDefinition.ToXml()`, `TestDefinition.ToXml()`, `PhaseDefinition.ToXml()`. Write to `pumps.xml` at the correct XPath location. Handle both insert (new pump) and update (existing pump) cases.
### 2. LastRotationDirection Never Loaded
**File:** `Services/Impl/ConfigurationService.cs``SaveSettings()` writes `<LastRotationDir>` but `LoadSettings()` never reads it.
**Fix:** Add `TryInt(r, "LastRotationDir", v => settings.LastRotationDirection = (short)v);` in `LoadSettings()`.
### 3. No SaveAlarms()
**File:** `Services/Impl/ConfigurationService.cs`
**Impact:** Alarm configuration changes cannot be persisted.
**Fix:** Add `SaveAlarms()` using `Alarm.ToXml()` for each alarm, write to `alarms.xml`.
### 4. SaveSettings() Side Effects
**File:** `Services/Impl/ConfigurationService.cs:101-102`
**Impact:** Calling `SaveSettings()` always also writes sensors.xml and clients.xml.
**Fix:** Split into `SaveSettings()`, `SaveSensors()`, `SaveClients()` called independently. Or document the coupling clearly.
## Bounds Validation Rules
Add these checks in the respective `FromXml`/`Load*` methods:
| Field | Location | Valid Range | Guard |
|-------|----------|-------------|-------|
| `byteh` / `bytel` | `CanBusParameter.FromXml`, `ParseParamElement` | 07 | Clamp or reject + log |
| `RefreshCanBusReadMs` | `LoadSettings` | >= 1 | Floor at 1 |
| `RefreshPumpParamsMs` | `LoadSettings` | >= 1 | Floor at 1 |
| `SecurityRpmLimit` | `LoadSettings` | 1005000 | Clamp |
| `MaxPressureBar` | `LoadSettings` | 1100 | Clamp |
| `PidP, PidI, PidD` | `LoadSettings` | >= 0 | Floor at 0 |
| `Relay.Bit` | `ParseRelayElement` | 063 | Reject + log |
| `SensorConfiguration.MaxVolt - MinVolt` | `GetValueFromRaw` | != 0 | Return 0 + log |
| P1P6 denominator | `GetTransformResult` | != 0 | Return 0 + log |
## Locale-Safe Parsing
All `double.Parse` / `int.Parse` calls in XML loading must use `CultureInfo.InvariantCulture`. Known violations:
- `SensorConfiguration.FromXml``double.Parse(v)` with no culture (line ~78-83)
- `CanBusParameter.ParseDecimal` — already uses `InvariantCulture` (correct)
- `ConfigurationService.TryDouble` — uses `double.TryParse` with `InvariantCulture` (correct)
## Config Versioning Approach
Add a `version` attribute to each XML root element:
```xml
<Config version="2">...</Config>
<Pumps version="1">...</Pumps>
```
On load, check version. If missing or old, run migration logic. Bump version after migration. This enables safe format evolution.
## Error Reporting Strategy
Replace all `catch { }` and `catch (Exception) { }` blocks with:
```csharp
catch (Exception ex)
{
_log.Warning(LogId, $"Skipped malformed element '{elementName}': {ex.Message}");
}
```
Files affected:
- `ConfigurationService.cs``TryInt`, `TryDouble`, `TryBool`, `TryString` helpers (lines 621-646)
- `SensorConfiguration.cs``TryParse` wrapper (line 100-103)
## Dead Fields
`AppSettings.Clients` and `AppSettings.PumpIds` are never populated by `LoadSettings()` — they are dead fields. Either remove them or wire up the loading. Current live data paths: `ConfigurationService._clients` and `GetPumpIds()`.
## Old CFG → XML Migration Strategy
See `gap-pump-data-migration.md` for the full field mapping. In summary:
1. Parse each CFG file using the pipe-delimited format documented in `old_source/HerlicScripts/Program.cs`
2. Map CAN IDs, P1-P6 formulas, status bit definitions, and EEPROM passwords to the pumps.xml and status.xml schemas
3. Run once as a migration tool, not as runtime logic

View File

@@ -0,0 +1,74 @@
# Gap: Ford Unlock Progress UI
## Problem
The `UnlockService` backend is fully functional (Phase 1 + Phase 2 + verification), but there is no dedicated UI for displaying unlock progress. The old app had `WUnlocker.xaml` — a modal dialog with a visual progress ring and status text.
## Current State
- `UnlockService.StatusChanged` fires every 1000ms with `"Unlocking... {pct}% ({MM:SS})"`
- `UnlockService.UnlockCompleted` fires once with `true`/`false`
- `MainViewModel` subscribes and pipes status into `VerboseStatus` (displayed as plain text somewhere in MainWindow)
- No progress bar, no percentage display, no cancel button, no dedicated dialog
## Old UI Reference (`WUnlocker.xaml`)
- Standalone modal `Window` (300x400px), dark background (#FF2B2929), Topmost, centered on owner
- Decorative `Ellipse` ring (200x200, #4D4D4D stroke, 10px thick) as the focal point
- Inside the ring: large percentage (Courier New 60pt), "P R O G R E S S" label, elapsed time (MM:SS)
- `LBLState` at top: live lock/immo status from CAN feedback ("Bloqueada/Desbloqueada")
- `LBLVerbose` at bottom: phase description ("Unlocking...", "Testing...", "Sending")
- "Cerrar" (Close) button disabled until progress reaches 100%
- Window close prevented via `OnWindowClosing` until completion
## Spec for New Implementation
### UnlockDialog.xaml (View)
- Modal dialog (MVVM, no code-behind logic)
- Progress bar (0-100%) + percentage text
- Elapsed time display (MM:SS)
- Phase indicator: "Phase 1: Sending unlock signals" / "Phase 2: Testing" / "Verifying..."
- Current unlock type indicator (Type 1 / Type 2)
- Cancel button (disabled during Phase 2 — it cannot be cancelled once started)
- Close button (enabled only after completion)
- Result indicator: green checkmark (success) / red X (failed)
### UnlockViewModel.cs (ViewModel)
- `[ObservableProperty] double Progress`
- `[ObservableProperty] string ElapsedTime`
- `[ObservableProperty] string Phase`
- `[ObservableProperty] string Result`
- `[ObservableProperty] bool IsComplete`
- `[ObservableProperty] bool CanCancel`
- `[RelayCommand] Cancel()` — calls `CancellationTokenSource.Cancel()`
- Subscribe to `IUnlockService.StatusChanged` — parse percentage from status string
- Subscribe to `IUnlockService.UnlockCompleted` — set result and enable close
### Integration
- Trigger: button in MainViewModel (currently exists but needs to open the dialog)
- The dialog should be shown via a dialog service or `Window.ShowDialog()` from MainViewModel
- Marshal all event handlers to UI thread
## Protocol Reference
### Type 1 (CAN IDs 0x700 + 0x300)
| Phase | ID | Data | Interval |
|-------|----|------|----------|
| Msg1 | 0x700 | `B2 00 00 00 00 00 00 00` | 500 ms |
| Msg2 | 0x300 | `01 48 50 C3 00 00 00 00` | 50 ms |
| TestUnlock states | 0x700 | `B2`, `B6`, `23`, `24` (byte[0]) x2 | 500 ms each |
| Verify | TestUnlock param | Success when value != 0 | One-shot |
### Type 2 (CAN IDs 0x700 + 0x500)
| Phase | ID | Data | Interval |
|-------|----|------|----------|
| Msg1 | 0x700 | `00 00 00 B2 00 00 00 00` | 500 ms |
| Msg2 | 0x500 | `00 00 00 00 78 00 00 00` | 50 ms |
| TestUnlock states | 0x700 | `B2`, `24`, `24`, `24` (byte[3]) x2 | 500 ms each |
| Verify | TestUnlock param | Success when value == 0xE4 | One-shot |
### Duration
Phase 1: 600,500 ms (10 min 0.5 sec). Phase 2: ~4 sec (8 messages x 500ms). Total: ~604.5 sec.
## Known Issue in Unlock Verification
The **Type 1 verification logic may be inverted** compared to the old code. Old: `Lock = (valor != 0)` meant non-zero = LOCKED. New: `Value != 0` returned as SUCCESS (unlocked). Needs hardware testing to confirm which is correct.
## Missing Feature: TestImmo Check
Old code tracked both `TestUnlock` and `TestImmo` CAN parameters and displayed combined status. New code only checks `TestUnlock`, ignoring `TestImmo` entirely. Consider adding the immobilizer state check for completeness.

View File

@@ -0,0 +1,85 @@
# Gap: Missing Dialogs and UI Components
## Priority-Ranked List
### CRITICAL — Safety Dialogs (prevent hardware damage)
#### 1. RPM Safety Warning (`WCareOnRpmOn`)
**Old behavior:** Shown when operator sets RPM > 0 but oil pump is not running. Three options: turn on oil pump + proceed, proceed without oil, cancel.
**Trigger:** RPM setpoint change in BenchControlViewModel
**MVVM:** Dialog returns enum (ProceedWithOil / ProceedWithout / Cancel)
**Why critical:** Running the pump motor without oil circulation can cause bearing damage.
#### 2. Oil Pump Confirmation (`WAcceptOilTurnOn`)
**Old behavior:** Confirmation dialog before activating oil pump. Ensures operator confirms oil level and connections are ready.
**Trigger:** Oil pump relay toggle in BenchControlViewModel
**MVVM:** Simple confirm/cancel dialog
#### 3. 27V Warning (`WAlert27v`)
**Old behavior:** Warning when pump requires 27V power supply (some Ford variants). Alerts operator to switch power supply before proceeding.
**Trigger:** Pump selection when pump definition indicates 27V requirement
**MVVM:** Informational dialog with acknowledge button
### HIGH — Functional Dialogs
#### 4. Ford Unlock Progress (`WUnlocker`)
See `gap-ford-unlock-ui.md` for full spec.
#### 5. COM Port / K-Line Selection (`KlineIDSelection`)
**Old behavior:** Dropdown listing available FTDI devices by serial number. User selects which adapter to use for K-Line communication.
**Current gap:** `KwpService.DetectKLinePort()` auto-detects the first FTDI device. No UI for manual selection when multiple adapters are connected.
**Trigger:** K-Line connection attempt, or settings panel
**MVVM:** ComboBox of detected FTDI serial numbers + Connect button
#### 6. User Management (`WUsersManage`)
**Old behavior:** Add/remove users, change passwords. User list displayed in a grid.
**Current state:** `UserCheckDialog` handles auth only. `ConfigurationService.UpdateUsers()` exists but no UI invokes it for CRUD.
**Trigger:** Admin menu or settings panel
**MVVM:** DataGrid with add/edit/remove buttons. Hash or encrypt passwords before storage (see gap-missing-features.md).
#### 7. Full Settings Panel (`WConfigPanel`)
**Old behavior:** Comprehensive dialog for all settings: PID tuning, refresh rates, safety limits, encoder resolution, motor calibration, company info, log retention, language selection.
**Current state:** `BenchParamConfigView` covers bench CAN parameter editing only. All other settings require hand-editing config.xml.
**Trigger:** Settings button in toolbar
**MVVM:** Tabbed dialog (General, Safety, PID, Company, Sensors, Language)
### MEDIUM — Utility Dialogs
#### 8. Generic Confirmation (`WAskQuestion`)
**Old behavior:** Reusable yes/no dialog with custom message.
**Alternative:** WPF's built-in `MessageBox.Show` with `MessageBoxButton.YesNo`. Can be used directly in ViewModels via a dialog service abstraction. No custom dialog needed unless the app's visual theme demands it.
#### 9. Generic Alert (`WGenericAlert`)
**Old behavior:** Reusable info/warning dialog with custom message + icon.
**Alternative:** Same as above — `MessageBox.Show` covers this. Implement a custom one only if visual consistency matters.
### MEDIUM — Missing Controls
#### 10. Test Timer/Countdown (`TimerDisplay`)
**Old behavior:** Visual countdown during conditioning and measurement phases. Shows remaining seconds in large digital font.
**Current gap:** Phase progress is communicated via `VerboseMessage` text events but no dedicated countdown UI.
**Implementation:** Either a UserControl with large text binding, or integrate into `TestDisplayView` with a progress ring.
#### 11. Bit-Level Status Display (`BitDisplay` / `SingleBit`)
**Old behavior:** Grid of toggleable bits showing pump status word state. Each bit shows label + green/red indicator based on PumpStatusDefinition.
**Current state:** `StatusDisplayView` exists but may not render individual bits as toggle indicators.
**Implementation:** ItemsControl with BitDisplay item template (colored circle + label per bit).
#### 12. Searchable ComboBox (`FilteredComboBox`)
**Old behavior:** Dropdown with text filtering for pump selection (100+ pumps).
**Alternative:** Extended.Wpf.Toolkit's `AutoFilteredComboBox` may cover this. Or implement as a standard ComboBox with `IsTextSearchEnabled="True"` and `IsEditable="True"`.
### LOW — Display Controls
#### 13. Temperature Display Widget (`TempDisplayer`)
**Current state:** Temperature values are shown inline in the main UI. A dedicated widget is nice-to-have but not functionally missing.
#### 14. Graphical Result Display (`GraphicResultDisplay` / `CustomChart`)
**Current state:** `FlowmeterChartView` + `ReportChartRenderer` partially cover this. LiveChartsCore handles real-time visualization. The old custom chart control is superseded.
## Implementation Pattern
All dialogs should follow the existing MVVM pattern:
- `Views/Dialogs/XxxDialog.xaml` — pure XAML, no code-behind logic
- `ViewModels/Dialogs/XxxViewModel.cs``[ObservableProperty]`, `[RelayCommand]`
- Opened from parent ViewModel via a dialog service or `Window.ShowDialog()`
- Results returned via ViewModel property, not code-behind event args

View File

@@ -0,0 +1,117 @@
# 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`.
### Recommended approach
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.cs``ValidateUser()`, `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:
```csharp
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`:
```csharp
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.

View File

@@ -0,0 +1,118 @@
# Gap: Pump Data Migration (Old CFG/TXT → New XML)
## Overview
The old system had 32 CFG files (Bosch PSG format), 117 test plan TXT files, and reference data files that were processed by `HerlicScripts/Program.cs` into an encrypted `data.herlic` pump database. The new system uses `pumps.xml` (plain XML). This document maps every old data field to its new equivalent and identifies what cannot be migrated.
## Source Files
- `old_source/HerlicScripts/CFGs/*.CFG` — 32 pump config files
- `old_source/HerlicScripts/TestPlansLargos/*.txt` — 117 test plan files
- `old_source/HerlicScripts/AngulosDeBloqueo.txt` — Lock angle reference (114 entries)
- `old_source/HerlicScripts/AvanceInyeccion.txt` — Injection advance CAN data
- `old_source/HerlicScripts/ListadoBombas.txt` — Master pump database (108 pumps)
- `old_source/HerlicScripts/PreDatos.txt` / `PosDatos.txt` — XML header/footer templates
- `old_source/HerlicScripts/Program.cs` — Migration tool source
## CFG Families
| Family | CFGs | Description | KENNUNG |
|--------|------|-------------|---------|
| Type 1 | T06102, T062xx (21 files) | PSG2/5-Opel | 0 |
| Type 2 | T15xxx, T31804 (7 files) | PSG5-PI with pre-injection | 2 or 10 |
| Type 3 | T18xxx (3 files) | PSG5-PI-Ford | 6 |
| Type 4 | T06301 (1 file) | PSG5-FIEONA | 1 |
## Field Mapping: CFG → pumps.xml
### Fully Migrated (present in new PumpDefinition model)
| CFG Field | New Model Property | Notes |
|-----------|--------------------|-------|
| `ID-SEND1` | `ParametersByName[me/FBKW/mepi].MessageId` | TX message ID |
| `ID-EMPF1` | `ParametersByName[Status].MessageId` | RX status ID |
| `ID-EMPF2` | `ParametersByName[RPM/Temp].MessageId` | RX diagnostics ID |
| `ID-EMPF3` | `ParametersByName[Empf3].MessageId` | RX self-test ID |
| `CAN-MESOLL` P1-P6 | `CanBusParameter.P1-P6` | Fuel quantity formula |
| `CAN-FB-KW` P1-P6 | `CanBusParameter.P1-P6` | FBKW injection angle |
| `CAN-KW-N` P1-P6 | `CanBusParameter.P1-P6` | RPM formula |
| `CAN-THYBR` P1-P6 | `CanBusParameter.P1-P6` | Temperature formula |
| `CAN-BAUDRATE` | `PumpDefinition.CanBaudrate` | 500 or 250 kBaud |
| Lock angles | `PumpDefinition.LockAngle` | From AngulosDeBloqueo.txt |
| Rotation direction | `PumpDefinition.Rotation` | left/right |
| Pre-injection flag | `PumpDefinition.HasPreInjection` | Type 2/3 pumps |
| Unlock type | `PumpDefinition.UnlockType` | 0/1/2 |
| Test plans | `PumpDefinition.Tests` | From test plan TXT files |
### Partially Migrated (structure exists but data incomplete)
| CFG Field | New Model | Gap |
|-----------|-----------|-----|
| `CAN-STATUS*` bit definitions | `PumpStatusDefinition` in status.xml | Only display info (bit, state, color, description) migrated. **Missing:** reaction codes (0=none, 1=abort, 2=warning, 3=log), special function codes, special parameters |
| `CAN-PSGTEST*` self-test bits | `PumpStatusDefinition` | Same gap as above — no reaction/function codes |
| `CAN-MESOLL-PI` / `CAN-PHIAD-PI` | `CanBusParameter` for mepi | Formula exists but only if pump HasPreInjection |
### NOT Migrated (no equivalent in new model)
| CFG Field | Purpose | Impact |
|-----------|---------|--------|
| `PAS-EPROM-LES` | EPROM read password (4 bytes + scope) | KWP passwords now handled in KwpService code, not per-pump config. Currently only 3 hardcoded password versions (V1/V2/V3-V4). If a pump needs a different password, it can't be configured. |
| `PAS-EEPROM-LES/SCHREIB` | EEPROM read/write passwords | Same as above |
| `PAS-RAM-SCHREIB` | RAM write password | Same |
| `CAN-PASSWORT-EWS` | EWS immobilizer password | Always 0xFFFF in all CFGs (unused in practice) |
| `BIP-STATUS*` | Needle-motion detection (8 definitions with HEX pattern matching) | Entirely absent. Pre-injection pumps use BIP to verify injection timing. |
| `EMPFINDLICHKEIT` | Flow regulator sensitivity (dAD, measurement time, tolerance, max sensitivity, regulator current) | Not stored per-pump. Bench-level config only. |
| `EMPFINDLICHKEIT-2` | Flow regulator part 2 (dFM-Empf, Fehl-zul, Messzeit) | Same |
| `ADR-MV-SCHALTZEIT` | Solenoid valve switching time RAM address | Diagnostic addresses not per-pump |
| `ADR-F_TK_TE_W` | Temperature compensation switch address | Same |
| `ADR-TK_AT_W` | Dynamic temp compensation switch | Same |
| `ADR-SV-SOLL` / `ADR-SV-IST` | SV actuator target/actual addresses | Same |
| `ADR-TO_MV_600_HE` | MV pre-control value address | Same |
| `ADR-MV-T-ABGLEICH*` | MV time adjustment addresses | Same |
| `ADR-S_BIP_HW_UW` | BIP status address | Same |
| `ADR-ID-EMPF2-SENDEN` | EMPF2 auto-send control address | Same |
| `ADR-REL-CAN-SRC` | CAN source relative address | Same |
| `ADR-LERN-VERF` | Learning procedure switch | Same |
| `ADR-RESET` | PSG auto-reset address | Same |
| `BASISADR` | EEPROM base address table | Same |
| `CAN-BUS-KENNUNG` | Protocol variant code (0/1/2/6/10) | Derived implicitly from CAN IDs and UnlockType |
| `PHI-LUECKE-SYNCH` | Sync pulse angle offset | Not stored |
| `ATS-SERVICE` | Ford service CAN ID | Not stored separately |
| `KW_SIM_UMSCHALTUNG` | SV control/regulation switching debounce | Not stored |
| `MSG-KONFIGURATION` | Message config byte | Not stored |
| WTSS formulas (`N-NW`, `MESOLL`, `PHIAD`, `FB-NW`, `FB-KW`, `PHI1`, `FB-MASS`, `THYBR-OFFSET`) | Secondary scaling for WTSS transfer | Not stored |
## Status Bit Reaction Codes — Impact Assessment
The old CFGs defined per-bit reaction behavior:
- **Reaction 0:** No action (display only)
- **Reaction 1:** Abort test immediately
- **Reaction 2:** Show warning, continue
- **Reaction 3:** Log only
The new `PumpStatusDefinition` stores only display info (description + color). There is no mechanism to:
- Abort a test when a specific status bit asserts
- Show a warning for specific bits during test execution
- Differentiate between critical and informational bits per pump model
**Recommendation:** Add a `Reaction` property (int, 0-3) to `StatusBitValue` in `PumpStatusDefinition.cs`. Wire it into `BenchService` test execution to check active status bits against their reaction codes per phase.
## BIP-STATUS — Impact Assessment
BIP (Brennraumindikator-Prüfung / combustion indicator test) is a per-cylinder needle-motion detection system used on pre-injection VP44 pumps. The old system defined 6-7 BIP status conditions with HEX pattern matching (e.g., "BIP detected OK", "No BIP in capture window", "BIP deviation too large").
**Impact:** Without BIP status monitoring, pre-injection pump testing lacks validation that the injection nozzle is actually opening correctly. This is a diagnostic gap for Type 2 (T15xxx) and Type 3 (T18xxx) pumps.
**Recommendation:** Add a `BipStatusDefinition` model class and integrate BIP pattern matching into the test execution flow for pre-injection pumps.
## Test Plan TXT Format
Each test plan file follows this structure:
```
[TestName] [TestType] [nPhases] [ConditioningTime] [MeasurementTime] [MeasurementsPerSec]
[PhaseName] [RPM] [me] [FBKW] [ME_PI] [T-In] [QOver] [Tolerance_me] [Tolerance_FBKW] ...
```
108 pump IDs have corresponding test plan files. These should already be in `pumps.xml` if the old `Program.cs` migration was run. Verify coverage by comparing pump IDs in `pumps.xml` against `ListadoBombas.txt`.
## Migration Tool Approach
If re-migration is needed:
1. Port the parsing logic from `old_source/HerlicScripts/Program.cs` into a standalone console app
2. Read each CFG file using the pipe-delimited parser (`GetParamCFG`)
3. Read test plans from TXT files
4. Read lock angles from `AngulosDeBloqueo.txt`
5. Generate `pumps.xml` and `status.xml` in the new schema
6. Run once, commit the generated files, do not ship the migration tool