Skip to content

Conversation

@nl-ruud
Copy link

@nl-ruud nl-ruud commented Jan 18, 2026

Omnipod Dash basal drift resolution

This pull request introduces a new "basal correction" feature for the Omnipod Dash pump integration. The main goal is to detect under-delivery of basal insulin and automatically trigger a small correction bolus when needed. The implementation tracks delivered basal and bolus pulses, calculates expected vs. actual insulin delivery, and manages correction logic with safety checks and cooldowns.

Recap of the issue

The Omnipod Dash pump exhibits behavior that causes it to deliver less basal insulin than AAPS expects (issue #4158). This is effectively a hardware limitation of the pump.

The Dash uses an internal timer to determine when a basal pulse of 0.05 U is delivered. Once the timer interval elapses, the pulse is delivered. However, this timer is restarted whenever a basal rate change occurs (and possibly also when a bolus or SMB is delivered).

When used in combination with looping, this leads to structural under-delivery of basal insulin, as the algorithm adjusts the basal rate frequently. While the Medtrum pump compensates for this behavior internally, the Dash does not, and neither does the current Dash driver implementation in AAPS.

The issue is most apparent during the night. During daytime operation, SMBs often result in a basal rate of 0, which masks the effect. In observed usage, this results in approximately 10% of the expected Total Daily Dose (TDD) not being delivered over a 24-hour period. Additionally, glucose targets are often not reached overnight, particularly after meals with prolonged glucose impact (e.g. pasta).

Approach

This pull request introduces automatic basal drift compensation by correcting the pump lag with small correction boluses. A correction bolus of 0.05 U is delivered as soon as the detected basal deficit reaches 0.025 U. Several safety constraints are applied. For example, corrections are not delivered during a temporary basal of 0 unless that temporary basal is the direct result of a recently delivered bolus.

With this approach, the deviation between expected and delivered basal insulin is kept within a bounded range of approximately −0.050 U to +0.025 U.

With this fix applied:

  • The TDD reported by AAPS (under Statistics) matches the total amount actually delivered by the pump (Dash menu → Pod managementHistory).
  • Overnight glucose targets are consistently reached.

Without this fix, a clear discrepancy between reported and delivered TDD can be observed.

Main Changes

Basal Correction Feature

  • Added a new custom command, CommandDeliverBasalCorrection, and integrated it into the command queue and handling logic in OmnipodDashPumpPlugin to trigger a basal correction bolus when under-delivery is detected.
  • Implemented the deliverBasalCorrection method to handle the actual delivery of the correction bolus, including safety checks (reservoir level, bolus in progress, cooldowns, etc.).

Basal Delivery Tracking and Drift Calculation

  • Added logic in OmnipodDashPodStateManagerImpl to track basal and bolus pulses separately, compute actual delivered basal, and calculate "drift" (difference between expected and actual basal delivery). This includes new fields in the pod state and methods for integrating expected delivery over time.
  • The needsBasalCorrection method determines when a correction is needed based on drift, cooldowns, and other safety criteria.

Pod State Update and Logging Refactor

  • Refactored pod state update logic to centralize updates in a new updatePodState method, which also updates basal tracking fields and logs basal delivery/drift for debugging. This method is now used in both default and alarm status response handlers and removes code duplication from these methods.

Logging example:

PUMP_BASAL act=8,10U (tot=33,25U bol=25,15U) exp=9,42U err=-1,32U dErr=-0,02U

Legend for the log fields:

Field Description
act Actual basal units delivered (totbol)
tot Total units delivered
bol Bolus units delivered
exp Expected basal units delivered
err Error / cumulative basal drift (act - exp)
dErr Delta of err on this pump status response

Interface and State Enhancements

  • Updated the OmnipodDashPodStateManager interface and its implementation to support new fields and methods for basal correction tracking (lastBasalCorrectionTime, basalCorrectionInProgress, needsBasalCorrection).

These changes together enable the system to automatically detect and correct small basal under-deliveries, improving insulin delivery reliability and safety.

Tests Performed

To verify the fix, we compared the total insulin delivered at 00:00 at the start of a day with the total at 00:00 at the end of the same day.

Before this fix, the difference consistently resulted in a lower number than the TDD reported by AAPS, confirming under-delivery. After applying the fix, this discrepancy no longer occurs: AAPS TDD matches the pump’s delivered total.

@vanelsberg
Copy link
Contributor

This PR contains unrelated commits from the dev branche, which I think is undesired?
Not an expert on this: maybe consult with @MilosKozak on how to fix.

@vanelsberg
Copy link
Contributor

vanelsberg commented Jan 19, 2026

In addition, it is stated: "It should be reviewed on top of PR #4467"
This makes merging this PR with AAPS-CI impossible. Is there a reason this PR's are separate?
Please consider combining PR#4467 and this PR into one?

@vanelsberg
Copy link
Contributor

vanelsberg commented Jan 19, 2026

Nice 👍
Will need to review and test implementation in detail and test to see how this PR does.

@vanelsberg
Copy link
Contributor

This PR contains lots of file changes and commits.
To enable proper reviewing, please consider squashing all commits into one?

@nl-ruud nl-ruud force-pushed the issue-4158-dev-fix branch from 568ed7f to df5aa07 Compare January 19, 2026 09:18
@nl-ruud nl-ruud force-pushed the issue-4158-dev-fix branch from df5aa07 to 189629d Compare January 19, 2026 09:21
@nl-ruud
Copy link
Author

nl-ruud commented Jan 19, 2026

@vanelsberg I think I fixed it, there are two commits now in this PR: the first one equals 4467 (quantifying the basal drift) and the second one is resolving the basal drift. does this make sense? I think that also would mean we can close #4467 as the distinction is now just clear in this PR.

@vanelsberg
Copy link
Contributor

vanelsberg commented Jan 19, 2026

I think I fixed it, there are two commits now in this PR....

Yes! This looks a lot better, making it easier to follow implementation. Helps reviewing/testing and - eventually - when ok, acceptance for merging with dev.

(When 4467 is no longer of use, I think best to close it to prevent confusion?)

}

// Add hour boundaries for basal program transitions
var nextHour = (startTime / 3600_000L + 1) * 3600_000L // Next whole hour
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do worry a little about hard-coding this to hourly. I guess it accurately reflects the current reality, though!

Just one of those things that down the line (if half hour basal segments for Omnipod became a thing) would need to be changed, but maybe those doing the change might miss.

Copy link
Author

@nl-ruud nl-ruud Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree! Fixed in 6b01383

Copy link
Author

@nl-ruud nl-ruud Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this update introduced a timezone issue as basal program times are in local time and not UTC. I removed the commit for now as it made things worse. Will commit a new update when I verified it's resolved.

@nl-ruud nl-ruud force-pushed the issue-4158-dev-fix branch 2 times, most recently from 6b01383 to 189629d Compare January 26, 2026 09:14
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants