Skip to content

Conversation

@bjorkert
Copy link
Contributor

@bjorkert bjorkert commented Aug 7, 2025

Description

This pull request implements the client-side functionality for receiving real-time status notifications for remote commands sent to Trio or Loop. This complements the backend changes and completes the feature, allowing users to get immediate push notification feedback confirming the success or failure of their actions.

To achieve this, the app is now capable of:

  1. Registering for and receiving push notifications from Apple's Push Notification Service (APNS).
  2. Constructing a return_notification payload to attach to every outgoing remote command.
  3. Handling scenarios where Loop Follow and the target app (Trio/Loop) are built with different Apple Developer Team IDs.

Technical Implementation

1. Push Notification Registration and Handling

  • AppDelegate: The app now registers for remote notifications on launch. New delegate methods have been implemented to:
    • Securely capture and store the device token from APNS upon successful registration.
    • Log any registration failures.
    • Receive and process incoming feedback notifications from Trio, displaying them as alerts to the user even when the app is in the foreground.
  • Project Configuration: The project's .entitlements and Info.plist files have been updated with the required aps-environment and remote-notification background mode capabilities, which are necessary for receiving push notifications.

2. Dynamic Return Payload Creation

  • A new method, createReturnNotificationInfo(), has been added to the LoopAPNSService and PushNotificationManager. This method is now called before any remote command is sent.
  • It constructs a return_notification object containing all the information the remote peer (Trio) needs to send a notification back to this specific Loop Follow app instance. This payload includes:
    • The Loop Follow app's unique device token.
    • The build environment (production/development).
    • The necessary APNS credentials (Team ID, Key ID, and APNS Key).

3. Support for Mismatched Developer Teams

A core part of this implementation is handling cases where Loop Follow is built with a different Apple Developer account than the target Loop/Trio app.

  • Build Script: The build script now captures the DEVELOPMENT_TEAM ID at compile time and stores it in BuildDetails.swift.
  • Conditional Logic: The app compares its own Team ID against the Team ID of the target remote app.
  • New Configuration UI: If the Team IDs are different, a new "Return Notification Settings" section dynamically appears in the Remote Settings view. This prompts the user to enter the APNS Key and Key ID associated with their Loop Follow developer account. These credentials are then used exclusively for the return notification path, ensuring that Trio can authenticate correctly to send the feedback notification. If the Team IDs are the same, the primary APNS credentials are reused for the return path, and no extra configuration is needed.

@bjorkert
Copy link
Contributor Author

bjorkert commented Aug 7, 2025

Companion PR: The server-side implementation for this feature can be found in the Trio repository: nightscout/Trio#740

@bjorkert
Copy link
Contributor Author

bjorkert commented Aug 8, 2025

I've pushed the latest updates to this PR, which now implements end-to-end encryption flow for remote commands.

Instead of sending the shared secret for verification, I now use it as a key to encrypt the entire command payload. Here are the technical details of the implementation:

Encryption Algorithm: I've implemented this using AES-256-GCM. The GCM (Galois/Counter Mode) is important because it's an authenticated encryption mode, meaning it not only ensures confidentiality but also provides data integrity, protecting against tampering.

Key Derivation: The encryption key is derived from the existing shared secret (the GUID). I pass the secret through a SHA-256 hash to produce the consistent 256-bit key required for the AES algorithm.

Nonce Handling: For each message sent, a new, cryptographically secure 12-byte nonce (Initialization Vector) is generated. This ensures that even identical commands result in unique ciphertext.

Authentication: The shared secret is no longer sent over the network. Authentication is now implicit: if Trio can successfully decrypt the payload, the sender is proven to be authentic.

Important: This is a breaking change. Current versions of LoopFollow and Trio dev will not be compatible with these new versions. Both apps must be updated together for the remote control feature to work.

@bjorkert bjorkert marked this pull request as ready for review August 8, 2025 19:56
@bjorkert bjorkert requested a review from marionbarker August 11, 2025 11:36
@bjorkert
Copy link
Contributor Author

Important step for Browser Builders: Now that LF receives push notifications, you need to enable the Push Notifications capability at the Apple Developer site.

@marionbarker
Copy link
Collaborator

marionbarker commented Sep 4, 2025

Test

Trio PR 740 and LoopFollow PR 445 were tested together

Summary:

  • Tests were successful
  • It is a breaking change so the merge of PR at Trio and LoopFollow must be coordinated
  • This needs to be announced before merging and the LoopFollowDocs should have a PR ready to merge as well

Comment:

  • There is no notification on the Trio phone when a remote command comes in and no notification of who it's from

Test Results

For these tests, Trio and LoopFollow are on the same phone, SE 3rd gen running iOS 18.6.2

  • Trio is using rPi DASH simulator

The tests consisted of sending Remote Bolus from LoopFollow to Trio.
The Notifications, which show up as Banners at top of screen, were configured to be persistent so I can read them and then swipe them up to see the next one.
Define terms:

  • LFN = LoopFollow Notification
  • Trio Action = Trio took action in response to remote

✅ LoopFollow Modal says OK - message got the Apple successfully, Trio successfully got the message, LFN bolus initiating, LFN properly reported result from Trio phone (success or failure with reason)
❌ Trio did not get the message or LFN was not received

Summary Table for Bolus Remote Commands

Trio LoopFollow Modal Trio Action LFN initiating LFN result
dev .23 3.2.0 N/A N/A
PR 740 3.2.0 N/A N/A
PR 740 PR 445
dev .23 PR 445

Detailed Tests Remote Commands

Configure so Trio and LoopFollow are on 2 different phones.

  • Trio PR 740 still on SE 3rd gen with rPi DASH
  • LoopFollow PR 445 is on SE 2nd gen

Status:
OK - both phones are unlocked
Off - Trio phone is powered off

Trio Phone is available

Status Remote Modal Trio Action LFN initiating LFN result
OK 2 g carb N/A
OK 0.25 U bolus
OK 0.25 U bolus pump disconnected failed to enact bolus
OK 0.2 U bolus already bolusing failed to enact bolus
OK Temp Target N/A
OK Override N/A

Trio Phone is off

When LoopFollow Modal says OK, it means the message got the Apple successfully. There is no response if Trio phone is offline.

Status Remote Modal Trio Action LFN initiating LFN result
Off 5 g carb Off N/A -
Off 0.25 U bolus Off - -
Off Temp Target Off N/A -
Off Override Off N/A -
Reboot 0.25 U bolus Not unlocked, Trio not active - -
On, Open Trio 0.25 U bolus

codebymini added a commit to CodeByMiniOrg/LoopFollow that referenced this pull request Sep 30, 2025
Copy link
Collaborator

@marionbarker marionbarker left a comment

Choose a reason for hiding this comment

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

I did all the testing and review (see #445 (comment)).

Checking the approval box now. The timing for this needs to be coordinated with Trio and LoopFollowDocs

@marionbarker
Copy link
Collaborator

Test

Repeat Test because of intervening merges to both Trio and LoopFollow.

Summary: Trio, with PR 740 merged, and LoopFollow, with PR 445 merged, still provide the updates described in this PR.

The updates for Trio, LoopFollow and LoopFollowDocs need to be coordinated - this will happen via direct messaging between developers.

Test Details

Repeat Test because of intervening merges to both Trio and LoopFollow.

Configuration:

  • LoopFollow phone is iPhone 8 running iOS 16.7.11
  • Trio phone is SE 2nd gen running iOS 18.7
  • Before starting the truth table below, issue and confirm remote Meal, Bolus, Temp Target and Override work with current configuration of Trio 0.5.1.28 and LoopFollow 3.2.8
  • To generate the truth table, it is sufficient to issue a bolus
  • Finish up with configuration of Trio with PR 740, LoopFollow with PR 445
    • Confirm remote Meal, Bolus, Temp Target and Override work as expected
    • Include reported error case where Trio phone pod is not connected
    • Include reported error case where Trio phone is already bolusing when remote bolus is issued

The tests consisted of sending Remote Bolus from LoopFollow to Trio.
The Notifications, which show up as Banners at top of screen, were configured to be persistent so I can read them and then swipe them up to see the next one.
Define terms:

  • LFN = LoopFollow Notification
  • Trio Action = Trio took action in response to remote using Nightscout CGM and rPi DASH pump

✅ LoopFollow Modal says OK - message got to Apple successfully, Trio successfully got the message, LFN bolus initiating, LFN properly reported result from Trio phone (success or failure with reason)
❌ Trio did not get the message or LFN was not received

Summary Table for Bolus Remote Commands

Trio LoopFollow Modal Trio Action LFN initiating LFN result
0.5.1.28 3.2.8 N/A N/A
PR 740 3.2.8 N/A N/A
PR 740 PR 445
0.5.1.28 PR 445

@marionbarker marionbarker changed the title Enable APNS feedback for remote commands Enable APNS feedback to LoopFollow for Trio remote commands Oct 2, 2025
@marionbarker marionbarker merged commit 0154e13 into dev Oct 6, 2025
@marionbarker marionbarker deleted the remote-apns-feedback branch October 6, 2025 22:07
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.

4 participants