Files
HC_APTBS/docs/gap-ford-unlock-ui.md
LucianoDev 37d099cdbd feat: add Ford VP44 unlock progress dialog, K-Line fast unlock, localization, safety dialogs, and settings
Unlock progress UI:
- UnlockProgressDialog with dark-themed progress ring, phase indicator, elapsed
  time, and cancel/close buttons (non-modal, draggable borderless window)
- UnlockProgressViewModel with event-driven progress tracking via IUnlockService
- Triggers on pump selection (manual or K-Line auto-detect), not test start

UnlockService rewrite:
- Persistent CAN senders that outlive the unlock sequence (StopSenders on pump change)
- Concurrent K-Line fast unlock: awaits session Connected, sends RAM timer shortcut
  ({02 88 02 03 A8 01 00}), verifies via CAN TestUnlock before skipping wait
- Fix Type 1 verification (Value == 0 means unlocked, was inverted)

K-Line fast unlock support:
- IKwpService.TryFastUnlockAsync / KwpService implementation

Additional features:
- ILocalizationService with ES/EN resource dictionaries and runtime switching
- Safety dialogs: VoltageWarning, OilPumpConfirm, RpmSafetyWarning
- SettingsDialog for app configuration
- BenchService enhancements, ConfigurationService improvements, PDF report updates
- All UI strings localized via DynamicResource

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

72 lines
4.6 KiB
Markdown

# Gap: Ford Unlock Progress UI — RESOLVED
## Status: Implemented
The unlock progress dialog, service refactoring, and K-Line fast unlock are fully implemented.
## What was done
### 1. UnlockProgressDialog (View + ViewModel)
- **`Views/Dialogs/UnlockProgressDialog.xaml`** — Dark-themed non-modal window (#2B2929), borderless with drag support, 200x200 ellipse progress ring, Courier New 60pt percentage, MM:SS elapsed time, phase indicator, linear progress bar, result text (green/red), Cancel + Close buttons
- **`Views/Dialogs/UnlockProgressDialog.xaml.cs`** — `ForceClose()` for programmatic close, `OnWindowClosing` prevents user close until `IsComplete`, `OnMouseDrag` for window dragging
- **`ViewModels/Dialogs/UnlockProgressViewModel.cs`** — `ObservableObject` + `IDisposable`, parses `StatusChanged` events via regex, marshals to UI thread, `CancelCommand` (Phase 1 only) / `CloseCommand` (after completion), `[NotifyCanExecuteChangedFor]` wiring
### 2. UnlockService rewrite (`Services/Impl/UnlockService.cs`)
- **Persistent CAN senders** — Start before unlock, run indefinitely until `StopSenders()` is called on pump deselection. Prevents pump from re-locking after unlock.
- **Concurrent fast unlock** — While the 600s CAN wait runs with progress reporting, a parallel task awaits K-Line session Connected state, then:
1. Checks if pump is already unlocked (via `VerifyUnlock`)
2. Sends K-Line fast unlock command (`{0x02, 0x88, 0x02, 0x03, 0xA8, 0x01, 0x00}`) which writes to pump RAM to fast-forward the internal 10 min timer
3. Waits 2s, then re-checks `VerifyUnlock`
4. If verified → cancels remaining wait, proceeds to Phase 2 immediately
- **`IUnlockService.StopSenders()`** — New interface method, called from `MainViewModel.CloseUnlockDialog()` on pump change
### 3. K-Line fast unlock support
- **`IKwpService.TryFastUnlockAsync()`** — New interface method
- **`KwpService.TryFastUnlockAsync()`** — Sends custom command over active session, returns true if no NAK (command accepted, not unlock confirmation)
### 4. MainViewModel integration
- **Trigger on pump selection** — `OnPumpChanged()` calls `StartUnlockIfRequired()` for pumps with `UnlockType != 0` (both manual and K-Line auto-detect)
- **Non-modal window** — `.Show()` instead of `.ShowDialog()`, user can interact with main UI during 10 min unlock
- **Test start guards** — `StartTestAsync` blocks if unlock is in progress or failed
- **Cleanup on pump change** — `CloseUnlockDialog()` stops senders, cancels CTS, disposes ViewModel, force-closes window
### 5. Bug fix: Type 1 verification
**Fixed.** Old code: `Lock = valor != 0` (non-zero = LOCKED). New code had `return Value != 0` (non-zero = SUCCESS). Changed to `return Value == 0`. Type 2 (`== 0xE4`) was already correct.
## 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 |
### K-Line fast unlock (timer shortcut)
| Command | `02 88 02 03 A8 01 00` |
|---------|------------------------|
| Effect | Writes pump RAM to fast-forward the internal 10 min timer |
| Prerequisite | Active K-Line session + CAN flood senders already running |
| ACK meaning | Command accepted (NOT unlock confirmed — must still verify via CAN TestUnlock) |
### Duration
- Phase 1 (normal): 600,500 ms (10 min 0.5 sec)
- Phase 1 (fast unlock): ~2 sec after K-Line ACK (+ K-Line read time)
- Phase 2: ~4 sec (8 messages x 500 ms)
- CAN senders: persist until pump deselection
### Critical: CAN sender lifecycle
CAN flood messages must be active **before** the fast unlock attempt (otherwise the timer resets instantly) and must **continue running after** unlock completes. Stopping them causes the pump to re-lock. `StopSenders()` is only called when the pump is deselected.
## Remaining gap: TestImmo check
Old code tracked both `TestUnlock` and `TestImmo` CAN parameters and displayed combined status ("Inmovilizada/Liberada | Bloqueada/Desbloqueada"). New code only checks `TestUnlock`. Consider adding immobilizer state display for completeness.