Skip to content

wip: Eversense E3 integration with AndroidAPS #4474

Open
n0rb33r7 wants to merge 4 commits intonightscout:devfrom
n0rb33r7:dev
Open

wip: Eversense E3 integration with AndroidAPS #4474
n0rb33r7 wants to merge 4 commits intonightscout:devfrom
n0rb33r7:dev

Conversation

@n0rb33r7
Copy link
Copy Markdown

@n0rb33r7 n0rb33r7 commented Jan 6, 2026

No description provided.

@bastiaanv
Copy link
Copy Markdown

bastiaanv commented Jan 6, 2026

Some screenshots:

image

I think this needs to be improved, but it has the relevant items for now

image

Proof the E3 can run multiple hours in perfect environment.

Current Todo's:

  • Eversense 365 support
  • Calibrations & calibration history
  • Alert history
  • Backfill
  • Reconnect mechanism
  • Translations

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Jan 9, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots

See analysis details on SonarQube Cloud

1 similar comment
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots

See analysis details on SonarQube Cloud

@CAPTCG
Copy link
Copy Markdown

CAPTCG commented Apr 1, 2026

Calling for build testers

This PR has been significantly updated — rebased on the latest dev branch (April 1, 2026) and builds successfully. It supports both Eversense E3 (180-day) and Eversense 365 (1-year) transmitters.


Eversense E3/365 — Usage Guide

⚠️ The Eversense CGM integration is experimental.

Wait until initialization phase is completed
During the initialization phase after insertion of a new sensor, glucose readings may be incorrect. Complete the initialization phase using the official Eversense app before using automated insulin delivery.

The transmitter connects to only one app at a time
The security protocol does not support multiple simultaneous connections.

Switching from Official Eversense app → AAPS:

  • In the official app, go to Connections → tap the Transmitter → select Disconnect
  • In AAPS, choose Eversense, log in, then select your transmitter
  • If pairing for the first time, you may need to put the transmitter into pairing mode

Switching from AAPS → Official Eversense app:

  • In AAPS, go to Settings → CGM → tap Release for Official App
  • In the official app, go to Connections → tap the Transmitter → select Connect

Pairing:

  • E3: Select the correct transmitter name (see SN on the bottom of your transmitter), accept the Android pairing prompt if shown, and wait for pairing to complete
  • 365: Requires internet connection and Eversense account credentials during pairing (needed to fetch security keys). Log in, select the correct transmitter, accept the pairing prompt, and wait for pairing to complete

To test: clone n0rb33r7/AndroidAPS, checkout the dev branch, build the full flavor in Android Studio.

Please report back:

  • Does the transmitter connect?
  • Are glucose readings received correctly?
  • Does the placement guide work?
  • Any crashes or unexpected behavior?

Thank you!

@CAPTCG
Copy link
Copy Markdown

CAPTCG commented Apr 4, 2026

Update: E3 protocol fixes, forced sync, dark mode improvement, and unit tests

Protocol fix — GetCalibrationPhasePacket & GetCalibrationReadinessPacket
Both packets were incorrectly annotated with ReadTwoByteSerialFlashRegisterCommandId/ResponseId. The E3 calibration phase and readiness registers are single-byte values and must use ReadSingleByteSerialFlashRegisterCommandId/ResponseId. This caused getStartIndex() to return the wrong offset, meaning parseResponse() was reading from the wrong position in receivedData. This would have resulted in incorrect calibration state on real E3 hardware.

Force sync — EversenseE3Communicator & EversenseCGMPlugin
EversenseE3Communicator.fullSync() has a 270-second (4.5 min) throttle guard that returns early if lastSync is too recent. Added a force: Boolean = false parameter that bypasses this guard when true. EversenseCGMPlugin.triggerFullSync() updated with the same parameter, propagating force through to fullSync(). EversensePlugin now calls triggerFullSync(force = true) when the user taps the Last Synchronisation preference, ensuring manual sync always executes regardless of throttle state.

TOO_SOON dark mode — EversensePlugin & strings.xml
The calibration action preference summary was rendering the raw enum name TOO_SOON as plain text, which has poor contrast against dark backgrounds in the Android preference UI. The summary now uses a dedicated string resource eversense_calibration_too_soon ("⏳ Too soon — calibration already done in the past 2 hours") with an explicit TOO_SOON branch in the when expression, separate from the generic readiness.name fallback for other non-READY states.

Unit tests — CalibrationPacketTest
Added GetCalibrationPhasePacketTest and GetCalibrationReadinessPacketTest covering:

  • All valid enum values for CalibrationPhase (7 cases) and CalibrationReadiness (11 cases)
  • Unknown/out-of-range byte values falling back to UNKNOWN
  • Empty receivedData returning null from parseResponse()
  • @EversensePacket annotation verified to use ReadSingleByteSerialFlashRegisterCommandId/ResponseId on both classes

Tests use JUnit 5 via the existing test-module-dependencies plugin, added to plugins/eversense/build.gradle.kts.

@CAPTCG
Copy link
Copy Markdown

CAPTCG commented Apr 11, 2026

Update — Eversense Plugin Sync (April 2026)

E365 Cloud Upload

  • Added EversenseHttp365Util with OAuth2 token management (getOrRefreshToken, 5-minute pre-expiry refresh) and uploadGlucoseReadings POSTing a bare JSON array to /api/v1.0/DiagnosticLog/PostEssentialLogs
  • EssentialLog field is base64-encoded raw BLE bytes (correct System.Byte[] format)
  • Upload gated by an Enable Eversense Data Upload toggle (E365 only); optional toast notification on result
  • Credentials and notification sections hidden when an E3 transmitter is linked

BLE Boot Race Fix

  • Exponential backoff for reconnect after GATT errors (e.g. status 133 - device busy when official app connects first on reboot): 5s -> 10s -> 20s -> 40s -> 60s cap, resets on successful connection
  • Status 19 (transmitter rejected) uses a fixed 30s; clean disconnects retry in 5s

Bug Fixes

  • Fixed duplicate onCGMRead callbacks - addWatcher was called in both init{} and onStart(); added matching removeWatcher in onStop()
  • Fixed CalibrationPhase.fromE3() - values 2 and 3 were swapped
  • Fixed login() missing conn.doOutput = true, causing ProtocolException on every POST

New Packets and Utils

  • PushAlarmWithDataPacket, PushKeepAlive365Packet, GetAlertsLogValuesPacket, GetCalibrationLogValuesPacket
  • MessageCoder utility
  • StorageKeys: added ACCESS_TOKEN, ACCESS_TOKEN_EXPIRY, SECURE_STATE

Dev Branch Compatibility

  • Plugin updated to work with the AAPS dev branch — uses NotificationManager API, BgSourceComposeContent, and corrected Gradle dependencies

Tests

  • 13 unit tests for EversenseHttp365Util via MockWebServer covering token caching, refresh, login, upload success/failure, empty list, and no-token skip

CAPTCG added 4 commits April 11, 2026 10:49
- Add plugins:eversense module with full BLE driver for E3 and 365 transmitters
- Add EversensePlugin integrating with AAPS BgSource interface
- Add placement guide activity with 500ms signal polling
- Add calibration activity
- Add Bluetooth permission request activity
- Add EVERSENSE_E3 and EVERSENSE_365 to SourceSensor and GlucoseValue enums
- Add Eversense notification IDs to NotificationId enum
- Register plugin in SourceModule, PluginsListModule and settings.gradle
- Use new AAPS NotificationManager API for all notifications
- Support both Eversense E3 (180-day) and Eversense 365 (1-year) transmitters
Full sync of all Eversense-related code:
- Complete eversense module: build.gradle.kts, manifest, proguard, all
  source files (callbacks, enums, models, e3/e365 packets, utils, crypto)
- E365 cloud upload: EversenseHttp365Util with token management,
  uploadGlucoseReadings (base64 EssentialLog, bare JSON array body)
- BLE reconnect exponential backoff: 5s→10s→20s→40s→60s cap for GATT
  errors; 30s for status-19 (transmitter rejection); 5s for clean disconnect
- EversensePlugin: cloud upload toggle, toast notifications, E3/E365
  section visibility gating, duplicate watcher registration fix
- Unit tests: EversenseHttp365UtilTest (13 tests via MockWebServer),
  CalibrationPacketTest (29 tests)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Remove deprecated kotlin-android plugin from eversense build.gradle.kts

Add serialization BOM to eversense build.gradle.kts

Update EversensePlugin to use dev branch NotificationManager and BgSourceComposeContent

Fix EversensePlugin for dev branch - use NotificationManager and BgSourceComposeContent

Fix Config parameter, remove advancedFilteringSupported, fix blockingGet

Add missing eversense_reconnecting string resource
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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.

3 participants