Emit device ids in lower-case on every platform (breaking, next major) - #270
Open
postmaxin wants to merge 1 commit into
Open
Emit device ids in lower-case on every platform (breaking, next major)#270postmaxin wants to merge 1 commit into
postmaxin wants to merge 1 commit into
Conversation
Follow-up to the case-insensitive matching in Navideck#269 (2.1.1): make the emitted case consistent too. Device ids are now canonicalised to lower-case throughout the Dart layer — every scan result, callback and stream carries the lower-case form regardless of the case the platform reports (Android upper-cased MACs, Windows/WinRT lower-cased them). Native BLE calls still need the platform's case (Android's getRemoteDevice REQUIRES upper-case; Apple's peripheral cache, Windows' address parse and Linux's BlueZ address are upper-case too), so the platform implementations convert back at their boundary — a single `_nativeId` helper in the pigeon channel, and one line in the Linux instance's device lookup. No Kotlin / Swift / C++ changes. This also lets the Navideck#269 stream matching collapse from a dual-case compare to a single lower-case one. BREAKING: callers that stored/compared an emitted id by exact case must now lower-case it (or compare case-insensitively). For the next major release. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR standardizes BLE device IDs to a single canonical form in the Dart layer by lower-casing them on ingestion and ensuring all emitted IDs from streams/callbacks are lower-case, while converting back to the native-required case at platform boundaries (Pigeon channel + Linux BlueZ lookup). This is a breaking change intended for the next major release and is documented in the changelog.
Changes:
- Canonicalize device IDs to lower-case in
UniversalBlePlatformupdate handlers and simplify stream matching to a single lower-case compare. - Upper-case device IDs at the Dart→native boundary for Pigeon platform operations, and normalize Linux device lookup to BlueZ’s expected case.
- Add tests asserting lower-case emission from update handlers; update changelog and example lockfile.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/device_id_case_insensitivity_test.dart | Adds tests asserting lower-case emission from update* handlers. |
| lib/src/universal_ble_pigeon/universal_ble_pigeon_channel.dart | Introduces _nativeId() and applies it to Pigeon native calls; keeps emitted IDs lower-case. |
| lib/src/universal_ble_linux/universal_ble_linux.dart | Normalizes Linux device lookup by upper-casing IDs before BlueZ resolution. |
| lib/src/interfaces/universal_ble_platform_interface.dart | Canonicalizes IDs to lower-case on ingestion and simplifies stream filters accordingly. |
| example/pubspec.lock | Bumps the path-dependency version recorded for the example app. |
| CHANGELOG.md | Documents the breaking change for “next major”. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| // Device ids are lower-case throughout the Dart layer (see UniversalBlePlatform), but the native side wants | ||
| // the upper-case form — Android's BluetoothAdapter.getRemoteDevice REQUIRES upper case, and Apple's peripheral | ||
| // cache / Windows' address parse / Linux's BlueZ address are upper-case too. Convert here, at the boundary. | ||
| String _nativeId(String deviceId) => deviceId.toUpperCase(); |
Comment on lines
+6
to
+8
| // Device ids are lower-case throughout the Dart layer (see UniversalBlePlatform), but the native side wants | ||
| // the upper-case form — Android's BluetoothAdapter.getRemoteDevice REQUIRES upper case, and Apple's peripheral | ||
| // cache / Windows' address parse / Linux's BlueZ address are upper-case too. Convert here, at the boundary. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #269 (merged in 2.1.1): make the emitted device-id case consistent too — the fully-universal, breaking version discussed there for the next major.
What changes
Device ids are now canonicalised to lower-case throughout the Dart layer and emitted lower-case on every platform (scan results + connection / value / pairing / connection-parameter callbacks and streams). Previously each platform reported its native case — Android upper-cased MACs, Windows/WinRT lower-cased them — so a caller holding the id in the "wrong" case could split state or (before #269) miss events.
How — Dart-only, no Kotlin / Swift / C++ changes
update*handlers lower-case on ingestion, so every event, callback and per-device map key is lower-case. This also lets Match device ids case-insensitively across event streams #269's dual-case stream matching collapse to a single lower-case compare.getRemoteDevicerequires upper-case and throws otherwise; Apple's peripheral cache is keyed by the upper-caseuuidString, Windows parses the address either way, Linux's BlueZ address is upper-case), so the platform implementations convert back at their boundary: a single_nativeId()helper at the pigeon-channel native-op sites, and one line in the Linux instance's device lookup (the single point every Linux op funnels through).Note the native side receives the same upper-case id it always has — it's just reconstructed at the Dart boundary now instead of being supplied by the caller — so native behaviour is unchanged.
Breaking
Callers that stored or compared an emitted id by exact case (e.g. an Android upper-case MAC) must now lower-case it, or compare case-insensitively.
CHANGELOGupdated under "next major".Testing
flutter test) andflutter analyzeis clean — including 5 new tests asserting lower-case emission from everyupdate*handler, with the existing Match device ids case-insensitively across event streams #269 case-insensitive-matching / dedup / cache tests still green.connect()) at this branch and confirmed the whole path: scan →connect()→ auth → characteristic streaming → and the reconnect/self-heal path. That's exactly the round-trip this change relies on — Android'sgetRemoteDevicethrows on a lower-case MAC, so a successful connect proves the boundary conversion is doing its job.Developed with AI assistance (noted via the commit's
Co-Authored-Bytrailer).