fix(medtronic): Medtronic pump stuck in PumpUnreachable state with no automatic recovery#4530
fix(medtronic): Medtronic pump stuck in PumpUnreachable state with no automatic recovery#4530mifi100 wants to merge 1 commit intonightscout:devfrom
Conversation
…ecovery When pump becomes unreachable and WakeAndTuneTask fails, RileyLinkServiceState transitions to PumpConnectorError. Previously, isPumpNotReachable would return false without calling isDeviceReachable(), blocking all automatic reconnection attempts. This deadlock required app restart to recover. Changes: - Add PumpConnectorError to states that allow reconnection attempts in isPumpNotReachable (MedtronicPumpPlugin.kt) - Restore RileyLinkServiceState to PumpConnectorReady upon successful connection when recovering from PumpConnectorError state (MedtronicCommunicationManager.kt) Fixes automatic recovery when pump becomes reachable again after being in PumpUnreachable + PumpConnectorError state. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
Update: Further analysis has shown that the current changes are insufficient to resolve the issue. Therefore, this PR is not yet ready for merge and requires additional work. Below, I've outlined several possible fixes. Thoughts and reviews from the community are welcome. Problem: Current Fix Is Unreachable Through the Normal Recovery PathContextCommit
Both changes are logically correct, but they are unreachable through the normal Root CauseThe recovery chain is:
Where When
This is confirmed by the log — Additional contextKey Medtronic methods inherited from
This means Proposed SolutionsAll solutions are scoped to Medtronic/RileyLink classes only. No changes to Solution A: Treat
|
| Criterion | Solution A | Solution B | Solution C |
|---|---|---|---|
| Number of methods changed | 2 | 2 | 2 |
| Semantic correctness | Low | High | Medium |
| Retry aggressiveness | 1x / 5 min | Continuous / 119s | 1x / 5 min |
| Temporary state inconsistency | No | No | Yes (brief) |
| Uses existing fix path (Changes 1&2) | Yes | Partially | Yes |
| Risk of side effects | Low | Medium | Low |



Preface
I've been facing issues with Medtronic+RileyLink connectivity stability for quite a long time. I found issue inside RL queue mechanism (see #3897) which improved stability. But still I could see that after pump became unreachable it couldn't connect again until AAPS reboot. Logs analysis gives good understanding that root cause is that system stops real connection attempts while it shouldn't after reaching PumpConnectorError RL state. I assessed all my findings with Claude Code which helped to document the change and do thorough review of the RCA and solution finalization.
I haven't tested this change yet, but I believe it should be safe and useful. Please review the proposal.
Summary
This fix addresses a deadlock condition where a Medtronic pump becomes permanently stuck in an unreachable state, requiring an application restart to recover. The issue occurs due to an interaction between two state machines (
PumpDeviceStateandRileyLinkServiceState) that prevents the regular connection retry mechanism from executing.Problem Description
Background
The Medtronic pump driver uses two independent state machines:
PumpDeviceState— tracks pump communication status (Sleeping,WakingUp,Active,PumpUnreachable, etc.)RileyLinkServiceState— tracks RileyLink device status (PumpConnectorReady,PumpConnectorError,RileyLinkReady, etc.)The Deadlock Scenario
Step 1: Pump becomes unreachable
When
isDeviceReachable()inMedtronicCommunicationManager.ktfails to connect after 5 attempts:PumpDeviceStateis set toPumpUnreachableWakeAndTuneTaskis triggered to re-tune the radio frequencyStep 2: Frequency tuning fails
When
WakeAndTuneTaskexecutes and the tuning process fails (e.g., pump is out of range or powered off):Step 3: Recovery path is blocked
The application uses
KeepAliveWorkerto periodically check pump status (approximately every 5 minutes). This triggers the following call chain:The
isPumpNotReachableproperty contained this logic:When
RileyLinkServiceStateisPumpConnectorError:ifstatement evaluate totruefalsewithout callingisDeviceReachable()Step 4: Permanent deadlock
The system is now stuck in an unrecoverable state:
PumpDeviceState=PumpUnreachableRileyLinkServiceState=PumpConnectorErrorKeepAliveWorkercheck never attempts to reconnect to the pumpState Diagram
The Fix
This fix consists of two changes, both in the Medtronic-specific code:
Change 1: Allow reconnection attempts when in
PumpConnectorErrorstateFile:
pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/MedtronicPumpPlugin.ktThis check aims to prevent real pump check if RileyLink device is not ready for that. And PumpConnectorError state is the state where RileyLink is reachable, so this state is just missed in the list.
Effect: When
RileyLinkServiceStateisPumpConnectorError, the code now proceeds to callisDeviceReachable(), which attempts up to 5 connection retries. This allows the system to recover when the pump becomes reachable again.Change 2: Restore
RileyLinkServiceStateupon successful connectionFile:
pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/comm/MedtronicCommunicationManager.ktEffect: When a connection is successfully established (valid pump model received), and the previous state was
PumpConnectorError, theRileyLinkServiceStateis restored toPumpConnectorReady. This ensures:isInitializedproperty returns the correct valueWhy this change is safe:
connectToDevice()withRileyLinkServiceState.PumpConnectorErrorwas previously unreachable (due to the early return inisPumpNotReachable)PumpConnectorErrorstate, not any other statesconnectToDevice()performs a real connection test (sends a request and validates the pump model response), so a successful result genuinely indicates working communicationImpact Assessment
OmnipodRileyLinkCommunicationManager)Testing Recommendations
Recovery test: Simulate pump unreachable state (e.g., move pump out of range), wait for
PumpConnectorErrorstate, then bring pump back in range. Verify automatic recovery without app restart.Normal operation test: Verify normal pump communication is not affected by the changes.
UI verification: Confirm the RileyLink status indicator shows correct state after recovery.
Files Changed
pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/MedtronicPumpPlugin.ktPumpConnectorErrorto the list of states that allow reconnection attemptspump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/comm/MedtronicCommunicationManager.ktRileyLinkServiceStateconnectToDevice()method