unified-ble-manager 4.0.23 → 4.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +113 -3
- package/MIGRATION_4.0.md +1 -1
- package/README.md +2 -2
- package/RELEASE.md +20 -3
- package/SBOM.cdx.json +4 -4
- package/THIRD_PARTY_LICENSES.json +1 -1
- package/android/build.gradle +4 -0
- package/android/src/main/java/com/sfourdrinier/unifiedblemanager/protocol/UnifiedBleProtocolAndroidDispatcher.kt +32 -15
- package/android/src/main/java/com/sfourdrinier/unifiedblemanager/radio/OwnedAndroidGattRadio.kt +480 -144
- package/android/src/test/java/com/sfourdrinier/unifiedblemanager/protocol/UnifiedBleProtocolAndroidDispatcherLifecycleTest.kt +300 -19
- package/android/src/test/java/com/sfourdrinier/unifiedblemanager/protocol/UnifiedBleProtocolAndroidDispatcherRadioIngressTest.kt +216 -0
- package/docs/BONDING.md +32 -32
- package/docs/ELECTRON.md +1 -1
- package/docs/EXPO_PLUGIN.md +1 -1
- package/docs/GAPS.4.0.md +1 -1
- package/docs/GETTING_STARTED.md +4 -3
- package/docs/NODE.md +1 -1
- package/docs/README.md +3 -0
- package/docs/TUTORIALS.md +2 -0
- package/docs/UNIFIED_SEMANTICS.md +4 -2
- package/docs/WEB.md +1 -1
- package/docs/generated/PLATFORM_SUPPORT.md +1 -1
- package/ios/Owned/OwnedCoreBluetoothProtocolRadio.swift +15 -11
- package/ios/Owned/OwnedCoreBluetoothProtocolRadioCancellation.swift +62 -0
- package/ios/Owned/OwnedCoreBluetoothProtocolRadioSupport.swift +71 -0
- package/lib/commonjs/backend-contract/errors.js +16 -0
- package/lib/commonjs/backend-contract/errors.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-backend-runtime.js +2 -0
- package/lib/commonjs/backends/bluez/bluez-backend-runtime.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-connection-runtime.js +304 -23
- package/lib/commonjs/backends/bluez/bluez-connection-runtime.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-property-waiters.js +4 -5
- package/lib/commonjs/backends/bluez/bluez-property-waiters.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-runtime-models.js +29 -0
- package/lib/commonjs/backends/bluez/bluez-runtime-models.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-runtime-types.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-scan-runtime.js +132 -10
- package/lib/commonjs/backends/bluez/bluez-scan-runtime.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-security.js +10 -7
- package/lib/commonjs/backends/bluez/bluez-security.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-subscription-runtime.js +31 -22
- package/lib/commonjs/backends/bluez/bluez-subscription-runtime.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-gatt-operations.js +12 -5
- package/lib/commonjs/backends/corebluetooth/corebluetooth-gatt-operations.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-read-notify-provenance.js +89 -0
- package/lib/commonjs/backends/corebluetooth/corebluetooth-read-notify-provenance.js.map +1 -0
- package/lib/commonjs/backends/reactnative/react-native-android-security.js +32 -21
- package/lib/commonjs/backends/reactnative/react-native-android-security.js.map +1 -1
- package/lib/commonjs/backends/winrt/winrt-backend.js +17 -3
- package/lib/commonjs/backends/winrt/winrt-backend.js.map +1 -1
- package/lib/commonjs/backends/winrt/winrt-gatt-operations.js +10 -4
- package/lib/commonjs/backends/winrt/winrt-gatt-operations.js.map +1 -1
- package/lib/commonjs/backends/winrt/winrt-handles.js +2 -1
- package/lib/commonjs/backends/winrt/winrt-handles.js.map +1 -1
- package/lib/commonjs/backends/winrt/winrt-security.js +43 -24
- package/lib/commonjs/backends/winrt/winrt-security.js.map +1 -1
- package/lib/commonjs/backends/winrt/winrt-subscription-runtime.js +130 -28
- package/lib/commonjs/backends/winrt/winrt-subscription-runtime.js.map +1 -1
- package/lib/commonjs/core/bounded-stream.js +20 -10
- package/lib/commonjs/core/bounded-stream.js.map +1 -1
- package/lib/commonjs/core/core-discovery.js +4 -0
- package/lib/commonjs/core/core-discovery.js.map +1 -1
- package/lib/commonjs/core/core-lifecycle-observer.js +46 -0
- package/lib/commonjs/core/core-lifecycle-observer.js.map +1 -1
- package/lib/commonjs/core/owned-bounded-stream.js +4 -4
- package/lib/commonjs/core/owned-bounded-stream.js.map +1 -1
- package/lib/commonjs/core/unified-ble-core.js +260 -94
- package/lib/commonjs/core/unified-ble-core.js.map +1 -1
- package/lib/commonjs/electron/connection-event-stream-registry.js +4 -1
- package/lib/commonjs/electron/connection-event-stream-registry.js.map +1 -1
- package/lib/commonjs/electron/renderer-stream-registry.js +4 -1
- package/lib/commonjs/electron/renderer-stream-registry.js.map +1 -1
- package/lib/commonjs/implementation-version.js +1 -1
- package/lib/commonjs/ipc/manager.js +39 -1
- package/lib/commonjs/ipc/manager.js.map +1 -1
- package/lib/commonjs/ipc/public-manager.js +23 -10
- package/lib/commonjs/ipc/public-manager.js.map +1 -1
- package/lib/commonjs/native-protocol/rn-android-boundary.js +10 -0
- package/lib/commonjs/native-protocol/rn-android-boundary.js.map +1 -1
- package/lib/commonjs/public/ble-manager.js +152 -46
- package/lib/commonjs/public/ble-manager.js.map +1 -1
- package/lib/commonjs/public/cleanup.js +1 -0
- package/lib/commonjs/public/cleanup.js.map +1 -1
- package/lib/commonjs/public/scan-state.js +46 -0
- package/lib/commonjs/public/scan-state.js.map +1 -1
- package/lib/commonjs/public/streams.js +12 -7
- package/lib/commonjs/public/streams.js.map +1 -1
- package/lib/commonjs/tck/first-party/winrt-tck-registration.js +5 -0
- package/lib/commonjs/tck/first-party/winrt-tck-registration.js.map +1 -1
- package/lib/commonjs/testing/deterministic/deterministic-stream.js +16 -5
- package/lib/commonjs/testing/deterministic/deterministic-stream.js.map +1 -1
- package/lib/commonjs/web/navigator-web-bluetooth-boundary.js +20 -0
- package/lib/commonjs/web/navigator-web-bluetooth-boundary.js.map +1 -1
- package/lib/commonjs/web/web-bluetooth-backend.js +135 -6
- package/lib/commonjs/web/web-bluetooth-backend.js.map +1 -1
- package/lib/commonjs/web.js.map +1 -1
- package/lib/module/backend-contract/errors.js +15 -0
- package/lib/module/backend-contract/errors.js.map +1 -1
- package/lib/module/backends/bluez/bluez-backend-runtime.js +3 -1
- package/lib/module/backends/bluez/bluez-backend-runtime.js.map +1 -1
- package/lib/module/backends/bluez/bluez-connection-runtime.js +305 -25
- package/lib/module/backends/bluez/bluez-connection-runtime.js.map +1 -1
- package/lib/module/backends/bluez/bluez-property-waiters.js +4 -6
- package/lib/module/backends/bluez/bluez-property-waiters.js.map +1 -1
- package/lib/module/backends/bluez/bluez-runtime-models.js +27 -0
- package/lib/module/backends/bluez/bluez-runtime-models.js.map +1 -1
- package/lib/module/backends/bluez/bluez-runtime-types.js.map +1 -1
- package/lib/module/backends/bluez/bluez-scan-runtime.js +133 -11
- package/lib/module/backends/bluez/bluez-scan-runtime.js.map +1 -1
- package/lib/module/backends/bluez/bluez-security.js +10 -7
- package/lib/module/backends/bluez/bluez-security.js.map +1 -1
- package/lib/module/backends/bluez/bluez-subscription-runtime.js +31 -22
- package/lib/module/backends/bluez/bluez-subscription-runtime.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-gatt-operations.js +12 -5
- package/lib/module/backends/corebluetooth/corebluetooth-gatt-operations.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-read-notify-provenance.js +79 -0
- package/lib/module/backends/corebluetooth/corebluetooth-read-notify-provenance.js.map +1 -0
- package/lib/module/backends/reactnative/react-native-android-security.js +32 -21
- package/lib/module/backends/reactnative/react-native-android-security.js.map +1 -1
- package/lib/module/backends/winrt/winrt-backend.js +17 -3
- package/lib/module/backends/winrt/winrt-backend.js.map +1 -1
- package/lib/module/backends/winrt/winrt-gatt-operations.js +12 -6
- package/lib/module/backends/winrt/winrt-gatt-operations.js.map +1 -1
- package/lib/module/backends/winrt/winrt-handles.js +2 -1
- package/lib/module/backends/winrt/winrt-handles.js.map +1 -1
- package/lib/module/backends/winrt/winrt-security.js +43 -24
- package/lib/module/backends/winrt/winrt-security.js.map +1 -1
- package/lib/module/backends/winrt/winrt-subscription-runtime.js +128 -28
- package/lib/module/backends/winrt/winrt-subscription-runtime.js.map +1 -1
- package/lib/module/core/bounded-stream.js +20 -10
- package/lib/module/core/bounded-stream.js.map +1 -1
- package/lib/module/core/core-discovery.js +4 -0
- package/lib/module/core/core-discovery.js.map +1 -1
- package/lib/module/core/core-lifecycle-observer.js +45 -0
- package/lib/module/core/core-lifecycle-observer.js.map +1 -1
- package/lib/module/core/owned-bounded-stream.js +4 -4
- package/lib/module/core/owned-bounded-stream.js.map +1 -1
- package/lib/module/core/unified-ble-core.js +261 -95
- package/lib/module/core/unified-ble-core.js.map +1 -1
- package/lib/module/electron/connection-event-stream-registry.js +5 -2
- package/lib/module/electron/connection-event-stream-registry.js.map +1 -1
- package/lib/module/electron/renderer-stream-registry.js +5 -2
- package/lib/module/electron/renderer-stream-registry.js.map +1 -1
- package/lib/module/implementation-version.js +1 -1
- package/lib/module/ipc/manager.js +40 -2
- package/lib/module/ipc/manager.js.map +1 -1
- package/lib/module/ipc/public-manager.js +24 -11
- package/lib/module/ipc/public-manager.js.map +1 -1
- package/lib/module/native-protocol/rn-android-boundary.js +10 -0
- package/lib/module/native-protocol/rn-android-boundary.js.map +1 -1
- package/lib/module/public/ble-manager.js +153 -47
- package/lib/module/public/ble-manager.js.map +1 -1
- package/lib/module/public/cleanup.js +1 -1
- package/lib/module/public/cleanup.js.map +1 -1
- package/lib/module/public/scan-state.js +44 -0
- package/lib/module/public/scan-state.js.map +1 -1
- package/lib/module/public/streams.js +13 -8
- package/lib/module/public/streams.js.map +1 -1
- package/lib/module/tck/first-party/winrt-tck-registration.js +5 -0
- package/lib/module/tck/first-party/winrt-tck-registration.js.map +1 -1
- package/lib/module/testing/deterministic/deterministic-stream.js +16 -5
- package/lib/module/testing/deterministic/deterministic-stream.js.map +1 -1
- package/lib/module/web/navigator-web-bluetooth-boundary.js +20 -0
- package/lib/module/web/navigator-web-bluetooth-boundary.js.map +1 -1
- package/lib/module/web/web-bluetooth-backend.js +135 -6
- package/lib/module/web/web-bluetooth-backend.js.map +1 -1
- package/lib/module/web.js.map +1 -1
- package/lib/typescript/commonjs/src/backend-contract/errors.d.ts +2 -0
- package/lib/typescript/commonjs/src/backend-contract/errors.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backend-contract/streams.d.ts +5 -1
- package/lib/typescript/commonjs/src/backend-contract/streams.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-backend-provider.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-backend-runtime.d.ts +2 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-backend-runtime.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-connection-runtime.d.ts +1 -0
- package/lib/typescript/commonjs/src/backends/bluez/bluez-connection-runtime.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-property-waiters.d.ts +1 -0
- package/lib/typescript/commonjs/src/backends/bluez/bluez-property-waiters.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-runtime-models.d.ts +3 -0
- package/lib/typescript/commonjs/src/backends/bluez/bluez-runtime-models.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-runtime-types.d.ts +22 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-runtime-types.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-scan-runtime.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-security.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-security.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-subscription-runtime.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-gatt-operations.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-identity.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-read-notify-provenance.d.ts +37 -0
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-read-notify-provenance.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/backends/reactnative/react-native-android-provider.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/reactnative/react-native-android-security.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/reactnative/react-native-android-security.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/reactnative/react-native-apple-provider.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-backend.d.ts +7 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-backend.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-boundary.d.ts +1 -0
- package/lib/typescript/commonjs/src/backends/winrt/winrt-boundary.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-gatt-operations.d.ts +1 -0
- package/lib/typescript/commonjs/src/backends/winrt/winrt-gatt-operations.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-handles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-provider.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-security.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-security.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-subscription-runtime.d.ts +4 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-subscription-runtime.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/bounded-stream.d.ts +5 -3
- package/lib/typescript/commonjs/src/core/bounded-stream.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/core-discovery.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/core-lifecycle-observer.d.ts +10 -0
- package/lib/typescript/commonjs/src/core/core-lifecycle-observer.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/owned-bounded-stream.d.ts +3 -3
- package/lib/typescript/commonjs/src/core/owned-bounded-stream.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/unified-ble-core.d.ts +6 -0
- package/lib/typescript/commonjs/src/core/unified-ble-core.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/electron/connection-event-stream-registry.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/electron/renderer-stream-registry.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/implementation-version.d.ts +1 -1
- package/lib/typescript/commonjs/src/ipc/manager.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/ipc/public-manager.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/manager/consumer-handles.d.ts +1 -0
- package/lib/typescript/commonjs/src/manager/consumer-handles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/native-protocol/rn-android-boundary.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/ble-manager.d.ts +13 -2
- package/lib/typescript/commonjs/src/public/ble-manager.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/cleanup.d.ts +3 -1
- package/lib/typescript/commonjs/src/public/cleanup.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/scan-state.d.ts +15 -0
- package/lib/typescript/commonjs/src/public/scan-state.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/streams.d.ts +1 -0
- package/lib/typescript/commonjs/src/public/streams.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/tck/first-party/winrt-tck-registration.d.ts +1 -0
- package/lib/typescript/commonjs/src/tck/first-party/winrt-tck-registration.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/testing/deterministic/deterministic-stream.d.ts +4 -2
- package/lib/typescript/commonjs/src/testing/deterministic/deterministic-stream.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/web/navigator-web-bluetooth-boundary.d.ts +9 -1
- package/lib/typescript/commonjs/src/web/navigator-web-bluetooth-boundary.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/web/web-bluetooth-backend.d.ts +16 -0
- package/lib/typescript/commonjs/src/web/web-bluetooth-backend.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/web/web-bluetooth-boundary.d.ts +11 -0
- package/lib/typescript/commonjs/src/web/web-bluetooth-boundary.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/web.d.ts +1 -1
- package/lib/typescript/commonjs/src/web.d.ts.map +1 -1
- package/lib/typescript/module/src/backend-contract/errors.d.ts +2 -0
- package/lib/typescript/module/src/backend-contract/errors.d.ts.map +1 -1
- package/lib/typescript/module/src/backend-contract/streams.d.ts +5 -1
- package/lib/typescript/module/src/backend-contract/streams.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-backend-provider.d.ts +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-backend-runtime.d.ts +2 -1
- package/lib/typescript/module/src/backends/bluez/bluez-backend-runtime.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-connection-runtime.d.ts +1 -0
- package/lib/typescript/module/src/backends/bluez/bluez-connection-runtime.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-property-waiters.d.ts +1 -0
- package/lib/typescript/module/src/backends/bluez/bluez-property-waiters.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-runtime-models.d.ts +3 -0
- package/lib/typescript/module/src/backends/bluez/bluez-runtime-models.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-runtime-types.d.ts +22 -1
- package/lib/typescript/module/src/backends/bluez/bluez-runtime-types.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-scan-runtime.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-security.d.ts +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-security.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-subscription-runtime.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-gatt-operations.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-identity.d.ts +1 -1
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-read-notify-provenance.d.ts +37 -0
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-read-notify-provenance.d.ts.map +1 -0
- package/lib/typescript/module/src/backends/reactnative/react-native-android-provider.d.ts +1 -1
- package/lib/typescript/module/src/backends/reactnative/react-native-android-security.d.ts +1 -1
- package/lib/typescript/module/src/backends/reactnative/react-native-android-security.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/reactnative/react-native-apple-provider.d.ts +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-backend.d.ts +7 -1
- package/lib/typescript/module/src/backends/winrt/winrt-backend.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-boundary.d.ts +1 -0
- package/lib/typescript/module/src/backends/winrt/winrt-boundary.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-gatt-operations.d.ts +1 -0
- package/lib/typescript/module/src/backends/winrt/winrt-gatt-operations.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-handles.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-provider.d.ts +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-security.d.ts +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-security.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-subscription-runtime.d.ts +4 -1
- package/lib/typescript/module/src/backends/winrt/winrt-subscription-runtime.d.ts.map +1 -1
- package/lib/typescript/module/src/core/bounded-stream.d.ts +5 -3
- package/lib/typescript/module/src/core/bounded-stream.d.ts.map +1 -1
- package/lib/typescript/module/src/core/core-discovery.d.ts.map +1 -1
- package/lib/typescript/module/src/core/core-lifecycle-observer.d.ts +10 -0
- package/lib/typescript/module/src/core/core-lifecycle-observer.d.ts.map +1 -1
- package/lib/typescript/module/src/core/owned-bounded-stream.d.ts +3 -3
- package/lib/typescript/module/src/core/owned-bounded-stream.d.ts.map +1 -1
- package/lib/typescript/module/src/core/unified-ble-core.d.ts +6 -0
- package/lib/typescript/module/src/core/unified-ble-core.d.ts.map +1 -1
- package/lib/typescript/module/src/electron/connection-event-stream-registry.d.ts.map +1 -1
- package/lib/typescript/module/src/electron/renderer-stream-registry.d.ts.map +1 -1
- package/lib/typescript/module/src/implementation-version.d.ts +1 -1
- package/lib/typescript/module/src/ipc/manager.d.ts.map +1 -1
- package/lib/typescript/module/src/ipc/public-manager.d.ts.map +1 -1
- package/lib/typescript/module/src/manager/consumer-handles.d.ts +1 -0
- package/lib/typescript/module/src/manager/consumer-handles.d.ts.map +1 -1
- package/lib/typescript/module/src/native-protocol/rn-android-boundary.d.ts.map +1 -1
- package/lib/typescript/module/src/public/ble-manager.d.ts +13 -2
- package/lib/typescript/module/src/public/ble-manager.d.ts.map +1 -1
- package/lib/typescript/module/src/public/cleanup.d.ts +3 -1
- package/lib/typescript/module/src/public/cleanup.d.ts.map +1 -1
- package/lib/typescript/module/src/public/scan-state.d.ts +15 -0
- package/lib/typescript/module/src/public/scan-state.d.ts.map +1 -1
- package/lib/typescript/module/src/public/streams.d.ts +1 -0
- package/lib/typescript/module/src/public/streams.d.ts.map +1 -1
- package/lib/typescript/module/src/tck/first-party/winrt-tck-registration.d.ts +1 -0
- package/lib/typescript/module/src/tck/first-party/winrt-tck-registration.d.ts.map +1 -1
- package/lib/typescript/module/src/testing/deterministic/deterministic-stream.d.ts +4 -2
- package/lib/typescript/module/src/testing/deterministic/deterministic-stream.d.ts.map +1 -1
- package/lib/typescript/module/src/web/navigator-web-bluetooth-boundary.d.ts +9 -1
- package/lib/typescript/module/src/web/navigator-web-bluetooth-boundary.d.ts.map +1 -1
- package/lib/typescript/module/src/web/web-bluetooth-backend.d.ts +16 -0
- package/lib/typescript/module/src/web/web-bluetooth-backend.d.ts.map +1 -1
- package/lib/typescript/module/src/web/web-bluetooth-boundary.d.ts +11 -0
- package/lib/typescript/module/src/web/web-bluetooth-boundary.d.ts.map +1 -1
- package/lib/typescript/module/src/web.d.ts +1 -1
- package/lib/typescript/module/src/web.d.ts.map +1 -1
- package/native/PREBUILDS.json +9 -9
- package/native/electron/corebluetooth/binding.gyp +2 -1
- package/native/electron/corebluetooth/prebuilds/darwin-arm64/unified_ble_corebluetooth.node +0 -0
- package/native/electron/corebluetooth/prebuilds/darwin-x64/unified_ble_corebluetooth.node +0 -0
- package/native/electron/corebluetooth/src/addon.mm +170 -24
- package/native/electron/winrt/prebuilds/win32-arm64/unified_ble_winrt.node +0 -0
- package/native/electron/winrt/prebuilds/win32-x64/unified_ble_winrt.node +0 -0
- package/native/electron/winrt/src/addon.cpp +19 -0
- package/native/electron/winrt/src/winrt-boundary.inc +28 -3
- package/native/protocol/CMakeLists.txt +14 -0
- package/native/protocol/include/OwnedCoreBluetoothReadNotifyProvenance.hpp +61 -0
- package/native/tauri/src/btleplug_dispatcher.rs +1836 -243
- package/package.json +1 -1
- package/src/backend-contract/errors.ts +20 -0
- package/src/backend-contract/streams.ts +5 -1
- package/src/backends/bluez/bluez-backend-runtime.ts +8 -1
- package/src/backends/bluez/bluez-connection-runtime.ts +406 -27
- package/src/backends/bluez/bluez-property-waiters.ts +8 -6
- package/src/backends/bluez/bluez-runtime-models.ts +24 -0
- package/src/backends/bluez/bluez-runtime-types.ts +23 -1
- package/src/backends/bluez/bluez-scan-runtime.ts +170 -14
- package/src/backends/bluez/bluez-security.ts +10 -7
- package/src/backends/bluez/bluez-subscription-runtime.ts +41 -22
- package/src/backends/corebluetooth/corebluetooth-gatt-operations.ts +12 -5
- package/src/backends/corebluetooth/corebluetooth-read-notify-provenance.ts +133 -0
- package/src/backends/reactnative/react-native-android-security.ts +35 -17
- package/src/backends/winrt/winrt-backend.ts +27 -3
- package/src/backends/winrt/winrt-boundary.ts +1 -0
- package/src/backends/winrt/winrt-gatt-operations.ts +19 -5
- package/src/backends/winrt/winrt-handles.ts +2 -0
- package/src/backends/winrt/winrt-security.ts +55 -26
- package/src/backends/winrt/winrt-subscription-runtime.ts +201 -38
- package/src/core/bounded-stream.ts +27 -11
- package/src/core/core-discovery.ts +4 -0
- package/src/core/core-lifecycle-observer.ts +54 -1
- package/src/core/owned-bounded-stream.ts +5 -5
- package/src/core/unified-ble-core.ts +329 -118
- package/src/electron/connection-event-stream-registry.ts +3 -1
- package/src/electron/renderer-stream-registry.ts +3 -1
- package/src/implementation-version.ts +1 -1
- package/src/ipc/manager.ts +49 -2
- package/src/ipc/public-manager.ts +19 -7
- package/src/manager/consumer-handles.ts +1 -0
- package/src/native-protocol/rn-android-boundary.ts +10 -0
- package/src/public/ble-manager.ts +172 -58
- package/src/public/cleanup.ts +1 -1
- package/src/public/scan-state.ts +60 -0
- package/src/public/streams.ts +15 -8
- package/src/tck/first-party/winrt-tck-registration.ts +6 -0
- package/src/testing/deterministic/deterministic-stream.ts +19 -6
- package/src/web/navigator-web-bluetooth-boundary.ts +50 -0
- package/src/web/web-bluetooth-backend.ts +167 -6
- package/src/web/web-bluetooth-boundary.ts +11 -0
- package/src/web.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,116 @@ All notable changes to `unified-ble-manager` are documented here.
|
|
|
6
6
|
|
|
7
7
|
No changes yet.
|
|
8
8
|
|
|
9
|
+
## [4.0.25] - 2026-09-05
|
|
10
|
+
|
|
11
|
+
### Fixes
|
|
12
|
+
|
|
13
|
+
- Tauri: separate live correlation capacity from 30s replay tombstones. Routed
|
|
14
|
+
cleanup still admits after a full replay window. Live exhaustion is retryable
|
|
15
|
+
backpressure, not `protocol.violation`. Replay of an old correlation still
|
|
16
|
+
rejects.
|
|
17
|
+
- Tauri: a native connect that completes after its caller/lease is gone gets an
|
|
18
|
+
orphan cleanup owner before compensating disconnect. Reservation and owner
|
|
19
|
+
release together, and only for the matching generation.
|
|
20
|
+
- Tauri: scan-stream failure keeps the scan owner in a stopping state until
|
|
21
|
+
native stop settles. A failed stop stays retryable and blocks a second scan.
|
|
22
|
+
Event and poll emit failures carry structured native diagnostics on the
|
|
23
|
+
shared `source-failed` terminal without inventing drop counters (#173).
|
|
24
|
+
- Tauri: post-await lease/generation checks on unsubscribe and scan stop.
|
|
25
|
+
Old-generation resources quarantine instead of attaching to a replacement
|
|
26
|
+
caller. Compensating unsubscribe after subscribe success uses the same orphan
|
|
27
|
+
owner instead of discarding the outcome.
|
|
28
|
+
- Tauri: overlapping stop requests for the same scan join one native
|
|
29
|
+
`stop_scan()`. Completions carry an attempt token, so a late stop of scan A
|
|
30
|
+
cannot take scan B’s stopping owner.
|
|
31
|
+
- Core: retain unadopted scan/connect leases when stale-admission `stop`/`release`
|
|
32
|
+
fails, and retry that exact lease on later manager cleanup. Aborted, destroyed,
|
|
33
|
+
or deadline-expired callers settle promptly; native work stays owned until
|
|
34
|
+
adopted or compensated.
|
|
35
|
+
- Core: coalesce concurrent `rediscoverGatt` waiters onto one replacement after
|
|
36
|
+
a shared in-flight discovery settles. A starter abort or timeout does not fail
|
|
37
|
+
a sibling waiter with its own admission.
|
|
38
|
+
- Public scan observation overflow is subscriber-local. Consuming only `events`
|
|
39
|
+
at full speed with `duplicates: 'all'` and `overflowPolicy: 'error'` no longer
|
|
40
|
+
terminates the scan because an unused observation queue filled.
|
|
41
|
+
- Drop-policy public scan overflow (`balanced` / `latest` / drop-*) reports an
|
|
42
|
+
overflow notice and keeps scanning. The radio stays up. `overflowPolicy:
|
|
43
|
+
'error'` (`lossless-bounded`) still fail-closes the consumed view as
|
|
44
|
+
`failed`/`overflow`; physical `stop()` remains cleanup.
|
|
45
|
+
- In-process and IPC scan sessions leave `active` when the host source ends
|
|
46
|
+
without `stop()`. An already-terminal source never publishes `active`; the
|
|
47
|
+
first state is the projected terminal (`failed` for `source-failed` /
|
|
48
|
+
`connection-lost` / `overflow`, `stopped` for ordinary close). That event is
|
|
49
|
+
ended delivery; `stop()` remains the physical cleanup path. The data pump
|
|
50
|
+
still drains advertisements already accepted by `finishWithReason` before
|
|
51
|
+
the observation terminal. Structured `source-failed` errors survive scan-state
|
|
52
|
+
binding and reach `scan.observations`.
|
|
53
|
+
- BlueZ `StopDiscovery` / `StopNotify` release this client’s session even if
|
|
54
|
+
another D-Bus client keeps `Discovering` / `Notifying` true.
|
|
55
|
+
- BlueZ `StartNotify` confirmation failure after native accept keeps a retryable
|
|
56
|
+
`StopNotify` owner instead of orphaning the notify session. A late enablement
|
|
57
|
+
success does not promote `removing` / `enabling-failed` back to `ready`.
|
|
58
|
+
- BlueZ `SetDiscoveryFilter`, `StartDiscovery`, and `ConnectDevice` honor caller
|
|
59
|
+
deadline/abort without dropping a later native allocation.
|
|
60
|
+
- BlueZ keeps a retryable compensating `Disconnect` when `ConnectDevice`
|
|
61
|
+
succeeds after the caller is gone. A failed first Disconnect is retried on
|
|
62
|
+
destroy instead of being logged and forgotten.
|
|
63
|
+
- BlueZ address-connect fallback checks scan-plan compatibility, waits out a
|
|
64
|
+
stopping scan, and widens an excluding live scan for concurrent address
|
|
65
|
+
waiters, restoring the owner filter only after the last borrower leaves
|
|
66
|
+
instead of waiting under a filter that cannot observe the target.
|
|
67
|
+
- Apple CoreBluetooth rejects an independent GATT read while that characteristic
|
|
68
|
+
is notifying, because `didUpdateValueFor` cannot distinguish a read response
|
|
69
|
+
from a notification. Electron/Node CoreBluetooth uses the same policy. A read
|
|
70
|
+
admitted while idle still completes from its ATT response if CCCD enable
|
|
71
|
+
races it; overlapping reads and subscribe-while-read are rejected; fused
|
|
72
|
+
values that cannot be attributed are dropped. Remaining native reject codes
|
|
73
|
+
(iOS 1031/1011/1032, Electron 413/414/415) map to `gatt.read-failed` or
|
|
74
|
+
`gatt.subscribe-failed`, not `platform.failure`.
|
|
75
|
+
- Android `setCharacteristicNotification(...) == false` is a local registration
|
|
76
|
+
failure, not proven link loss. Generation-matched disconnect and GATT status 19
|
|
77
|
+
remain the physical-loss authority. The 4.0.22 250 ms CCCD/disconnect two-signal
|
|
78
|
+
arbitration is unchanged. Notifications that arrive after the CCCD write and
|
|
79
|
+
before `onDescriptorWrite` SUCCESS are staged and flushed to admitted
|
|
80
|
+
subscribers. A later same-generation CCCD SUCCESS claims the arbiter instead
|
|
81
|
+
of leaving the peer enabled after a failed public subscribe.
|
|
82
|
+
- WinRT stages `ValueChanged` notifications that arrive before CCCD enablement
|
|
83
|
+
completes, then flushes them once and in order only to admitted subscribers.
|
|
84
|
+
Staging continues until every pending waiter is admitted, and a per-subscriber
|
|
85
|
+
overflow does not discard siblings’ pending buffer.
|
|
86
|
+
- WinRT subscription invalidation waits are bounded. If native `startNotify`
|
|
87
|
+
never settles, disconnect still completes within the cleanup budget. A late
|
|
88
|
+
enable issues a compensating `stopNotify` when the native CCCD key is vacant,
|
|
89
|
+
and skips that disable only when a replacement generation already occupies it.
|
|
90
|
+
Native notification map entries are keyed by connection generation.
|
|
91
|
+
- `cancelPairing()` honors abort and deadline on Android, WinRT, and BlueZ.
|
|
92
|
+
Admission runs before native cancellation. A timed-out wait is not reported as
|
|
93
|
+
`'cancelled'`. An abandoned waiter leaves the in-flight pairing owned.
|
|
94
|
+
`pair()` abort/deadline keeps the pairing owned until the native result;
|
|
95
|
+
a later native `paired`/`rejected` is authoritative for both `pair()` and
|
|
96
|
+
`cancelPairing()`.
|
|
97
|
+
- Web adapter `watchState()` follows browser `availabilitychanged` instead of
|
|
98
|
+
staying stale until another API samples availability. When that event is
|
|
99
|
+
missing, watches share one bounded `getAvailability()` poll. A completed
|
|
100
|
+
availability sample is applied unless a newer sample has already been applied,
|
|
101
|
+
so an outstanding later probe cannot make `attach()` throw `adapter.unavailable`
|
|
102
|
+
from a stale unavailable cache.
|
|
103
|
+
|
|
104
|
+
## [4.0.24] - 2026-09-05
|
|
105
|
+
|
|
106
|
+
### Fixes
|
|
107
|
+
|
|
108
|
+
- Arbitrate an Android characteristic-write callback failure against an
|
|
109
|
+
already-in-flight disconnect callback. A provisional write status such as
|
|
110
|
+
133 is retained for a bounded 250 ms evidence window, allowing the
|
|
111
|
+
authoritative connection-state callback to report typed `connection.lost`
|
|
112
|
+
without relabeling an isolated status 133 as link loss.
|
|
113
|
+
- Preserve the Android GATT operation and status for synchronous and
|
|
114
|
+
asynchronous characteristic-write failures that are not proven link loss.
|
|
115
|
+
- Make exact and UUID-keyed pending-write cleanup identity-safe so stale
|
|
116
|
+
teardown and late callbacks cannot settle a replacement write or remove its
|
|
117
|
+
payload.
|
|
118
|
+
|
|
9
119
|
## [4.0.23] - 2026-09-05
|
|
10
120
|
|
|
11
121
|
### Fixes
|
|
@@ -239,7 +349,7 @@ hardware reproduced a later callback ordering that required the 4.0.22 fix.
|
|
|
239
349
|
|
|
240
350
|
### Changed behaviour
|
|
241
351
|
|
|
242
|
-
- `cancelPairing()` reports what the cancellation **achieved**, not what it requested, and can no longer contradict the pairing it cancelled. Every backend answered `'cancelled'` unconditionally the moment the cancel was dispatched, so a cancellation that lost the race told the caller no bond exists while one did — and a caller who believes that never looks again. It now reads the in-flight pairing's own result rather than forming a second opinion, which is what makes the two calls incapable of disagreeing: there is one source of truth and the cancellation reads it. `SecurityCancelPairingResult` gains the words to say so — `'paired'` when the bond completed before the cancellation arrived, and `'rejected'` (carrying the peer's reason) when the peer refused, because claiming credit for stopping something that stopped itself is the same substitution with the arrow reversed. A pairing that
|
|
352
|
+
- `cancelPairing()` reports what the cancellation **achieved**, not what it requested, and can no longer contradict the pairing it cancelled. Every backend answered `'cancelled'` unconditionally the moment the cancel was dispatched, so a cancellation that lost the race told the caller no bond exists while one did — and a caller who believes that never looks again. It now reads the in-flight pairing's own result rather than forming a second opinion, which is what makes the two calls incapable of disagreeing: there is one source of truth and the cancellation reads it. `SecurityCancelPairingResult` gains the words to say so — `'paired'` when the bond completed before the cancellation arrived, and `'rejected'` (carrying the peer's reason) when the peer refused, because claiming credit for stopping something that stopped itself is the same substitution with the arrow reversed. A pairing that _fails_ is not given an invented outcome: `cancelPairing()` rejects with the error the pairing rejected with. `'paired'` deliberately matches `SecurityPairResult`'s `'paired'` — a bond exists as a result of this operation — and is not `'already-paired'`, which in that type means the peer was bonded _before_ the call; one word, one meaning, in both types. Applies to BlueZ, Android, WinRT **and** the deterministic `/testing` backend, since a mock that answers differently from every real radio lets a consumer's suite pass against a contract no device honours. WinRT additionally short-circuited _upstream_ of the shared mapper — when its dispatcher reported the operation already terminal, which is exactly the lost race, it answered `'not-pairing'`, contradicting its own `pair()` and making that word mean both "there was nothing to stop" and "it was already over" (#159).
|
|
243
353
|
|
|
244
354
|
### Additions
|
|
245
355
|
|
|
@@ -247,13 +357,13 @@ hardware reproduced a later callback ordering that required the 4.0.22 fix.
|
|
|
247
357
|
|
|
248
358
|
This package never acquires that privilege: it opens no management socket, shells out to nothing, and does not assume it is root. A library that silently escalates hands an application capabilities its author did not choose and cannot audit. The **host** supplies the operation via `BluezBackendProviderOptions.pairingGeneration`, which makes the escalation visible in the application that opted into it. Omit it and `'require'`/`'disallow'` keep failing closed exactly as in 4.0.6 — the default posture is unchanged.
|
|
249
359
|
|
|
250
|
-
Three properties of the kernel setting a host must accept, documented in `docs/BONDING.md` rather than discovered: it is **adapter-wide**, not per-pairing, so every pairing on that controller uses the selected generation while it is held; it **outlives the process**, because the kernel keeps it until something sets it back; and a **failed restore never changes the pairing's outcome** — a bond that was created is reported as created, with the restore failure reported separately, because leaving a controller in LE Legacy and telling a caller they are not bonded are both serious and are different facts. Concurrent
|
|
360
|
+
Three properties of the kernel setting a host must accept, documented in `docs/BONDING.md` rather than discovered: it is **adapter-wide**, not per-pairing, so every pairing on that controller uses the selected generation while it is held; it **outlives the process**, because the kernel keeps it until something sets it back; and a **failed restore never changes the pairing's outcome** — a bond that was created is reported as created, with the restore failure reported separately, because leaving a controller in LE Legacy and telling a caller they are not bonded are both serious and are different facts. Concurrent _directed_ pairings on one adapter are serialised so they cannot corrupt each other's restore value; an undirected (`'prefer'`) pairing does not take that lock and uses whichever generation is held, which `docs/BONDING.md` states beside the option.
|
|
251
361
|
|
|
252
362
|
`security:pairing-generation` joins the capability catalog and is reported by the instantiated backend at runtime: `unsupported` with the platform reason when no operation was supplied, `limited` when one was — so two BlueZ backends on one machine legitimately answer differently. Evidence is deterministic tests only; this is **not** physical-radio proof, and the label says so (#144).
|
|
253
363
|
|
|
254
364
|
### Fixes
|
|
255
365
|
|
|
256
|
-
- A Tauri connect that succeeds physically but is then denied admission no longer strands the peer. Both compensation branches — the caller vanished, and the caller's lease went stale — removed the peer reservation
|
|
366
|
+
- A Tauri connect that succeeds physically but is then denied admission no longer strands the peer. Both compensation branches — the caller vanished, and the caller's lease went stale — removed the peer reservation _before_ attempting the disconnect and then discarded its result with `.ok()`. If that disconnect failed or hung while the peripheral stayed connected, the result was a connected peer with no owner and no handle: nothing could reach it, nothing could retry it, and the caller was told only that admission was denied. Compensation now follows the rule the explicit disconnect already follows — a bounded wait, a fresh state reading, and a D-Bus error naming a vanished device object read as evidence of release rather than as a failed question — and surrenders the reservation only when the platform proves the link is down. Genuine indeterminacy keeps it so a retry can reclaim the peer, and the admission error carries what compensation could not undo, which is the difference between "try again" and "a peer is stranded" (#146).
|
|
257
367
|
|
|
258
368
|
### Known limitations
|
|
259
369
|
|
package/MIGRATION_4.0.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Migrating from react-native-ble-plx
|
|
4
4
|
|
|
5
|
-
This source targets `4.0.
|
|
5
|
+
This source targets `4.0.25`. The `4.0.0` release is a new package and a new contract. It is **not a source-compatible rename**. There is no `new BleManager()` facade, no Base64 characteristic values, and no public transaction IDs.
|
|
6
6
|
|
|
7
7
|
This page is for a React Native app that already uses `react-native-ble-plx`. Web, Electron, Node, and Tauri are new hosts — use those pages after you understand the RN rewrite.
|
|
8
8
|
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ root import does not pick a radio. Package SemVer and backend support labels are
|
|
|
18
18
|
independent: each radio backend keeps its evidence-derived label. See
|
|
19
19
|
[`docs/PLATFORMS.md`](docs/PLATFORMS.md).
|
|
20
20
|
|
|
21
|
-
This source tree is versioned `4.0.
|
|
21
|
+
This source tree is versioned `4.0.25`. Install the exact version shown in the npm
|
|
22
22
|
registry. During release preparation, the version in `package.json` can be ahead
|
|
23
23
|
of npm until the matching tag-driven workflow publishes it; the registry and
|
|
24
24
|
GitHub release remain authoritative.
|
|
@@ -243,7 +243,7 @@ Web Bluetooth replaces the scan with `ble.choose(...)` from a user gesture. The
|
|
|
243
243
|
|
|
244
244
|
| Member | Use |
|
|
245
245
|
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
246
|
-
| `observations` | Bounded stream: `value`, `overflow`, or `terminal`
|
|
246
|
+
| `observations` | Bounded stream: `value`, `overflow`, or `terminal`. Drop-policy overflow means ads were missed; the scan stays up. `error` fail-closes. |
|
|
247
247
|
| `events` | Optional derived current-view events: `observed` and monotonic `lost` (`observation.reportLostAfterMs`); unsupported host façades reject this option |
|
|
248
248
|
| `plan` | Host-owned native/residual planning diagnostics, or `null` when this host has no planner |
|
|
249
249
|
| `stop()` | End the scan and return a cleanup receipt. `find` already does this. |
|
package/RELEASE.md
CHANGED
|
@@ -82,8 +82,9 @@ Active `4.0.0-rc.*` release-train candidates publish to npm `latest` so a bare `
|
|
|
82
82
|
On release day, set `release_candidate` to the exact candidate required by the
|
|
83
83
|
release plan. RC2, RC3, RC4, `4.0.0-rc.4.1`, and RC5 are already immutable
|
|
84
84
|
once tagged. Stable `4.0.0` through `4.0.20` are immutable. The unpublished
|
|
85
|
-
`v4.0.21` tag is also immutable after its cancelled workflow. `4.0.22
|
|
86
|
-
|
|
85
|
+
`v4.0.21` tag is also immutable after its cancelled workflow. `4.0.22`,
|
|
86
|
+
`4.0.23`, and `4.0.24` are immutable tagged history. This branch prepares
|
|
87
|
+
`4.0.25`.
|
|
87
88
|
|
|
88
89
|
```sh
|
|
89
90
|
release_candidate=4.0.0-rc.N
|
|
@@ -111,6 +112,22 @@ The first stable tag `v4.0.0` is immutable published history. Do not recreate or
|
|
|
111
112
|
git tag -a v4.0.0 -m "v4.0.0"
|
|
112
113
|
```
|
|
113
114
|
|
|
115
|
+
## Releasing 4.0.25
|
|
116
|
+
|
|
117
|
+
Release `v4.0.25` only from the exact current `main` commit after its canonical
|
|
118
|
+
CI succeeds. Verify `package.json` is `4.0.25`, the worktree is clean, and
|
|
119
|
+
release-note extraction finds `## [4.0.25]`. Push a new annotated `v4.0.25`
|
|
120
|
+
tag; never move the immutable `v4.0.24` tag. Follow the required local validation,
|
|
121
|
+
publish workflow, and registry verification below.
|
|
122
|
+
|
|
123
|
+
## Releasing 4.0.24
|
|
124
|
+
|
|
125
|
+
Release `v4.0.24` only from the exact current `main` commit after its canonical
|
|
126
|
+
CI succeeds. Verify `package.json` is `4.0.24`, the worktree is clean, and
|
|
127
|
+
release-note extraction finds `## [4.0.24]`. Push a new annotated `v4.0.24`
|
|
128
|
+
tag; never move an earlier immutable tag. Follow the required local validation,
|
|
129
|
+
publish workflow, and registry verification below.
|
|
130
|
+
|
|
114
131
|
## Releasing 4.0.23
|
|
115
132
|
|
|
116
133
|
Release `v4.0.23` only from the exact current `main` commit after its canonical
|
|
@@ -483,7 +500,7 @@ a green publish job and a package a consumer can actually install are not the
|
|
|
483
500
|
same claim.
|
|
484
501
|
|
|
485
502
|
```sh
|
|
486
|
-
version=4.0.
|
|
503
|
+
version=4.0.25
|
|
487
504
|
|
|
488
505
|
npm view "unified-ble-manager@$version" version
|
|
489
506
|
npm view unified-ble-manager dist-tags --json
|
package/SBOM.cdx.json
CHANGED
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
"metadata": {
|
|
7
7
|
"component": {
|
|
8
8
|
"type": "library",
|
|
9
|
-
"bom-ref": "pkg:npm/unified-ble-manager@4.0.
|
|
9
|
+
"bom-ref": "pkg:npm/unified-ble-manager@4.0.25",
|
|
10
10
|
"name": "unified-ble-manager",
|
|
11
|
-
"version": "4.0.
|
|
11
|
+
"version": "4.0.25",
|
|
12
12
|
"licenses": [
|
|
13
13
|
{
|
|
14
14
|
"expression": "Apache-2.0"
|
|
15
15
|
}
|
|
16
16
|
],
|
|
17
|
-
"purl": "pkg:npm/unified-ble-manager@4.0.
|
|
17
|
+
"purl": "pkg:npm/unified-ble-manager@4.0.25"
|
|
18
18
|
},
|
|
19
19
|
"properties": [
|
|
20
20
|
{
|
|
@@ -537,7 +537,7 @@
|
|
|
537
537
|
"dependsOn": []
|
|
538
538
|
},
|
|
539
539
|
{
|
|
540
|
-
"ref": "pkg:npm/unified-ble-manager@4.0.
|
|
540
|
+
"ref": "pkg:npm/unified-ble-manager@4.0.25",
|
|
541
541
|
"dependsOn": [
|
|
542
542
|
"pkg:npm/%40babel/runtime@7.29.7",
|
|
543
543
|
"pkg:npm/node-addon-api@8.9.0",
|
package/android/build.gradle
CHANGED
|
@@ -89,6 +89,9 @@ android {
|
|
|
89
89
|
kotlinOptions {
|
|
90
90
|
jvmTarget = "17"
|
|
91
91
|
}
|
|
92
|
+
testOptions {
|
|
93
|
+
unitTests.returnDefaultValues = true
|
|
94
|
+
}
|
|
92
95
|
externalNativeBuild {
|
|
93
96
|
cmake {
|
|
94
97
|
path file("src/main/jni/CMakeLists.txt")
|
|
@@ -105,6 +108,7 @@ dependencies {
|
|
|
105
108
|
implementation "com.facebook.react:react-android"
|
|
106
109
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
107
110
|
testImplementation "junit:junit:4.13.2"
|
|
111
|
+
testImplementation "org.mockito:mockito-core:5.14.2"
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
react {
|
|
@@ -30,6 +30,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
30
30
|
private val establishedConnections = ConcurrentHashMap<String, ProtocolWireRecord>()
|
|
31
31
|
private val activeDatabases = ConcurrentHashMap<String, ProtocolWireRecord>()
|
|
32
32
|
private val activeSubscriptions = ConcurrentHashMap<String, SubscriptionRoute>()
|
|
33
|
+
private val pendingSubscriptions = ConcurrentHashMap<String, SubscriptionRoute>()
|
|
33
34
|
private val radioOperationIds = ConcurrentHashMap<String, Long>()
|
|
34
35
|
private val activeScanCommand = AtomicReference<ProtocolWireRecord?>(null)
|
|
35
36
|
private val cancelledScanCommands = ConcurrentHashMap<String, ProtocolWireRecord>()
|
|
@@ -78,11 +79,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
78
79
|
activeDatabases.remove(deviceKey)
|
|
79
80
|
failPendingCommandsForDevice(deviceKey, "Android GATT link was lost")
|
|
80
81
|
if (established != null) {
|
|
81
|
-
|
|
82
|
-
if (entry.value.endpoint.deviceId.equals(deviceId, ignoreCase = true)) {
|
|
83
|
-
activeSubscriptions.remove(entry.key, entry.value)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
82
|
+
clearSubscriptionRoutesForDevice(deviceId)
|
|
86
83
|
emitConnectionLost(established, status)
|
|
87
84
|
}
|
|
88
85
|
}
|
|
@@ -134,7 +131,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
134
131
|
}
|
|
135
132
|
}
|
|
136
133
|
radio.onProtocolNotification = { deviceId, characteristic, value ->
|
|
137
|
-
activeSubscriptions.values
|
|
134
|
+
(pendingSubscriptions.values.asSequence() + activeSubscriptions.values.asSequence())
|
|
138
135
|
.filter { route -> route.matches(deviceId, characteristic, radio) }
|
|
139
136
|
.forEach { route ->
|
|
140
137
|
UnifiedBleProtocolJsiBinding.emitNotification(nativeHandle, route.subscriptionId, value)
|
|
@@ -166,6 +163,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
166
163
|
}
|
|
167
164
|
establishedConnections.clear()
|
|
168
165
|
activeDatabases.clear()
|
|
166
|
+
pendingSubscriptions.clear()
|
|
169
167
|
activeSubscriptions.clear()
|
|
170
168
|
}
|
|
171
169
|
|
|
@@ -272,6 +270,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
272
270
|
pendingConnects.clear()
|
|
273
271
|
establishedConnections.clear()
|
|
274
272
|
activeDatabases.clear()
|
|
273
|
+
pendingSubscriptions.clear()
|
|
275
274
|
activeSubscriptions.clear()
|
|
276
275
|
activeScanCommand.set(null)
|
|
277
276
|
}
|
|
@@ -409,7 +408,9 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
409
408
|
) { result ->
|
|
410
409
|
result.fold(
|
|
411
410
|
onSuccess = { emitSuccess(command, "write") },
|
|
412
|
-
onFailure = { error ->
|
|
411
|
+
onFailure = { error ->
|
|
412
|
+
emitGattOperationFailure(command, "writeFailed", error, "Android GATT write failed")
|
|
413
|
+
}
|
|
413
414
|
)
|
|
414
415
|
}
|
|
415
416
|
radioOperationIds[operationKey(command)] = radioOperationId
|
|
@@ -599,6 +600,14 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
599
600
|
return
|
|
600
601
|
}
|
|
601
602
|
val endpoint = characteristicEndpoint(command.requiredRecord(4))
|
|
603
|
+
val route = SubscriptionRoute(
|
|
604
|
+
subscriptionId,
|
|
605
|
+
endpoint,
|
|
606
|
+
command.optionalString(21)
|
|
607
|
+
)
|
|
608
|
+
if (enable) {
|
|
609
|
+
pendingSubscriptions[subscriptionId] = route
|
|
610
|
+
}
|
|
602
611
|
val radioOperationId = radio.setNotifyExact(
|
|
603
612
|
endpoint.deviceId,
|
|
604
613
|
endpoint.serviceUuid,
|
|
@@ -611,6 +620,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
611
620
|
result.fold(
|
|
612
621
|
onSuccess = {
|
|
613
622
|
if (!isPending(command)) {
|
|
623
|
+
pendingSubscriptions.remove(subscriptionId, route)
|
|
614
624
|
if (enable) {
|
|
615
625
|
radio.setNotifyExact(
|
|
616
626
|
endpoint.deviceId,
|
|
@@ -632,17 +642,16 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
632
642
|
return@fold
|
|
633
643
|
}
|
|
634
644
|
if (enable) {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
endpoint,
|
|
638
|
-
command.optionalString(21)
|
|
639
|
-
)
|
|
645
|
+
pendingSubscriptions.remove(subscriptionId, route)
|
|
646
|
+
activeSubscriptions[subscriptionId] = route
|
|
640
647
|
} else {
|
|
648
|
+
pendingSubscriptions.remove(subscriptionId)
|
|
641
649
|
activeSubscriptions.remove(subscriptionId)
|
|
642
650
|
}
|
|
643
651
|
emitSuccess(command, if (enable) "subscribed" else "unsubscribed")
|
|
644
652
|
},
|
|
645
653
|
onFailure = { error ->
|
|
654
|
+
pendingSubscriptions.remove(subscriptionId, route)
|
|
646
655
|
emitGattOperationFailure(command, "subscriptionFailed", error, "Android CCCD operation failed")
|
|
647
656
|
}
|
|
648
657
|
)
|
|
@@ -663,6 +672,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
663
672
|
pendingConnects.clear()
|
|
664
673
|
establishedConnections.clear()
|
|
665
674
|
activeDatabases.clear()
|
|
675
|
+
pendingSubscriptions.clear()
|
|
666
676
|
activeSubscriptions.clear()
|
|
667
677
|
if (result.isSuccessful) {
|
|
668
678
|
activeScanCommand.set(null)
|
|
@@ -735,7 +745,9 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
735
745
|
}
|
|
736
746
|
if (commandKind == "subscribe") {
|
|
737
747
|
val endpoint = characteristicEndpoint(command.requiredRecord(4))
|
|
738
|
-
|
|
748
|
+
val subscriptionId = command.requiredString(7)
|
|
749
|
+
pendingSubscriptions.remove(subscriptionId)
|
|
750
|
+
activeSubscriptions.remove(subscriptionId)
|
|
739
751
|
radio.setNotifyExact(
|
|
740
752
|
endpoint.deviceId,
|
|
741
753
|
endpoint.serviceUuid,
|
|
@@ -880,8 +892,8 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
880
892
|
androidGattStatus: Int? = null
|
|
881
893
|
) {
|
|
882
894
|
// Claim before constructing or emitting the terminal. Link loss can race a
|
|
883
|
-
// native
|
|
884
|
-
// publish a result for the same operation.
|
|
895
|
+
// native GATT operation callback; a check followed by a later claim lets
|
|
896
|
+
// both paths publish a result for the same operation.
|
|
885
897
|
if (!claimExactPendingCommand(pendingCommands, operationKey(command), command)) return
|
|
886
898
|
val errorFields = mutableMapOf<Int, ProtocolWireValue>(
|
|
887
899
|
1 to ProtocolWireValue.StringValue(code),
|
|
@@ -1135,6 +1147,11 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
1135
1147
|
}
|
|
1136
1148
|
|
|
1137
1149
|
private fun clearSubscriptionRoutesForDevice(deviceId: String) {
|
|
1150
|
+
pendingSubscriptions.entries.forEach { entry ->
|
|
1151
|
+
if (entry.value.endpoint.deviceId.equals(deviceId, ignoreCase = true)) {
|
|
1152
|
+
pendingSubscriptions.remove(entry.key, entry.value)
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1138
1155
|
activeSubscriptions.entries.forEach { entry ->
|
|
1139
1156
|
if (entry.value.endpoint.deviceId.equals(deviceId, ignoreCase = true)) {
|
|
1140
1157
|
activeSubscriptions.remove(entry.key, entry.value)
|