Skip to content

wip: Eversense E3 integration with AndroidAPS #4474

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

wip: Eversense E3 integration with AndroidAPS #4474
n0rb33r7 wants to merge 5 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

@CAPTCG
Copy link
Copy Markdown

CAPTCG commented Apr 13, 2026

Update — April 2026 (AAPS 4.0 migration, E365 cloud upload fixes, new plugin repo)

This is a summary of the latest two commits pushed to this PR.


Commit 1: Sync Eversense plugin and migrate to AAPS 4.0 notification API

  • AAPS 4.0 notification API — all Eversense notifications migrated to the new NotificationManager API used by the compose-based dev branch
  • Sync from AndroidAPSEversenseCoexist — brought in all fixes accumulated on the stable master branch into this dev branch, including:
    • BLE reconnect with exponential backoff (5s → 10s → 20s → 40s → 60s cap) to win the boot race against the official Eversense app on E3 devices
    • New enum classes: BatteryLevel, CalibrationFlag, CommandError, SignalStrength, TransmitterAlert
    • New E3 packets: GetAlertLogPacket, GetBleDisconnectPacket, GetCalibrationLogPacket, GetCalibrationLogRangePacket, GetCompletedCalibrationsCountPacket, GetGlucoseAlertsAndStatusPacket, GetGlucoseLogPacket, GetGlucoseLogRangePacket, GetIsOneCalPhasePacket, PingPacket, SetBloodGlucosePointPacket, interval packets
    • New E365 packets: GetAlertsLogValuesPacket, GetCalibrationLogValuesPacket, PushAlarmWithDataPacket, PushKeepAlive365Packet
    • MessageCoder utility for BLE message encoding/decoding
    • E365 OAuth2 cloud upload (EversenseHttp365Util) with getOrRefreshToken and 5-minute pre-expiry token refresh
    • 13 HTTP unit tests + 29 packet/calibration unit tests (42 total)
  • Missing string resource — added eversense_reconnecting string that was referenced but absent (caused a crash on reconnect)

Commit 2: E365 cloud upload and calibration notification fixes

  • TransmitterId fix — the DMS PostEssentialLogs API requires the full transmitter name (e.g. T313576), not just the raw serial number bytes. Fixed Eversense365Communicator to store transmitterName from the BLE GetSensorInformationPacket and pass it as TransmitterId
  • Timestamp fix — upload timestamps now use UTC with Z suffix (was local time with no timezone info)
  • Backfill skip — readings with an empty rawResponseHex (backfill entries) are now excluded from cloud upload; only live readings with a full BLE response are uploaded
  • Calibration Due notification — when calibration is overdue, the plugin now shows a "Calibration Due Now" notification instead of incorrectly showing "Transmitter Error"

Easy integration — CAPTCG/EversensePlugin

To make it easier for others to add the Eversense plugin to their own AndroidAPS fork without cloning this entire PR, I've created a standalone plugin-only repository:

https://github.com/CAPTCG/EversensePlugin

It contains only the Eversense plugin files (no full AndroidAPS build), with two branches:

Branch For AndroidAPS version
master AndroidAPS 3.4.x stable
dev AndroidAPS dev (compose)

Each branch has the complete plugins/eversense/ module, the Eversense source plugin files, and 9 small patch files for the existing AAPS files that need Eversense entries added. The README has step-by-step instructions.

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