Skip to content

Conversation

@ps2
Copy link

@ps2 ps2 commented Aug 27, 2020

ps2 and others added 30 commits July 18, 2019 16:57
* Update carthage to use g6 hotfix

* Bump version for hotfix release

* Use CGMBLEKit v3.1
* Updating genstrings, Adding new localizable.strings, adding some new translations to existing languages

* cleaning up unused files and adding Vietnamese, Swedish, Danish, Finnish, Japanese, Portuguese (BRA)

* typos and minor missing translations.

* cleanup unnecessary .strings and typo fixes

* Adding Romanian

* Italian updates

* Danish translations

* German touchups

* Finnish touchups

* Japanese and French touchups

* Norwegian, dutch, Portuguese, Romanian, russian, swedish, vietnamese, and chinese finished

* polish

Co-authored-by: Pete Schwamb <pete@schwamb.net>
* Track cgm device when uploading BG data

* Bump carthage revs
…olds

Include current bg for suspend threshold and dosing thresholds
@ps2 ps2 changed the title Ps2/loop 1689/diy sync Sync from DIY Aug 27, 2020
Copy link

@nhamming nhamming left a comment

Choose a reason for hiding this comment

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

LGTM

Comment on lines -1 to +6
github "LoopKit/LoopKit" "dev"
github "LoopKit/CGMBLEKit" "dev"
github "LoopKit/LoopKit" "merge-from-tidepool"
github "LoopKit/CGMBLEKit" "merge-from-tidepool"
github "i-schuetz/SwiftCharts" == 0.6.5
github "LoopKit/dexcom-share-client-swift" "dev"
github "LoopKit/G4ShareSpy" "dev"
github "ps2/rileylink_ios" "dev"
github "LoopKit/dexcom-share-client-swift" "merge-from-tidepool"
github "LoopKit/G4ShareSpy" "merge-from-tidepool"
github "ps2/rileylink_ios" "merge-from-tidepool"
Copy link

Choose a reason for hiding this comment

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

[nit] why not dev here?

Copy link
Author

Choose a reason for hiding this comment

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

This is an artifact of me making the tidepool -> diy merge available for DIY testers to try out using the normal build method (non-workspace) that most DIYers use.

Tidepool doesn't use this file in its builds at all, so I'd just treat this as noise for now.

Copy link

@rickpasetto rickpasetto left a comment

Choose a reason for hiding this comment

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

I've added a few questions I would love to know the answers to before I approve this.

Similar comment as my LoopKit review: I'd feel more comfortable if there were unit tests covering the changes made.


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

private var isAfterFirstUnlock: Bool {

Choose a reason for hiding this comment

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

Yay!

[super-nit] it always felt a teeny bit weird to me that this was computed variable with a side-effect of writing a file. IMHO I'd change it to

private func isAfterFirstUnlock() -> Bool {

let fileURL = documentDirectory.appendingPathComponent("protection.test")
guard fileManager.fileExists(atPath: fileURL.path) else {
let contents = Data("unimportant".utf8)
try? contents.write(to: fileURL, options: .completeFileProtectionUntilFirstUserAuthentication)

Choose a reason for hiding this comment

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

IIRC, I think in my work around this I replaced this try? with a try. Seems safe enough to do...WDYT?

Choose a reason for hiding this comment

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

Yea, I don't think this works. This entire function is to see if we have access to the local file system (thus indicating after first unlock).

Unless the let documentDirectory = try fileManager.url throws when it is locked (and I don't think it does), then the rest won't work. The fileExists call would return false (by definition, because we don't have access to the local file system before first unlock), the guard clause would be executed, the try? contents.write would do nothing (because of the try?) and it would return true. We'd need to change the try? to try to make this work.

Furthermore, I'd change let contents = try? Data to just try and let it throw. And then update the log.error message in the catch to be more accurate.

If let documentDirectory = try fileManager.url does throw when it is locked, then the rest of the function (and writing/reading the file) is unnecessary.

Choose a reason for hiding this comment

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

@darinkrauss are you saying you don't think my suggestion works, or you think this whole code change won't work?

I'm not 100% sure I agree you can guarantee that fileExists will fail because the file system is unavailable. See the following note in the docs:

It’s far better to attempt an operation (such as loading a file or creating a directory), check for errors, and handle those errors gracefully than it is to try to figure out ahead of time whether the operation will succeed.

Therefore, that's why I suggest try instead of try? when writing to the file. Otherwise any potential error/exception thrown (admittedly very unlikely, but we never know across versions of iOS) will be ignored.

(P.S. Way back when I was working on this, I am pretty sure I tested this code extensively and it worked...)

Choose a reason for hiding this comment

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

Sorry I wasn't more clear. Yes, your fix is what will make it work. That is, changing the try? to try.

Copy link
Author

Choose a reason for hiding this comment

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

The file existence check here does work before first unlock; this makes sense as individual files can have different access levels applied to them. The logic here is known to be working, and very hard to test; it requires specific minor versions of iOS that I don't know if we can actually install anymore. So I am loathe to make any changes.

@rickpasetto, you were not able to reproduce actually launching Loop before first unlock, iirc, so I don't know how you could've tested any changes to this.

The way it's written right now is that it will tend to launch if there are unexpected changes in iOS behavior. I think this is what we want. The preventative measure is in place and works if we see the same behavior that we saw in some versions of iOS 11 and early versions of 12. If we see other behavior, we'll have to deal with that. We have word from Apple that launching via bluetooth before unlock was a bug, and this code addresses that situation specifically.

Choose a reason for hiding this comment

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

Huh, well, I don't see how it would logically, but perhaps it is throwing some non-Swift exception from fileExists or write, but then why would the Swift catch actually catch it? The difficulty I have is with try? contents.write in that it just silently fails. 🤷‍♂️

Copy link

@rickpasetto rickpasetto Sep 8, 2020

Choose a reason for hiding this comment

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

@ps2 At some point, I was. It was months ago now, though. I just don't recall...maybe I had tested on iOS 12? 🤷‍♂️

At any rate, I agree that this is "bulletproofing" code. I see no reason why changing the try? to a try is a problem, but this is not something I'll lie down on the tracks for, so if you feel strongly about not changing it I'd yield.

Copy link
Author

@ps2 ps2 Sep 8, 2020

Choose a reason for hiding this comment

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

The try? contents.write isn't where we're checking for before/after first unlock; that's the code that is run if we're in the first run of the app, and we decide to create the file for later use. If it fails, there's not much we can do, and we should continue on launching the app.

Choose a reason for hiding this comment

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

If that try fails, we can log an error if it fails (indeed, there's already a catch for this). If we ever see it, we would know the behavior changed (e.g. an iOS version change modified the behavior somehow).

let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
deviceLog = PersistentDeviceLog(storageFile: documentsDirectory.appendingPathComponent("DeviceLog.sqlite"), maxEntryAge: localCacheDuration)
let deviceLogDirectory = documentsDirectory.appendingPathComponent("DeviceLog")
deviceLog = PersistentDeviceLog(storageFile: deviceLogDirectory.appendingPathComponent("Storage.sqlite"), maxEntryAge: localCacheDuration)

Choose a reason for hiding this comment

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

After this change goes in, doing an Issue Report won't return any (old) device logs. (That is, this effectively starts the logging over). Is that ok?

Copy link
Author

Choose a reason for hiding this comment

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

For Tidepool, yes, since we do not have any live users. For DIY, this is the way it has always been, since the change was made before any DIY code was released.


let percentEffected = 1 - model.percentEffectRemaining(at: time)
// For 0 <= time <= effectDelay, assume a small amount effected. This will result in large unit recommendation rather than no recommendation at all.
let percentEffected = Swift.max(.ulpOfOne, 1 - model.percentEffectRemaining(at: time))

Choose a reason for hiding this comment

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

Is there an associated unit test for this change?

Copy link
Author

Choose a reason for hiding this comment

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

The tests in DoseMath did change for this, and cover this code.

let tempBasal = predictedGlucose.recommendedTempBasal(
to: glucoseTargetRange,
at: now(),
at: predictedGlucose[0].startDate,

Choose a reason for hiding this comment

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

Hm... this looks like a significant change to me. Is there an explanation I can read? A unit test?

Copy link
Author

Choose a reason for hiding this comment

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

Here is the original PR for this fix: LoopKit#1235. There is also some discussion in the linked issue.

The change aligns LoopDataManager more with what was being tested as well. The tests for recommendedTempBasal almost exclusively use the date of the first predicted glucose (which is current bg).

Copy link

@darinkrauss darinkrauss left a comment

Choose a reason for hiding this comment

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

Mostly nits, a few questions, but some concerns for you to look at. Setting as "Request changes" since there may be some required, but let me know otherwise.

let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
let fileURL = documentDirectory.appendingPathComponent("protection.test")
guard fileManager.fileExists(atPath: fileURL.path) else {
let contents = Data("unimportant".utf8)

Choose a reason for hiding this comment

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

[nit] Write empty data?

Copy link
Author

Choose a reason for hiding this comment

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

Not sure what you're asking here.

Choose a reason for hiding this comment

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

Sorry, rather than writing the string "unimportant" just write Data(). No big deal, though.

let fileURL = documentDirectory.appendingPathComponent("protection.test")
guard fileManager.fileExists(atPath: fileURL.path) else {
let contents = Data("unimportant".utf8)
try? contents.write(to: fileURL, options: .completeFileProtectionUntilFirstUserAuthentication)

Choose a reason for hiding this comment

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

Yea, I don't think this works. This entire function is to see if we have access to the local file system (thus indicating after first unlock).

Unless the let documentDirectory = try fileManager.url throws when it is locked (and I don't think it does), then the rest won't work. The fileExists call would return false (by definition, because we don't have access to the local file system before first unlock), the guard clause would be executed, the try? contents.write would do nothing (because of the try?) and it would return true. We'd need to change the try? to try to make this work.

Furthermore, I'd change let contents = try? Data to just try and let it throw. And then update the log.error message in the catch to be more accurate.

If let documentDirectory = try fileManager.url does throw when it is locked, then the rest of the function (and writing/reading the file) is unnecessary.

runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n echo \"Bootstrapping carthage dependencies\"\n unset LLVM_TARGET_TRIPLE_SUFFIX\n if ! cmp -s Cartfile.Resolved Carthage/Cartfile.resolved; then\n time /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds --verbose\n cp Cartfile.resolved Carthage\n else\n echo \"Carthage: not bootstrapping\"\n fi\nfi\n";
shellScript = "if [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n echo \"Bootstrapping carthage dependencies\"\n unset LLVM_TARGET_TRIPLE_SUFFIX\n if ! cmp -s Cartfile.Resolved Carthage/Cartfile.resolved; then\n time /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds\n cp Cartfile.resolved Carthage\n else\n echo \"Carthage: not bootstrapping\"\n fi\nfi\n";

Choose a reason for hiding this comment

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

@rickpasetto Do we need the --verbose flag on Carthage bootstrap for Circle CI to not timeout? I forgot why the flag was added in the first place.

Choose a reason for hiding this comment

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

@darinkrauss IIRC this was put here for TravisCI, not CircleCI. CircleCI's timeout is configurable (and set for 30 min). That said, I don't mind leaving this in. If you feel strongly, we can remove it in a later PR.

Choose a reason for hiding this comment

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

This PR removes it, and I'm good with that. 👍

Copy link
Author

Choose a reason for hiding this comment

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

I think I was having problems with Travis thinking the log was too big. 🙄

Copy link

@darinkrauss darinkrauss left a comment

Choose a reason for hiding this comment

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

LGTM! 🚀

Copy link

@rickpasetto rickpasetto left a comment

Choose a reason for hiding this comment

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

LGTM

@ps2 ps2 merged commit 74bafb9 into dev Sep 10, 2020
@ps2 ps2 deleted the ps2/LOOP-1689/diy-sync branch October 20, 2020 17:32
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.