Code Customization
Build then Customize¶
For new Loopers, please build the code before you make any changes. Start with Open Loop and familiarize yourself with the interface. Later, you can make the customization(s) you desire and build again. The second build will be much easier than your first build.
These customizations require you to build the Loop app onto your iPhone, they cannot be done from within the app itself.
Customization Options¶
Read about the customizations on this page before applying them.
You take responsibility
You are responsible when you decide to use customizations.
Be sure to report what changes you made if you need to ask for assistance with your app.
Some customizations are the same for everyone and have been prepared for easy use.
- Mac-Xcode builders can use the Loop and Learn: Loop Customizations script
- This script automatically finds the most recent download and when you are done selecting customizations, opens Xcode to that download
- Even if you don't want to apply customizations, you can use this script as a easy way to find and open your download
- GitHub builders can use Loop and Learn: Customization: Prepared Customizations
Other customizations require that you create your own personalized version.
- Mac-Xcode builders: all the information required is on this page
- GitHub builders: read this page and use LoopDocs: GitHub Customization
For GitHub Browser Build, you can skip over the Mac-Xcode specific section and skip ahead to Build-Time Features.
When applying a customization using Mac-Xcode, the downloaded code should be fairly recent. If you are not sure, get a fresh download. If you know your downloaded code is the Current Release, you can skip the download and use the same folder as last time.
Find My Downloaded Loop Code¶
Refer to the graphic below. The Downloads folder in Finder is highlighted on the upper left. The full path to Loop.xcworkspace is highlighted along the bottom.
Loop to LoopWorkspace
Note that the directory Loop.xcworkspace
has been renamed to LoopWorkspace.xcworkspace
in the released code. For experienced builders - you realize this is good because the build process is easier.
The words were updated, but it will take time for the graphics to be updated.
- Open Finder
- Navigate to Downloads/BuildLoop and look for your download by name and date
- Open that folder, for example, Downloads/BuildLoop/Loop-220803-1145, and inside that folder open the LoopWorkspace folder
- Inside the Downloads/BuildLoop/Loop-220803-1145/LoopWorkspace folder, double-click on LoopWorkspace.xcworkspace (graphic not updated yet)
- Xcode automatically opens to that particular download
- You can then make the customizations and build to your phone
Experienced Builders
Experienced builders will often build a fresh download to a simulator for their phone iOS (not their phone) to ensure download is good and is compatible with macOS, Xcode and phone iOS. Once the build is successful, they apply their customizations and build again to the simulator. Last step is to build the customized version to their real phone.
Be sure to read the Instructions for Finding the Lines.
Line numbers may change
Every effort will be made to update the line numbers as the code is updated, but there may be times where the screenshots and line numbers differ from the current version of Loop code.
-
You may notice some customizations list line numbers for different branches
-
If you cannot identify a line that looks exactly like the example - do not guess - go to your favorite social media group and ask for help
Loop 2.2.x vs Loop 3
- Loop 3 has been released but there are some people using older code.
- The labels below indicate Loop 2.2.x or Loop 3, if they are different
- Users of Loop 2.2.9 (or earlier) or FreeAPS should refer to the Loop 2.2.x examples.
- Some 2.2.x customizations will be removed as time goes on
- Users of Loop 3 should refer to the Loop 3 examples.
- Note that some changes are in a different file for Loop 3 (part of the architecture upgrade for the app).
Build-Time Features¶
Build-time features are not available with Loop 2.2.x.
With Loop 3, some features are enabled or disabled by default but can be modified by adding a "flag" in the LoopConfigOverride.xcconfig file.
If you use the GitHub Build Method, these build-time features can be added to your copy of the LoopConfigOverride.xcconfig file. Use the pencil icon in that file on GitHub and then commit the change to your fork.
If you use the Mac-Xcode Build Method, this is the same file used to automatically sign all your targets. You can edit the version in your LoopWorkspace folder (it shows up as the top item in the Xcode folder view) - or - if you use the build script, you can edit the copy found in ~/Downloads/BuildLoop after the first time you use the script. For that second case, the "flags" you add in ~/Downloads/BuildLoop/LoopConfigOverride.xcconfig are applied to all downloads created with the script.
These flags are always upper case with underscore separating words for clarity, for example MY_EXAMPLE_FLAG
. If you have more than one flag, they are separated by a space. Do not enter a line break between selections; in other words, do not hit return or enter. Xcode will automatically word-wrap the line for clarity. All values need to be on a single line.
New Instructions
The instructions are more robust than earlier instructions that had you editing a line instead of adding new ones.
Copy the text below, add it to the end of your LoopConfigOverride.xcconfig file and then insert the desired flags in place of MY_EXAMPLE_FLAG
. If you want more than one flag, separate them by a space.
// Add Build-Time features to compilation conditions
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(SWIFT_ACTIVE_COMPILATION_CONDITIONS) MY_EXAMPLE_FLAG
Code Before Modification
// Put your team id here for signing
//LOOP_DEVELOPMENT_TEAM = UY678SP37Q
The example below is for someone who is using a Free Developer ID - which does not support Siri.
Code After Modification
// Put your team id here for signing
//LOOP_DEVELOPMENT_TEAM = UY678SP37Q
// Add Build-Time features to compilation conditions
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(SWIFT_ACTIVE_COMPILATION_CONDITIONS) SIRI_DISABLED
List of some flags and what they do:
FLAG | PURPOSE |
---|---|
SIRI_DISABLED | Required to build Loop from Xcode with a free developer account |
ADULT_CHILD_INSULIN_MODEL_SELECTION_ENABLED | The choice for Child Model is enabled in Therapy Settings. Please read Enable Child Model. |
REMOTE_OVERRIDES_DISABLED | Remote commands: override, carbs or boluses will not be accepted even if all the Remote Command requirements are configured If you do configure this and later try to set up remote commands, they will not work and there is no error message. Remote Errors: Loop REMOTE_OVERRIDES_DISABLED |
OBSERVE_HEALTH_KIT_CARB_SAMPLES_FROM_OTHER_APPS_ENABLED | Turns on ability for Loop to read third party carb entries. You must also make sure Health permissions allow Loop to read carbs from Health. Be vigilant if you select this; added carbs lead to added insulin dosing when closed loop is enabled |
SHOW_EVENTUAL_BLOOD_GLUCOSE_ON_WATCH_DISABLED | The Apple Watch screens show current glucose, trend arrow and eventual glucose by default. This flag disables the display of eventual glucose on the watch if you find the display distracting. |
PREDICTED_GLUCOSE_CHART_CLAMP_ENABLED | Chart Clamp |
ALLOW_ALGORITHM_EXPERIMENTS | dev branch only This is enabled by default to show Algorithm Experiments below the Therapy Settings row. This enables the user to separately enable or disable Glucose Based Partial Application and Integral Retrospective Correction |
Chart Clamp¶
What the heck is a chart clamp? It means the range displayed will not be smaller than the clamp but it can be bigger.
Loop automatically scales the glucose charts based on the history shown. Some people don't like to see the vertical axis changing, so they turn on the "clamp".
When the PREDICTED_GLUCOSE_CHART_CLAMP_ENABLED
build time flag is added:
- the range shown is never smaller than
glucoseChartDefaultDisplayBoundClamped
- 80 to 240 mg/dL (4.4 to 13.3 mmol/L)
When you do not add that build time flag:
- the range shown is never smaller than
glucoseChartDefaultDisplayBound
- 100 to 175 mg/dL (5.6 to 9.7 mmol/L)
If glucose within the display history is outside of the bound, the graph range expands to include that glucose level. This prevents glucose readings from being "hidden".
You can customize chart display settings if you want. The original lines of code are shown below. You will need to read the rest of this page to figure out how to modify these to meet what you prefer. If you can't figure this out - reach out for help.
- Module: Loop
- Loop 3
- Folder: Loop/Models
- File: LoopConstants.swift
- Lines: 32 to 45
// MARK - Display settings
static let minimumChartWidthPerHour: CGFloat = 50
static let statusChartMinimumHistoryDisplay: TimeInterval = .hours(1)
static let glucoseChartDefaultDisplayBound =
HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 100)...HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 175)
static let glucoseChartDefaultDisplayRangeWide =
HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 60)...HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 200)
static let glucoseChartDefaultDisplayBoundClamped =
HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 80)...HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 240)
Instructions for Finding the Lines¶
The instructions on this page were originally prepared for the Mac-Xcode method.
The GitHub Browser Build method instructions are similar, but each one is used to edit your fork of the particular Module in your GitHub account as instructed on the Customize with GitHub page.
For each customization, you will be given landmarks to find the correct location in the code. You can choose to search using the Key_Phrase
or navigate to the file in the folder structure and look for ( Cmd+L # ) the line number.
Some customizations are the same for all users, and do not require personalization. See Loop and Learn: Customization: Single Customization List.
For Mac-Xcode builders:
- Either Key_Phrase or Module, Folder, File can be used to find the lines
- Be sure to save the file when you make a change - otherwise the modification does not get built into your app
- Some folder icons show different names in Xcode, see Folders and Icons
For GitHub Browser builders;
- Some customizations can be copied from the Loop and Learn: Customization: Single Customization List
- Otherwise, create your own customization for the Module identified under Module, Folder, File as instructed on the Customize with GitHub page
Key_Phrase¶
use the copy button at right, paste into search
The copy button for this exampe is just for practice
Do not paste the result anywhere
To search using the Key_Phrase
(see graphic below for clarification):
- A copy button is available when you hover your mouse in the right-hand side of the block below the title
Key_Phrase
; click on it to copy the phrase - In Xcode, tap the Find menu item and select
Find in Workspace
- Paste the text into the Find search-box that opens on upper left of Xcode screen and hit enter
- If you don't see the phrase in the box, hit backspace - your system copied an extra return
- You should see a message
1 result in 1 file
(for most cases)- Some customizations will show more than one result, but that will be explained in the directions for that customization
- The file in which the line is located is reported showing the line in that file containing the
Key_Phrase
- Click on the one you think is correct and it will display in the main middle window of Xcode with the Keyword highlighted on the line you selected
- The
Key_Phrase
was selected to limit the search to just the relevant line (if possible) - In some cases, the
Key_Phrase
gets you close but not exactly on the line where you need to make the modifications - please read carefully
- The
Module, Folder, File¶
Each customization will also show Module, Folder and File bullet below the key phrase.
- Module: Loop
- Folder: Loop/subfolder1/subfolder2/etc.
- File: filename.swift, line number(s)
Customizations:¶
The customizations below show the original line of code that you will be changing.
There may be a figure illustrating the change.
Below the figure, the original, and in some cases, the modified code will be displayed as text.
- Sometimes that line is long and you may need to use the scroll bar to see the entire line in LoopDocs
- In most cases, an example customization is shown to assist you in deciding how to edit the line to meet your needs
Disable Authentication for Bolusing¶
Depending on your iPhone Settings and model, you may have Face ID or Touch ID enabled. Those security features will also be used to authenticate bolus delivery in Loop. You can choose to disable authentication (i.e., not require Face ID, Touch ID, or passcode for bolusing) through the following code customization.
Safety Measure
If you disable this, you are removing an important safety feature.
In addition to authenticating every manual bolus, this helps to protect against sleep bolusing and pocket bolusing.
For Loop 3, this controls the authorization requirement to modify Therapy Settings as well as to confirm bolus delivery.
canEvaluatePolicy(.deviceOwnerAuthentication
- Module: LoopKit
- Loop 3
- Folder: LoopKit/LoopKitUI/Extensions/
- File: Environment+Authenticate.swift, Line 20
Loop 3¶
Code Before Modification
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
Code After Modification
if false && context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
Loop 2.2.x¶
- Loop 2.2.x
- Folder: Loop/View Controllers
- File: BolusViewController.swift, Line 529
The screenshot below was taken with Loop v2.0 when the line number was 201; with Loop 2.2.x versions, that same code is found at line 529. Add the false &&
as shown in the screenshot below:
Code Before Modification
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) {
Code After Modification
if false && context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) {
Default Carb Absorption Times¶
Loop’s default carb absorption times are based on the high, medium, and low glycemic index absorption curves presented in Think Like A Pancreas by Gary Scheiner. With Loop 2.2.x, the lollipop (fast) icon is set for 2 hours, taco (medium) icon for 3 hours, and pizza (slow) icon for 4 hours. This is modified for Loop 3 to 30 minutes, 3 hours and 5 hours respectively.
defaultCarbAbsorptionTimes: CarbStore.DefaultAbsorptionTimes
- Module: Loop
-
Loop 3
- Folder: Loop/LoopCore
- File: LoopCoreConstants.swift
- Line: 16
-
Loop 2.2.x
- Folder: Loop/LoopCore
- File: LoopSettings.swift
- Line: 16 (2.2.4 master), 41 (2.2.4 AB), 50 (2.2.5 and later)
For example, if you wanted to modify Loop 2.2.9 so that lollipop represents a 30 minute absorption and pizza a 5 hour absorption, the edit would be as follows:
Code Before Modification for Loop 2.2.x
public static let defaultCarbAbsorptionTimes: CarbStore.DefaultAbsorptionTimes = (fast: .hours(2), medium: .hours(3), slow: .hours(4))
Code After Modification or default for Loop 3
public static let defaultCarbAbsorptionTimes: CarbStore.DefaultAbsorptionTimes = (fast: .minutes(30), medium: .hours(3), slow: .hours(5))
Note that if you change from 2 hours to 30 minutes, you must also change the indication before the parentheses.
Adjust Percent Bolus for Automatic Bolus¶
If you are mostly happy with the Dosing Strategy of Automatic Bolus but wish it delivered more or less insulin during every Loop interval, then this customization is for you.
This customization changes the percent of the recommended bolus used for automatic delivery. The method for calculating that recommendation is not changed by this modification. The default value is 40% (0.4). It is recommended you take small changes of 0.1 at a time. Once you modify it once and try it out for a while, it’s easy to go back and change it again.
Change just the number and double check that the value is less than 1.
let bolusPartialApplicationFactor
- Module: Loop
- Loop 3
- Folder: Loop/Loop/Models
- File: LoopConstants.swift
- Line: 53
Code Before Modification
static let bolusPartialApplicationFactor = 0.4
Code After Modification to 50% of recommended insulin
static let bolusPartialApplicationFactor = 0.5
Do not exceed 1.0
This number should never be bigger than 1 (you’d be getting more than Loop recommends). If you think you need more than 1, consider your settings and meal entries.
Modify Override Insulin Needs Picker¶
Some people want finer settings on the override insulin needs picker (5% instead of 10%) and may want to limit the overall range for overrides – especially for children.
1% Settings Available without Customization
With the advent of Loop 3, the Override Insulin Needs values are not limited by the default picker values of 10%.
- Not available in Loop 2.2.x
- Not available in FreeAPS (based off Loop 2.2.x)
- Select 1% Insulin Needs
Any override more than a factor of 2 from 100% can cause Loop predictions to be wrong – especially if a carb count is entered. (An override is NOT the same as a manual temp basal - it changes insulin sensitivity factor and carb ratio in addition to the basal rate needed for zero change in IOB for the duration of the override.)
A Sensitivity of 0% is NOT Valid
Do not set the lower level of the sensitivity range to be 0%.
If you configure to allow that and someone chooses it, they will be telling Loop to divide by zero in some of the calculations. They will see NaN (not a number) in Loop predictions until that override is removed and will continue to see that for the full duration of insulin action (6 hours).
This example customization changes the lower bound for sensitivity to 50% (factor of 2 smaller than 100%) and provides 5% steps.
let allScaleFactorPercentages
- Module: LoopKit
- Folder: LoopKit/LoopKitUI/Views
- File: InsulinSensitivityScalingTableViewCell.swift, Line 19
Code Before Modification
private let allScaleFactorPercentages = Array(stride(from: 10, through: 200, by: 10))
Code After Modification to 50% to 200% by steps of 5%
private let allScaleFactorPercentages = Array(stride(from: 50, through: 200, by: 5))
Modify Maximum and Warning Carb Entry¶
Loop 3 Carb Entry Variables¶
Loop 3 has both a maxCarbEntryQuantity and a warningCarbEntryQuantity, found adjacent to each other in the code. The warning value is the level at which you are asked if you really meant to enter that amount:
let maxCarbEntryQuantity =
- Module: Loop
- Folder: Loop/Loop/Models
- File: LoopConstants.swift, line 18
Code Before Modification
static let maxCarbEntryQuantity = HKQuantity(unit: .gram(), doubleValue: 250) // cannot exceed this value
static let warningCarbEntryQuantity = HKQuantity(unit: .gram(), doubleValue: 99) // user is warned above this value
This first example might be used by a parent for a child with very small carb entries.
Code After Modification to enable the warning at lower levels and limit maximum
static let maxCarbEntryQuantity = HKQuantity(unit: .gram(), doubleValue: 99) // cannot exceed this value
static let warningCarbEntryQuantity = HKQuantity(unit: .gram(), doubleValue: 49) // user is warned above this value
This second example might be used by a person who routinely enters large meals and does not want to be warned with every meal.
Code After Modification to warn if entry is between 201 and 300g
static let maxCarbEntryQuantity = HKQuantity(unit: .gram(), doubleValue: 300) // cannot exceed this value
static let warningCarbEntryQuantity = HKQuantity(unit: .gram(), doubleValue: 200) // user is warned above this value
Loop 2.2.x Max Carb Entry¶
Users of Loop 2.2.9 and earlier or FreeAPS must use the following method for modifying maximum carb entry:
Some people want to limit the maximum number of carbs that can be entered in one entry – especially for children or folks who eat lower carb. This helps prevent accidental typos, e.g., entry of 115 g instead of 15 g for a meal.
maxQuantity =
As shown in the graphic below, this phrase shows up in 2 places, only the first one should be modified.
- Loop 2.2.x
- Folder: Loop/Loop/View Controllers
- File: CarbEntryViewController.swift, Line 33 (Loop 2.2.x)
Code Before Modification
var maxQuantity = HKQuantity(unit: .gram(), doubleValue: 250)
Code After Modification to limit carb entry to 99 g
var maxQuantity = HKQuantity(unit: .gram(), doubleValue: 99)
Pods: Add Extra Insulin on Insertion¶
The default value is 0.0 U of extra insulin. If you use this customization, start with a small number and work your way up. If you are coming from manual podding and routinely gave yourself an extra bolus with your PDM at pod change time, you may not need nearly as much with Loop - be conservative.
Note that Loop does not include the amount of insulin in the prime or insertion steps in your IOB. The pod reports every pulse that it delivers to Loop. If you look in the Pod Settings insulin delivered row, that is the total delivered by the pod minus the (prime plus insertion) amounts. The only way to know that you successfully made this change is to count the clicks. Normal insertion is 0.5 U (0.5 U / 0.05 U per click = 10 clicks). So if you add 0.35 U to the "extra" value, you should get 0.35 / 0.05 = 7 extra clicks. In other words, 17 total clicks after you press insert.
This code change is found in one location for Eros Pods (called Omnipod throughout the app) and DASH Pods (called Omnipod Dash throughout the app). I tend to change both files, but if you're only using one kind of pod, that is really not necessary.
let cannulaInsertionUnitsExtra
- Module: OmniBLE (DASH) or OmniKit (Eros)
- DASH or Eros Pod (Loop 3 only)
- Folder: OmniBLE/OmniBLE/OmnipodCommon (DASH)
- Folder: OmniKit/OmniKit/OmnipodCommon (Eros)
- File: Pod.swift, Line 82 (DASH); Line 87 (Eros);
- Loop 2.2.x: Eros Pod (still configured in rileylink_ios - use Key_Phrase)
Code Before Modification
public static let cannulaInsertionUnitsExtra = 0.0 // edit to add a fixed additional amount of insulin during cannula insertion
Code After Modification to add 0.35 U
public static let cannulaInsertionUnitsExtra = 0.35 // edit to add a fixed additional amount of insulin during cannula insertion
Modify the Guardrails¶
The Therapy Setting Guardrails are for Loop 3 only.
Glucose Guardrails¶
If you build Loop 3 over a version of Loop 2.2.x or FreeAPS where the Correction Range is lower than the default value of 87 mg/dL (4.8 mmol/L), your app requires you to satisfy the new guardrail before you can save that Therapy Setting when you onboard.
Guardrail(absoluteBounds:
- Module: LoopKit
- Folder: LoopKit/Extensions
- File: Guardrail+Settings.swift
- Line: 12 for suspendThreshold
- Line: 26 for correctionRange
Code Before Modification
static let suspendThreshold = Guardrail(absoluteBounds: 67...110, recommendedBounds: 74...80, unit: .milligramsPerDeciliter, startingSuggestion: 80)
and
static let correctionRange = Guardrail(absoluteBounds: 87...180, recommendedBounds: 100...115, unit: .milligramsPerDeciliter, startingSuggestion: 100)
Modify the 67 for suspendThreshold or 87 for correctionRange to the desired value. Loop automatically converts from mg/dL. So you must enter values reasonable for mg/dL (18 times higher than for mmol/L).
Modify Guardrails for Insulin Sensitivity Factor (ISF)¶
Similar to the instructions for glucose guardrails above, but use this Key_Phrase
and modify the absoluteBounds row, next line.
static let insulinSensitivity = Guardrail(
- Module: LoopKit
- Folder: LoopKit/Extensions
- File: Guardrail+Settings.swift, line: 81
Modify Guardrails for Carb Ratio (CR)¶
Similar to the instructions for glucose guardrails above, but use this Key_Phrase
and modify the absoluteBounds row, next line.
static let carbRatio = Guardrail(
- Module: LoopKit
- Folder: LoopKit/Extensions
- File: Guardrail+Settings.swift, line: 88
Adjust Future Carbs Time Interval¶
Loop 3 limits the future time change allowed to 1 hour.
cell.datePicker.maximumDate = date.addingTimeInterval
- Module: Loop
- Folder: Loop/Loop/View Controllers
- File:CarbEntryViewController.swift, Line 438
Default shown below (for maximum and minimum):
Code Before Modification
cell.datePicker.maximumDate = date.addingTimeInterval(.hours(1))
cell.datePicker.minimumDate = date.addingTimeInterval(.hours(-12))
Change the maximumDate to the number of hours in the future you desire. Remember that Loop may increase insulin dosing for future carbs - make sure that they actually arrive.
The minimumDate is how far back in the past you can modify time. The default is 12 hours in the past.
Adjust the Watch Crown Sensitivity¶
The rate of change of the carb and bolus entry pickers when using the digital crown can be altered as can the rotation required to confirm a bolus on the watch. If you are running an older series watch - you may want to make these customizations. When I switched from Series 3 to Series 7 watch - it was amazing. I got a graph on the main watch screen I didn't even know existed and the bolus acceptance was a breeze!
There are a number of places where you need to make changes (2 for sensitivity and 2 for bolus confirmation for Loop 2.2.x), so walk though them one at a time. For the Watch Crown Sensitivity
, the 1/24 value is the ratio of rotations of the crown to the amount of change in the value. Changing it to 1/12 would mean that half as many turns would be needed for the same amount of carb or bolus entry.
- The Loop 2.2.x customizations are throughly tested by many users.
- The Loop 3 customization is provided from code inspection and one test - use with care.
Loop 2.2.x Sensitivity¶
let rotationsPerIncrement
- Folder: Loop/WatchApp Extension/Controllers
- File: AddCarbsInterfaceController.swift, Line: 249
- Initial Value: 1/24; try 1/12 to increase change in picker value for a given motion
let rotationsPerValue
- Folder: Loop/WatchApp Extension/Controllers
- File: BolusInterfaceController.swift, Line: 191
- Initial Value: 1/24; try 1/12 to increase change in picker value for a given motion
Loop 2.2.x Bolus Confirmation¶
In order to reduce the amount the user has to spin the watch crown to confirm a bolus, there are 3 numbers on 2 lines that must be modified. You will be working in the same file you just used to modify the watch sensitivity to adjusting the bolus amount, BolusInterfaceController.swift.
For example to change rotation required to 70% of the default, change 1.0 to 0.7 in 3 places on those 2 lines. This Key_Phrase
returns 3 lines, the second 2 of which are the ones in that file where the change is required:
abs(accumulatedRotation)
- Folder: Loop/WatchApp Extension/Controllers
- File: BolusInterfaceController.swift, Lines: 311 and 360
- Initial Value: 1.0; try 0.7 to decrease how much is needed to confirm bolus
Loop 3 Digital Crown Adjustments¶
These are new instructions and the user should take care - and please report back if you have problems.
First - try it with no customization. Then make small changes.
This key phrase will indicate three different files in the same folder as shown in the graphic below - you can adjust each in turn as you desire. When you click on the line, the quantity you change is a few lines below where you find the Key_Phrase
, except for the CarbAndDateInput file.
.digitalCrownRotation
- Module: Loop
- Folder: Loop/WatchApp Extension/Views/Carb Entry & Bolus
Modify Bolus Confirmation Motion¶
- File: BolusConfirmationView.swift, line 59
- Initial Value for
scalingRotationBy
is 4 - Decrease to require less motion to confirm bolus (use whole numbers only), start with 3
Modify Bolus Picker Sensitivity¶
- File: BolusInput.swift, line 53
- Initial Value for
rotationsPerIncrement
is 1/24 - A change to 1/12 increases the change in picker value for a given motion
Modify Carb and Time Picker Sensitivity¶
- File: CarbAndDateInput.swift, line 68
- Initial Value for
rotationsPerIncrement
is 1/24 - A change to 1/12 increases the change in picker value for a given motion
Expiration Notification Customization¶
An expiration notification feature has been added to Loop. You get a notification when you open the Loop app to alert you that the expiration is approaching. (Not available with version v2.2.4 and earlier.)
- Read Loop App Expiration Notification to see the expiration reminder
- Read Loop App Expiration Date if you have an older version of Loop
If you prefer a different notification time and frequency, there are two lines you can modify:
- Module: Loop
- Folder: Loop/Managers
- File: ProfileExpirationAlerter.swift
- Line 16: modify how long before expiration you get the FIRST notification
- Line 28: modify how frequently you will be notified
expirationAlertWindow: TimeInterval
minimumTimeBetweenAlerts: TimeInterval
Default code for line 16:
static let expirationAlertWindow: TimeInterval = .days(20)
Example modifications to First Notification:
- 30 days: change
.days(20)
to.days(30)
- 12 hours: change
.days(20)
to.hours(12)
Default code for line 28:
let minimumTimeBetweenAlerts: TimeInterval = timeUntilExpiration > .hours(24) ? .days(2) : .hours(1)
Modify Frequency of Repeated Notifications (Three Values):
- This phrase:
> .hours(24) ? .days(2) : .hours(1)
- Rewritten as:
> Time_A ? Frequency_A : Frequency_B
, means:- Use Frequency_A if there is more time between now and the expiration date than Time_A
- Use Frequency_B if there is less time between now and the expiration date than Time_A
You can enter Time or Frequency as .days(value)
, .hours(value)
or .minutes(value)
.
Free App Users:
An example change that a Free Loop App user (who has to build once a week) might choose is:
> .hours(4) ? .days(10) : .hours(2)
.hours(12)
on line 16, they would get notified at 12 hours, 4 hours and 2 hours before expiration on the day of expiration and only when the app is opened. Since you'll be building once a week, you can play around with these values until you are happy.
Exponential Insulin Curve¶
Enable Child Model¶
Loop 3, by default, does not include the concept of child versus adult for rapid-acting insulin, i.e., Humalog, Novalog and Apidra.
- The child model can be enabled following the directions in Build-Time Features, adding ADULT_CHILD_INSULIN_MODEL_SELECTION_ENABLED to the LoopConfigOverride.xcconfig file and rebuilding
- Insulin Model is then found in the Therapy Setting section of Loop 3 with Adult selected by default
- Insulin Type continues to be associated with the pump and can be modified in the Pump Settings screen
Insulin Model Customization¶
Each exponential model has 3 parameters that can be adjusted:
- actionDuration: Duration of insulin activity (minutes)
- peakActivity: Peak of insulin activity (minutes)
- delay: Delay before insulin begins to acts after delivery starts (minutes)
Please read the nitty-gritty discussion that went into the development of the "exponential insulin models" in this GitHub Issue Comment.
If you wish to customize these values, please make sure you know what you are doing. This is not a modification recommended for Loop novices.
MARK: - Model generation
- Module: LoopKit
- Loop 3
- Folder: LoopKit/LoopKit/Insulin/ << NOTE new location
- File: ExponentialInsulinModelPreset.swift
- Lines:
- actionDuration (19 to 32)
- peakActivity (34 to 47)
- delay (49 to 62)
- Loop 2.2.x
- Folder: Loop/LoopCore/Insulin
- File: ExponentialInsulinModelPreset.swift
- Lines:
- actionDuration (20 to 29)
- peakActivity (31 to 40)
- effectDelay (42 to 51)
This Loop 3 table of default values is provided for convenience. The times are all in minutes.
Model | DIA | Peak | Delay |
---|---|---|---|
rapidActingAdult | 360 | 75 | 10 |
rapidActingChild | 360 | 65 | 10 |
fiasp | 360 | 55 | 10 |
lyumjev | 360 | 55 | 10 |
afrezza | 300 | 29 | 10 |
Loop Logo¶
Mac-Xcode Instructions
This can be done with GitHub but the instructions might need to be adjusted for that case.
If you want an app logo other than the default green circle for your Loop app, you can easily customize this. To make it easy to generate the correct sizes of icons, you can use a site like appicon.build or appicon.co and just drag and drop your source image. The source image needs to be 1024 pixels x 1024 pixels. The site will email you a zip file or automatically download a set of files. Highlight and copy the contents of the Appicon.appiconset that you are sent, including the Contents.json file
Use Finder to Navigate to the LoopWorkspace folder. These instructions assume you used the Build Select Script - if your files are in a different folder, make the appropriate adjustment.
For Loop 2.2.x:
- Use Finder to navigate to Downloads / BuildLoop and open the folder with the most recent date (e.g., Loop-Master-211006-0524)
- Double-click on the LoopWorkspace folder
- Double-click on the AdditionaAssets.xcassets folder
- Double-click on the CustomLoopIcon.appiconset folder
- Delete the contents of the CustomLoopIcon.appiconset folder and copy/paste your new images and Contents.json file.
- Rebuild your app
For Loop 3:
- Make sure Xcode is closed
- Use Finder to navigate to Downloads / BuildLoop and open the folder with the most recent date (e.g., Loop-230114-1153)
- Double-click on the LoopWorkspace folder
- Double-click on the OverrideAssetsLoop.xcassets folder
- Double-click on the AppIcon.appiconset folder
- Delete the contents of the Appicon.appiconset and copy/paste your new images and Contents.json file.
- Rebuild your app
You may see a yellow warning that there are “unassigned children” depending on the images the app icon generator tool produced. The unassigned children alert will not prevent your app from building, it’s simply because there are more sizes of images than Loop app uses. You can just leave the unassigned children alone (wow...how often do you get to say that phrase?).
And now you'll be the proud new owner of a custom Loop icon.
Additional Customizations for Loop 3¶
Some customizations on this page add support for Libre sensors. If you are willing to build a dev branch, then Libre support is already added to that version. Please read Support for Libre Sensors.
If you want to add these customizations: CustomTypeOne LoopPatches and clients for xDrip4iOS and GlucoseDirect, which assist those using Libre sensors, you can add them yourself (with either Mac-Xcode or GitHub browser build method).
Open a Terminal in LoopWorkspace Folder¶
Refer to the graphic below. The Downloads folder in Finder is highlighted on the upper left. The full path to Loop.xcworkspace is highlighted along the bottom. Double clicking on that file opens Xcode; but to apply customizations, you need to type commands in the terminal.
- Open Finder
- Navigate to Downloads/BuildLoop and look for your download by name and date
- Open that folder, for example, Downloads/BuildLoop/Loop-220803-1145
- Find the LoopWorkspace folder icon (dashed-blue rectangle)
- Hold down the CTRL key and click (or right-click) LoopWorkspace
- A menu appears - select
New Terminal at Folder
(near the bottom of the list)
This new terminal window is ready to accept commands as needed when the instructions say to start a terminal in the LoopWorkspace folder.
To confirm you are in the correct location, type pwd
and return in the terminal. The response must end in LoopWorkspace. For example, using the graphic below, the response to pwd
should be similar to:
/Users/marion/Downloads/BuildLoop/Loop-20220803-1145/LoopWorkspace
Custom Type One LoopPatches¶
If you do not already use this set of customizations, please do not start.
Several items were consolidated into a set of patches known as CustomTypeOne LoopPatches. The easiest way to get CustomTypeOne LoopPatches is to use the Loop and Learn: Customization Select Script. This script can be used with either Mac-Xcode or GitHub Browser build methods.
Please read the documentation and test any patch that you enable. These patches don't have the nice guardrails found in Loop 3 and must be configured at the iOS Settings, Loop interface. They cannot be adjusted inside the Loop app.
Although special versions of Custom Type One LoopPatches are supplied via the Customization Select Script that are compatible with the dev branch and will be compatible with Loop 3.4.x, it is strongly recommended that if you don't already use these patches - do not start. The support for some features has already been replaced with features inside Loop that will be standard with Loop 3.4, and other changes are expected in the future.
Libre Support for Loop 3.2.x Code¶
Libre included in dev branch
Libre support is now included in dev branch, which will soon be released as Loop 3.4.
If you are willing to build Loop-dev, you do not need any of these customizations to use a compatible Libre sensor.
Add Libre App to Loop Phone¶
LibreTransmitter for Loop is already included in the dev branch. README file on github repository. If you Build Loop-dev, you do not need to add a Libre app to your phone.
You must do your own research to decide which code to use. Be aware that you must perform careful calibrations to maintain accurate glucose estimates.
These are Libre iOS app options that work with Loop 3.2.x. In other words, you install one of these CGM apps on your phone and modify Loop 3.2.x to interface with the CGM app using a shared App Group.
- xDrip4iOS: Documentation
- Check to see if your sensor is compatible
- To use this code with Loop, you must "build it yourself" with the same developer ID as you use with Loop
- You can use the Loop and Learn: Build Select Script and choose Option 2: Build Related Apps and then select xDrip4iOS
- If you use the TestFlight installation method with someone else's apple developer id, you will need an internet connection to Loop
- GlucoseDirect: README file on github repository
- To use this code with Loop, you must "build it yourself" with the same developer ID as you use with Loop
- You can use the Loop and Learn: Build Select Script and choose Option 2: Build Related Apps and then select GlucoseDirect
- If you use the TestFlight installation method with someone else's apple developer id, you will need an internet connection to Loop
- To use this code with Loop, you must "build it yourself" with the same developer ID as you use with Loop
Modify Loop to use Libre¶
These customizations are only for Loop 3.2.x. They do not work for the dev branch, soon to be released as Loop 3.4.
For your selected app to read the Libre, you must also add a client to Loop 3.2.x to interface with the "reader" app. You only need to add the client for the app you've chosen for accessing your Libre sensor. However, you may find watching the video for GlucoseDirectClient and reading the step-by-step instructions for xdrip-client-swift or LibreTransmitter may together give you a better idea how to incorporate your preferred app with Loop 3.2.x.
Add a client that interfaces with xDrip4iOS:
- Add xdrip-client-swift to Loop 3.2.x
- Note - there are extra details visible when you click on the black arrow icons in this file
- zulipchat converstation
Add a client that interfaces with GlucoseDirect:
- Add GlucoseDirectClient
- zulipchat conversation
- The instructions are in the video on the GlucoseDirectClient repo page
LibreTransmitter¶
LibreTransmitter is included in Loop dev and will be in Loop 3.4 when it is released:
- LibreTransmitter for Loop: README file on github repository
- LibreTransmitter is incorporated into Loop directly, so there not a separate app to be installed
- See BuildLoopDev Script
Limit Loop for Faster CGM¶
The released code of Loop 3 (3.0.0 through 3.2.3) allows Loop to run at higher rates of CGM updates. One consequence of this can be increased usage of pump batteries. This can contribute to pod faults with Eros pods or even DASH pods when using a Libre sensor with 1-minute CGM updates. Medtronic pumps are very unhappy with faster Loop cycles and should not be subjected to this.
This modification limits the period for Loop cycles to 4.2 minutes or longer. See also Loop and Learn: Customization List.
If your CGM updates at 1-minute rates, please add this customization
This customization is consistent with the code currently in the dev branch, soon to be released as Loop 3.4.
This is only needed for Loop 3.2.2 and earlier versions.
- When building with Mac-Xcode, copy the command (below), paste into a terminal window on the Mac and choose
Limit CGM driven Loop Cycle to 5 minutes
:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/loopandlearn/lnl-scripts/main/CustomizationSelect.sh)"
- When using GitHub Browser build, please refer to Loop and Learn: Code Customization: Prepared Customizations
Folders and Icons¶
The folders listed in the code customization steps are the actual directory names as stored on your computer. However, a shortened name is used for some folders when being displayed as icons in Xcode. Some people prefer to search through the folder icons to find a file instead of using the Find in Workspace
feature.
In the graphic below, the user searched for an item found for both Eros and DASH pods (in two different files). The top part of the graphic shows the result of the search with user clicking on one instance. On the right side of the top graphic (highlighted by red rectangle) is the name of the selected file on the computer with the full directory name.
- Inset 1: User clicked on the folder icon (highlighted by red square) to see the list of icons for folders included in the LoopWorkspace
- Inset 2: User opens folders under RileyLink icon to open OmniKit, then OmnipodCommon to find the Pod.swift file (NOTE - the Eros information is in a different Module now, OmniKit, but the graphic has not been updated.)
These folder icon names are different from the directory names on the computer:
Folder Icon Name | Directory Name | |
---|---|---|
ShareClient | dexcom-share-client-swift | |
RileyLink | rileylink_ios | |
Amplitude | Amplitude-iOS |
All other icons and directory names match.