Skip to content

Commit

Permalink
Merge pull request #250 from loopandlearn/future-carbs
Browse files Browse the repository at this point in the history
Allow future carbs
  • Loading branch information
marionbarker authored Dec 20, 2023
2 parents 85f00d5 + 519ef9f commit a16f79b
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 74 deletions.
2 changes: 1 addition & 1 deletion Config.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
unique_id = ${DEVELOPMENT_TEAM}

//Version (DEFAULT)
LOOP_FOLLOW_MARKETING_VERSION = 2.1.2
LOOP_FOLLOW_MARKETING_VERSION = 2.1.3
2 changes: 1 addition & 1 deletion LoopFollow/Controllers/Nightscout/CAge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
extension MainViewController {
// NS Cage Web Call
func webLoadNSCage() {
let currentTimeString = dateTimeUtils.getCurrentDateTimeString()
let currentTimeString = dateTimeUtils.getDateTimeString()

let parameters: [String: String] = [
"find[eventType]": NightscoutUtils.EventType.cage.rawValue,
Expand Down
4 changes: 2 additions & 2 deletions LoopFollow/Controllers/Nightscout/SAge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import Foundation
extension MainViewController {
// NS Sage Web Call
func webLoadNSSage() {
let lastDateString = dateTimeUtils.nowMinus60DaysTimeInterval()
let currentTimeString = dateTimeUtils.getCurrentDateTimeString()
let lastDateString = dateTimeUtils.getDateTimeString(addingDays: -60)
let currentTimeString = dateTimeUtils.getDateTimeString()

let parameters: [String: String] = [
"find[eventType]": NightscoutUtils.EventType.sage.rawValue,
Expand Down
5 changes: 2 additions & 3 deletions LoopFollow/Controllers/Nightscout/Treatments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ extension MainViewController {
if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Download: Treatments") }
if !UserDefaultsRepository.downloadTreatments.value { return }

let graphHours = 24 * UserDefaultsRepository.downloadDays.value
let startTimeString = dateTimeUtils.nowMinusNHoursTimeInterval(N: graphHours)
let currentTimeString = dateTimeUtils.getCurrentDateTimeString()
let startTimeString = dateTimeUtils.getDateTimeString(addingDays: -1 * UserDefaultsRepository.downloadDays.value)
let currentTimeString = dateTimeUtils.getDateTimeString(addingHours: 6)
let parameters: [String: String] = [
"find[created_at][$gte]": startTimeString,
"find[created_at][$lte]": currentTimeString
Expand Down
2 changes: 1 addition & 1 deletion LoopFollow/Controllers/Nightscout/Treatments/Carbs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ extension MainViewController {
offset = bolusTime.offset ? 70 : 20
}

if dateTimeStamp < (dateTimeUtils.getNowTimeIntervalUTC() + (60 * 60)) {
if dateTimeStamp < (dateTimeUtils.getNowTimeIntervalUTC() + (3600 * UserDefaultsRepository.predictionToLoad.value)) {
// Make the dot
let dot = carbGraphStruct(value: Double(carbs), date: Double(dateTimeStamp), sgv: Int(sgv.sgv + Double(offset)), absorptionTime: absorptionTime)
carbData.append(dot)
Expand Down
5 changes: 5 additions & 0 deletions LoopFollow/ViewControllers/SettingsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class SettingsViewController: FormViewController {
row.hidden = "$showNS == false"
}.cellSetup { (cell, row) in
cell.textField.autocorrectionType = .no
cell.textField.autocapitalizationType = .none
}.onChange { row in
guard let value = row.value else {
UserDefaultsRepository.url.value = ""
Expand All @@ -104,6 +105,8 @@ class SettingsViewController: FormViewController {
row.hidden = "$showNS == false"
}.cellSetup { (cell, row) in
cell.textField.autocorrectionType = .no
cell.textField.autocapitalizationType = .none
cell.textField.textContentType = .password
}.onChange { row in
if row.value == nil {
UserDefaultsRepository.token.value = ""
Expand Down Expand Up @@ -144,6 +147,7 @@ class SettingsViewController: FormViewController {
row.hidden = "$showDex == false"
}.cellSetup { (cell, row) in
cell.textField.autocorrectionType = .no
cell.textField.autocapitalizationType = .none
}.onChange { row in
if row.value == nil {
UserDefaultsRepository.shareUserName.value = ""
Expand All @@ -159,6 +163,7 @@ class SettingsViewController: FormViewController {
}.cellSetup { (cell, row) in
cell.textField.autocorrectionType = .no
cell.textField.isSecureTextEntry = true
cell.textField.autocapitalizationType = .none
}.onChange { row in
if row.value == nil {
UserDefaultsRepository.sharePassword.value = ""
Expand Down
42 changes: 13 additions & 29 deletions LoopFollow/helpers/DateTime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,42 +57,26 @@ class dateTimeUtils {
return utcTime
}

static func getCurrentDateTimeString() -> String {
let currentTimeInterval = getNowTimeIntervalUTC()
static func getDateTimeString(addingHours hours: Int? = nil, addingDays days: Int? = nil) -> String {
let currentDate = Date()
var date = currentDate

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.timeZone = TimeZone.init(secondsFromGMT: 0)
if let hoursToAdd = hours {
date = Calendar.current.date(byAdding: .hour, value: hoursToAdd, to: currentDate)!
}

let currentDate = Date(timeIntervalSince1970: currentTimeInterval)
let currentTimeString = dateFormatter.string(from: currentDate)
if let daysToAdd = days {
date = Calendar.current.date(byAdding: .day, value: daysToAdd, to: currentDate)!
}

return currentTimeString
}

static func nowMinusNHoursTimeInterval(N: Int) -> String {
let today = Date()
let nHoursAgo = Calendar.current.date(byAdding: .hour, value: -N, to: today)!
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.timeZone = TimeZone.init(secondsFromGMT: 0)
let nHoursAgoString = dateFormatter.string(from: nHoursAgo)
return nHoursAgoString
}

static func nowMinus60DaysTimeInterval() -> String {
let today = Date()
let oldDate = Calendar.current.date(byAdding: .day, value: -10, to: today)!
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.timeZone = TimeZone.init(secondsFromGMT: 0)
let dayString = dateFormatter.string(from: oldDate)
return dayString
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)

return dateFormatter.string(from: date)
}

static func printNow() -> String {
let date = Date()
let formatter = DateFormatter()
Expand Down
76 changes: 39 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ The _display_name_ is found in a single file.
Summary instructions by build method:

* Browser Build:
* Fork and setup the repository for each Loop Follow instance you want to use:
* https://github.com/loopandlearn/LoopFollow
* https://github.com/loopandlearn/LoopFollow_Second
* https://github.com/loopandlearn/LoopFollow_Third
* Commit the desired _display_name_ in the LoopFollowDisplayNameConfig.xcconfig file of your forked repository for LoopFollow, LoopFollow_Second or LoopFollow_Third
* Mac-Xcode Build
* First build with script, you will be prompted to enter the desired _display_name_
Expand All @@ -73,58 +77,56 @@ When modifications and versions are updated, there might be a slight delay for g

Please review the list on [Loop and Learn: Loop Follow](https://www.loopandlearn.org/loop-follow/) which may be updated more frequently than this README.md file.

- scrollable/scalable graph display with BG, basal, bolus, and carb details plus Loop status, Loop Prediction, and the General NS Care portal info.
- Override DND and system volume for all alerts.
- snoozes per alert, presnooze, edit existing snooze, and snooze all alert settings.
- the standard Low/High, Urgent Low/High, and missed reading alerts with additonal option to select persistence; for example, alert when high for x minutes.
- fast drop/rise alerts with BG limits; for example, alert for fast drop only when glucose is below specific value.
- sage/cage reminder alerts for x hours before change.
- Not Looping with glucose limits alert: you can configure the alert if under or over a glucose range.
- Missed Bolus alert.
- calendar entries to use watch complication with BG, arrow, delta, cob, iob and minutes ago (if old reading).
- background silent audio to keep iOS from killing the app. This is why it can’t go in the App Store for just a simple download.
Each time a release is made, the features added or bugs fixed are found at [Loop Follow Releases](https://github.com/loopandlearn/LoopFollow/releases).

Each of the features below is selectable - you decide whether to use them.  Additionally, many features are adjustable because YDMV (your diabetes may vary).

1. Scrollable/scalable graph display with BG, IOB, COB, Basal, Bolus, and the General Nightscout Care portal info
* Supports Glucose display when Dexcom is available but Nightscout is not
* Supports Loop and iAPS when Nightscout URL is provided and Download Loop/iAPS data is enabled (show Nightscout Settings to see the enable slider)
* Loop: Loop status, Loop Prediction
* iAPS: iAPS status, iAPS Prediction lines, Autosens
2. Tap on Alarms on Toolbar to configure.
* Override DND (Do Not Disturb) and system volume for all alerts with a Snooze All Until and a Mute All Until
* List of Alarms covers the standard high/low/rise/fall/urgent glucose but also include alerts for missed glucose readings, if below configured glucose, IOB, COB, Not Looping, Overrides, Pump, Missed Bolus, SAGE, CAGE and Battery
* Each Alarm has configurable settings including Sound selection, PreSnooze (set to be quiet At Night, During Day or Never) and Snooze Until
3. Calendar entries (displayed on watch and/or carplay at 5 minute intervals) pre-formatted with two lines that the user can modify:
* BG, arrow, delta,  MINAGO (minutes ago for reading)
* COB, IOB, Basal (U/hr)
4. Background silent audio is played to keep iOS from killing the app; this trick is why it can’t go into the App Store for a simple download and why Loop Follow puts an extra load on the phone battery
5. Badge displays the current BG value on the app icon
6. Information Display Settings allows user to configure the items selected and their order for the right panel when Nightscout URL is provided
* IOB, COB, Basal, Override, Battery, Pump, SAGE, CAGE, (Recommended) Rec. Bolus, (Glucose Eventually) Pred., Carbs today (Loop and iAPS)
* Autosens (iAPS only)
7. Pull down on the glucose value to force a refresh from Nightscout (iPhone only - does not work on Mac)
8. When adding a Nightscout site, NS Status says "Checking", "Site Not Found", "Token Required", "Invalid Token", or "OK"
9. New with v2.1.2: Multiple Loopers (up to 3) are easily supported with either Browser Build or Mac-Xcode build
10. New with v2.1.2: The app name (displayed on phone) can be customized when building
* If enabled, that custom name will be displayed on the main Loop Follow display

### Open Source DIY
- This is a DIY open source project that may or may not function as you expect. You take full responsibility for building and running this app and do so at your own risk.

## For Developers

> * If you are interested in assisting with this app and want to work on new features and improvements for Loop, iAPS and Nightscout functionality, please reach out.
> * Issues and Pull Requests in GitHub are monitored and will get a response.
> * Please always direct your PR to the dev branch.
## Versions

### Versions

We added version numbers that are incremented with each pull request (or group of pull requests) merged.

New PR are directed to the dev branch. If you direct one to main, we will move it to point to dev. So always start with your code aligned with dev.
We added version numbers to Loop Follow. Typically the main branch and dev branch are at the same version, but when work is underway, the dev branch may have different code, which we try to indicate with a different version number.

The versioning is:

* major.minor.micro
* For example our first version is 2.0.0

After a PR is merged to dev, the repository maintainers will bump up the verion number before merging to main - please do not modify the version in your branch.
For the most part, the deveopers keep main and dev branches at the same level. But sometimes we want to combine several PR or keep a modification in dev for additional testing.

For the most part, the deveopers keep main and dev branches at the same level. But sometimes we want modification to remain in dev for additional testing.
## For Developers

#### Version Example
> * If you are interested in assisting with this app and want to work on new features and improvements for Loop, iAPS and Nightscout functionality, please reach out.
> * Issues and Pull Requests in GitHub are monitored and will get a response.
Starting with version 2.1.0
New PR are directed to the dev branch. If you direct one to main, we will move it to point to dev. So always start with your code aligned with dev.

* PR with Feature A gets merged to dev
* Maintainers, bump dev to 2.1.0
* Maintainers merge dev into main
* both main and dev are at 2.1.0
* PR with Feature B gets merged to dev
* Maintainers, bump dev to 2.1.1
* main is still at 2.1.0
* PR with Feature C gets merged to dev
* Maintainers, bump dev to 2.1.2
* main is still at 2.1.0
* Maintainers merge dev into main
* both main and dev are at 2.1.2
After a PR is merged to dev, the repository maintainers will bump up the verion number before merging to main - please do not modify the version in your branch.

#### Version Updates

Modify the LOOP_FOLLOW_MARKETING_VERSION in Config.xcconfig file to change the version reported by Loop Follow.
Only the maintainers for Loop Follow will update version numbers. This is done by incrementing the LOOP_FOLLOW_MARKETING_VERSION in Config.xcconfig file.

0 comments on commit a16f79b

Please sign in to comment.