8000 feat(sensor): add CBio/SIBIONICS GS1 evidence lane by shroominic · Pull Request #120 · shroominic/OpenGlucose · GitHub
[go: up one dir, main page]

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ expectations are defined in [docs/compatibility.md](docs/compatibility.md).

### Added

- Add a `cgm_cbio` GS1 scaffold, pure `FF30` discovery mapping, synthetic
contract/frame tests, offline plaintext inspection, and SiSensing UUID/protocol
evidence. The package has no
transport, app registration, authentication, or glucose support. Record a
separately authorized Mac bench probe in the evidence document.
- Add a private Android Gen1 Libre 2 receiver path with an explicitly initiated
NFC streaming exchange, encrypted receiver state, durable login counters,
exact-target Bluetooth connection, and CRC-validated packet diagnostics.
Expand Down
10 changes: 10 additions & 0 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ The public API of a package is the surface exported from its top-level library:
- `package:cgm_core/cgm_core.dart`
- `package:cgm_ble/cgm_ble.dart`
- `package:cgm_aidex/cgm_aidex.dart`
- `package:cgm_cbio/cgm_cbio.dart` (offline, target-unverified scaffold)
- `package:cgm_libre2/cgm_libre2.dart`
- `package:cgm_libre2_glucose/cgm_libre2_glucose.dart` (separate GPL bench decoder)
- `package:cgm_yuwell_anytime/cgm_yuwell_anytime.dart`
Expand Down Expand Up @@ -104,6 +105,15 @@ last-verified release/date. A shared name, service UUID, or demo-driver result
alone is not compatibility evidence. Protocol changes should remain tolerant
of unknown data while failing safely on malformed or unauthenticated input.

`cgm_cbio` 0.0.1 is a Cbio GS1 scaffold with pure `FF30` discovery mapping.
Matches are unverified Cbio / SiSensing candidates because GS1 and GS3 share
the UUID. It declares no sensor capabilities and fails scan/connect without transport
access. It is not registered in any app build. Local SiSensing GS1/GS3 APK
evidence and a Mac GATT connection do not prove glucose compatibility. The
offline plaintext parser returns raw ACK/record fields, never normalized
glucose; unsupported layouts and unknown counter wrap fail closed. See the
[offline evidence record](testing/cbio-gs1-offline.md).

`cgm_libre2` includes a target-unverified, explicitly bootstrapped Gen1 BLE
receiver. Android private debug builds can use a journaled NFC streaming
operation and encrypted receiver state to select the exact target, reserve
Expand Down
13 changes: 13 additions & 0 deletions docs/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ See [NOTICE.md](../NOTICE.md) for distribution guidance and
[docs/compatibility.md](compatibility.md) for dependency-related support-floor
changes.

## Offline Cbio GS1 scaffold

`cgm_cbio` uses only the existing in-repository `cgm_core` and `cgm_ble`
contracts, plus the existing `lints` and `test` development tools. The package
is MIT, unpublished, and has no native components, permissions, network
destinations, telemetry, build scripts, credentials, or persistent data.
It imports no vendor library or al 8000 gorithm. Offline resolution uses the local
Pub cache; no new external package is introduced. The app manifest and lockfile
are unchanged. Library lockfiles stay uncommitted. Remove the scaffold and its
workspace enumeration to roll back; no sensor or storage migration is needed.
Exact-model protocol and licensing review are still required before adding
any vendor-derived implementation.

## Private Libre Gen1 receiver integration

The application depends on the in-repository `cgm_libre2` package; that
Expand Down
2,154 changes: 2,154 additions & 0 deletions docs/testing/cbio-gs1-offline.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/cgm_cbio/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/pubspec.lock
16 changes: 16 additions & 0 deletions packages/cgm_cbio/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Changelog

## 0.0.1

- Reserve the `cbio` driver contract for offline GS1 research.
- Add app-derived `FF30` discovery candidates and `FF31`/`FF32` UUID constants.
- Keep all capabilities false and fail scan/connect without transport access.
- Add strict offline plaintext ACK and packed-record inspection, with synthetic
integrity, bounds, bit-field, and counter tests. Raw fields have no assigned units.
- Add synthetic contract tests. No live protocol or glucose support is claimed.
- Add separate offline `08` raw-data, `F0/04` storage, and `F0/03` time parsers
with exact frame bounds and synthetic rejection tests. Preserve the existing
generic frame parser contract; no units, epoch, or sensor-state meaning is inferred.
- Add separate offline `F0/02` activation-state and expected `07`/`03` ACK
inspection. Preserve all state/result bytes without granting write permission;
test state/control separation and zero-history fields with synthetic fixtures.
21 changes: 21 additions & 0 deletions packages/cgm_cbio/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 OpenGlucose contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
61 changes: 61 additions & 0 deletions packages/cgm_cbio/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# cgm_cbio

Pure Dart scaffold for the Cbio GS1 / SiSensing investigation. Version 0.0.1
has pure discovery mapping and offline frame inspection. It cannot scan,
connect, authenticate, activate, publish glucose, or change a sensor.

`CbioSensorDriver` reserves driver ID `cbio` and implements `CgmDriver`.
Both I/O entry points fail with `CbioProtocolUnavailableException`; a scan
failure is not reported as a successful scan with no devices. The constructor
has no transport. All capabilities are false. `CbioDiscovery` maps advertisements
with service `FF30` to an unverified Cbio / SiSensing candidate. The UUID is
shared by the GS1 and GS3 apps; it does not identify the exact sensor model.
`CbioUuids` also records `FF31` receive and `FF32` command characteristics.
Name-only matches, characteristic-only matches, and empty device IDs are rejected.

The package is not registered in the app. The registry requires a nonempty
service list; use `CbioDiscovery.scanServiceUuids` for a future explicit bench
composition. Candidate metadata cannot open a session. See the [registry map and RE evidence](../../docs/testing/cbio-gs1-offline.md)
for the macOS integration point and remaining work.

Dependencies are only the existing `cgm_core` and `cgm_ble` contracts. There
is no Flutter, native binary, FFI, network, storage, or cryptography dependency.
The implementation contains no vendor-derived algorithm or source.

`parseCbioPlaintextFrame` inspects a complete, already-decrypted V120 frame.
It separates five-byte acknowledgements from packed `0A` record batches and
checks byte range, exact length/count, checksum, and counter bounds. It retains
raw ACK status and raw packed record fields; it does not infer success, units,
epoch, or a `CgmReading`. It contains no key, decryption, fragment assembly,
command writer, automatic retry, or sensor identifier. Only synthetic fixtures
are used in tests. Vendor format observations are recorded in the evidence doc.

Separate offline entry points inspect `08` raw-data batches,
`F0/04` storage replies, and `F0/03` time replies:
`parseCbioRawDataFrame`, `parseCbioStorageFrame`, and `parseCbioTimeFrame`.
These require complete plaintext data frames and reject control ACKs. Raw
records retain temperature/current/dump integers plus packed fields; none is
converted to a physical unit. Time fields have no assigned epoch, and storage
status is not interpreted. The existing `CbioFrame` hierarchy and generic
parser acceptance remain unchanged. These entry points do not select firmware,
send queries, or authorize a live read.

`parseCbioActivationFrame` separately reads the five-byte `F0/02` state reply
and preserves its raw byte without an active/inactive enum.
`parseCbioStartAckFrame` checks an explicitly expected `07` activation or `03`
clock-update ACK and retains unknown result/status values. These inspect bytes
only. The package contains no activation/clock builder or live write path.

Run package checks from this directory with the pinned Dart SDK:

```sh
dart pub get --offline
dart format --output=none --set-exit-if-changed lib test
dart analyze --fatal-infos
dart test
```

Root workspace checks also enumerate this package. Test inputs are synthetic.
The evidence record covers the separately authorized Mac bench probe. A live
protocol and glucose compatibility remain unverified. OpenGlucose is
wellness/reference software, not a diagnosis or treatment system.
5 changes: 5 additions & 0 deletions packages/cgm_cbio/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include: package:lints/recommended.yaml

linter:
rules:
avoid_print: true
5 changes: 5 additions & 0 deletions packages/cgm_cbio/lib/cgm_cbio.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// Offline Cbio GS1 research boundary. No sensor compatibility is claimed.
library;

export 'src/cbio_driver.dart';
export 'src/cbio_frames.dart';
74 changes: 74 additions & 0 deletions packages/cgm_cbio/lib/src/cbio_driver.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import 'package:cgm_ble/cgm_ble.dart';
import 'package:cgm_core/cgm_core.dart';

/// UUID candidates recovered from both SiSensing GS1 and GS3 Java payloads.
/// Shared UUIDs do not establish a sensor model or protocol compatibility.
abstract final class CbioUuids {
static const String service = '0000ff30-0000-1000-8000-00805f9b34fb';
static const String receive = '0000ff31-0000-1000-8000-00805f9b34fb';
static const String command = '0000ff32-0000-1000-8000-00805f9b34fb';
}

/// Pure candidate mapping; performs no Bluetooth operations.
final class CbioDiscovery {
const CbioDiscovery();

static const List<String> scanServiceUuids = <String>[CbioUuids.service];

DiscoveredSensor? mapScanResult(BleScanResult result) {
final matches = result.serviceUuids.any((uuid) {
final normalized = uuid.trim().toLowerCase();
return normalized == CbioUuids.service ||
normalized == 'ff30' ||
normalized == '0000ff30';
});
if (!matches || result.deviceId.trim().isEmpty) return null;
return DiscoveredSensor(
driverId: 'cbio',
deviceId: result.deviceId,
displayName: 'Cbio / SiSensing candidate',
storageKey: result.deviceId,
rssi: result.rssi,
capabilities: CbioSensorDriver.capabilities,
notes: 'FF30 service candidate. Sensor model and protocol unverified.',
metadata: const {'cgm.cbio.discovery': 'ff30-candidate'},
);
}
}

/// A reserved driver contract for offline work, with no transport access.
///
/// This scaffold deliberately accepts no [BleTransport]. Neither direct calls
/// nor restored sensor metadata can start radio operations. Registration in a
/// physical scan registry still needs a separate live implementation and
/// target verification. Discovery candidates cannot enable a live session.
final class CbioSensorDriver implements CgmDriver {
const CbioSensorDriver();

static const CgmCapabilities capabilities = CgmCapabilities();

@override
String get driverId => 'cbio';

@override
Stream<DiscoveredSensor> scan({
Duration? timeout,
bool allowDuplicates = true,
}) =>
Stream<DiscoveredSensor>.error(const CbioProtocolUnavailableException());

@override
Future<CgmSession> connect(DiscoveredSensor sensor) =>
Future<CgmSession>.error(const CbioProtocolUnavailableException());
}

/// An identifier-free failure, distinct from an empty successful scan.
final class CbioProtocolUnavailableException implements Exception {
const CbioProtocolUnavailableException();

String get diagnosticCode => 'cgm.cbio.protocol-unavailable';

@override
String toString() =>
'CbioProtocolUnavailableException: Cbio GS1 live protocol is unavailable.';
}
Loading
Loading
0