Add therapy settings upload to Tidepool#975
Add therapy settings upload to Tidepool#975blalezarian wants to merge 16 commits intonightscout:devfrom
Conversation
Adds an "Include Therapy Settings" toggle to the Tidepool settings screen, allowing users to opt-in to uploading their therapy configuration (basal schedules, carb ratios, insulin sensitivity factors, BG targets, and override presets) alongside their diabetes data. Tidepool represents these as "Pump Settings" in their data model. Architecture decisions: - The toggle state is stored in TrioSettings (persisted via FileStorage) rather than in the TidepoolService submodule. This keeps all Trio settings in one place and avoids modifying upstream dependencies. - TrioSettingsAdapter converts Trio's JSON-based settings format to LoopKit's StoredSettings format, which TidepoolService then converts to the Tidepool API format. This two-step conversion maintains clean separation between Trio's data model and the upload mechanism. - The toggle is disabled when Tidepool is not connected, preventing users from enabling a feature that would have no effect. - TidepoolManager listens for therapy setting changes via the existing observer pattern (SettingsObserver, BasalProfileObserver, etc.) and triggers debounced uploads when the toggle is enabled. - Upload requests are debounced (1.5s) to prevent redundant uploads when multiple settings observers fire in rapid succession. - syncIdentifier uses a content-based SHA-256 hash of therapy values instead of a random UUID, enabling Tidepool server-side deduplication. - Basal schedule conversion uses the numeric minutes field directly instead of parsing the start time string, avoiding format mismatches. Note: CarbRatios and InsulinSensitivities observers are not yet wired up to trigger uploads - this will be addressed in a follow-up commit.
Therapy setting changes for carb ratios and insulin sensitivity factors were not triggering Tidepool uploads because the observer pattern was incomplete. BGTargets and BasalProfile had observers, but CarbRatios and InsulinSensitivities did not. Changes: - Add CarbRatiosObserver protocol to CarbRatios.swift - Add InsulinSensitivitiesObserver protocol to InsulinSensitivities.swift - Broadcast changes from CarbRatioEditorStateModel.save() - Broadcast changes from ISFEditorStateModel.save() - Register TidepoolManager for both new observers - Implement observer methods to trigger uploadSettings() Now all four therapy settings (BG targets, basal profile, carb ratios, and insulin sensitivities) properly trigger Tidepool uploads when the "Include Therapy Settings" toggle is enabled.
Converts currently active Profile Overrides and Temp Targets to Tidepool's scheduleOverride format for upload. Profile Overrides include insulin needs scaling (percentage), while Temp Targets only modify the glucose target. Note: Override presets and active overrides are included in the upload payload, but Tidepool's web UI does not currently display them. The data is present in the API response and may be surfaced in the future once Trio is registered as a recognized app with Tidepool. The UI description has been updated to not mention overrides to avoid user confusion. Also adds TempTargetsObserver registration to trigger uploads when temp targets change, and documents the hostIdentifier mapping issue.
|
General question: why was this put behind a setting + toggle? What was your idea behind making this optional? Is there any user benefit or (keeping it deactivated) potential downside ? |
|
@dnzxy good question - I wasn't sure how existing users that rebuild an update know about all the new additions, so the thinking was this makes it visible, explicit and allows them to turn it on if they want. But I agree, in most cases it makes sense to just have it on by default. Want me to remove the toggle / state and just leave the language in the information tooltip to mention that therapy settings will also be included? That would make it simpler. Only downside I can think of is larger payload sent via API call to Tidepool but it's minimal data and not really a real issue. |
|
Thanks for adding some background to that @blalezarian 😊 I‘d suggest that we just add it. There’s no real downside to this being sent to TP. I‘d suggest just extending the help hint text content (when you tap (?) below the TP connectivity section) and listing there what we actually upload and adding pump settings to that. Maybe adding a little nugget like "Tap more for a full list of all uploaded data" or something along those lines. I‘ll try and review + have this PR tested over the next few days. Thanks for this contribution and a definite +1 for adding unit testing to it. |
Therapy settings (basal schedules, carb ratios, insulin sensitivities, and BG targets) are now uploaded automatically whenever connected to Tidepool, removing the opt-in "Include Therapy Settings" toggle per PR review feedback.
|
Noting that currently in Tidepool > Devices this data will show under the device "DIY Loop". When we later change the hostIdentifier in TidepoolManager to be "org.nightscout.Trio", the pump settings will show up under a new device (e.g. "DIY Trio" or "Trio") so the user will show two separate device settings in Tidepool (original "DIY Loop" and new "Trio). It's not a deal breaker, it won't break the code, it's just not the cleanest. So options are:
|
dnzxy
left a comment
There was a problem hiding this comment.
Thanks for tackling this @blalezarian
I have reviewed the code and have a few comments, some questions, and some change request.
I won't get to test running this code, but either someone else will add dedicated "end user" test feedback, or I will have to find the time :)
Overrides are buggy and temp targets shouldn't be mixed with them. Remove all override/temp target conversion code, Core Data queries, related observers, and corresponding tests.
threshold_setting in Preferences is always stored in mg/dL, but was being labeled with the user's display unit (bgUnit). If the user displays in mmol/L, a value like 70 (mg/dL) would be incorrectly labeled as 70 mmol/L. Always create the GlucoseThreshold in milligramsPerDeciliter since that matches the stored value. TidepoolServiceKit converts all glucose values to mg/dL before uploading (via convertTo(unit:)), and the Tidepool API always stores data in mg/dL. The mmol/L option in the Tidepool web UI is a display preference only.
- Read DIA from pumpSettings.insulinActionCurve (5-10h) instead of hard-coded 6h - Use ExponentialInsulinModelPreset defaults for peak activity (75min for rapidActing, 55min for fiasp/lyumjev) instead of hard-coded 2.5/3 hours which were incorrect - Respect useCustomPeakTime toggle — when enabled, use the user's insulinPeakTime setting (35-120min) - Distinguish Fiasp vs Lyumjev via pumpManager's configured insulin type instead of mapping both to .fiasp Note: TidepoolServiceKit currently maps .lyumjev model type to .other in its Tidepool datum conversion. When TidepoolServiceKit adds native .lyumjev support, the correct model type will flow through automatically.
|
I'll work on these, I'll tackle them in logical groups with 1 commit each so it's easier to follow changes. If you prefer to squash in 1 commit let me know |
…loads Move all therapy settings conversion logic from the standalone TrioSettingsAdapter into a BaseTidepoolManager extension, eliminating the separate injectable class. Replace observer-based upload pattern (CarbRatios, InsulinSensitivities, BasalProfile, BGTargets, PumpSettings observers) with direct Task.detached upload calls in each state model's save(), matching the existing Nightscout upload pattern. Keep SettingsObserver and PreferencesObserver for closedLoop/units/algorithm preference changes.
Clarify what data Trio uploads: glucose, carb entries, insulin (bolus and basal), pump settings, and therapy settings. List therapy settings explicitly: basal schedules, carb ratios, insulin sensitivities, and glucose targets.
|
@dnzxy changes are updated and ready for review. I'm new to the codebase but tried to follow patterns based on your feedback and tried not to duplicate anything that may already exist elsewhere. If I'm getting anything wrong, just let me know |
|
Added to my TODO to review your updates. Thanks for tackling this so quickly @blalezarian 🙏 |
marionbarker
left a comment
There was a problem hiding this comment.
Approve from Test:
- The test was successful.
No code review performed
TestConfigure a Trio instance and upload information to a tidepool account to which Tidepool engineers were granted sharing access. Start with blalezarian:feat/tidepool-pump-settings, commit d46c691
Hardware
Therapy Settings
Services
Active as of 2026-03-12 just before 16:00 PDT. |
|
There has been back and fourth with the Tidepool engineering team, so I have made two small changes and pushed them, plus a sync w/ dev. |
TestRepeat test with latest version of blalezarian:feat/tidepool-pump-settings on 20 Mar 2026, around noon PDT. Configuration LoopMy test Tidepool site is connected to a Loop phone.
Configuration TrioLog out of Tidepool with the Loop phone
Quit out of Trio
screenshot |
Test earlier commitConfigurationContinue from prior comment. Clean build folder
Login works this time. On Trio phone, modify basal rates from 1.2 U/hr to 1.3 U/hr Device upload did not work as expected.
|
Test earlier commitBack up another commit to caf7d54.
Modify basal rates back to 1.2 U/hr from 1.3 U/hr Refresh Tidepool display. Now the Device values shown are the Trio upload with the Loop label.
|
|
Thanks for testing :) I think we have two options here now:
I'm personally fine with either. What do you think @blalezarian @marionbarker ? |
|
So, after quick conferral with the guys at Tidepool two quick updates:
This PR should be good to go now, because we can ship this and as soon as the Tidepool frontend changes go live, pump settings will show up and for as long as it hasn't been shipped, there's no difference for Trio users vs. what Tidepool currently shows – nothing. |
|
Thanks, all, for working on this. As a Trio user and someone who works at Tidepool, I'm excited to give this option to PwDs who want to share their Tidepool data with their healthcare team. I'll come back here and give an update when this ships on the Tidepool side to production. |
Test✅ error when trying to upload, which is expected until Tidepool fixes their end Narrative and ConfigurationStep 1: build latest dev to test phone that has Medtrum pump added, choose the SE Phone, 3rd gen, iOS 26.4
Step 2: Check all my test phones to make sure Loop is not uploading to Tidepool
Step 3: Login to Tidepool with the Trio phone using dev 0.6.0.75
Step 4: Pull in PR 975 code (
Xcode debug log |
Test for carb and dosing uploads❌ this failed For completeness:
This used to work. Test that dev uploads carbs and dosingRestore to dev and test upload to Tidepool
In Xcode log I see:
|
marionbarker
left a comment
There was a problem hiding this comment.
I revoke my approval.
The current version breaks what used to work.
- ❌ carbs and dosing changes are no longer uploaded








Addresses #915
Adds an opt-in "Include Therapy Settings" toggle to the Tidepool settings screen, enabling upload of therapy configuration alongside existing glucose, carb, and insulin data. Tidepool represents these as "Pump Settings" in their data model.
What's uploaded
scheduleOverride)How it works
TrioSettingsAdapterconverts Trio's JSON-based settings to LoopKit'sStoredSettingsformat, whichTidepoolServicethen converts to the Tidepool API formatBasalProfileObserver,CarbRatiosObserver,InsulinSensitivitiesObserver,BGTargetsObserver,PreferencesObserver,PumpSettingsObserver,TempTargetsObserver) and a CoreData publisher for override changesTrioSettings(not in the TidepoolService submodule) to keep all Trio settings in one placeKnown limitations
Host identifier: Trio currently identifies as
com.loopkit.Loopto Tidepool because Tidepool doesn't have a mapping fororg.nightscout.Trioand would display the device as "unknown". With the Loop identifier, Tidepool displays it as "DIY Loop". The proper fix is to request Tidepool add a mapping for Trio — this is noted as a TODO.Override display: Override presets and active overrides are included in the upload payload and are present in the Tidepool API response, but Tidepool's web UI does not currently display them. This may require Trio to be registered as a recognized app with Tidepool. The user-facing description has been updated to not mention overrides to avoid confusion.
Testing