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>
4.6 KiB
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 buttonsViews/Dialogs/UnlockProgressDialog.xaml.cs—ForceClose()for programmatic close,OnWindowClosingprevents user close untilIsComplete,OnMouseDragfor window draggingViewModels/Dialogs/UnlockProgressViewModel.cs—ObservableObject+IDisposable, parsesStatusChangedevents 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:
- Checks if pump is already unlocked (via
VerifyUnlock) - 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 - Waits 2s, then re-checks
VerifyUnlock - If verified → cancels remaining wait, proceeds to Phase 2 immediately
- Checks if pump is already unlocked (via
IUnlockService.StopSenders()— New interface method, called fromMainViewModel.CloseUnlockDialog()on pump change
3. K-Line fast unlock support
IKwpService.TryFastUnlockAsync()— New interface methodKwpService.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()callsStartUnlockIfRequired()for pumps withUnlockType != 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 —
StartTestAsyncblocks 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.