Update Universal BLE Plugin for Peripheral Support and Code Generation
- Updated autogenerated files to reflect changes from Pigeon v26.3.4. - Added new classes for UniversalBlePeripheralConfig, UniversalBlePeripheralService, UniversalBlePeripheralCharacteristic, UniversalBlePeripheralDescriptor, and UniversalBlePeripheralWriteEvent to handle peripheral configurations and events. - Modified UniversalBlePlugin to implement methods for peripheral support, including StartPeripheral, StopPeripheral, UpdatePeripheralCharacteristicValue, and NotifyPeripheralCharacteristic, returning appropriate error messages for unsupported features on Windows. - Updated HasPermissions method to include an additional parameter for Bluetooth advertising permissions. - Adjusted method signatures and implementations across the plugin to accommodate new peripheral functionality. Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
## 1.3.0
|
||||
* Add Linux BLE peripheral/GATT-server support through BlueZ GATT application and LE advertisement registration
|
||||
* Add `requestConnectionPriority` to allow tuning BLE connection intervals on Android
|
||||
* Add SPM support on Apple
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE
|
||||
- [Connecting](#connecting)
|
||||
- [Discovering Services](#discovering-services)
|
||||
- [Reading & Writing data](#reading--writing-data)
|
||||
- [Peripheral Mode](#peripheral-mode)
|
||||
- [Pairing](#pairing)
|
||||
- [Bluetooth Availability](#bluetooth-availability)
|
||||
- [Requesting MTU](#requesting-mtu)
|
||||
@@ -57,6 +58,7 @@ A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE
|
||||
| requestConnectionPriority | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||
| readRssi | ✔️ | ✔️ | ✔️ | ❌ | 🚧 | ❌ |
|
||||
| requestPermissions | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||
| peripheral/GATT server | ✔️ | 🚧 | 🚧 | 🚧 | ✔️ | ❌ |
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -338,6 +340,49 @@ Unsubscribe from notifications and indications of this characteristic.
|
||||
await characteristic.unsubscribe();
|
||||
```
|
||||
|
||||
## Peripheral Mode
|
||||
|
||||
`UniversalBlePeripheral` exposes a local GATT-server API for apps that need to advertise services and accept central/client writes. Android and Linux are implemented; Apple and Windows currently report `notSupported` until their platform server implementations are added. Web browsers do not expose a standard GATT-server API.
|
||||
|
||||
On Linux, peripheral mode uses BlueZ `GattManager1` and `LEAdvertisingManager1`. The Bluetooth adapter must be powered, support the peripheral role, and the app process must be allowed to register GATT applications and LE advertisements on the system bus.
|
||||
|
||||
```dart
|
||||
await UniversalBle.requestPermissions(withAndroidBluetoothAdvertise: true);
|
||||
|
||||
await UniversalBlePeripheral.start(
|
||||
BlePeripheralConfig(
|
||||
advertisedName: 'DALI Relay',
|
||||
services: [
|
||||
BlePeripheralService(
|
||||
uuid: 'fff0',
|
||||
characteristics: [
|
||||
BlePeripheralCharacteristic(
|
||||
uuid: 'fff1',
|
||||
properties: const [
|
||||
CharacteristicProperty.read,
|
||||
CharacteristicProperty.write,
|
||||
CharacteristicProperty.writeWithoutResponse,
|
||||
CharacteristicProperty.notify,
|
||||
],
|
||||
permissions: const [
|
||||
BlePeripheralCharacteristicPermission.read,
|
||||
BlePeripheralCharacteristicPermission.write,
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
UniversalBlePeripheral.writeStream.listen((event) {
|
||||
debugPrint('Central ${event.deviceId} wrote ${event.value}');
|
||||
});
|
||||
|
||||
await UniversalBlePeripheral.notify('fff0', 'fff1', Uint8List.fromList([1, 2]));
|
||||
await UniversalBlePeripheral.stop();
|
||||
```
|
||||
|
||||
### Pairing
|
||||
|
||||
#### Trigger pairing
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
<uses-permission
|
||||
android:name="android.permission.BLUETOOTH_ADMIN"
|
||||
android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
</manifest>
|
||||
|
||||
@@ -35,12 +35,12 @@ class PermissionHandler(
|
||||
/**
|
||||
* Check if we have required permissions
|
||||
*/
|
||||
fun hasPermissions(withFineLocation: Boolean): Boolean {
|
||||
val validationError = validateRequiredPermissions(withFineLocation)
|
||||
fun hasPermissions(withFineLocation: Boolean, withAdvertise: Boolean): Boolean {
|
||||
val validationError = validateRequiredPermissions(withFineLocation, withAdvertise)
|
||||
if (validationError != null) {
|
||||
throw validationError
|
||||
}
|
||||
val permissionsToRequest = getRequiredPermissions(withFineLocation)
|
||||
val permissionsToRequest = getRequiredPermissions(withFineLocation, withAdvertise)
|
||||
return permissionsToRequest.isEmpty()
|
||||
}
|
||||
|
||||
@@ -55,17 +55,18 @@ class PermissionHandler(
|
||||
*/
|
||||
fun requestPermissions(
|
||||
withFineLocation: Boolean,
|
||||
withAdvertise: Boolean,
|
||||
callback: (Result<Unit>) -> Unit,
|
||||
) {
|
||||
// Validate required permissions are declared in manifest
|
||||
val validationError = validateRequiredPermissions(withFineLocation)
|
||||
val validationError = validateRequiredPermissions(withFineLocation, withAdvertise)
|
||||
if (validationError != null) {
|
||||
callback(Result.failure(validationError))
|
||||
return
|
||||
}
|
||||
|
||||
// Check which permissions need to be requested
|
||||
val permissionsToRequest = getRequiredPermissions(withFineLocation)
|
||||
val permissionsToRequest = getRequiredPermissions(withFineLocation, withAdvertise)
|
||||
|
||||
if (permissionsToRequest.isEmpty()) {
|
||||
// All required permissions are already granted
|
||||
@@ -163,7 +164,7 @@ class PermissionHandler(
|
||||
*
|
||||
* Returns a list of permissions that need to be requested (excluding already granted ones)
|
||||
*/
|
||||
private fun getRequiredPermissions(withFineLocation: Boolean): List<String> {
|
||||
private fun getRequiredPermissions(withFineLocation: Boolean, withAdvertise: Boolean): List<String> {
|
||||
val permissionsToRequest = mutableListOf<String>()
|
||||
// Android 12+ (API 31+)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
@@ -175,6 +176,9 @@ class PermissionHandler(
|
||||
if (!hasPermissionGranted(Manifest.permission.BLUETOOTH_CONNECT)) {
|
||||
permissionsToRequest.add(Manifest.permission.BLUETOOTH_CONNECT)
|
||||
}
|
||||
if (withAdvertise && !hasPermissionGranted(Manifest.permission.BLUETOOTH_ADVERTISE)) {
|
||||
permissionsToRequest.add(Manifest.permission.BLUETOOTH_ADVERTISE)
|
||||
}
|
||||
// Location permission is optional - only request if user wants it
|
||||
if (withFineLocation) {
|
||||
// Prefer ACCESS_FINE_LOCATION over ACCESS_COARSE_LOCATION
|
||||
@@ -236,7 +240,7 @@ class PermissionHandler(
|
||||
* @param withFineLocation Whether location permission should be requested
|
||||
* @return FlutterError if validation fails, null if all required permissions are declared
|
||||
*/
|
||||
private fun validateRequiredPermissions(withFineLocation: Boolean): FlutterError? {
|
||||
private fun validateRequiredPermissions(withFineLocation: Boolean, withAdvertise: Boolean): FlutterError? {
|
||||
val sdkInt = Build.VERSION.SDK_INT
|
||||
val missingPermissions = mutableListOf<String>()
|
||||
|
||||
@@ -259,6 +263,10 @@ class PermissionHandler(
|
||||
missingPermissions.add(Manifest.permission.BLUETOOTH_CONNECT)
|
||||
}
|
||||
|
||||
if (withAdvertise && !hasPermissionInManifest(Manifest.permission.BLUETOOTH_ADVERTISE)) {
|
||||
missingPermissions.add(Manifest.permission.BLUETOOTH_ADVERTISE)
|
||||
}
|
||||
|
||||
// Location permission is optional on Android 12+ (depends on neverForLocation and withFineLocation)
|
||||
// Only validate if it's actually needed
|
||||
if (withFineLocation && !hasDeclaredLocationPermission) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Autogenerated from Pigeon (v26.1.4), do not edit directly.
|
||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
||||
|
||||
@@ -37,36 +37,150 @@ private object UniversalBlePigeonUtils {
|
||||
)
|
||||
}
|
||||
}
|
||||
fun doubleEquals(a: Double, b: Double): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun floatEquals(a: Float, b: Float): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun doubleHash(d: Double): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (d == 0.0) 0.0 else d
|
||||
val bits = java.lang.Double.doubleToLongBits(normalized)
|
||||
return (bits xor (bits ushr 32)).toInt()
|
||||
}
|
||||
|
||||
fun floatHash(f: Float): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (f == 0.0f) 0.0f else f
|
||||
return java.lang.Float.floatToIntBits(normalized)
|
||||
}
|
||||
|
||||
fun deepEquals(a: Any?, b: Any?): Boolean {
|
||||
if (a === b) {
|
||||
return true
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return false
|
||||
}
|
||||
if (a is ByteArray && b is ByteArray) {
|
||||
return a.contentEquals(b)
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is IntArray && b is IntArray) {
|
||||
return a.contentEquals(b)
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is LongArray && b is LongArray) {
|
||||
return a.contentEquals(b)
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is DoubleArray && b is DoubleArray) {
|
||||
return a.contentEquals(b)
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!doubleEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is FloatArray && b is FloatArray) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!floatEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Array<*> && b is Array<*>) {
|
||||
return a.size == b.size &&
|
||||
a.indices.all{ deepEquals(a[it], b[it]) }
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!deepEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is List<*> && b is List<*>) {
|
||||
return a.size == b.size &&
|
||||
a.indices.all{ deepEquals(a[it], b[it]) }
|
||||
if (a.size != b.size) return false
|
||||
val iterA = a.iterator()
|
||||
val iterB = b.iterator()
|
||||
while (iterA.hasNext() && iterB.hasNext()) {
|
||||
if (!deepEquals(iterA.next(), iterB.next())) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Map<*, *> && b is Map<*, *>) {
|
||||
return a.size == b.size && a.all {
|
||||
(b as Map<Any?, Any?>).contains(it.key) &&
|
||||
deepEquals(it.value, b[it.key])
|
||||
if (a.size != b.size) return false
|
||||
for (entry in a) {
|
||||
val key = entry.key
|
||||
var found = false
|
||||
for (bEntry in b) {
|
||||
if (deepEquals(key, bEntry.key)) {
|
||||
if (deepEquals(entry.value, bEntry.value)) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Double && b is Double) {
|
||||
return doubleEquals(a, b)
|
||||
}
|
||||
if (a is Float && b is Float) {
|
||||
return floatEquals(a, b)
|
||||
}
|
||||
return a == b
|
||||
}
|
||||
|
||||
|
||||
fun deepHash(value: Any?): Int {
|
||||
return when (value) {
|
||||
null -> 0
|
||||
is ByteArray -> value.contentHashCode()
|
||||
is IntArray -> value.contentHashCode()
|
||||
is LongArray -> value.contentHashCode()
|
||||
is DoubleArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + doubleHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is FloatArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + floatHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Array<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is List<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Map<*, *> -> {
|
||||
var result = 0
|
||||
for (entry in value) {
|
||||
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
|
||||
}
|
||||
result
|
||||
}
|
||||
is Double -> doubleHash(value)
|
||||
is Float -> floatHash(value)
|
||||
else -> value.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +193,7 @@ class FlutterError (
|
||||
val code: String,
|
||||
override val message: String? = null,
|
||||
val details: Any? = null
|
||||
) : Throwable()
|
||||
) : RuntimeException()
|
||||
|
||||
enum class UniversalBleLogLevel(val raw: Int) {
|
||||
NONE(0),
|
||||
@@ -219,15 +333,28 @@ data class UniversalBleScanResult (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleScanResult) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalBleScanResult
|
||||
return UniversalBlePigeonUtils.deepEquals(this.deviceId, other.deviceId) && UniversalBlePigeonUtils.deepEquals(this.name, other.name) && UniversalBlePigeonUtils.deepEquals(this.isPaired, other.isPaired) && UniversalBlePigeonUtils.deepEquals(this.rssi, other.rssi) && UniversalBlePigeonUtils.deepEquals(this.manufacturerDataList, other.manufacturerDataList) && UniversalBlePigeonUtils.deepEquals(this.serviceData, other.serviceData) && UniversalBlePigeonUtils.deepEquals(this.services, other.services) && UniversalBlePigeonUtils.deepEquals(this.timestamp, other.timestamp)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.deviceId)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.name)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.isPaired)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.rssi)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.manufacturerDataList)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.serviceData)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.services)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.timestamp)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -250,15 +377,22 @@ data class UniversalBleService (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleService) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalBleService
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid) && UniversalBlePigeonUtils.deepEquals(this.characteristics, other.characteristics)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.characteristics)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -284,15 +418,23 @@ data class UniversalBleCharacteristic (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleCharacteristic) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalBleCharacteristic
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid) && UniversalBlePigeonUtils.deepEquals(this.properties, other.properties) && UniversalBlePigeonUtils.deepEquals(this.descriptors, other.descriptors)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.properties)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.descriptors)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -312,15 +454,235 @@ data class UniversalBleDescriptor (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleDescriptor) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalBleDescriptor
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBlePeripheralConfig (
|
||||
val advertisedName: String,
|
||||
val services: List<UniversalBlePeripheralService>
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBlePeripheralConfig {
|
||||
val advertisedName = pigeonVar_list[0] as String
|
||||
val services = pigeonVar_list[1] as List<UniversalBlePeripheralService>
|
||||
return UniversalBlePeripheralConfig(advertisedName, services)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
advertisedName,
|
||||
services,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as UniversalBlePeripheralConfig
|
||||
return UniversalBlePigeonUtils.deepEquals(this.advertisedName, other.advertisedName) && UniversalBlePigeonUtils.deepEquals(this.services, other.services)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.advertisedName)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.services)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBlePeripheralService (
|
||||
val uuid: String,
|
||||
val characteristics: List<UniversalBlePeripheralCharacteristic>
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBlePeripheralService {
|
||||
val uuid = pigeonVar_list[0] as String
|
||||
val characteristics = pigeonVar_list[1] as List<UniversalBlePeripheralCharacteristic>
|
||||
return UniversalBlePeripheralService(uuid, characteristics)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
uuid,
|
||||
characteristics,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as UniversalBlePeripheralService
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid) && UniversalBlePigeonUtils.deepEquals(this.characteristics, other.characteristics)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.characteristics)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBlePeripheralCharacteristic (
|
||||
val uuid: String,
|
||||
val properties: List<Long>,
|
||||
val permissions: List<Long>,
|
||||
val descriptors: List<UniversalBlePeripheralDescriptor>,
|
||||
val initialValue: ByteArray? = null
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBlePeripheralCharacteristic {
|
||||
val uuid = pigeonVar_list[0] as String
|
||||
val properties = pigeonVar_list[1] as List<Long>
|
||||
val permissions = pigeonVar_list[2] as List<Long>
|
||||
val descriptors = pigeonVar_list[3] as List<UniversalBlePeripheralDescriptor>
|
||||
val initialValue = pigeonVar_list[4] as ByteArray?
|
||||
return UniversalBlePeripheralCharacteristic(uuid, properties, permissions, descriptors, initialValue)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
uuid,
|
||||
properties,
|
||||
permissions,
|
||||
descriptors,
|
||||
initialValue,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as UniversalBlePeripheralCharacteristic
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid) && UniversalBlePigeonUtils.deepEquals(this.properties, other.properties) && UniversalBlePigeonUtils.deepEquals(this.permissions, other.permissions) && UniversalBlePigeonUtils.deepEquals(this.descriptors, other.descriptors) && UniversalBlePigeonUtils.deepEquals(this.initialValue, other.initialValue)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.properties)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.permissions)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.descriptors)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.initialValue)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBlePeripheralDescriptor (
|
||||
val uuid: String,
|
||||
val permissions: List<Long>,
|
||||
val initialValue: ByteArray? = null
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBlePeripheralDescriptor {
|
||||
val uuid = pigeonVar_list[0] as String
|
||||
val permissions = pigeonVar_list[1] as List<Long>
|
||||
val initialValue = pigeonVar_list[2] as ByteArray?
|
||||
return UniversalBlePeripheralDescriptor(uuid, permissions, initialValue)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
uuid,
|
||||
permissions,
|
||||
initialValue,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as UniversalBlePeripheralDescriptor
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid) && UniversalBlePigeonUtils.deepEquals(this.permissions, other.permissions) && UniversalBlePigeonUtils.deepEquals(this.initialValue, other.initialValue)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.permissions)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.initialValue)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBlePeripheralWriteEvent (
|
||||
val deviceId: String,
|
||||
val service: String,
|
||||
val characteristic: String,
|
||||
val value: ByteArray
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBlePeripheralWriteEvent {
|
||||
val deviceId = pigeonVar_list[0] as String
|
||||
val service = pigeonVar_list[1] as String
|
||||
val characteristic = pigeonVar_list[2] as String
|
||||
val value = pigeonVar_list[3] as ByteArray
|
||||
return UniversalBlePeripheralWriteEvent(deviceId, service, characteristic, value)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
value,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as UniversalBlePeripheralWriteEvent
|
||||
return UniversalBlePigeonUtils.deepEquals(this.deviceId, other.deviceId) && UniversalBlePigeonUtils.deepEquals(this.service, other.service) && UniversalBlePigeonUtils.deepEquals(this.characteristic, other.characteristic) && UniversalBlePigeonUtils.deepEquals(this.value, other.value)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.deviceId)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.service)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.characteristic)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.value)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -355,15 +717,23 @@ data class AndroidOptions (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is AndroidOptions) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as AndroidOptions
|
||||
return UniversalBlePigeonUtils.deepEquals(this.requestLocationPermission, other.requestLocationPermission) && UniversalBlePigeonUtils.deepEquals(this.scanMode, other.scanMode) && UniversalBlePigeonUtils.deepEquals(this.reportDelayMillis, other.reportDelayMillis)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.requestLocationPermission)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.scanMode)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.reportDelayMillis)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -383,15 +753,21 @@ data class UniversalScanConfig (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalScanConfig) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalScanConfig
|
||||
return UniversalBlePigeonUtils.deepEquals(this.android, other.android)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.android)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -421,15 +797,23 @@ data class UniversalScanFilter (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalScanFilter) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalScanFilter
|
||||
return UniversalBlePigeonUtils.deepEquals(this.withServices, other.withServices) && UniversalBlePigeonUtils.deepEquals(this.withNamePrefix, other.withNamePrefix) && UniversalBlePigeonUtils.deepEquals(this.withManufacturerData, other.withManufacturerData)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.withServices)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.withNamePrefix)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.withManufacturerData)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -455,15 +839,23 @@ data class UniversalManufacturerDataFilter (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalManufacturerDataFilter) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalManufacturerDataFilter
|
||||
return UniversalBlePigeonUtils.deepEquals(this.companyIdentifier, other.companyIdentifier) && UniversalBlePigeonUtils.deepEquals(this.data, other.data) && UniversalBlePigeonUtils.deepEquals(this.mask, other.mask)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.companyIdentifier)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.data)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.mask)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -486,15 +878,22 @@ data class UniversalManufacturerData (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalManufacturerData) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalManufacturerData
|
||||
return UniversalBlePigeonUtils.deepEquals(this.companyIdentifier, other.companyIdentifier) && UniversalBlePigeonUtils.deepEquals(this.data, other.data)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.companyIdentifier)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.data)
|
||||
return result
|
||||
}
|
||||
}
|
||||
private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
@@ -536,25 +935,50 @@ private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||
}
|
||||
136.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
AndroidOptions.fromList(it)
|
||||
UniversalBlePeripheralConfig.fromList(it)
|
||||
}
|
||||
}
|
||||
137.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalScanConfig.fromList(it)
|
||||
UniversalBlePeripheralService.fromList(it)
|
||||
}
|
||||
}
|
||||
138.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalScanFilter.fromList(it)
|
||||
UniversalBlePeripheralCharacteristic.fromList(it)
|
||||
}
|
||||
}
|
||||
139.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalManufacturerDataFilter.fromList(it)
|
||||
UniversalBlePeripheralDescriptor.fromList(it)
|
||||
}
|
||||
}
|
||||
140.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalBlePeripheralWriteEvent.fromList(it)
|
||||
}
|
||||
}
|
||||
141.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
AndroidOptions.fromList(it)
|
||||
}
|
||||
}
|
||||
142.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalScanConfig.fromList(it)
|
||||
}
|
||||
}
|
||||
143.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalScanFilter.fromList(it)
|
||||
}
|
||||
}
|
||||
144.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalManufacturerDataFilter.fromList(it)
|
||||
}
|
||||
}
|
||||
145.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalManufacturerData.fromList(it)
|
||||
}
|
||||
@@ -592,26 +1016,46 @@ private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||
stream.write(135)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is AndroidOptions -> {
|
||||
is UniversalBlePeripheralConfig -> {
|
||||
stream.write(136)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalScanConfig -> {
|
||||
is UniversalBlePeripheralService -> {
|
||||
stream.write(137)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalScanFilter -> {
|
||||
is UniversalBlePeripheralCharacteristic -> {
|
||||
stream.write(138)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerDataFilter -> {
|
||||
is UniversalBlePeripheralDescriptor -> {
|
||||
stream.write(139)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerData -> {
|
||||
is UniversalBlePeripheralWriteEvent -> {
|
||||
stream.write(140)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is AndroidOptions -> {
|
||||
stream.write(141)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalScanConfig -> {
|
||||
stream.write(142)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalScanFilter -> {
|
||||
stream.write(143)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerDataFilter -> {
|
||||
stream.write(144)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerData -> {
|
||||
stream.write(145)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
@@ -625,8 +1069,8 @@ private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||
*/
|
||||
interface UniversalBlePlatformChannel {
|
||||
fun getBluetoothAvailabilityState(callback: (Result<Long>) -> Unit)
|
||||
fun hasPermissions(withAndroidFineLocation: Boolean): Boolean
|
||||
fun requestPermissions(withAndroidFineLocation: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
fun hasPermissions(withAndroidFineLocation: Boolean, withAndroidBluetoothAdvertise: Boolean): Boolean
|
||||
fun requestPermissions(withAndroidFineLocation: Boolean, withAndroidBluetoothAdvertise: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
fun enableBluetooth(callback: (Result<Boolean>) -> Unit)
|
||||
fun disableBluetooth(callback: (Result<Boolean>) -> Unit)
|
||||
fun startScan(filter: UniversalScanFilter?, config: UniversalScanConfig?)
|
||||
@@ -646,6 +1090,11 @@ interface UniversalBlePlatformChannel {
|
||||
fun getConnectionState(deviceId: String): Long
|
||||
fun readRssi(deviceId: String, callback: (Result<Long>) -> Unit)
|
||||
fun requestConnectionPriority(deviceId: String, priority: Long, callback: (Result<Unit>) -> Unit)
|
||||
fun isPeripheralSupported(): Boolean
|
||||
fun startPeripheral(config: UniversalBlePeripheralConfig, callback: (Result<Unit>) -> Unit)
|
||||
fun stopPeripheral(callback: (Result<Unit>) -> Unit)
|
||||
fun updatePeripheralCharacteristicValue(service: String, characteristic: String, value: ByteArray, callback: (Result<Unit>) -> Unit)
|
||||
fun notifyPeripheralCharacteristic(service: String, characteristic: String, value: ByteArray, indicate: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
fun setLogLevel(logLevel: UniversalBleLogLevel)
|
||||
|
||||
companion object {
|
||||
@@ -681,8 +1130,9 @@ interface UniversalBlePlatformChannel {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val withAndroidFineLocationArg = args[0] as Boolean
|
||||
val withAndroidBluetoothAdvertiseArg = args[1] as Boolean
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.hasPermissions(withAndroidFineLocationArg))
|
||||
listOf(api.hasPermissions(withAndroidFineLocationArg, withAndroidBluetoothAdvertiseArg))
|
||||
} catch (exception: Throwable) {
|
||||
UniversalBlePigeonUtils.wrapError(exception)
|
||||
}
|
||||
@@ -698,7 +1148,8 @@ interface UniversalBlePlatformChannel {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val withAndroidFineLocationArg = args[0] as Boolean
|
||||
api.requestPermissions(withAndroidFineLocationArg) { result: Result<Unit> ->
|
||||
val withAndroidBluetoothAdvertiseArg = args[1] as Boolean
|
||||
api.requestPermissions(withAndroidFineLocationArg, withAndroidBluetoothAdvertiseArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
@@ -1078,6 +1529,100 @@ interface UniversalBlePlatformChannel {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPeripheralSupported$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.isPeripheralSupported())
|
||||
} catch (exception: Throwable) {
|
||||
UniversalBlePigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startPeripheral$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val configArg = args[0] as UniversalBlePeripheralConfig
|
||||
api.startPeripheral(configArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopPeripheral$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.stopPeripheral{ result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.updatePeripheralCharacteristicValue$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val serviceArg = args[0] as String
|
||||
val characteristicArg = args[1] as String
|
||||
val valueArg = args[2] as ByteArray
|
||||
api.updatePeripheralCharacteristicValue(serviceArg, characteristicArg, valueArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.notifyPeripheralCharacteristic$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val serviceArg = args[0] as String
|
||||
val characteristicArg = args[1] as String
|
||||
val valueArg = args[2] as ByteArray
|
||||
val indicateArg = args[3] as Boolean
|
||||
api.notifyPeripheralCharacteristic(serviceArg, characteristicArg, valueArg, indicateArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setLogLevel$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
@@ -1125,7 +1670,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onPairStateChange(deviceIdArg: String, isPairedArg: Boolean, errorArg: String?, callback: (Result<Unit>) -> Unit)
|
||||
@@ -1142,7 +1687,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onScanResult(resultArg: UniversalBleScanResult, callback: (Result<Unit>) -> Unit)
|
||||
@@ -1159,7 +1704,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onValueChanged(deviceIdArg: String, characteristicIdArg: String, valueArg: ByteArray, timestampArg: Long?, callback: (Result<Unit>) -> Unit)
|
||||
@@ -1176,7 +1721,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onConnectionChanged(deviceIdArg: String, connectedArg: Boolean, errorArg: String?, callback: (Result<Unit>) -> Unit)
|
||||
@@ -1193,7 +1738,58 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onPeripheralConnectionChanged(deviceIdArg: String, connectedArg: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPeripheralConnectionChanged$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(deviceIdArg, connectedArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onPeripheralWrite(eventArg: UniversalBlePeripheralWriteEvent, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPeripheralWrite$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(eventArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onPeripheralSubscriptionChanged(deviceIdArg: String, serviceArg: String, characteristicArg: String, subscribedArg: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPeripheralSubscriptionChanged$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(deviceIdArg, serviceArg, characteristicArg, subscribedArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,16 @@ import android.bluetooth.BluetoothGatt
|
||||
import android.bluetooth.BluetoothGattCallback
|
||||
import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothGattDescriptor
|
||||
import android.bluetooth.BluetoothGattServer
|
||||
import android.bluetooth.BluetoothGattServerCallback
|
||||
import android.bluetooth.BluetoothGattService
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.BluetoothProfile
|
||||
import android.bluetooth.BluetoothStatusCodes
|
||||
import android.bluetooth.le.AdvertiseCallback
|
||||
import android.bluetooth.le.AdvertiseData
|
||||
import android.bluetooth.le.AdvertiseSettings
|
||||
import android.bluetooth.le.BluetoothLeAdvertiser
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanFilter
|
||||
import android.bluetooth.le.ScanResult
|
||||
@@ -24,6 +31,7 @@ import android.content.IntentFilter
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.ParcelUuid
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
@@ -63,6 +71,12 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
private val rssiResultFutureList = mutableListOf<RssiResultFuture>()
|
||||
private val autoConnectDevices = mutableSetOf<String>()
|
||||
|
||||
private var peripheralGattServer: BluetoothGattServer? = null
|
||||
private var peripheralAdvertiser: BluetoothLeAdvertiser? = null
|
||||
private var peripheralPendingStartCallback: ((Result<Unit>) -> Unit)? = null
|
||||
private val peripheralConnectedDevices = mutableSetOf<BluetoothDevice>()
|
||||
private val peripheralCharacteristics = mutableMapOf<String, BluetoothGattCharacteristic>()
|
||||
|
||||
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
UniversalBlePlatformChannel.setUp(flutterPluginBinding.binaryMessenger, this)
|
||||
callbackChannel = UniversalBleCallbackChannel(flutterPluginBinding.binaryMessenger)
|
||||
@@ -84,6 +98,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
|
||||
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||||
bluetoothManager.adapter.bluetoothLeScanner?.stopScan(scanCallback)
|
||||
stopPeripheralInternal()
|
||||
context.unregisterReceiver(broadcastReceiver)
|
||||
callbackChannel = null
|
||||
mainThreadHandler = null
|
||||
@@ -99,12 +114,19 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun hasPermissions(withAndroidFineLocation: Boolean): Boolean {
|
||||
return permissionHandler?.hasPermissions(withAndroidFineLocation) ?: false
|
||||
override fun hasPermissions(
|
||||
withAndroidFineLocation: Boolean,
|
||||
withAndroidBluetoothAdvertise: Boolean,
|
||||
): Boolean {
|
||||
return permissionHandler?.hasPermissions(
|
||||
withAndroidFineLocation,
|
||||
withAndroidBluetoothAdvertise,
|
||||
) ?: false
|
||||
}
|
||||
|
||||
override fun requestPermissions(
|
||||
withAndroidFineLocation: Boolean,
|
||||
withAndroidBluetoothAdvertise: Boolean,
|
||||
callback: (Result<Unit>) -> Unit,
|
||||
) {
|
||||
if (permissionHandler == null) {
|
||||
@@ -117,7 +139,11 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
)
|
||||
)
|
||||
}
|
||||
permissionHandler?.requestPermissions(withAndroidFineLocation, callback)
|
||||
permissionHandler?.requestPermissions(
|
||||
withAndroidFineLocation,
|
||||
withAndroidBluetoothAdvertise,
|
||||
callback,
|
||||
)
|
||||
}
|
||||
|
||||
override fun enableBluetooth(callback: (Result<Boolean>) -> Unit) {
|
||||
@@ -801,6 +827,319 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun isPeripheralSupported(): Boolean {
|
||||
val adapter = bluetoothManager.adapter ?: return false
|
||||
return adapter.isEnabled && adapter.isMultipleAdvertisementSupported
|
||||
}
|
||||
|
||||
override fun startPeripheral(
|
||||
config: UniversalBlePeripheralConfig,
|
||||
callback: (Result<Unit>) -> Unit,
|
||||
) {
|
||||
val adapter = bluetoothManager.adapter
|
||||
if (adapter == null || !adapter.isEnabled) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.BLUETOOTH_NOT_ENABLED,
|
||||
"Bluetooth not enabled"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
if (!adapter.isMultipleAdvertisementSupported) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.NOT_SUPPORTED,
|
||||
"BLE peripheral advertising is not supported on this device"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
if (peripheralPendingStartCallback != null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.OPERATION_IN_PROGRESS,
|
||||
"Peripheral start already in progress"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
stopPeripheralInternal()
|
||||
|
||||
val server = bluetoothManager.openGattServer(context, peripheralGattServerCallback)
|
||||
if (server == null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Unable to open GATT server"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
peripheralCharacteristics.clear()
|
||||
config.services.forEach { serviceConfig ->
|
||||
val service = BluetoothGattService(
|
||||
UUID.fromString(serviceConfig.uuid),
|
||||
BluetoothGattService.SERVICE_TYPE_PRIMARY,
|
||||
)
|
||||
serviceConfig.characteristics.forEach { characteristicConfig ->
|
||||
val characteristic = BluetoothGattCharacteristic(
|
||||
UUID.fromString(characteristicConfig.uuid),
|
||||
characteristicConfig.properties.toPeripheralPropertyFlags(),
|
||||
characteristicConfig.permissions.toPeripheralPermissionFlags(),
|
||||
)
|
||||
@Suppress("DEPRECATION")
|
||||
characteristic.value = characteristicConfig.initialValue ?: ByteArray(0)
|
||||
characteristicConfig.descriptors.forEach { descriptorConfig ->
|
||||
val descriptor = BluetoothGattDescriptor(
|
||||
UUID.fromString(descriptorConfig.uuid),
|
||||
descriptorConfig.permissions.toPeripheralPermissionFlags(),
|
||||
)
|
||||
@Suppress("DEPRECATION")
|
||||
descriptor.value = descriptorConfig.initialValue ?: ByteArray(0)
|
||||
characteristic.addDescriptor(descriptor)
|
||||
}
|
||||
if (characteristicConfig.properties.any {
|
||||
it == CharacteristicProperty.Notify.value ||
|
||||
it == CharacteristicProperty.Indicate.value
|
||||
} && characteristic.getDescriptor(ccdCharacteristic) == null
|
||||
) {
|
||||
characteristic.addDescriptor(
|
||||
BluetoothGattDescriptor(
|
||||
ccdCharacteristic,
|
||||
BluetoothGattDescriptor.PERMISSION_READ or
|
||||
BluetoothGattDescriptor.PERMISSION_WRITE,
|
||||
)
|
||||
)
|
||||
}
|
||||
service.addCharacteristic(characteristic)
|
||||
peripheralCharacteristics[peripheralCharacteristicKey(serviceConfig.uuid, characteristicConfig.uuid)] = characteristic
|
||||
}
|
||||
if (!server.addService(service)) {
|
||||
throw createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to add GATT service ${serviceConfig.uuid}"
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e: FlutterError) {
|
||||
server.close()
|
||||
peripheralCharacteristics.clear()
|
||||
callback(Result.failure(e))
|
||||
return
|
||||
} catch (e: Exception) {
|
||||
server.close()
|
||||
peripheralCharacteristics.clear()
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to create GATT services",
|
||||
e.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
peripheralGattServer = server
|
||||
try {
|
||||
adapter.name = config.advertisedName
|
||||
} catch (_: SecurityException) {
|
||||
}
|
||||
|
||||
val advertiser = adapter.bluetoothLeAdvertiser
|
||||
if (advertiser == null) {
|
||||
stopPeripheralInternal()
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.NOT_SUPPORTED,
|
||||
"BLE advertiser not available"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val settings = AdvertiseSettings.Builder()
|
||||
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
|
||||
.setConnectable(true)
|
||||
.setTimeout(0)
|
||||
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
|
||||
.build()
|
||||
val dataBuilder = AdvertiseData.Builder().setIncludeDeviceName(true)
|
||||
config.services.forEach { service ->
|
||||
dataBuilder.addServiceUuid(ParcelUuid(UUID.fromString(service.uuid)))
|
||||
}
|
||||
peripheralAdvertiser = advertiser
|
||||
peripheralPendingStartCallback = callback
|
||||
advertiser.startAdvertising(settings, dataBuilder.build(), peripheralAdvertiseCallback)
|
||||
}
|
||||
|
||||
override fun stopPeripheral(callback: (Result<Unit>) -> Unit) {
|
||||
peripheralPendingStartCallback?.invoke(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.OPERATION_CANCELLED,
|
||||
"Peripheral start cancelled"
|
||||
)
|
||||
)
|
||||
)
|
||||
peripheralPendingStartCallback = null
|
||||
stopPeripheralInternal()
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
|
||||
override fun updatePeripheralCharacteristicValue(
|
||||
service: String,
|
||||
characteristic: String,
|
||||
value: ByteArray,
|
||||
callback: (Result<Unit>) -> Unit,
|
||||
) {
|
||||
val gattCharacteristic = peripheralCharacteristics[peripheralCharacteristicKey(service, characteristic)]
|
||||
if (gattCharacteristic == null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||
"Unknown peripheral characteristic $characteristic"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
gattCharacteristic.value = value
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
|
||||
override fun notifyPeripheralCharacteristic(
|
||||
service: String,
|
||||
characteristic: String,
|
||||
value: ByteArray,
|
||||
indicate: Boolean,
|
||||
callback: (Result<Unit>) -> Unit,
|
||||
) {
|
||||
val server = peripheralGattServer
|
||||
val gattCharacteristic = peripheralCharacteristics[peripheralCharacteristicKey(service, characteristic)]
|
||||
if (server == null || gattCharacteristic == null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||
"Unknown peripheral characteristic $characteristic"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
gattCharacteristic.value = value
|
||||
val devices = synchronized(peripheralConnectedDevices) {
|
||||
peripheralConnectedDevices.toList()
|
||||
}
|
||||
devices.forEach { device ->
|
||||
server.notifyCharacteristicChanged(device, gattCharacteristic, indicate)
|
||||
}
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
|
||||
private fun stopPeripheralInternal() {
|
||||
peripheralAdvertiser?.stopAdvertising(peripheralAdvertiseCallback)
|
||||
peripheralAdvertiser = null
|
||||
peripheralGattServer?.close()
|
||||
peripheralGattServer = null
|
||||
synchronized(peripheralConnectedDevices) {
|
||||
peripheralConnectedDevices.clear()
|
||||
}
|
||||
peripheralCharacteristics.clear()
|
||||
}
|
||||
|
||||
private fun peripheralCharacteristicKey(service: String, characteristic: String): String {
|
||||
return "${service.lowercase()}|${characteristic.lowercase()}"
|
||||
}
|
||||
|
||||
private fun List<Long>.toPeripheralPropertyFlags(): Int {
|
||||
var flags = 0
|
||||
forEach { property ->
|
||||
when (CharacteristicProperty.entries.firstOrNull { it.value == property }) {
|
||||
CharacteristicProperty.Broadcast -> flags = flags or BluetoothGattCharacteristic.PROPERTY_BROADCAST
|
||||
CharacteristicProperty.Read -> flags = flags or BluetoothGattCharacteristic.PROPERTY_READ
|
||||
CharacteristicProperty.WriteWithoutResponse -> flags = flags or BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE
|
||||
CharacteristicProperty.Write -> flags = flags or BluetoothGattCharacteristic.PROPERTY_WRITE
|
||||
CharacteristicProperty.Notify -> flags = flags or BluetoothGattCharacteristic.PROPERTY_NOTIFY
|
||||
CharacteristicProperty.Indicate -> flags = flags or BluetoothGattCharacteristic.PROPERTY_INDICATE
|
||||
CharacteristicProperty.AuthenticatedSignedWrites -> flags = flags or BluetoothGattCharacteristic.PROPERTY_SIGNED_WRITE
|
||||
CharacteristicProperty.ExtendedProperties -> flags = flags or BluetoothGattCharacteristic.PROPERTY_EXTENDED_PROPS
|
||||
null -> {}
|
||||
}
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
private fun List<Long>.toPeripheralPermissionFlags(): Int {
|
||||
var flags = 0
|
||||
forEach { permission ->
|
||||
when (permission) {
|
||||
0L -> flags = flags or BluetoothGattCharacteristic.PERMISSION_READ
|
||||
1L -> flags = flags or BluetoothGattCharacteristic.PERMISSION_WRITE
|
||||
}
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
private fun callbackPeripheralConnection(deviceId: String, connected: Boolean) {
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onPeripheralConnectionChanged(deviceId, connected) {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun callbackPeripheralSubscription(
|
||||
deviceId: String,
|
||||
service: String,
|
||||
characteristic: String,
|
||||
subscribed: Boolean,
|
||||
) {
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onPeripheralSubscriptionChanged(
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
subscribed,
|
||||
) {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun callbackPeripheralWrite(
|
||||
deviceId: String,
|
||||
service: String,
|
||||
characteristic: String,
|
||||
value: ByteArray,
|
||||
) {
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onPeripheralWrite(
|
||||
UniversalBlePeripheralWriteEvent(
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
value,
|
||||
)
|
||||
) {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
|
||||
val deviceId = gatt?.device?.address ?: return
|
||||
mtuResultFutureList.removeAll {
|
||||
@@ -1191,6 +1530,157 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
}
|
||||
|
||||
private val peripheralAdvertiseCallback = object : AdvertiseCallback() {
|
||||
override fun onStartSuccess(settingsInEffect: AdvertiseSettings) {
|
||||
peripheralPendingStartCallback?.invoke(Result.success(Unit))
|
||||
peripheralPendingStartCallback = null
|
||||
}
|
||||
|
||||
override fun onStartFailure(errorCode: Int) {
|
||||
peripheralPendingStartCallback?.invoke(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"BLE advertising failed with code $errorCode",
|
||||
errorCode.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
peripheralPendingStartCallback = null
|
||||
stopPeripheralInternal()
|
||||
}
|
||||
}
|
||||
|
||||
private val peripheralGattServerCallback = object : BluetoothGattServerCallback() {
|
||||
override fun onConnectionStateChange(device: BluetoothDevice, status: Int, newState: Int) {
|
||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
synchronized(peripheralConnectedDevices) {
|
||||
peripheralConnectedDevices.add(device)
|
||||
}
|
||||
callbackPeripheralConnection(device.address, true)
|
||||
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
synchronized(peripheralConnectedDevices) {
|
||||
peripheralConnectedDevices.remove(device)
|
||||
}
|
||||
callbackPeripheralConnection(device.address, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCharacteristicReadRequest(
|
||||
device: BluetoothDevice,
|
||||
requestId: Int,
|
||||
offset: Int,
|
||||
characteristic: BluetoothGattCharacteristic,
|
||||
) {
|
||||
@Suppress("DEPRECATION")
|
||||
val value = characteristic.value ?: ByteArray(0)
|
||||
if (offset > value.size) {
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_INVALID_OFFSET,
|
||||
offset,
|
||||
null,
|
||||
)
|
||||
return
|
||||
}
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_SUCCESS,
|
||||
offset,
|
||||
value.copyOfRange(offset, value.size),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCharacteristicWriteRequest(
|
||||
device: BluetoothDevice,
|
||||
requestId: Int,
|
||||
characteristic: BluetoothGattCharacteristic,
|
||||
preparedWrite: Boolean,
|
||||
responseNeeded: Boolean,
|
||||
offset: Int,
|
||||
value: ByteArray,
|
||||
) {
|
||||
@Suppress("DEPRECATION")
|
||||
characteristic.value = value
|
||||
if (responseNeeded) {
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_SUCCESS,
|
||||
offset,
|
||||
null,
|
||||
)
|
||||
}
|
||||
callbackPeripheralWrite(
|
||||
device.address,
|
||||
characteristic.service.uuid.toString(),
|
||||
characteristic.uuid.toString(),
|
||||
value,
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDescriptorReadRequest(
|
||||
device: BluetoothDevice,
|
||||
requestId: Int,
|
||||
offset: Int,
|
||||
descriptor: BluetoothGattDescriptor,
|
||||
) {
|
||||
@Suppress("DEPRECATION")
|
||||
val value = descriptor.value ?: ByteArray(0)
|
||||
if (offset > value.size) {
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_INVALID_OFFSET,
|
||||
offset,
|
||||
null,
|
||||
)
|
||||
return
|
||||
}
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_SUCCESS,
|
||||
offset,
|
||||
value.copyOfRange(offset, value.size),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDescriptorWriteRequest(
|
||||
device: BluetoothDevice,
|
||||
requestId: Int,
|
||||
descriptor: BluetoothGattDescriptor,
|
||||
preparedWrite: Boolean,
|
||||
responseNeeded: Boolean,
|
||||
offset: Int,
|
||||
value: ByteArray,
|
||||
) {
|
||||
@Suppress("DEPRECATION")
|
||||
descriptor.value = value
|
||||
if (responseNeeded) {
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_SUCCESS,
|
||||
offset,
|
||||
null,
|
||||
)
|
||||
}
|
||||
if (descriptor.uuid == ccdCharacteristic) {
|
||||
val subscribed = value.contentEquals(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE) ||
|
||||
value.contentEquals(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)
|
||||
callbackPeripheralSubscription(
|
||||
device.address,
|
||||
descriptor.characteristic.service.uuid.toString(),
|
||||
descriptor.characteristic.uuid.toString(),
|
||||
subscribed,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onConnectionStateChange(
|
||||
gatt: BluetoothGatt,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Autogenerated from Pigeon (v26.1.4), do not edit directly.
|
||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
import Foundation
|
||||
@@ -50,7 +50,7 @@ private func wrapError(_ error: Any) -> [Any?] {
|
||||
}
|
||||
return [
|
||||
"\(error)",
|
||||
"\(type(of: error))",
|
||||
"\(Swift.type(of: error))",
|
||||
"Stacktrace: \(Thread.callStackSymbols)",
|
||||
]
|
||||
}
|
||||
@@ -68,6 +68,19 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
|
||||
return value as! T?
|
||||
}
|
||||
|
||||
private func doubleEqualsUniversalBle(_ lhs: Double, _ rhs: Double) -> Bool {
|
||||
return (lhs.isNaN && rhs.isNaN) || lhs == rhs
|
||||
}
|
||||
|
||||
private func doubleHashUniversalBle(_ value: Double, _ hasher: inout Hasher) {
|
||||
if value.isNaN {
|
||||
hasher.combine(0x7FF8000000000000)
|
||||
} else {
|
||||
// Normalize -0.0 to 0.0
|
||||
hasher.combine(value == 0 ? 0 : value)
|
||||
}
|
||||
}
|
||||
|
||||
func deepEqualsUniversalBle(_ lhs: Any?, _ rhs: Any?) -> Bool {
|
||||
let cleanLhs = nilOrValue(lhs) as Any?
|
||||
let cleanRhs = nilOrValue(rhs) as Any?
|
||||
@@ -78,59 +91,92 @@ func deepEqualsUniversalBle(_ lhs: Any?, _ rhs: Any?) -> Bool {
|
||||
case (nil, _), (_, nil):
|
||||
return false
|
||||
|
||||
case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs:
|
||||
return true
|
||||
|
||||
case is (Void, Void):
|
||||
return true
|
||||
|
||||
case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable):
|
||||
return cleanLhsHashable == cleanRhsHashable
|
||||
|
||||
case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]):
|
||||
guard cleanLhsArray.count == cleanRhsArray.count else { return false }
|
||||
for (index, element) in cleanLhsArray.enumerated() {
|
||||
if !deepEqualsUniversalBle(element, cleanRhsArray[index]) {
|
||||
case (let lhsArray, let rhsArray) as ([Any?], [Any?]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !deepEqualsUniversalBle(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
|
||||
guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false }
|
||||
for (key, cleanLhsValue) in cleanLhsDictionary {
|
||||
guard cleanRhsDictionary.index(forKey: key) != nil else { return false }
|
||||
if !deepEqualsUniversalBle(cleanLhsValue, cleanRhsDictionary[key]!) {
|
||||
case (let lhsArray, let rhsArray) as ([Double], [Double]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !doubleEqualsUniversalBle(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
|
||||
guard lhsDictionary.count == rhsDictionary.count else { return false }
|
||||
for (lhsKey, lhsValue) in lhsDictionary {
|
||||
var found = false
|
||||
for (rhsKey, rhsValue) in rhsDictionary {
|
||||
if deepEqualsUniversalBle(lhsKey, rhsKey) {
|
||||
if deepEqualsUniversalBle(lhsValue, rhsValue) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found { return false }
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhs as Double, let rhs as Double):
|
||||
return doubleEqualsUniversalBle(lhs, rhs)
|
||||
|
||||
case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable):
|
||||
return lhsHashable == rhsHashable
|
||||
|
||||
default:
|
||||
// Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue.
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func deepHashUniversalBle(value: Any?, hasher: inout Hasher) {
|
||||
if let valueList = value as? [AnyHashable] {
|
||||
for item in valueList { deepHashUniversalBle(value: item, hasher: &hasher) }
|
||||
return
|
||||
}
|
||||
|
||||
if let valueDict = value as? [AnyHashable: AnyHashable] {
|
||||
for key in valueDict.keys {
|
||||
hasher.combine(key)
|
||||
deepHashUniversalBle(value: valueDict[key]!, hasher: &hasher)
|
||||
let cleanValue = nilOrValue(value) as Any?
|
||||
if let cleanValue = cleanValue {
|
||||
if let doubleValue = cleanValue as? Double {
|
||||
doubleHashUniversalBle(doubleValue, &hasher)
|
||||
} else if let valueList = cleanValue as? [Any?] {
|
||||
for item in valueList {
|
||||
deepHashUniversalBle(value: item, hasher: &hasher)
|
||||
}
|
||||
} else if let valueList = cleanValue as? [Double] {
|
||||
for item in valueList {
|
||||
doubleHashUniversalBle(item, &hasher)
|
||||
}
|
||||
} else if let valueDict = cleanValue as? [AnyHashable: Any?] {
|
||||
var result = 0
|
||||
for (key, value) in valueDict {
|
||||
var entryKeyHasher = Hasher()
|
||||
deepHashUniversalBle(value: key, hasher: &entryKeyHasher)
|
||||
var entryValueHasher = Hasher()
|
||||
deepHashUniversalBle(value: value, hasher: &entryValueHasher)
|
||||
result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize())
|
||||
}
|
||||
hasher.combine(result)
|
||||
} else if let hashableValue = cleanValue as? AnyHashable {
|
||||
hasher.combine(hashableValue)
|
||||
} else {
|
||||
hasher.combine(String(describing: cleanValue))
|
||||
}
|
||||
return
|
||||
} else {
|
||||
hasher.combine(0)
|
||||
}
|
||||
|
||||
if let hashableValue = value as? AnyHashable {
|
||||
hasher.combine(hashableValue.hashValue)
|
||||
}
|
||||
|
||||
return hasher.combine(String(describing: value))
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum UniversalBleLogLevel: Int {
|
||||
case none = 0
|
||||
@@ -261,9 +307,22 @@ struct UniversalBleScanResult: Hashable {
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalBleScanResult, rhs: UniversalBleScanResult) -> Bool {
|
||||
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.deviceId, rhs.deviceId) && deepEqualsUniversalBle(lhs.name, rhs.name) && deepEqualsUniversalBle(lhs.isPaired, rhs.isPaired) && deepEqualsUniversalBle(lhs.rssi, rhs.rssi) && deepEqualsUniversalBle(lhs.manufacturerDataList, rhs.manufacturerDataList) && deepEqualsUniversalBle(lhs.serviceData, rhs.serviceData) && deepEqualsUniversalBle(lhs.services, rhs.services) && deepEqualsUniversalBle(lhs.timestamp, rhs.timestamp)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||
hasher.combine("UniversalBleScanResult")
|
||||
deepHashUniversalBle(value: deviceId, hasher: &hasher)
|
||||
deepHashUniversalBle(value: name, hasher: &hasher)
|
||||
deepHashUniversalBle(value: isPaired, hasher: &hasher)
|
||||
deepHashUniversalBle(value: rssi, hasher: &hasher)
|
||||
deepHashUniversalBle(value: manufacturerDataList, hasher: &hasher)
|
||||
deepHashUniversalBle(value: serviceData, hasher: &hasher)
|
||||
deepHashUniversalBle(value: services, hasher: &hasher)
|
||||
deepHashUniversalBle(value: timestamp, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,9 +349,16 @@ struct UniversalBleService: Hashable {
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalBleService, rhs: UniversalBleService) -> Bool {
|
||||
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.uuid, rhs.uuid) && deepEqualsUniversalBle(lhs.characteristics, rhs.characteristics)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||
hasher.combine("UniversalBleService")
|
||||
deepHashUniversalBle(value: uuid, hasher: &hasher)
|
||||
deepHashUniversalBle(value: characteristics, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,9 +389,17 @@ struct UniversalBleCharacteristic: Hashable {
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalBleCharacteristic, rhs: UniversalBleCharacteristic) -> Bool {
|
||||
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.uuid, rhs.uuid) && deepEqualsUniversalBle(lhs.properties, rhs.properties) && deepEqualsUniversalBle(lhs.descriptors, rhs.descriptors)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||
hasher.combine("UniversalBleCharacteristic")
|
||||
deepHashUniversalBle(value: uuid, hasher: &hasher)
|
||||
deepHashUniversalBle(value: properties, hasher: &hasher)
|
||||
deepHashUniversalBle(value: descriptors, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,9 +422,225 @@ struct UniversalBleDescriptor: Hashable {
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalBleDescriptor, rhs: UniversalBleDescriptor) -> Bool {
|
||||
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.uuid, rhs.uuid)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||
hasher.combine("UniversalBleDescriptor")
|
||||
deepHashUniversalBle(value: uuid, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct UniversalBlePeripheralConfig: Hashable {
|
||||
var advertisedName: String
|
||||
var services: [UniversalBlePeripheralService]
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBlePeripheralConfig? {
|
||||
let advertisedName = pigeonVar_list[0] as! String
|
||||
let services = pigeonVar_list[1] as! [UniversalBlePeripheralService]
|
||||
|
||||
return UniversalBlePeripheralConfig(
|
||||
advertisedName: advertisedName,
|
||||
services: services
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
advertisedName,
|
||||
services,
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalBlePeripheralConfig, rhs: UniversalBlePeripheralConfig) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.advertisedName, rhs.advertisedName) && deepEqualsUniversalBle(lhs.services, rhs.services)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("UniversalBlePeripheralConfig")
|
||||
deepHashUniversalBle(value: advertisedName, hasher: &hasher)
|
||||
deepHashUniversalBle(value: services, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct UniversalBlePeripheralService: Hashable {
|
||||
var uuid: String
|
||||
var characteristics: [UniversalBlePeripheralCharacteristic]
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBlePeripheralService? {
|
||||
let uuid = pigeonVar_list[0] as! String
|
||||
let characteristics = pigeonVar_list[1] as! [UniversalBlePeripheralCharacteristic]
|
||||
|
||||
return UniversalBlePeripheralService(
|
||||
uuid: uuid,
|
||||
characteristics: characteristics
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
uuid,
|
||||
characteristics,
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalBlePeripheralService, rhs: UniversalBlePeripheralService) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.uuid, rhs.uuid) && deepEqualsUniversalBle(lhs.characteristics, rhs.characteristics)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("UniversalBlePeripheralService")
|
||||
deepHashUniversalBle(value: uuid, hasher: &hasher)
|
||||
deepHashUniversalBle(value: characteristics, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct UniversalBlePeripheralCharacteristic: Hashable {
|
||||
var uuid: String
|
||||
var properties: [Int64]
|
||||
var permissions: [Int64]
|
||||
var descriptors: [UniversalBlePeripheralDescriptor]
|
||||
var initialValue: FlutterStandardTypedData? = nil
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBlePeripheralCharacteristic? {
|
||||
let uuid = pigeonVar_list[0] as! String
|
||||
let properties = pigeonVar_list[1] as! [Int64]
|
||||
let permissions = pigeonVar_list[2] as! [Int64]
|
||||
let descriptors = pigeonVar_list[3] as! [UniversalBlePeripheralDescriptor]
|
||||
let initialValue: FlutterStandardTypedData? = nilOrValue(pigeonVar_list[4])
|
||||
|
||||
return UniversalBlePeripheralCharacteristic(
|
||||
uuid: uuid,
|
||||
properties: properties,
|
||||
permissions: permissions,
|
||||
descriptors: descriptors,
|
||||
initialValue: initialValue
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
uuid,
|
||||
properties,
|
||||
permissions,
|
||||
descriptors,
|
||||
initialValue,
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalBlePeripheralCharacteristic, rhs: UniversalBlePeripheralCharacteristic) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.uuid, rhs.uuid) && deepEqualsUniversalBle(lhs.properties, rhs.properties) && deepEqualsUniversalBle(lhs.permissions, rhs.permissions) && deepEqualsUniversalBle(lhs.descriptors, rhs.descriptors) && deepEqualsUniversalBle(lhs.initialValue, rhs.initialValue)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("UniversalBlePeripheralCharacteristic")
|
||||
deepHashUniversalBle(value: uuid, hasher: &hasher)
|
||||
deepHashUniversalBle(value: properties, hasher: &hasher)
|
||||
deepHashUniversalBle(value: permissions, hasher: &hasher)
|
||||
deepHashUniversalBle(value: descriptors, hasher: &hasher)
|
||||
deepHashUniversalBle(value: initialValue, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct UniversalBlePeripheralDescriptor: Hashable {
|
||||
var uuid: String
|
||||
var permissions: [Int64]
|
||||
var initialValue: FlutterStandardTypedData? = nil
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBlePeripheralDescriptor? {
|
||||
let uuid = pigeonVar_list[0] as! String
|
||||
let permissions = pigeonVar_list[1] as! [Int64]
|
||||
let initialValue: FlutterStandardTypedData? = nilOrValue(pigeonVar_list[2])
|
||||
|
||||
return UniversalBlePeripheralDescriptor(
|
||||
uuid: uuid,
|
||||
permissions: permissions,
|
||||
initialValue: initialValue
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
uuid,
|
||||
permissions,
|
||||
initialValue,
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalBlePeripheralDescriptor, rhs: UniversalBlePeripheralDescriptor) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.uuid, rhs.uuid) && deepEqualsUniversalBle(lhs.permissions, rhs.permissions) && deepEqualsUniversalBle(lhs.initialValue, rhs.initialValue)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("UniversalBlePeripheralDescriptor")
|
||||
deepHashUniversalBle(value: uuid, hasher: &hasher)
|
||||
deepHashUniversalBle(value: permissions, hasher: &hasher)
|
||||
deepHashUniversalBle(value: initialValue, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct UniversalBlePeripheralWriteEvent: Hashable {
|
||||
var deviceId: String
|
||||
var service: String
|
||||
var characteristic: String
|
||||
var value: FlutterStandardTypedData
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBlePeripheralWriteEvent? {
|
||||
let deviceId = pigeonVar_list[0] as! String
|
||||
let service = pigeonVar_list[1] as! String
|
||||
let characteristic = pigeonVar_list[2] as! String
|
||||
let value = pigeonVar_list[3] as! FlutterStandardTypedData
|
||||
|
||||
return UniversalBlePeripheralWriteEvent(
|
||||
deviceId: deviceId,
|
||||
service: service,
|
||||
characteristic: characteristic,
|
||||
value: value
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
value,
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalBlePeripheralWriteEvent, rhs: UniversalBlePeripheralWriteEvent) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.deviceId, rhs.deviceId) && deepEqualsUniversalBle(lhs.service, rhs.service) && deepEqualsUniversalBle(lhs.characteristic, rhs.characteristic) && deepEqualsUniversalBle(lhs.value, rhs.value)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("UniversalBlePeripheralWriteEvent")
|
||||
deepHashUniversalBle(value: deviceId, hasher: &hasher)
|
||||
deepHashUniversalBle(value: service, hasher: &hasher)
|
||||
deepHashUniversalBle(value: characteristic, hasher: &hasher)
|
||||
deepHashUniversalBle(value: value, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,9 +678,17 @@ struct AndroidOptions: Hashable {
|
||||
]
|
||||
}
|
||||
static func == (lhs: AndroidOptions, rhs: AndroidOptions) -> Bool {
|
||||
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.requestLocationPermission, rhs.requestLocationPermission) && deepEqualsUniversalBle(lhs.scanMode, rhs.scanMode) && deepEqualsUniversalBle(lhs.reportDelayMillis, rhs.reportDelayMillis)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||
hasher.combine("AndroidOptions")
|
||||
deepHashUniversalBle(value: requestLocationPermission, hasher: &hasher)
|
||||
deepHashUniversalBle(value: scanMode, hasher: &hasher)
|
||||
deepHashUniversalBle(value: reportDelayMillis, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,9 +711,15 @@ struct UniversalScanConfig: Hashable {
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalScanConfig, rhs: UniversalScanConfig) -> Bool {
|
||||
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.android, rhs.android)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||
hasher.combine("UniversalScanConfig")
|
||||
deepHashUniversalBle(value: android, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,9 +752,17 @@ struct UniversalScanFilter: Hashable {
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalScanFilter, rhs: UniversalScanFilter) -> Bool {
|
||||
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.withServices, rhs.withServices) && deepEqualsUniversalBle(lhs.withNamePrefix, rhs.withNamePrefix) && deepEqualsUniversalBle(lhs.withManufacturerData, rhs.withManufacturerData)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||
hasher.combine("UniversalScanFilter")
|
||||
deepHashUniversalBle(value: withServices, hasher: &hasher)
|
||||
deepHashUniversalBle(value: withNamePrefix, hasher: &hasher)
|
||||
deepHashUniversalBle(value: withManufacturerData, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,9 +793,17 @@ struct UniversalManufacturerDataFilter: Hashable {
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalManufacturerDataFilter, rhs: UniversalManufacturerDataFilter) -> Bool {
|
||||
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.companyIdentifier, rhs.companyIdentifier) && deepEqualsUniversalBle(lhs.data, rhs.data) && deepEqualsUniversalBle(lhs.mask, rhs.mask)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||
hasher.combine("UniversalManufacturerDataFilter")
|
||||
deepHashUniversalBle(value: companyIdentifier, hasher: &hasher)
|
||||
deepHashUniversalBle(value: data, hasher: &hasher)
|
||||
deepHashUniversalBle(value: mask, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -510,9 +830,16 @@ struct UniversalManufacturerData: Hashable {
|
||||
]
|
||||
}
|
||||
static func == (lhs: UniversalManufacturerData, rhs: UniversalManufacturerData) -> Bool {
|
||||
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsUniversalBle(lhs.companyIdentifier, rhs.companyIdentifier) && deepEqualsUniversalBle(lhs.data, rhs.data)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
deepHashUniversalBle(value: toList(), hasher: &hasher)
|
||||
hasher.combine("UniversalManufacturerData")
|
||||
deepHashUniversalBle(value: companyIdentifier, hasher: &hasher)
|
||||
deepHashUniversalBle(value: data, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,14 +873,24 @@ private class UniversalBlePigeonCodecReader: FlutterStandardReader {
|
||||
case 135:
|
||||
return UniversalBleDescriptor.fromList(self.readValue() as! [Any?])
|
||||
case 136:
|
||||
return AndroidOptions.fromList(self.readValue() as! [Any?])
|
||||
return UniversalBlePeripheralConfig.fromList(self.readValue() as! [Any?])
|
||||
case 137:
|
||||
return UniversalScanConfig.fromList(self.readValue() as! [Any?])
|
||||
return UniversalBlePeripheralService.fromList(self.readValue() as! [Any?])
|
||||
case 138:
|
||||
return UniversalScanFilter.fromList(self.readValue() as! [Any?])
|
||||
return UniversalBlePeripheralCharacteristic.fromList(self.readValue() as! [Any?])
|
||||
case 139:
|
||||
return UniversalManufacturerDataFilter.fromList(self.readValue() as! [Any?])
|
||||
return UniversalBlePeripheralDescriptor.fromList(self.readValue() as! [Any?])
|
||||
case 140:
|
||||
return UniversalBlePeripheralWriteEvent.fromList(self.readValue() as! [Any?])
|
||||
case 141:
|
||||
return AndroidOptions.fromList(self.readValue() as! [Any?])
|
||||
case 142:
|
||||
return UniversalScanConfig.fromList(self.readValue() as! [Any?])
|
||||
case 143:
|
||||
return UniversalScanFilter.fromList(self.readValue() as! [Any?])
|
||||
case 144:
|
||||
return UniversalManufacturerDataFilter.fromList(self.readValue() as! [Any?])
|
||||
case 145:
|
||||
return UniversalManufacturerData.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
@@ -584,21 +921,36 @@ private class UniversalBlePigeonCodecWriter: FlutterStandardWriter {
|
||||
} else if let value = value as? UniversalBleDescriptor {
|
||||
super.writeByte(135)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? AndroidOptions {
|
||||
} else if let value = value as? UniversalBlePeripheralConfig {
|
||||
super.writeByte(136)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? UniversalScanConfig {
|
||||
} else if let value = value as? UniversalBlePeripheralService {
|
||||
super.writeByte(137)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? UniversalScanFilter {
|
||||
} else if let value = value as? UniversalBlePeripheralCharacteristic {
|
||||
super.writeByte(138)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? UniversalManufacturerDataFilter {
|
||||
} else if let value = value as? UniversalBlePeripheralDescriptor {
|
||||
super.writeByte(139)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? UniversalManufacturerData {
|
||||
} else if let value = value as? UniversalBlePeripheralWriteEvent {
|
||||
super.writeByte(140)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? AndroidOptions {
|
||||
super.writeByte(141)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? UniversalScanConfig {
|
||||
super.writeByte(142)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? UniversalScanFilter {
|
||||
super.writeByte(143)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? UniversalManufacturerDataFilter {
|
||||
super.writeByte(144)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? UniversalManufacturerData {
|
||||
super.writeByte(145)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
@@ -625,8 +977,8 @@ class UniversalBlePigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol UniversalBlePlatformChannel {
|
||||
func getBluetoothAvailabilityState(completion: @escaping (Result<Int64, Error>) -> Void)
|
||||
func hasPermissions(withAndroidFineLocation: Bool) throws -> Bool
|
||||
func requestPermissions(withAndroidFineLocation: Bool, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func hasPermissions(withAndroidFineLocation: Bool, withAndroidBluetoothAdvertise: Bool) throws -> Bool
|
||||
func requestPermissions(withAndroidFineLocation: Bool, withAndroidBluetoothAdvertise: Bool, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func enableBluetooth(completion: @escaping (Result<Bool, Error>) -> Void)
|
||||
func disableBluetooth(completion: @escaping (Result<Bool, Error>) -> Void)
|
||||
func startScan(filter: UniversalScanFilter?, config: UniversalScanConfig?) throws
|
||||
@@ -646,6 +998,11 @@ protocol UniversalBlePlatformChannel {
|
||||
func getConnectionState(deviceId: String) throws -> Int64
|
||||
func readRssi(deviceId: String, completion: @escaping (Result<Int64, Error>) -> Void)
|
||||
func requestConnectionPriority(deviceId: String, priority: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func isPeripheralSupported() throws -> Bool
|
||||
func startPeripheral(config: UniversalBlePeripheralConfig, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func stopPeripheral(completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func updatePeripheralCharacteristicValue(service: String, characteristic: String, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func notifyPeripheralCharacteristic(service: String, characteristic: String, value: FlutterStandardTypedData, indicate: Bool, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func setLogLevel(logLevel: UniversalBleLogLevel) throws
|
||||
}
|
||||
|
||||
@@ -675,8 +1032,9 @@ class UniversalBlePlatformChannelSetup {
|
||||
hasPermissionsChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let withAndroidFineLocationArg = args[0] as! Bool
|
||||
let withAndroidBluetoothAdvertiseArg = args[1] as! Bool
|
||||
do {
|
||||
let result = try api.hasPermissions(withAndroidFineLocation: withAndroidFineLocationArg)
|
||||
let result = try api.hasPermissions(withAndroidFineLocation: withAndroidFineLocationArg, withAndroidBluetoothAdvertise: withAndroidBluetoothAdvertiseArg)
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
@@ -690,7 +1048,8 @@ class UniversalBlePlatformChannelSetup {
|
||||
requestPermissionsChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let withAndroidFineLocationArg = args[0] as! Bool
|
||||
api.requestPermissions(withAndroidFineLocation: withAndroidFineLocationArg) { result in
|
||||
let withAndroidBluetoothAdvertiseArg = args[1] as! Bool
|
||||
api.requestPermissions(withAndroidFineLocation: withAndroidFineLocationArg, withAndroidBluetoothAdvertise: withAndroidBluetoothAdvertiseArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@@ -1017,6 +1376,90 @@ class UniversalBlePlatformChannelSetup {
|
||||
} else {
|
||||
requestConnectionPriorityChannel.setMessageHandler(nil)
|
||||
}
|
||||
let isPeripheralSupportedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPeripheralSupported\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
isPeripheralSupportedChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
let result = try api.isPeripheralSupported()
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isPeripheralSupportedChannel.setMessageHandler(nil)
|
||||
}
|
||||
let startPeripheralChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startPeripheral\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
startPeripheralChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let configArg = args[0] as! UniversalBlePeripheralConfig
|
||||
api.startPeripheral(config: configArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
startPeripheralChannel.setMessageHandler(nil)
|
||||
}
|
||||
let stopPeripheralChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopPeripheral\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
stopPeripheralChannel.setMessageHandler { _, reply in
|
||||
api.stopPeripheral { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stopPeripheralChannel.setMessageHandler(nil)
|
||||
}
|
||||
let updatePeripheralCharacteristicValueChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.updatePeripheralCharacteristicValue\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
updatePeripheralCharacteristicValueChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let serviceArg = args[0] as! String
|
||||
let characteristicArg = args[1] as! String
|
||||
let valueArg = args[2] as! FlutterStandardTypedData
|
||||
api.updatePeripheralCharacteristicValue(service: serviceArg, characteristic: characteristicArg, value: valueArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updatePeripheralCharacteristicValueChannel.setMessageHandler(nil)
|
||||
}
|
||||
let notifyPeripheralCharacteristicChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.notifyPeripheralCharacteristic\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
notifyPeripheralCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let serviceArg = args[0] as! String
|
||||
let characteristicArg = args[1] as! String
|
||||
let valueArg = args[2] as! FlutterStandardTypedData
|
||||
let indicateArg = args[3] as! Bool
|
||||
api.notifyPeripheralCharacteristic(service: serviceArg, characteristic: characteristicArg, value: valueArg, indicate: indicateArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
notifyPeripheralCharacteristicChannel.setMessageHandler(nil)
|
||||
}
|
||||
let setLogLevelChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setLogLevel\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
setLogLevelChannel.setMessageHandler { message, reply in
|
||||
@@ -1043,6 +1486,9 @@ protocol UniversalBleCallbackChannelProtocol {
|
||||
func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||
func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, timestamp timestampArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||
func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||
func onPeripheralConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||
func onPeripheralWrite(event eventArg: UniversalBlePeripheralWriteEvent, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||
func onPeripheralSubscriptionChanged(deviceId deviceIdArg: String, service serviceArg: String, characteristic characteristicArg: String, subscribed subscribedArg: Bool, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||
}
|
||||
class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
||||
private let binaryMessenger: FlutterBinaryMessenger
|
||||
@@ -1144,4 +1590,58 @@ class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
|
||||
}
|
||||
}
|
||||
}
|
||||
func onPeripheralConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPeripheralConnectionChanged\(messageChannelSuffix)"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([deviceIdArg, connectedArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName: channelName)))
|
||||
return
|
||||
}
|
||||
if listResponse.count > 1 {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||
} else {
|
||||
completion(.success(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func onPeripheralWrite(event eventArg: UniversalBlePeripheralWriteEvent, completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPeripheralWrite\(messageChannelSuffix)"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([eventArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName: channelName)))
|
||||
return
|
||||
}
|
||||
if listResponse.count > 1 {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||
} else {
|
||||
completion(.success(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func onPeripheralSubscriptionChanged(deviceId deviceIdArg: String, service serviceArg: String, characteristic characteristicArg: String, subscribed subscribedArg: Bool, completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPeripheralSubscriptionChanged\(messageChannelSuffix)"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([deviceIdArg, serviceArg, characteristicArg, subscribedArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName: channelName)))
|
||||
return
|
||||
}
|
||||
if listResponse.count > 1 {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||
} else {
|
||||
completion(.success(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,11 +58,15 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
}
|
||||
}
|
||||
|
||||
func hasPermissions(withAndroidFineLocation _: Bool) throws -> Bool {
|
||||
func hasPermissions(withAndroidFineLocation _: Bool, withAndroidBluetoothAdvertise _: Bool) throws -> Bool {
|
||||
return CBCentralManager.authorization == .allowedAlways
|
||||
}
|
||||
|
||||
func requestPermissions(withAndroidFineLocation _: Bool, completion: @escaping (Result<Void, any Error>) -> Void) {
|
||||
func requestPermissions(
|
||||
withAndroidFineLocation _: Bool,
|
||||
withAndroidBluetoothAdvertise _: Bool,
|
||||
completion: @escaping (Result<Void, any Error>) -> Void
|
||||
) {
|
||||
if manager.state != .unknown {
|
||||
completePermissionRequest(completion: completion)
|
||||
} else {
|
||||
@@ -379,6 +383,37 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
completion(.failure(createFlutterError(code: .notSupported, message: "requestConnectionPriority is not supported on Apple platforms")))
|
||||
}
|
||||
|
||||
func isPeripheralSupported() throws -> Bool {
|
||||
false
|
||||
}
|
||||
|
||||
func startPeripheral(config _: UniversalBlePeripheralConfig, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
completion(.failure(createFlutterError(code: .notSupported, message: "BLE peripheral mode is not implemented on Apple platforms yet")))
|
||||
}
|
||||
|
||||
func stopPeripheral(completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func updatePeripheralCharacteristicValue(
|
||||
service _: String,
|
||||
characteristic _: String,
|
||||
value _: FlutterStandardTypedData,
|
||||
completion: @escaping (Result<Void, Error>) -> Void
|
||||
) {
|
||||
completion(.failure(createFlutterError(code: .notSupported, message: "BLE peripheral mode is not implemented on Apple platforms yet")))
|
||||
}
|
||||
|
||||
func notifyPeripheralCharacteristic(
|
||||
service _: String,
|
||||
characteristic _: String,
|
||||
value _: FlutterStandardTypedData,
|
||||
indicate _: Bool,
|
||||
completion: @escaping (Result<Void, Error>) -> Void
|
||||
) {
|
||||
completion(.failure(createFlutterError(code: .notSupported, message: "BLE peripheral mode is not implemented on Apple platforms yet")))
|
||||
}
|
||||
|
||||
func readRssi(deviceId: String, completion: @escaping (Result<Int64, Error>) -> Void) {
|
||||
UniversalBleLogger.shared.logDebug("READ_RSSI -> \(deviceId)")
|
||||
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />
|
||||
|
||||
@@ -54,8 +54,7 @@ class MockUniversalBle extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<BleService>> discoverServices(
|
||||
String deviceId, bool withDescriptors) async {
|
||||
Future<List<BleService>> discoverServices(String deviceId, bool withDescriptors) async {
|
||||
return [_mockService];
|
||||
}
|
||||
|
||||
@@ -87,11 +86,7 @@ class MockUniversalBle extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeValue(
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value,
|
||||
Future<void> writeValue(String deviceId, String service, String characteristic, Uint8List value,
|
||||
BleOutputProperty bleOutputProperty) async {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
_serviceValue = value;
|
||||
@@ -110,8 +105,8 @@ class MockUniversalBle extends UniversalBlePlatform {
|
||||
) async {}
|
||||
|
||||
@override
|
||||
Future<void> setNotifiable(String deviceId, String service,
|
||||
String characteristic, BleInputProperty bleInputProperty) async {}
|
||||
Future<void> setNotifiable(String deviceId, String service, String characteristic,
|
||||
BleInputProperty bleInputProperty) async {}
|
||||
|
||||
@override
|
||||
Future<bool> isPaired(String deviceId) async {
|
||||
@@ -141,7 +136,10 @@ class MockUniversalBle extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> requestPermissions({bool withAndroidFineLocation = false}) {
|
||||
Future<void> requestPermissions({
|
||||
bool withAndroidFineLocation = false,
|
||||
bool withAndroidBluetoothAdvertise = false,
|
||||
}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@@ -333,7 +333,7 @@ packages:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:universal_ble/universal_ble.dart';
|
||||
|
||||
enum BlePeripheralCharacteristicPermission { read, write }
|
||||
|
||||
class BlePeripheralConfig {
|
||||
BlePeripheralConfig({required this.advertisedName, required this.services});
|
||||
|
||||
final String advertisedName;
|
||||
final List<BlePeripheralService> services;
|
||||
}
|
||||
|
||||
class BlePeripheralService {
|
||||
BlePeripheralService({required String uuid, required this.characteristics})
|
||||
: uuid = BleUuidParser.string(uuid);
|
||||
|
||||
final String uuid;
|
||||
final List<BlePeripheralCharacteristic> characteristics;
|
||||
}
|
||||
|
||||
class BlePeripheralCharacteristic {
|
||||
BlePeripheralCharacteristic({
|
||||
required String uuid,
|
||||
required this.properties,
|
||||
required this.permissions,
|
||||
this.descriptors = const [],
|
||||
Uint8List? initialValue,
|
||||
}) : uuid = BleUuidParser.string(uuid),
|
||||
initialValue = initialValue == null ? null : Uint8List.fromList(initialValue);
|
||||
|
||||
final String uuid;
|
||||
final List<CharacteristicProperty> properties;
|
||||
final List<BlePeripheralCharacteristicPermission> permissions;
|
||||
final List<BlePeripheralDescriptor> descriptors;
|
||||
final Uint8List? initialValue;
|
||||
}
|
||||
|
||||
class BlePeripheralDescriptor {
|
||||
BlePeripheralDescriptor({
|
||||
required String uuid,
|
||||
required this.permissions,
|
||||
Uint8List? initialValue,
|
||||
}) : uuid = BleUuidParser.string(uuid),
|
||||
initialValue = initialValue == null ? null : Uint8List.fromList(initialValue);
|
||||
|
||||
final String uuid;
|
||||
final List<BlePeripheralCharacteristicPermission> permissions;
|
||||
final Uint8List? initialValue;
|
||||
}
|
||||
|
||||
class BlePeripheralWriteEvent {
|
||||
BlePeripheralWriteEvent({
|
||||
required this.deviceId,
|
||||
required String service,
|
||||
required String characteristic,
|
||||
required Uint8List value,
|
||||
}) : service = BleUuidParser.string(service),
|
||||
characteristic = BleUuidParser.string(characteristic),
|
||||
value = Uint8List.fromList(value);
|
||||
|
||||
final String deviceId;
|
||||
final String service;
|
||||
final String characteristic;
|
||||
final Uint8List value;
|
||||
}
|
||||
|
||||
class BlePeripheralConnectionEvent {
|
||||
BlePeripheralConnectionEvent({required this.deviceId, required this.connected});
|
||||
|
||||
final String deviceId;
|
||||
final bool connected;
|
||||
}
|
||||
|
||||
class BlePeripheralSubscriptionEvent {
|
||||
BlePeripheralSubscriptionEvent({
|
||||
required this.deviceId,
|
||||
required String service,
|
||||
required String characteristic,
|
||||
required this.subscribed,
|
||||
}) : service = BleUuidParser.string(service),
|
||||
characteristic = BleUuidParser.string(characteristic);
|
||||
|
||||
final String deviceId;
|
||||
final String service;
|
||||
final String characteristic;
|
||||
final bool subscribed;
|
||||
}
|
||||
@@ -13,3 +13,4 @@ export 'package:universal_ble/src/models/ble_device.dart';
|
||||
export 'package:universal_ble/src/models/ble_command.dart';
|
||||
export 'package:universal_ble/src/models/ble_capabilities.dart';
|
||||
export 'package:universal_ble/src/models/ble_connection_priority.dart';
|
||||
export 'package:universal_ble/src/models/ble_peripheral.dart';
|
||||
|
||||
+84
-113
@@ -14,8 +14,7 @@ class UniversalBle {
|
||||
static final BleCommandQueue _bleCommandQueue = BleCommandQueue();
|
||||
|
||||
/// Set custom platform specific implementation (e.g. for testing).
|
||||
static void setInstance(UniversalBlePlatform instance) =>
|
||||
_platform = instance;
|
||||
static void setInstance(UniversalBlePlatform instance) => _platform = instance;
|
||||
|
||||
/// Set global timeout for all commands.
|
||||
/// Default timeout is 10 seconds.
|
||||
@@ -47,40 +46,36 @@ class UniversalBle {
|
||||
static Stream<BleDevice> get scanStream => _platform.scanStream;
|
||||
|
||||
/// Bluetooth availability state stream
|
||||
static Stream<AvailabilityState> get availabilityStream =>
|
||||
_platform.availabilityStream;
|
||||
static Stream<AvailabilityState> get availabilityStream => _platform.availabilityStream;
|
||||
|
||||
/// Connection stream of a device
|
||||
static Stream<bool> connectionStream(String deviceId) =>
|
||||
_platform.connectionStream(deviceId);
|
||||
static Stream<bool> connectionStream(String deviceId) => _platform.connectionStream(deviceId);
|
||||
|
||||
/// Characteristic value stream
|
||||
static Stream<Uint8List> characteristicValueStream(
|
||||
String deviceId,
|
||||
String characteristicId,
|
||||
) => _platform.characteristicValueStream(deviceId, characteristicId);
|
||||
static Stream<Uint8List> characteristicValueStream(String deviceId, String characteristicId) =>
|
||||
_platform.characteristicValueStream(deviceId, characteristicId);
|
||||
|
||||
/// Pairing state stream
|
||||
static Stream<bool> pairingStateStream(String deviceId) =>
|
||||
_platform.pairingStateStream(deviceId);
|
||||
static Stream<bool> pairingStateStream(String deviceId) => _platform.pairingStateStream(deviceId);
|
||||
|
||||
/// Get Bluetooth availability state.
|
||||
/// To be notified of updates, set [onAvailabilityChange] listener.
|
||||
static Future<AvailabilityState> getBluetoothAvailabilityState() async {
|
||||
return await _bleCommandQueue.queueCommand(
|
||||
() => _platform.getBluetoothAvailabilityState(),
|
||||
);
|
||||
return await _bleCommandQueue.queueCommand(() => _platform.getBluetoothAvailabilityState());
|
||||
}
|
||||
|
||||
/// Check if has permissions.
|
||||
/// [withAndroidFineLocation] is used to check fine location permission on Android 12+ (API 31+).
|
||||
/// [withAndroidBluetoothAdvertise] is used to check Android 12+ advertise permission for peripheral mode.
|
||||
/// On Android lower than 12, this method will check location permission regardless of the [withAndroidFineLocation] value.
|
||||
/// `Windows`, `Linux` and `Web` will always return true.
|
||||
static Future<bool> hasPermissions({
|
||||
bool withAndroidFineLocation = false,
|
||||
bool withAndroidBluetoothAdvertise = false,
|
||||
}) async {
|
||||
return _platform.hasPermissions(
|
||||
withAndroidFineLocation: withAndroidFineLocation,
|
||||
withAndroidBluetoothAdvertise: withAndroidBluetoothAdvertise,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -88,13 +83,16 @@ class UniversalBle {
|
||||
/// if all permissions are already granted or granted by user, this method will succeed.
|
||||
/// it will throw exception if permissions are denied by user.
|
||||
/// [withAndroidFineLocation] is used to request fine location permission on Android 12+ (API 31+).
|
||||
/// [withAndroidBluetoothAdvertise] is used to request Android 12+ advertise permission for peripheral mode.
|
||||
/// on Android lower than 12, this method will request location permission regardless of the [withAndroidFineLocation] value.
|
||||
/// `Windows`, `Linux` and `Web` will always succeed.
|
||||
static Future<void> requestPermissions({
|
||||
bool withAndroidFineLocation = false,
|
||||
bool withAndroidBluetoothAdvertise = false,
|
||||
}) async {
|
||||
return _platform.requestPermissions(
|
||||
withAndroidFineLocation: withAndroidFineLocation,
|
||||
withAndroidBluetoothAdvertise: withAndroidBluetoothAdvertise,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -102,15 +100,9 @@ class UniversalBle {
|
||||
/// Scan results will arrive in [onScanResult] listener.
|
||||
/// It might throw errors if Bluetooth is not available.
|
||||
/// `webRequestOptions` is supported on Web only.
|
||||
static Future<void> startScan({
|
||||
ScanFilter? scanFilter,
|
||||
PlatformConfig? platformConfig,
|
||||
}) async {
|
||||
static Future<void> startScan({ScanFilter? scanFilter, PlatformConfig? platformConfig}) async {
|
||||
return await _bleCommandQueue.queueCommandWithoutTimeout(
|
||||
() => _platform.startScan(
|
||||
scanFilter: scanFilter,
|
||||
platformConfig: platformConfig,
|
||||
),
|
||||
() => _platform.startScan(scanFilter: scanFilter, platformConfig: platformConfig),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -118,9 +110,7 @@ class UniversalBle {
|
||||
/// Set [onScanResult] listener to `null` if you don't need it anymore.
|
||||
/// It might throw errors if Bluetooth is not available.
|
||||
static Future<void> stopScan() async {
|
||||
return await _bleCommandQueue.queueCommandWithoutTimeout(
|
||||
() => _platform.stopScan(),
|
||||
);
|
||||
return await _bleCommandQueue.queueCommandWithoutTimeout(() => _platform.stopScan());
|
||||
}
|
||||
|
||||
/// Check if currently scanning for devices.
|
||||
@@ -147,17 +137,14 @@ class UniversalBle {
|
||||
bool autoConnect = false,
|
||||
}) async {
|
||||
timeout ??= const Duration(seconds: 60);
|
||||
Completer<bool> completer = _connectionEventCompleter(
|
||||
deviceId,
|
||||
timeout: timeout,
|
||||
);
|
||||
Completer<bool> completer = _connectionEventCompleter(deviceId, timeout: timeout);
|
||||
|
||||
_platform
|
||||
.connect(deviceId, connectionTimeout: timeout, autoConnect: autoConnect)
|
||||
.catchError((error) {
|
||||
if (completer.isCompleted) return;
|
||||
completer.completeError(ConnectionException(error));
|
||||
});
|
||||
_platform.connect(deviceId, connectionTimeout: timeout, autoConnect: autoConnect).catchError((
|
||||
error,
|
||||
) {
|
||||
if (completer.isCompleted) return;
|
||||
completer.completeError(ConnectionException(error));
|
||||
});
|
||||
|
||||
if (!await completer.future.timeout(timeout)) {
|
||||
throw ConnectionException("Failed to connect");
|
||||
@@ -176,17 +163,10 @@ class UniversalBle {
|
||||
}
|
||||
|
||||
try {
|
||||
Completer<bool> completer = _connectionEventCompleter(
|
||||
deviceId,
|
||||
timeout: timeout,
|
||||
);
|
||||
Completer<bool> completer = _connectionEventCompleter(deviceId, timeout: timeout);
|
||||
|
||||
await _bleCommandQueue
|
||||
.queueCommand(
|
||||
() => _platform.disconnect(deviceId),
|
||||
timeout: timeout,
|
||||
deviceId: deviceId,
|
||||
)
|
||||
.queueCommand(() => _platform.disconnect(deviceId), timeout: timeout, deviceId: deviceId)
|
||||
.catchError((error) {
|
||||
if (completer.isCompleted) return;
|
||||
completer.completeError(ConnectionException(error));
|
||||
@@ -204,9 +184,7 @@ class UniversalBle {
|
||||
}
|
||||
|
||||
if (await completer.future.timeout(timeout)) {
|
||||
UniversalLogger.logError(
|
||||
"Device $deviceId is still connected after disconnect attempt",
|
||||
);
|
||||
UniversalLogger.logError("Device $deviceId is still connected after disconnect attempt");
|
||||
}
|
||||
} catch (e) {
|
||||
UniversalLogger.logError("Disconnect failed: $e");
|
||||
@@ -315,9 +293,7 @@ class UniversalBle {
|
||||
BleUuidParser.string(service),
|
||||
BleUuidParser.string(characteristic),
|
||||
value,
|
||||
withoutResponse
|
||||
? BleOutputProperty.withoutResponse
|
||||
: BleOutputProperty.withResponse,
|
||||
withoutResponse ? BleOutputProperty.withoutResponse : BleOutputProperty.withResponse,
|
||||
),
|
||||
timeout: timeout,
|
||||
deviceId: deviceId,
|
||||
@@ -339,11 +315,7 @@ class UniversalBle {
|
||||
///
|
||||
/// **Best Practices:** Design for default ATT MTU (23 bytes), treat requests as
|
||||
/// opportunistic, and implement fragmentation for larger payloads.
|
||||
static Future<int> requestMtu(
|
||||
String deviceId,
|
||||
int expectedMtu, {
|
||||
Duration? timeout,
|
||||
}) async {
|
||||
static Future<int> requestMtu(String deviceId, int expectedMtu, {Duration? timeout}) async {
|
||||
return await _bleCommandQueue.queueCommand(
|
||||
() => _platform.requestMtu(deviceId, expectedMtu),
|
||||
timeout: timeout,
|
||||
@@ -445,11 +417,7 @@ class UniversalBle {
|
||||
///
|
||||
/// On `Web/Windows` and `Web/Linux`, it does not work for devices that use `ConfirmOnly` pairing.
|
||||
/// Can throw `PairingException`, `ConnectionException` or `PlatformException`.
|
||||
static Future<void> pair(
|
||||
String deviceId, {
|
||||
BleCommand? pairingCommand,
|
||||
Duration? timeout,
|
||||
}) async {
|
||||
static Future<void> pair(String deviceId, {BleCommand? pairingCommand, Duration? timeout}) async {
|
||||
if (BleCapabilities.hasSystemPairingApi) {
|
||||
bool paired = await _bleCommandQueue.queueCommand(
|
||||
() => _platform.pair(deviceId),
|
||||
@@ -461,11 +429,7 @@ class UniversalBle {
|
||||
if (pairingCommand == null) {
|
||||
UniversalLogger.logWarning("PairingCommand required to get result");
|
||||
}
|
||||
await _connectAndExecuteBleCommand(
|
||||
deviceId,
|
||||
pairingCommand,
|
||||
timeout: timeout,
|
||||
);
|
||||
await _connectAndExecuteBleCommand(deviceId, pairingCommand, timeout: timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,10 +461,7 @@ class UniversalBle {
|
||||
/// Returns connection state of the device.
|
||||
/// All platforms will return `Connected/Disconnected` states.
|
||||
/// `Android` and `Apple` can also return `Connecting/Disconnecting` states.
|
||||
static Future<BleConnectionState> getConnectionState(
|
||||
String deviceId, {
|
||||
Duration? timeout,
|
||||
}) async {
|
||||
static Future<BleConnectionState> getConnectionState(String deviceId, {Duration? timeout}) async {
|
||||
return await _bleCommandQueue.queueCommand(
|
||||
() => _platform.getConnectionState(deviceId),
|
||||
timeout: timeout,
|
||||
@@ -511,10 +472,7 @@ class UniversalBle {
|
||||
/// It might throw errors if Bluetooth is not available.
|
||||
/// Not supported on `Web` and `Apple`.
|
||||
static Future<bool> enableBluetooth({Duration? timeout}) async {
|
||||
return await _bleCommandQueue.queueCommand(
|
||||
() => _platform.enableBluetooth(),
|
||||
timeout: timeout,
|
||||
);
|
||||
return await _bleCommandQueue.queueCommand(() => _platform.enableBluetooth(), timeout: timeout);
|
||||
}
|
||||
|
||||
/// Disable Bluetooth.
|
||||
@@ -540,8 +498,7 @@ class UniversalBle {
|
||||
/// For this feature to work, you need to enable the `chrome://flags/#enable-experimental-web-platform-features` flag.
|
||||
/// Not every browser supports this API yet.
|
||||
/// Even if the browser supports it, sometimes it won't fire any advertisement events even though the device may be sending them.
|
||||
static bool receivesAdvertisements(String deviceId) =>
|
||||
_platform.receivesAdvertisements(deviceId);
|
||||
static bool receivesAdvertisements(String deviceId) => _platform.receivesAdvertisements(deviceId);
|
||||
|
||||
/// Get Bluetooth state availability.
|
||||
static set onAvailabilityChange(OnAvailabilityChange? onAvailabilityChange) {
|
||||
@@ -555,21 +512,14 @@ class UniversalBle {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"Use [subscribeNotifications] or [subscribeIndications] or [unsubscribe] instead",
|
||||
)
|
||||
@Deprecated("Use [subscribeNotifications] or [subscribeIndications] or [unsubscribe] instead")
|
||||
static Future<void> setNotifiable(
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic,
|
||||
BleInputProperty bleInputProperty,
|
||||
) async {
|
||||
return _sendBleInputPropertyCommand(
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
bleInputProperty,
|
||||
);
|
||||
return _sendBleInputPropertyCommand(deviceId, service, characteristic, bleInputProperty);
|
||||
}
|
||||
|
||||
@Deprecated("Use [write] instead")
|
||||
@@ -599,10 +549,7 @@ class UniversalBle {
|
||||
return read(deviceId, service, characteristic, timeout: timeout);
|
||||
}
|
||||
|
||||
static Completer<bool> _connectionEventCompleter(
|
||||
String deviceId, {
|
||||
Duration? timeout,
|
||||
}) {
|
||||
static Completer<bool> _connectionEventCompleter(String deviceId, {Duration? timeout}) {
|
||||
timeout ??= const Duration(seconds: 60);
|
||||
StreamSubscription? connectionSubscription;
|
||||
Completer<bool> completer = Completer();
|
||||
@@ -618,9 +565,7 @@ class UniversalBle {
|
||||
completer.completeError(ConnectionException(error));
|
||||
}
|
||||
|
||||
connectionSubscription = _platform
|
||||
.bleConnectionUpdateStreamController
|
||||
.stream
|
||||
connectionSubscription = _platform.bleConnectionUpdateStreamController.stream
|
||||
.where((e) => e.deviceId == deviceId)
|
||||
.listen(
|
||||
(e) {
|
||||
@@ -681,10 +626,7 @@ class UniversalBle {
|
||||
await connect(deviceId, timeout: timeout);
|
||||
}
|
||||
|
||||
List<BleService> services = await discoverServices(
|
||||
deviceId,
|
||||
timeout: timeout,
|
||||
);
|
||||
List<BleService> services = await discoverServices(deviceId, timeout: timeout);
|
||||
UniversalLogger.logInfo("Discovered services: ${services.length}");
|
||||
|
||||
if (bleCommand == null) {
|
||||
@@ -737,10 +679,7 @@ class UniversalBle {
|
||||
for (BleService service in services) {
|
||||
if (BleUuidParser.compareStrings(service.uuid, bleCommand.service)) {
|
||||
for (BleCharacteristic char in service.characteristics) {
|
||||
if (BleUuidParser.compareStrings(
|
||||
char.uuid,
|
||||
bleCommand.characteristic,
|
||||
)) {
|
||||
if (BleUuidParser.compareStrings(char.uuid, bleCommand.characteristic)) {
|
||||
characteristic = char;
|
||||
break;
|
||||
}
|
||||
@@ -756,16 +695,10 @@ class UniversalBle {
|
||||
bool? withoutResponse;
|
||||
if (characteristic.properties.contains(CharacteristicProperty.write)) {
|
||||
withoutResponse = false;
|
||||
} else if (characteristic.properties.contains(
|
||||
CharacteristicProperty.writeWithoutResponse,
|
||||
)) {
|
||||
} else if (characteristic.properties.contains(CharacteristicProperty.writeWithoutResponse)) {
|
||||
withoutResponse = true;
|
||||
} else if (!characteristic.properties.contains(
|
||||
CharacteristicProperty.read,
|
||||
)) {
|
||||
throw PairingException(
|
||||
"BleCommand does not support read or write operation",
|
||||
);
|
||||
} else if (!characteristic.properties.contains(CharacteristicProperty.read)) {
|
||||
throw PairingException("BleCommand does not support read or write operation");
|
||||
}
|
||||
|
||||
Uint8List? value = bleCommand.writeValue;
|
||||
@@ -799,16 +732,14 @@ class UniversalBle {
|
||||
_bleCommandQueue.onQueueUpdate = onQueueUpdate;
|
||||
|
||||
/// Get scan results.
|
||||
static set onScanResult(OnScanResult? onScanResult) =>
|
||||
_platform.onScanResult = onScanResult;
|
||||
static set onScanResult(OnScanResult? onScanResult) => _platform.onScanResult = onScanResult;
|
||||
|
||||
/// Get connection state changes.
|
||||
static set onConnectionChange(OnConnectionChange? onConnectionChange) =>
|
||||
_platform.onConnectionChange = onConnectionChange;
|
||||
|
||||
/// Get characteristic value updates, after calling [subscribeNotifications] or [subscribeIndications]
|
||||
static set onValueChange(OnValueChange? onValueChange) =>
|
||||
_platform.onValueChange = onValueChange;
|
||||
static set onValueChange(OnValueChange? onValueChange) => _platform.onValueChange = onValueChange;
|
||||
|
||||
/// Get pair state changes.
|
||||
static set onPairingStateChange(OnPairingStateChange pairingStateChange) =>
|
||||
@@ -822,3 +753,43 @@ class UniversalBle {
|
||||
return UniversalBlePigeonChannel.instance;
|
||||
}
|
||||
}
|
||||
|
||||
class UniversalBlePeripheral {
|
||||
static Stream<BlePeripheralConnectionEvent> get connectionStream =>
|
||||
UniversalBle._platform.peripheralConnectionStream;
|
||||
|
||||
static Stream<BlePeripheralWriteEvent> get writeStream =>
|
||||
UniversalBle._platform.peripheralWriteStream;
|
||||
|
||||
static Stream<BlePeripheralSubscriptionEvent> get subscriptionStream =>
|
||||
UniversalBle._platform.peripheralSubscriptionStream;
|
||||
|
||||
static Future<bool> isSupported() => UniversalBle._platform.isPeripheralSupported();
|
||||
|
||||
static Future<void> start(BlePeripheralConfig config) =>
|
||||
UniversalBle._platform.startPeripheral(config);
|
||||
|
||||
static Future<void> stop() => UniversalBle._platform.stopPeripheral();
|
||||
|
||||
static Future<void> updateCharacteristicValue(
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value,
|
||||
) => UniversalBle._platform.updatePeripheralCharacteristicValue(
|
||||
BleUuidParser.string(service),
|
||||
BleUuidParser.string(characteristic),
|
||||
value,
|
||||
);
|
||||
|
||||
static Future<void> notify(
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value, {
|
||||
bool indicate = false,
|
||||
}) => UniversalBle._platform.notifyPeripheralCharacteristic(
|
||||
BleUuidParser.string(service),
|
||||
BleUuidParser.string(characteristic),
|
||||
value,
|
||||
indicate: indicate,
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,7 @@ import 'package:universal_ble/universal_ble.dart';
|
||||
|
||||
class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
static UniversalBlePigeonChannel? _instance;
|
||||
static UniversalBlePigeonChannel get instance =>
|
||||
_instance ??= UniversalBlePigeonChannel._();
|
||||
static UniversalBlePigeonChannel get instance => _instance ??= UniversalBlePigeonChannel._();
|
||||
late final UniversalBleFilterUtil _bleFilter = UniversalBleFilterUtil();
|
||||
|
||||
UniversalBlePigeonChannel._() {
|
||||
@@ -17,9 +16,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
|
||||
@override
|
||||
Future<AvailabilityState> getBluetoothAvailabilityState() async {
|
||||
int state = await _executeWithErrorHandling(
|
||||
() => _channel.getBluetoothAvailabilityState(),
|
||||
);
|
||||
int state = await _executeWithErrorHandling(() => _channel.getBluetoothAvailabilityState());
|
||||
return AvailabilityState.parse(state);
|
||||
}
|
||||
|
||||
@@ -40,10 +37,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startScan({
|
||||
ScanFilter? scanFilter,
|
||||
PlatformConfig? platformConfig,
|
||||
}) async {
|
||||
Future<void> startScan({ScanFilter? scanFilter, PlatformConfig? platformConfig}) async {
|
||||
await _ensureInitialized(platformConfig);
|
||||
_bleFilter.scanFilter = scanFilter;
|
||||
await _executeWithErrorHandling(
|
||||
@@ -55,48 +49,32 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopScan() =>
|
||||
_executeWithErrorHandling(() => _channel.stopScan());
|
||||
Future<void> stopScan() => _executeWithErrorHandling(() => _channel.stopScan());
|
||||
|
||||
@override
|
||||
Future<bool> isScanning() =>
|
||||
_executeWithErrorHandling(() => _channel.isScanning());
|
||||
Future<bool> isScanning() => _executeWithErrorHandling(() => _channel.isScanning());
|
||||
|
||||
@override
|
||||
Future<BleConnectionState> getConnectionState(String deviceId) async {
|
||||
int state = await _executeWithErrorHandling(
|
||||
() => _channel.getConnectionState(deviceId),
|
||||
);
|
||||
int state = await _executeWithErrorHandling(() => _channel.getConnectionState(deviceId));
|
||||
return BleConnectionState.parse(state);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(
|
||||
String deviceId, {
|
||||
Duration? connectionTimeout,
|
||||
bool autoConnect = false,
|
||||
}) => _executeWithErrorHandling(
|
||||
() => _channel.connect(deviceId, autoConnect: autoConnect),
|
||||
);
|
||||
Future<void> connect(String deviceId, {Duration? connectionTimeout, bool autoConnect = false}) =>
|
||||
_executeWithErrorHandling(() => _channel.connect(deviceId, autoConnect: autoConnect));
|
||||
|
||||
@override
|
||||
Future<void> disconnect(String deviceId) =>
|
||||
_executeWithErrorHandling(() => _channel.disconnect(deviceId));
|
||||
|
||||
@override
|
||||
Future<List<BleService>> discoverServices(
|
||||
String deviceId,
|
||||
bool withDescriptors,
|
||||
) async {
|
||||
List<UniversalBleService?> universalBleServices =
|
||||
await _executeWithErrorHandling(
|
||||
() => _channel.discoverServices(deviceId, withDescriptors),
|
||||
);
|
||||
Future<List<BleService>> discoverServices(String deviceId, bool withDescriptors) async {
|
||||
List<UniversalBleService?> universalBleServices = await _executeWithErrorHandling(
|
||||
() => _channel.discoverServices(deviceId, withDescriptors),
|
||||
);
|
||||
return List<BleService>.from(
|
||||
universalBleServices
|
||||
.where((e) => e != null)
|
||||
.map((e) => e!.toBleService(deviceId))
|
||||
.toList(),
|
||||
universalBleServices.where((e) => e != null).map((e) => e!.toBleService(deviceId)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -108,12 +86,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
BleInputProperty bleInputProperty,
|
||||
) {
|
||||
return _executeWithErrorHandling(
|
||||
() => _channel.setNotifiable(
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
bleInputProperty.index,
|
||||
),
|
||||
() => _channel.setNotifiable(deviceId, service, characteristic, bleInputProperty.index),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -124,9 +97,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
String characteristic, {
|
||||
final Duration? timeout,
|
||||
}) {
|
||||
return _executeWithErrorHandling(
|
||||
() => _channel.readValue(deviceId, service, characteristic),
|
||||
);
|
||||
return _executeWithErrorHandling(() => _channel.readValue(deviceId, service, characteristic));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -138,32 +109,51 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
BleOutputProperty bleOutputProperty,
|
||||
) {
|
||||
return _executeWithErrorHandling(
|
||||
() => _channel.writeValue(
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
value,
|
||||
bleOutputProperty.index,
|
||||
),
|
||||
() => _channel.writeValue(deviceId, service, characteristic, value, bleOutputProperty.index),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> requestMtu(String deviceId, int expectedMtu) =>
|
||||
_executeWithErrorHandling(
|
||||
() => _channel.requestMtu(deviceId, expectedMtu),
|
||||
);
|
||||
_executeWithErrorHandling(() => _channel.requestMtu(deviceId, expectedMtu));
|
||||
|
||||
@override
|
||||
Future<int> readRssi(String deviceId) =>
|
||||
_executeWithErrorHandling(() => _channel.readRssi(deviceId));
|
||||
|
||||
@override
|
||||
Future<void> requestConnectionPriority(
|
||||
String deviceId,
|
||||
BleConnectionPriority priority,
|
||||
Future<void> requestConnectionPriority(String deviceId, BleConnectionPriority priority) =>
|
||||
_executeWithErrorHandling(() => _channel.requestConnectionPriority(deviceId, priority.index));
|
||||
|
||||
@override
|
||||
Future<bool> isPeripheralSupported() =>
|
||||
_executeWithErrorHandling(() => _channel.isPeripheralSupported());
|
||||
|
||||
@override
|
||||
Future<void> startPeripheral(BlePeripheralConfig config) => _executeWithErrorHandling(
|
||||
() => _channel.startPeripheral(config.toUniversalPeripheralConfig()),
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> stopPeripheral() => _executeWithErrorHandling(() => _channel.stopPeripheral());
|
||||
|
||||
@override
|
||||
Future<void> updatePeripheralCharacteristicValue(
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value,
|
||||
) => _executeWithErrorHandling(
|
||||
() => _channel.requestConnectionPriority(deviceId, priority.index),
|
||||
() => _channel.updatePeripheralCharacteristicValue(service, characteristic, value),
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> notifyPeripheralCharacteristic(
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value, {
|
||||
bool indicate = false,
|
||||
}) => _executeWithErrorHandling(
|
||||
() => _channel.notifyPeripheralCharacteristic(service, characteristic, value, indicate),
|
||||
);
|
||||
|
||||
@override
|
||||
@@ -171,26 +161,29 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
_executeWithErrorHandling(() => _channel.isPaired(deviceId));
|
||||
|
||||
@override
|
||||
Future<bool> pair(String deviceId) =>
|
||||
_executeWithErrorHandling(() => _channel.pair(deviceId));
|
||||
Future<bool> pair(String deviceId) => _executeWithErrorHandling(() => _channel.pair(deviceId));
|
||||
|
||||
@override
|
||||
Future<void> unpair(String deviceId) =>
|
||||
_executeWithErrorHandling(() => _channel.unPair(deviceId));
|
||||
|
||||
@override
|
||||
Future<bool> hasPermissions({bool withAndroidFineLocation = false}) async {
|
||||
Future<bool> hasPermissions({
|
||||
bool withAndroidFineLocation = false,
|
||||
bool withAndroidBluetoothAdvertise = false,
|
||||
}) async {
|
||||
return await _executeWithErrorHandling(
|
||||
() => _channel.hasPermissions(withAndroidFineLocation),
|
||||
() => _channel.hasPermissions(withAndroidFineLocation, withAndroidBluetoothAdvertise),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> requestPermissions({
|
||||
bool withAndroidFineLocation = false,
|
||||
bool withAndroidBluetoothAdvertise = false,
|
||||
}) async {
|
||||
await _executeWithErrorHandling(
|
||||
() => _channel.requestPermissions(withAndroidFineLocation),
|
||||
() => _channel.requestPermissions(withAndroidFineLocation, withAndroidBluetoothAdvertise),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -199,15 +192,12 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
var devices = await _executeWithErrorHandling(
|
||||
() => _channel.getSystemDevices(withServices ?? []),
|
||||
);
|
||||
return List<BleDevice>.from(
|
||||
devices.map((e) => e.toBleDevice(isSystemDevice: true)).toList(),
|
||||
);
|
||||
return List<BleDevice>.from(devices.map((e) => e.toBleDevice(isSystemDevice: true)).toList());
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setLogLevel(BleLogLevel logLevel) => _executeWithErrorHandling(
|
||||
() => _channel.setLogLevel(logLevel.toUniversalBleLogLevel()),
|
||||
);
|
||||
Future<void> setLogLevel(BleLogLevel logLevel) =>
|
||||
_executeWithErrorHandling(() => _channel.setLogLevel(logLevel.toUniversalBleLogLevel()));
|
||||
|
||||
/// To set listeners
|
||||
void _setupListeners() {
|
||||
@@ -223,6 +213,9 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
connectionChanged: updateConnection,
|
||||
valueChanged: updateCharacteristicValue,
|
||||
pairStateChange: updatePairingState,
|
||||
peripheralConnectionChanged: updatePeripheralConnection,
|
||||
peripheralWrite: updatePeripheralWrite,
|
||||
peripheralSubscriptionChanged: updatePeripheralSubscription,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -246,8 +239,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
|
||||
defaultTargetPlatform == TargetPlatform.iOS ||
|
||||
defaultTargetPlatform == TargetPlatform.macOS) {
|
||||
await requestPermissions(
|
||||
withAndroidFineLocation:
|
||||
platformConfig?.android?.requestLocationPermission ?? false,
|
||||
withAndroidFineLocation: platformConfig?.android?.requestLocationPermission ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -277,12 +269,70 @@ extension _BleServiceExtension on UniversalBleService {
|
||||
}
|
||||
}
|
||||
|
||||
extension _BlePeripheralConfigExtension on BlePeripheralConfig {
|
||||
UniversalBlePeripheralConfig toUniversalPeripheralConfig() {
|
||||
return UniversalBlePeripheralConfig(
|
||||
advertisedName: advertisedName,
|
||||
services: services.map((service) => service.toUniversalPeripheralService()).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension _BlePeripheralServiceExtension on BlePeripheralService {
|
||||
UniversalBlePeripheralService toUniversalPeripheralService() {
|
||||
return UniversalBlePeripheralService(
|
||||
uuid: uuid,
|
||||
characteristics: characteristics
|
||||
.map((characteristic) => characteristic.toUniversalPeripheralCharacteristic())
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension _BlePeripheralCharacteristicExtension on BlePeripheralCharacteristic {
|
||||
UniversalBlePeripheralCharacteristic toUniversalPeripheralCharacteristic() {
|
||||
return UniversalBlePeripheralCharacteristic(
|
||||
uuid: uuid,
|
||||
properties: properties.map((property) => property.index).toList(),
|
||||
permissions: permissions.map((permission) => permission.index).toList(),
|
||||
descriptors: descriptors
|
||||
.map((descriptor) => descriptor.toUniversalPeripheralDescriptor())
|
||||
.toList(),
|
||||
initialValue: initialValue,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension _BlePeripheralDescriptorExtension on BlePeripheralDescriptor {
|
||||
UniversalBlePeripheralDescriptor toUniversalPeripheralDescriptor() {
|
||||
return UniversalBlePeripheralDescriptor(
|
||||
uuid: uuid,
|
||||
permissions: permissions.map((permission) => permission.index).toList(),
|
||||
initialValue: initialValue,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension _UniversalBlePeripheralWriteEventExtension on UniversalBlePeripheralWriteEvent {
|
||||
BlePeripheralWriteEvent toBlePeripheralWriteEvent() {
|
||||
return BlePeripheralWriteEvent(
|
||||
deviceId: deviceId,
|
||||
service: service,
|
||||
characteristic: characteristic,
|
||||
value: value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _UniversalBleCallbackHandler extends UniversalBleCallbackChannel {
|
||||
OnAvailabilityChange availabilityChange;
|
||||
OnScanResult scanResult;
|
||||
OnConnectionChange connectionChanged;
|
||||
OnValueChange valueChanged;
|
||||
OnPairingStateChange pairStateChange;
|
||||
void Function(String deviceId, bool connected) peripheralConnectionChanged;
|
||||
void Function(BlePeripheralWriteEvent event) peripheralWrite;
|
||||
void Function(BlePeripheralSubscriptionEvent event) peripheralSubscriptionChanged;
|
||||
|
||||
_UniversalBleCallbackHandler({
|
||||
required this.availabilityChange,
|
||||
@@ -290,31 +340,51 @@ class _UniversalBleCallbackHandler extends UniversalBleCallbackChannel {
|
||||
required this.connectionChanged,
|
||||
required this.valueChanged,
|
||||
required this.pairStateChange,
|
||||
required this.peripheralConnectionChanged,
|
||||
required this.peripheralWrite,
|
||||
required this.peripheralSubscriptionChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
void onAvailabilityChanged(int state) =>
|
||||
availabilityChange(AvailabilityState.parse(state));
|
||||
void onAvailabilityChanged(int state) => availabilityChange(AvailabilityState.parse(state));
|
||||
|
||||
@override
|
||||
void onConnectionChanged(String deviceId, bool connected, String? error) =>
|
||||
connectionChanged(deviceId, connected, error);
|
||||
|
||||
@override
|
||||
void onScanResult(UniversalBleScanResult result) =>
|
||||
scanResult(result.toBleDevice());
|
||||
void onScanResult(UniversalBleScanResult result) => scanResult(result.toBleDevice());
|
||||
|
||||
@override
|
||||
void onValueChanged(
|
||||
String deviceId,
|
||||
String characteristicId,
|
||||
Uint8List value,
|
||||
int? timestamp,
|
||||
) => valueChanged(deviceId, characteristicId, value, timestamp);
|
||||
void onValueChanged(String deviceId, String characteristicId, Uint8List value, int? timestamp) =>
|
||||
valueChanged(deviceId, characteristicId, value, timestamp);
|
||||
|
||||
@override
|
||||
void onPairStateChange(String deviceId, bool isPaired, String? error) =>
|
||||
pairStateChange(deviceId, isPaired);
|
||||
|
||||
@override
|
||||
void onPeripheralConnectionChanged(String deviceId, bool connected) =>
|
||||
peripheralConnectionChanged(deviceId, connected);
|
||||
|
||||
@override
|
||||
void onPeripheralWrite(UniversalBlePeripheralWriteEvent event) =>
|
||||
peripheralWrite(event.toBlePeripheralWriteEvent());
|
||||
|
||||
@override
|
||||
void onPeripheralSubscriptionChanged(
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic,
|
||||
bool subscribed,
|
||||
) => peripheralSubscriptionChanged(
|
||||
BlePeripheralSubscriptionEvent(
|
||||
deviceId: deviceId,
|
||||
service: service,
|
||||
characteristic: characteristic,
|
||||
subscribed: subscribed,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
extension _UniversalBleScanResultExtension on UniversalBleScanResult {
|
||||
@@ -339,8 +409,7 @@ extension _UniversalBleScanResultExtension on UniversalBleScanResult {
|
||||
|
||||
extension _ScanFilterExtension on ScanFilter? {
|
||||
UniversalScanFilter? toUniversalScanFilter() {
|
||||
List<UniversalManufacturerDataFilter>? manufacturerDataFilters = this
|
||||
?.withManufacturerData
|
||||
List<UniversalManufacturerDataFilter>? manufacturerDataFilters = this?.withManufacturerData
|
||||
.map(
|
||||
(e) => UniversalManufacturerDataFilter(
|
||||
companyIdentifier: e.companyIdentifier,
|
||||
|
||||
@@ -17,23 +17,26 @@ abstract class UniversalBlePlatform {
|
||||
final _scanStreamController = UniversalBleStreamController<BleDevice>();
|
||||
|
||||
final bleConnectionUpdateStreamController =
|
||||
UniversalBleStreamController<
|
||||
({String deviceId, bool isConnected, String? error})
|
||||
>();
|
||||
UniversalBleStreamController<({String deviceId, bool isConnected, String? error})>();
|
||||
|
||||
final _valueStreamController =
|
||||
UniversalBleStreamController<
|
||||
({String deviceId, String characteristicId, Uint8List value})
|
||||
>();
|
||||
UniversalBleStreamController<({String deviceId, String characteristicId, Uint8List value})>();
|
||||
|
||||
final _pairStateStreamController =
|
||||
UniversalBleStreamController<({String deviceId, bool isPaired})>();
|
||||
|
||||
final _peripheralConnectionStreamController =
|
||||
UniversalBleStreamController<BlePeripheralConnectionEvent>();
|
||||
|
||||
final _peripheralWriteStreamController = UniversalBleStreamController<BlePeripheralWriteEvent>();
|
||||
|
||||
final _peripheralSubscriptionStreamController =
|
||||
UniversalBleStreamController<BlePeripheralSubscriptionEvent>();
|
||||
|
||||
/// Send latest availability state upon subscribing
|
||||
late final _availabilityStreamController =
|
||||
UniversalBleStreamController<AvailabilityState>(
|
||||
initialEvent: getBluetoothAvailabilityState,
|
||||
);
|
||||
late final _availabilityStreamController = UniversalBleStreamController<AvailabilityState>(
|
||||
initialEvent: getBluetoothAvailabilityState,
|
||||
);
|
||||
|
||||
Future<AvailabilityState> getBluetoothAvailabilityState();
|
||||
|
||||
@@ -41,35 +44,29 @@ abstract class UniversalBlePlatform {
|
||||
|
||||
Future<bool> disableBluetooth();
|
||||
|
||||
Future<bool> hasPermissions({bool withAndroidFineLocation = false}) async {
|
||||
Future<bool> hasPermissions({
|
||||
bool withAndroidFineLocation = false,
|
||||
bool withAndroidBluetoothAdvertise = false,
|
||||
}) async {
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> requestPermissions({
|
||||
bool withAndroidFineLocation = false,
|
||||
bool withAndroidBluetoothAdvertise = false,
|
||||
}) async {}
|
||||
|
||||
Future<void> startScan({
|
||||
ScanFilter? scanFilter,
|
||||
PlatformConfig? platformConfig,
|
||||
});
|
||||
Future<void> startScan({ScanFilter? scanFilter, PlatformConfig? platformConfig});
|
||||
|
||||
Future<void> stopScan();
|
||||
|
||||
Future<bool> isScanning();
|
||||
|
||||
Future<void> connect(
|
||||
String deviceId, {
|
||||
Duration? connectionTimeout,
|
||||
bool autoConnect = false,
|
||||
});
|
||||
Future<void> connect(String deviceId, {Duration? connectionTimeout, bool autoConnect = false});
|
||||
|
||||
Future<void> disconnect(String deviceId);
|
||||
|
||||
Future<List<BleService>> discoverServices(
|
||||
String deviceId,
|
||||
bool withDescriptors,
|
||||
);
|
||||
Future<List<BleService>> discoverServices(String deviceId, bool withDescriptors);
|
||||
|
||||
Future<void> setNotifiable(
|
||||
String deviceId,
|
||||
@@ -97,10 +94,34 @@ abstract class UniversalBlePlatform {
|
||||
|
||||
Future<int> readRssi(String deviceId);
|
||||
|
||||
Future<void> requestConnectionPriority(
|
||||
String deviceId,
|
||||
BleConnectionPriority priority,
|
||||
);
|
||||
Future<void> requestConnectionPriority(String deviceId, BleConnectionPriority priority);
|
||||
|
||||
Future<bool> isPeripheralSupported() async => false;
|
||||
|
||||
Future<void> startPeripheral(BlePeripheralConfig config) {
|
||||
throw UnsupportedError('BLE peripheral mode is not supported');
|
||||
}
|
||||
|
||||
Future<void> stopPeripheral() {
|
||||
throw UnsupportedError('BLE peripheral mode is not supported');
|
||||
}
|
||||
|
||||
Future<void> updatePeripheralCharacteristicValue(
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value,
|
||||
) {
|
||||
throw UnsupportedError('BLE peripheral mode is not supported');
|
||||
}
|
||||
|
||||
Future<void> notifyPeripheralCharacteristic(
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value, {
|
||||
bool indicate = false,
|
||||
}) {
|
||||
throw UnsupportedError('BLE peripheral mode is not supported');
|
||||
}
|
||||
|
||||
Future<bool> isPaired(String deviceId);
|
||||
|
||||
@@ -112,39 +133,39 @@ abstract class UniversalBlePlatform {
|
||||
|
||||
Future<List<BleDevice>> getSystemDevices(List<String>? withServices);
|
||||
|
||||
Future<void> setLogLevel(BleLogLevel logLevel) async =>
|
||||
UniversalLogger.setLogLevel(logLevel);
|
||||
Future<void> setLogLevel(BleLogLevel logLevel) async => UniversalLogger.setLogLevel(logLevel);
|
||||
|
||||
bool receivesAdvertisements(String deviceId) => true;
|
||||
|
||||
/// Streams
|
||||
Stream<BleDevice> get scanStream => _scanStreamController.stream;
|
||||
|
||||
Stream<AvailabilityState> get availabilityStream =>
|
||||
_availabilityStreamController.stream;
|
||||
Stream<AvailabilityState> get availabilityStream => _availabilityStreamController.stream;
|
||||
|
||||
Stream<bool> connectionStream(String deviceId) =>
|
||||
bleConnectionUpdateStreamController.stream
|
||||
.where((e) => e.deviceId == deviceId)
|
||||
.map((e) => e.isConnected);
|
||||
Stream<bool> connectionStream(String deviceId) => bleConnectionUpdateStreamController.stream
|
||||
.where((e) => e.deviceId == deviceId)
|
||||
.map((e) => e.isConnected);
|
||||
|
||||
Stream<Uint8List> characteristicValueStream(
|
||||
String deviceId,
|
||||
String characteristicId,
|
||||
) {
|
||||
Stream<Uint8List> characteristicValueStream(String deviceId, String characteristicId) {
|
||||
characteristicId = BleUuidParser.string(characteristicId);
|
||||
return _valueStreamController.stream
|
||||
.where((e) {
|
||||
return e.deviceId == deviceId &&
|
||||
e.characteristicId == characteristicId;
|
||||
return e.deviceId == deviceId && e.characteristicId == characteristicId;
|
||||
})
|
||||
.map((e) => e.value);
|
||||
}
|
||||
|
||||
Stream<bool> pairingStateStream(String deviceId) => _pairStateStreamController
|
||||
.stream
|
||||
.where((e) => e.deviceId == deviceId)
|
||||
.map((e) => e.isPaired);
|
||||
Stream<bool> pairingStateStream(String deviceId) =>
|
||||
_pairStateStreamController.stream.where((e) => e.deviceId == deviceId).map((e) => e.isPaired);
|
||||
|
||||
Stream<BlePeripheralConnectionEvent> get peripheralConnectionStream =>
|
||||
_peripheralConnectionStreamController.stream;
|
||||
|
||||
Stream<BlePeripheralWriteEvent> get peripheralWriteStream =>
|
||||
_peripheralWriteStreamController.stream;
|
||||
|
||||
Stream<BlePeripheralSubscriptionEvent> get peripheralSubscriptionStream =>
|
||||
_peripheralSubscriptionStreamController.stream;
|
||||
|
||||
/// Update Handlers
|
||||
void updateScanResult(BleDevice bleDevice) {
|
||||
@@ -206,19 +227,27 @@ abstract class UniversalBlePlatform {
|
||||
onPairingStateChange?.call(deviceId, isPaired);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
void updatePeripheralConnection(String deviceId, bool connected) {
|
||||
_peripheralConnectionStreamController.add(
|
||||
BlePeripheralConnectionEvent(deviceId: deviceId, connected: connected),
|
||||
);
|
||||
}
|
||||
|
||||
void updatePeripheralWrite(BlePeripheralWriteEvent event) {
|
||||
_peripheralWriteStreamController.add(event);
|
||||
}
|
||||
|
||||
void updatePeripheralSubscription(BlePeripheralSubscriptionEvent event) {
|
||||
_peripheralSubscriptionStreamController.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Callback types
|
||||
typedef OnConnectionChange =
|
||||
void Function(String deviceId, bool isConnected, String? error);
|
||||
typedef OnConnectionChange = void Function(String deviceId, bool isConnected, String? error);
|
||||
|
||||
typedef OnValueChange =
|
||||
void Function(
|
||||
String deviceId,
|
||||
String characteristicId,
|
||||
Uint8List value,
|
||||
int? timestamp,
|
||||
);
|
||||
void Function(String deviceId, String characteristicId, Uint8List value, int? timestamp);
|
||||
|
||||
typedef OnScanResult = void Function(BleDevice scanResult);
|
||||
|
||||
|
||||
+90
-65
@@ -6,8 +6,7 @@ import 'package:pigeon/pigeon.dart';
|
||||
dartPackageName: 'universal_ble',
|
||||
dartOut: 'lib/src/universal_ble_pigeon/universal_ble.g.dart',
|
||||
dartOptions: DartOptions(),
|
||||
kotlinOut:
|
||||
'android/src/main/kotlin/com/navideck/universal_ble/UniversalBle.g.kt',
|
||||
kotlinOut: 'android/src/main/kotlin/com/navideck/universal_ble/UniversalBle.g.kt',
|
||||
swiftOut: 'darwin/universal_ble/Sources/universal_ble/UniversalBle.g.swift',
|
||||
kotlinOptions: KotlinOptions(package: 'com.navideck.universal_ble'),
|
||||
swiftOptions: SwiftOptions(),
|
||||
@@ -17,17 +16,16 @@ import 'package:pigeon/pigeon.dart';
|
||||
debugGenerators: true,
|
||||
),
|
||||
)
|
||||
|
||||
/// Flutter -> Native
|
||||
@HostApi()
|
||||
abstract class UniversalBlePlatformChannel {
|
||||
@async
|
||||
int getBluetoothAvailabilityState();
|
||||
|
||||
bool hasPermissions(bool withAndroidFineLocation);
|
||||
bool hasPermissions(bool withAndroidFineLocation, bool withAndroidBluetoothAdvertise);
|
||||
|
||||
@async
|
||||
void requestPermissions(bool withAndroidFineLocation);
|
||||
void requestPermissions(bool withAndroidFineLocation, bool withAndroidBluetoothAdvertise);
|
||||
|
||||
@async
|
||||
bool enableBluetooth();
|
||||
@@ -46,25 +44,13 @@ abstract class UniversalBlePlatformChannel {
|
||||
void disconnect(String deviceId);
|
||||
|
||||
@async
|
||||
void setNotifiable(
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic,
|
||||
int bleInputProperty,
|
||||
);
|
||||
void setNotifiable(String deviceId, String service, String characteristic, int bleInputProperty);
|
||||
|
||||
@async
|
||||
List<UniversalBleService> discoverServices(
|
||||
String deviceId,
|
||||
bool withDescriptors,
|
||||
);
|
||||
List<UniversalBleService> discoverServices(String deviceId, bool withDescriptors);
|
||||
|
||||
@async
|
||||
Uint8List readValue(
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic,
|
||||
);
|
||||
Uint8List readValue(String deviceId, String service, String characteristic);
|
||||
|
||||
@async
|
||||
int requestMtu(String deviceId, int expectedMtu);
|
||||
@@ -87,9 +73,7 @@ abstract class UniversalBlePlatformChannel {
|
||||
void unPair(String deviceId);
|
||||
|
||||
@async
|
||||
List<UniversalBleScanResult> getSystemDevices(
|
||||
List<String> withServices,
|
||||
);
|
||||
List<UniversalBleScanResult> getSystemDevices(List<String> withServices);
|
||||
|
||||
int getConnectionState(String deviceId);
|
||||
|
||||
@@ -99,6 +83,25 @@ abstract class UniversalBlePlatformChannel {
|
||||
@async
|
||||
void requestConnectionPriority(String deviceId, int priority);
|
||||
|
||||
bool isPeripheralSupported();
|
||||
|
||||
@async
|
||||
void startPeripheral(UniversalBlePeripheralConfig config);
|
||||
|
||||
@async
|
||||
void stopPeripheral();
|
||||
|
||||
@async
|
||||
void updatePeripheralCharacteristicValue(String service, String characteristic, Uint8List value);
|
||||
|
||||
@async
|
||||
void notifyPeripheralCharacteristic(
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value,
|
||||
bool indicate,
|
||||
);
|
||||
|
||||
void setLogLevel(UniversalBleLogLevel logLevel);
|
||||
}
|
||||
|
||||
@@ -111,17 +114,19 @@ abstract class UniversalBleCallbackChannel {
|
||||
|
||||
void onScanResult(UniversalBleScanResult result);
|
||||
|
||||
void onValueChanged(
|
||||
String deviceId,
|
||||
String characteristicId,
|
||||
Uint8List value,
|
||||
int? timestamp,
|
||||
);
|
||||
void onValueChanged(String deviceId, String characteristicId, Uint8List value, int? timestamp);
|
||||
|
||||
void onConnectionChanged(
|
||||
void onConnectionChanged(String deviceId, bool connected, String? error);
|
||||
|
||||
void onPeripheralConnectionChanged(String deviceId, bool connected);
|
||||
|
||||
void onPeripheralWrite(UniversalBlePeripheralWriteEvent event);
|
||||
|
||||
void onPeripheralSubscriptionChanged(
|
||||
String deviceId,
|
||||
bool connected,
|
||||
String? error,
|
||||
String service,
|
||||
String characteristic,
|
||||
bool subscribed,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -147,14 +152,7 @@ class UniversalBleScanResult {
|
||||
});
|
||||
}
|
||||
|
||||
enum UniversalBleLogLevel {
|
||||
none,
|
||||
error,
|
||||
warning,
|
||||
info,
|
||||
debug,
|
||||
verbose,
|
||||
}
|
||||
enum UniversalBleLogLevel { none, error, warning, info, debug, verbose }
|
||||
|
||||
class UniversalBleService {
|
||||
String uuid;
|
||||
@@ -174,14 +172,56 @@ class UniversalBleDescriptor {
|
||||
UniversalBleDescriptor(this.uuid);
|
||||
}
|
||||
|
||||
class UniversalBlePeripheralConfig {
|
||||
String advertisedName;
|
||||
List<UniversalBlePeripheralService> services;
|
||||
|
||||
UniversalBlePeripheralConfig(this.advertisedName, this.services);
|
||||
}
|
||||
|
||||
class UniversalBlePeripheralService {
|
||||
String uuid;
|
||||
List<UniversalBlePeripheralCharacteristic> characteristics;
|
||||
|
||||
UniversalBlePeripheralService(this.uuid, this.characteristics);
|
||||
}
|
||||
|
||||
class UniversalBlePeripheralCharacteristic {
|
||||
String uuid;
|
||||
List<int> properties;
|
||||
List<int> permissions;
|
||||
List<UniversalBlePeripheralDescriptor> descriptors;
|
||||
Uint8List? initialValue;
|
||||
|
||||
UniversalBlePeripheralCharacteristic(
|
||||
this.uuid,
|
||||
this.properties,
|
||||
this.permissions,
|
||||
this.descriptors,
|
||||
this.initialValue,
|
||||
);
|
||||
}
|
||||
|
||||
class UniversalBlePeripheralDescriptor {
|
||||
String uuid;
|
||||
List<int> permissions;
|
||||
Uint8List? initialValue;
|
||||
|
||||
UniversalBlePeripheralDescriptor(this.uuid, this.permissions, this.initialValue);
|
||||
}
|
||||
|
||||
class UniversalBlePeripheralWriteEvent {
|
||||
String deviceId;
|
||||
String service;
|
||||
String characteristic;
|
||||
Uint8List value;
|
||||
|
||||
UniversalBlePeripheralWriteEvent(this.deviceId, this.service, this.characteristic, this.value);
|
||||
}
|
||||
|
||||
/// Scan config
|
||||
|
||||
enum AndroidScanMode {
|
||||
balanced,
|
||||
lowLatency,
|
||||
lowPower,
|
||||
opportunistic,
|
||||
}
|
||||
enum AndroidScanMode { balanced, lowLatency, lowPower, opportunistic }
|
||||
|
||||
/// Android options to scan devices
|
||||
/// [requestLocationPermission] is used to request location permission on Android 12+ (API 31+).
|
||||
@@ -193,11 +233,7 @@ class AndroidOptions {
|
||||
bool? requestLocationPermission;
|
||||
AndroidScanMode? scanMode;
|
||||
int? reportDelayMillis;
|
||||
AndroidOptions({
|
||||
this.requestLocationPermission,
|
||||
this.scanMode,
|
||||
this.reportDelayMillis,
|
||||
});
|
||||
AndroidOptions({this.requestLocationPermission, this.scanMode, this.reportDelayMillis});
|
||||
}
|
||||
|
||||
class UniversalScanConfig {
|
||||
@@ -211,32 +247,21 @@ class UniversalScanFilter {
|
||||
final List<String> withNamePrefix;
|
||||
final List<UniversalManufacturerDataFilter> withManufacturerData;
|
||||
|
||||
UniversalScanFilter(
|
||||
this.withServices,
|
||||
this.withNamePrefix,
|
||||
this.withManufacturerData,
|
||||
);
|
||||
UniversalScanFilter(this.withServices, this.withNamePrefix, this.withManufacturerData);
|
||||
}
|
||||
|
||||
class UniversalManufacturerDataFilter {
|
||||
int companyIdentifier;
|
||||
Uint8List? data;
|
||||
Uint8List? mask;
|
||||
UniversalManufacturerDataFilter({
|
||||
required this.companyIdentifier,
|
||||
this.data,
|
||||
this.mask,
|
||||
});
|
||||
UniversalManufacturerDataFilter({required this.companyIdentifier, this.data, this.mask});
|
||||
}
|
||||
|
||||
class UniversalManufacturerData {
|
||||
final int companyIdentifier;
|
||||
final Uint8List data;
|
||||
|
||||
UniversalManufacturerData({
|
||||
required this.companyIdentifier,
|
||||
required this.data,
|
||||
});
|
||||
UniversalManufacturerData({required this.companyIdentifier, required this.data});
|
||||
}
|
||||
|
||||
/// Unified error codes for all platforms
|
||||
|
||||
@@ -33,6 +33,7 @@ dependencies:
|
||||
plugin_platform_interface: ^2.1.8
|
||||
flutter_web_bluetooth: ^1.1.0
|
||||
bluez: ^0.8.3
|
||||
dbus: ^0.7.11
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -26,8 +26,7 @@ void main() {
|
||||
group('BleCharacteristic Tests', () {
|
||||
test("DiscoverServices test", () async {
|
||||
debugPrint("Discovering services");
|
||||
List<BleService> services =
|
||||
await UniversalBle.discoverServices(mockDeviceId);
|
||||
List<BleService> services = await UniversalBle.discoverServices(mockDeviceId);
|
||||
expect(services.length, 1);
|
||||
|
||||
BleService service = services.first;
|
||||
@@ -35,18 +34,9 @@ void main() {
|
||||
expect(service.characteristics.length, 1);
|
||||
|
||||
BleCharacteristic characteristic = service.characteristics.first;
|
||||
expect(
|
||||
BleUuidParser.compareStrings(characteristic.uuid, characteristicId),
|
||||
true,
|
||||
);
|
||||
expect(BleUuidParser.compareStrings(characteristic.uuid, characteristicId), true);
|
||||
expect(characteristic.metaData?.deviceId, mockDeviceId);
|
||||
expect(
|
||||
BleUuidParser.compareStrings(
|
||||
characteristic.metaData!.serviceId,
|
||||
serviceId,
|
||||
),
|
||||
true,
|
||||
);
|
||||
expect(BleUuidParser.compareStrings(characteristic.metaData!.serviceId, serviceId), true);
|
||||
});
|
||||
|
||||
test("Subscription Test", () async {
|
||||
@@ -87,14 +77,17 @@ class _UniversalBleMock extends UniversalBlePlatformMock {
|
||||
Uint8List? charValue;
|
||||
|
||||
@override
|
||||
Future<List<BleService>> discoverServices(
|
||||
String deviceId, bool withDescriptors) async {
|
||||
Future<List<BleService>> discoverServices(String deviceId, bool withDescriptors) async {
|
||||
return <BleService>[mockBleService];
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setNotifiable(String deviceId, String service,
|
||||
String characteristic, BleInputProperty bleInputProperty) async {
|
||||
Future<void> setNotifiable(
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic,
|
||||
BleInputProperty bleInputProperty,
|
||||
) async {
|
||||
if (bleInputProperty == BleInputProperty.disabled) {
|
||||
notifierTimer?.cancel();
|
||||
notifierTimer = null;
|
||||
@@ -113,23 +106,30 @@ class _UniversalBleMock extends UniversalBlePlatformMock {
|
||||
|
||||
@override
|
||||
Future<void> writeValue(
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value,
|
||||
BleOutputProperty bleOutputProperty) async {
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value,
|
||||
BleOutputProperty bleOutputProperty,
|
||||
) async {
|
||||
charValue = value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readValue(
|
||||
String deviceId, String service, String characteristic,
|
||||
{Duration? timeout}) async {
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic, {
|
||||
Duration? timeout,
|
||||
}) async {
|
||||
return charValue ?? Uint8List(0);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> requestPermissions({bool withAndroidFineLocation = false}) {
|
||||
Future<void> requestPermissions({
|
||||
bool withAndroidFineLocation = false,
|
||||
bool withAndroidBluetoothAdvertise = false,
|
||||
}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:universal_ble/universal_ble.dart';
|
||||
|
||||
void main() {
|
||||
group('BlePeripheral models', () {
|
||||
test('normalizes UUIDs and defensively copies characteristic values', () {
|
||||
final initialValue = Uint8List.fromList([1, 2, 3]);
|
||||
|
||||
final characteristic = BlePeripheralCharacteristic(
|
||||
uuid: 'fff1',
|
||||
properties: const [CharacteristicProperty.read],
|
||||
permissions: const [BlePeripheralCharacteristicPermission.read],
|
||||
initialValue: initialValue,
|
||||
);
|
||||
|
||||
initialValue[0] = 9;
|
||||
|
||||
expect(
|
||||
BleUuidParser.compareStrings(characteristic.uuid, '0000fff1-0000-1000-8000-00805f9b34fb'),
|
||||
isTrue,
|
||||
);
|
||||
expect(characteristic.initialValue, [1, 2, 3]);
|
||||
});
|
||||
|
||||
test('normalizes write event UUIDs and defensively copies payloads', () {
|
||||
final value = Uint8List.fromList([4, 5, 6]);
|
||||
|
||||
final event = BlePeripheralWriteEvent(
|
||||
deviceId: 'client-1',
|
||||
service: 'fff0',
|
||||
characteristic: 'fff1',
|
||||
value: value,
|
||||
);
|
||||
|
||||
value[0] = 8;
|
||||
|
||||
expect(event.deviceId, 'client-1');
|
||||
expect(BleUuidParser.compareStrings(event.service, 'fff0'), isTrue);
|
||||
expect(BleUuidParser.compareStrings(event.characteristic, 'fff1'), isTrue);
|
||||
expect(event.value, [4, 5, 6]);
|
||||
});
|
||||
});
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// Autogenerated from Pigeon (v26.1.4), do not edit directly.
|
||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
#ifndef PIGEON_UNIVERSAL_BLE_G_H_
|
||||
@@ -23,17 +23,17 @@ class FlutterError {
|
||||
: code_(code) {}
|
||||
explicit FlutterError(const std::string& code, const std::string& message)
|
||||
: code_(code), message_(message) {}
|
||||
explicit FlutterError(const std::string& code, const std::string& message, const flutter::EncodableValue& details)
|
||||
explicit FlutterError(const std::string& code, const std::string& message, const ::flutter::EncodableValue& details)
|
||||
: code_(code), message_(message), details_(details) {}
|
||||
|
||||
const std::string& code() const { return code_; }
|
||||
const std::string& message() const { return message_; }
|
||||
const flutter::EncodableValue& details() const { return details_; }
|
||||
const ::flutter::EncodableValue& details() const { return details_; }
|
||||
|
||||
private:
|
||||
std::string code_;
|
||||
std::string message_;
|
||||
flutter::EncodableValue details_;
|
||||
::flutter::EncodableValue details_;
|
||||
};
|
||||
|
||||
template<class T> class ErrorOr {
|
||||
@@ -152,9 +152,9 @@ class UniversalBleScanResult {
|
||||
const std::string* name,
|
||||
const bool* is_paired,
|
||||
const int64_t* rssi,
|
||||
const flutter::EncodableList* manufacturer_data_list,
|
||||
const flutter::EncodableMap* service_data,
|
||||
const flutter::EncodableList* services,
|
||||
const ::flutter::EncodableList* manufacturer_data_list,
|
||||
const ::flutter::EncodableMap* service_data,
|
||||
const ::flutter::EncodableList* services,
|
||||
const int64_t* timestamp);
|
||||
|
||||
const std::string& device_id() const;
|
||||
@@ -172,25 +172,29 @@ class UniversalBleScanResult {
|
||||
void set_rssi(const int64_t* value_arg);
|
||||
void set_rssi(int64_t value_arg);
|
||||
|
||||
const flutter::EncodableList* manufacturer_data_list() const;
|
||||
void set_manufacturer_data_list(const flutter::EncodableList* value_arg);
|
||||
void set_manufacturer_data_list(const flutter::EncodableList& value_arg);
|
||||
const ::flutter::EncodableList* manufacturer_data_list() const;
|
||||
void set_manufacturer_data_list(const ::flutter::EncodableList* value_arg);
|
||||
void set_manufacturer_data_list(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
const flutter::EncodableMap* service_data() const;
|
||||
void set_service_data(const flutter::EncodableMap* value_arg);
|
||||
void set_service_data(const flutter::EncodableMap& value_arg);
|
||||
const ::flutter::EncodableMap* service_data() const;
|
||||
void set_service_data(const ::flutter::EncodableMap* value_arg);
|
||||
void set_service_data(const ::flutter::EncodableMap& value_arg);
|
||||
|
||||
const flutter::EncodableList* services() const;
|
||||
void set_services(const flutter::EncodableList* value_arg);
|
||||
void set_services(const flutter::EncodableList& value_arg);
|
||||
const ::flutter::EncodableList* services() const;
|
||||
void set_services(const ::flutter::EncodableList* value_arg);
|
||||
void set_services(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
const int64_t* timestamp() const;
|
||||
void set_timestamp(const int64_t* value_arg);
|
||||
void set_timestamp(int64_t value_arg);
|
||||
|
||||
bool operator==(const UniversalBleScanResult& other) const;
|
||||
bool operator!=(const UniversalBleScanResult& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalBleScanResult FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
static UniversalBleScanResult FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
@@ -198,9 +202,9 @@ class UniversalBleScanResult {
|
||||
std::optional<std::string> name_;
|
||||
std::optional<bool> is_paired_;
|
||||
std::optional<int64_t> rssi_;
|
||||
std::optional<flutter::EncodableList> manufacturer_data_list_;
|
||||
std::optional<flutter::EncodableMap> service_data_;
|
||||
std::optional<flutter::EncodableList> services_;
|
||||
std::optional<::flutter::EncodableList> manufacturer_data_list_;
|
||||
std::optional<::flutter::EncodableMap> service_data_;
|
||||
std::optional<::flutter::EncodableList> services_;
|
||||
std::optional<int64_t> timestamp_;
|
||||
};
|
||||
|
||||
@@ -214,23 +218,27 @@ class UniversalBleService {
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalBleService(
|
||||
const std::string& uuid,
|
||||
const flutter::EncodableList* characteristics);
|
||||
const ::flutter::EncodableList* characteristics);
|
||||
|
||||
const std::string& uuid() const;
|
||||
void set_uuid(std::string_view value_arg);
|
||||
|
||||
const flutter::EncodableList* characteristics() const;
|
||||
void set_characteristics(const flutter::EncodableList* value_arg);
|
||||
void set_characteristics(const flutter::EncodableList& value_arg);
|
||||
const ::flutter::EncodableList* characteristics() const;
|
||||
void set_characteristics(const ::flutter::EncodableList* value_arg);
|
||||
void set_characteristics(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
bool operator==(const UniversalBleService& other) const;
|
||||
bool operator!=(const UniversalBleService& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalBleService FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
static UniversalBleService FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
std::string uuid_;
|
||||
std::optional<flutter::EncodableList> characteristics_;
|
||||
std::optional<::flutter::EncodableList> characteristics_;
|
||||
};
|
||||
|
||||
|
||||
@@ -240,27 +248,31 @@ class UniversalBleCharacteristic {
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalBleCharacteristic(
|
||||
const std::string& uuid,
|
||||
const flutter::EncodableList& properties,
|
||||
const flutter::EncodableList& descriptors);
|
||||
const ::flutter::EncodableList& properties,
|
||||
const ::flutter::EncodableList& descriptors);
|
||||
|
||||
const std::string& uuid() const;
|
||||
void set_uuid(std::string_view value_arg);
|
||||
|
||||
const flutter::EncodableList& properties() const;
|
||||
void set_properties(const flutter::EncodableList& value_arg);
|
||||
const ::flutter::EncodableList& properties() const;
|
||||
void set_properties(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
const flutter::EncodableList& descriptors() const;
|
||||
void set_descriptors(const flutter::EncodableList& value_arg);
|
||||
const ::flutter::EncodableList& descriptors() const;
|
||||
void set_descriptors(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
bool operator==(const UniversalBleCharacteristic& other) const;
|
||||
bool operator!=(const UniversalBleCharacteristic& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalBleCharacteristic FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
static UniversalBleCharacteristic FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
std::string uuid_;
|
||||
flutter::EncodableList properties_;
|
||||
flutter::EncodableList descriptors_;
|
||||
::flutter::EncodableList properties_;
|
||||
::flutter::EncodableList descriptors_;
|
||||
};
|
||||
|
||||
|
||||
@@ -273,9 +285,13 @@ class UniversalBleDescriptor {
|
||||
const std::string& uuid() const;
|
||||
void set_uuid(std::string_view value_arg);
|
||||
|
||||
bool operator==(const UniversalBleDescriptor& other) const;
|
||||
bool operator!=(const UniversalBleDescriptor& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalBleDescriptor FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
static UniversalBleDescriptor FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
@@ -283,6 +299,195 @@ class UniversalBleDescriptor {
|
||||
};
|
||||
|
||||
|
||||
// Generated class from Pigeon that represents data sent in messages.
|
||||
class UniversalBlePeripheralConfig {
|
||||
public:
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalBlePeripheralConfig(
|
||||
const std::string& advertised_name,
|
||||
const ::flutter::EncodableList& services);
|
||||
|
||||
const std::string& advertised_name() const;
|
||||
void set_advertised_name(std::string_view value_arg);
|
||||
|
||||
const ::flutter::EncodableList& services() const;
|
||||
void set_services(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
bool operator==(const UniversalBlePeripheralConfig& other) const;
|
||||
bool operator!=(const UniversalBlePeripheralConfig& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalBlePeripheralConfig FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
std::string advertised_name_;
|
||||
::flutter::EncodableList services_;
|
||||
};
|
||||
|
||||
|
||||
// Generated class from Pigeon that represents data sent in messages.
|
||||
class UniversalBlePeripheralService {
|
||||
public:
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalBlePeripheralService(
|
||||
const std::string& uuid,
|
||||
const ::flutter::EncodableList& characteristics);
|
||||
|
||||
const std::string& uuid() const;
|
||||
void set_uuid(std::string_view value_arg);
|
||||
|
||||
const ::flutter::EncodableList& characteristics() const;
|
||||
void set_characteristics(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
bool operator==(const UniversalBlePeripheralService& other) const;
|
||||
bool operator!=(const UniversalBlePeripheralService& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalBlePeripheralService FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
std::string uuid_;
|
||||
::flutter::EncodableList characteristics_;
|
||||
};
|
||||
|
||||
|
||||
// Generated class from Pigeon that represents data sent in messages.
|
||||
class UniversalBlePeripheralCharacteristic {
|
||||
public:
|
||||
// Constructs an object setting all non-nullable fields.
|
||||
explicit UniversalBlePeripheralCharacteristic(
|
||||
const std::string& uuid,
|
||||
const ::flutter::EncodableList& properties,
|
||||
const ::flutter::EncodableList& permissions,
|
||||
const ::flutter::EncodableList& descriptors);
|
||||
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalBlePeripheralCharacteristic(
|
||||
const std::string& uuid,
|
||||
const ::flutter::EncodableList& properties,
|
||||
const ::flutter::EncodableList& permissions,
|
||||
const ::flutter::EncodableList& descriptors,
|
||||
const std::vector<uint8_t>* initial_value);
|
||||
|
||||
const std::string& uuid() const;
|
||||
void set_uuid(std::string_view value_arg);
|
||||
|
||||
const ::flutter::EncodableList& properties() const;
|
||||
void set_properties(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
const ::flutter::EncodableList& permissions() const;
|
||||
void set_permissions(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
const ::flutter::EncodableList& descriptors() const;
|
||||
void set_descriptors(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
const std::vector<uint8_t>* initial_value() const;
|
||||
void set_initial_value(const std::vector<uint8_t>* value_arg);
|
||||
void set_initial_value(const std::vector<uint8_t>& value_arg);
|
||||
|
||||
bool operator==(const UniversalBlePeripheralCharacteristic& other) const;
|
||||
bool operator!=(const UniversalBlePeripheralCharacteristic& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalBlePeripheralCharacteristic FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
std::string uuid_;
|
||||
::flutter::EncodableList properties_;
|
||||
::flutter::EncodableList permissions_;
|
||||
::flutter::EncodableList descriptors_;
|
||||
std::optional<std::vector<uint8_t>> initial_value_;
|
||||
};
|
||||
|
||||
|
||||
// Generated class from Pigeon that represents data sent in messages.
|
||||
class UniversalBlePeripheralDescriptor {
|
||||
public:
|
||||
// Constructs an object setting all non-nullable fields.
|
||||
explicit UniversalBlePeripheralDescriptor(
|
||||
const std::string& uuid,
|
||||
const ::flutter::EncodableList& permissions);
|
||||
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalBlePeripheralDescriptor(
|
||||
const std::string& uuid,
|
||||
const ::flutter::EncodableList& permissions,
|
||||
const std::vector<uint8_t>* initial_value);
|
||||
|
||||
const std::string& uuid() const;
|
||||
void set_uuid(std::string_view value_arg);
|
||||
|
||||
const ::flutter::EncodableList& permissions() const;
|
||||
void set_permissions(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
const std::vector<uint8_t>* initial_value() const;
|
||||
void set_initial_value(const std::vector<uint8_t>* value_arg);
|
||||
void set_initial_value(const std::vector<uint8_t>& value_arg);
|
||||
|
||||
bool operator==(const UniversalBlePeripheralDescriptor& other) const;
|
||||
bool operator!=(const UniversalBlePeripheralDescriptor& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalBlePeripheralDescriptor FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
std::string uuid_;
|
||||
::flutter::EncodableList permissions_;
|
||||
std::optional<std::vector<uint8_t>> initial_value_;
|
||||
};
|
||||
|
||||
|
||||
// Generated class from Pigeon that represents data sent in messages.
|
||||
class UniversalBlePeripheralWriteEvent {
|
||||
public:
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalBlePeripheralWriteEvent(
|
||||
const std::string& device_id,
|
||||
const std::string& service,
|
||||
const std::string& characteristic,
|
||||
const std::vector<uint8_t>& value);
|
||||
|
||||
const std::string& device_id() const;
|
||||
void set_device_id(std::string_view value_arg);
|
||||
|
||||
const std::string& service() const;
|
||||
void set_service(std::string_view value_arg);
|
||||
|
||||
const std::string& characteristic() const;
|
||||
void set_characteristic(std::string_view value_arg);
|
||||
|
||||
const std::vector<uint8_t>& value() const;
|
||||
void set_value(const std::vector<uint8_t>& value_arg);
|
||||
|
||||
bool operator==(const UniversalBlePeripheralWriteEvent& other) const;
|
||||
bool operator!=(const UniversalBlePeripheralWriteEvent& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalBlePeripheralWriteEvent FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
std::string device_id_;
|
||||
std::string service_;
|
||||
std::string characteristic_;
|
||||
std::vector<uint8_t> value_;
|
||||
};
|
||||
|
||||
|
||||
// Android options to scan devices
|
||||
// [requestLocationPermission] is used to request location permission on Android 12+ (API 31+).
|
||||
// [scanMode] is used to set the scan mode for for Bluetooth LE scan.
|
||||
@@ -314,9 +519,13 @@ class AndroidOptions {
|
||||
void set_report_delay_millis(const int64_t* value_arg);
|
||||
void set_report_delay_millis(int64_t value_arg);
|
||||
|
||||
bool operator==(const AndroidOptions& other) const;
|
||||
bool operator!=(const AndroidOptions& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static AndroidOptions FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
static AndroidOptions FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalScanConfig;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
@@ -345,9 +554,13 @@ class UniversalScanConfig {
|
||||
void set_android(const AndroidOptions* value_arg);
|
||||
void set_android(const AndroidOptions& value_arg);
|
||||
|
||||
bool operator==(const UniversalScanConfig& other) const;
|
||||
bool operator!=(const UniversalScanConfig& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalScanConfig FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
static UniversalScanConfig FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
@@ -362,28 +575,32 @@ class UniversalScanFilter {
|
||||
public:
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalScanFilter(
|
||||
const flutter::EncodableList& with_services,
|
||||
const flutter::EncodableList& with_name_prefix,
|
||||
const flutter::EncodableList& with_manufacturer_data);
|
||||
const ::flutter::EncodableList& with_services,
|
||||
const ::flutter::EncodableList& with_name_prefix,
|
||||
const ::flutter::EncodableList& with_manufacturer_data);
|
||||
|
||||
const flutter::EncodableList& with_services() const;
|
||||
void set_with_services(const flutter::EncodableList& value_arg);
|
||||
const ::flutter::EncodableList& with_services() const;
|
||||
void set_with_services(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
const flutter::EncodableList& with_name_prefix() const;
|
||||
void set_with_name_prefix(const flutter::EncodableList& value_arg);
|
||||
const ::flutter::EncodableList& with_name_prefix() const;
|
||||
void set_with_name_prefix(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
const flutter::EncodableList& with_manufacturer_data() const;
|
||||
void set_with_manufacturer_data(const flutter::EncodableList& value_arg);
|
||||
const ::flutter::EncodableList& with_manufacturer_data() const;
|
||||
void set_with_manufacturer_data(const ::flutter::EncodableList& value_arg);
|
||||
|
||||
bool operator==(const UniversalScanFilter& other) const;
|
||||
bool operator!=(const UniversalScanFilter& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalScanFilter FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
static UniversalScanFilter FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
flutter::EncodableList with_services_;
|
||||
flutter::EncodableList with_name_prefix_;
|
||||
flutter::EncodableList with_manufacturer_data_;
|
||||
::flutter::EncodableList with_services_;
|
||||
::flutter::EncodableList with_name_prefix_;
|
||||
::flutter::EncodableList with_manufacturer_data_;
|
||||
};
|
||||
|
||||
|
||||
@@ -410,9 +627,13 @@ class UniversalManufacturerDataFilter {
|
||||
void set_mask(const std::vector<uint8_t>* value_arg);
|
||||
void set_mask(const std::vector<uint8_t>& value_arg);
|
||||
|
||||
bool operator==(const UniversalManufacturerDataFilter& other) const;
|
||||
bool operator!=(const UniversalManufacturerDataFilter& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalManufacturerDataFilter FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
static UniversalManufacturerDataFilter FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
@@ -436,9 +657,13 @@ class UniversalManufacturerData {
|
||||
const std::vector<uint8_t>& data() const;
|
||||
void set_data(const std::vector<uint8_t>& value_arg);
|
||||
|
||||
bool operator==(const UniversalManufacturerData& other) const;
|
||||
bool operator!=(const UniversalManufacturerData& other) const;
|
||||
/// Returns a hash code value for the object. This method is supported for the benefit of hash tables.
|
||||
size_t Hash() const;
|
||||
private:
|
||||
static UniversalManufacturerData FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
static UniversalManufacturerData FromEncodableList(const ::flutter::EncodableList& list);
|
||||
::flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class PigeonInternalCodecSerializer;
|
||||
@@ -447,7 +672,7 @@ class UniversalManufacturerData {
|
||||
};
|
||||
|
||||
|
||||
class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer {
|
||||
class PigeonInternalCodecSerializer : public ::flutter::StandardCodecSerializer {
|
||||
public:
|
||||
PigeonInternalCodecSerializer();
|
||||
inline static PigeonInternalCodecSerializer& GetInstance() {
|
||||
@@ -456,12 +681,12 @@ class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer {
|
||||
}
|
||||
|
||||
void WriteValue(
|
||||
const flutter::EncodableValue& value,
|
||||
flutter::ByteStreamWriter* stream) const override;
|
||||
const ::flutter::EncodableValue& value,
|
||||
::flutter::ByteStreamWriter* stream) const override;
|
||||
protected:
|
||||
flutter::EncodableValue ReadValueOfType(
|
||||
::flutter::EncodableValue ReadValueOfType(
|
||||
uint8_t type,
|
||||
flutter::ByteStreamReader* stream) const override;
|
||||
::flutter::ByteStreamReader* stream) const override;
|
||||
};
|
||||
|
||||
// Flutter -> Native
|
||||
@@ -473,9 +698,12 @@ class UniversalBlePlatformChannel {
|
||||
UniversalBlePlatformChannel& operator=(const UniversalBlePlatformChannel&) = delete;
|
||||
virtual ~UniversalBlePlatformChannel() {}
|
||||
virtual void GetBluetoothAvailabilityState(std::function<void(ErrorOr<int64_t> reply)> result) = 0;
|
||||
virtual ErrorOr<bool> HasPermissions(bool with_android_fine_location) = 0;
|
||||
virtual ErrorOr<bool> HasPermissions(
|
||||
bool with_android_fine_location,
|
||||
bool with_android_bluetooth_advertise) = 0;
|
||||
virtual void RequestPermissions(
|
||||
bool with_android_fine_location,
|
||||
bool with_android_bluetooth_advertise,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) = 0;
|
||||
virtual void EnableBluetooth(std::function<void(ErrorOr<bool> reply)> result) = 0;
|
||||
virtual void DisableBluetooth(std::function<void(ErrorOr<bool> reply)> result) = 0;
|
||||
@@ -497,7 +725,7 @@ class UniversalBlePlatformChannel {
|
||||
virtual void DiscoverServices(
|
||||
const std::string& device_id,
|
||||
bool with_descriptors,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result) = 0;
|
||||
std::function<void(ErrorOr<::flutter::EncodableList> reply)> result) = 0;
|
||||
virtual void ReadValue(
|
||||
const std::string& device_id,
|
||||
const std::string& service,
|
||||
@@ -522,8 +750,8 @@ class UniversalBlePlatformChannel {
|
||||
std::function<void(ErrorOr<bool> reply)> result) = 0;
|
||||
virtual std::optional<FlutterError> UnPair(const std::string& device_id) = 0;
|
||||
virtual void GetSystemDevices(
|
||||
const flutter::EncodableList& with_services,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result) = 0;
|
||||
const ::flutter::EncodableList& with_services,
|
||||
std::function<void(ErrorOr<::flutter::EncodableList> reply)> result) = 0;
|
||||
virtual ErrorOr<int64_t> GetConnectionState(const std::string& device_id) = 0;
|
||||
virtual void ReadRssi(
|
||||
const std::string& device_id,
|
||||
@@ -532,20 +760,36 @@ class UniversalBlePlatformChannel {
|
||||
const std::string& device_id,
|
||||
int64_t priority,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) = 0;
|
||||
virtual ErrorOr<bool> IsPeripheralSupported() = 0;
|
||||
virtual void StartPeripheral(
|
||||
const UniversalBlePeripheralConfig& config,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) = 0;
|
||||
virtual void StopPeripheral(std::function<void(std::optional<FlutterError> reply)> result) = 0;
|
||||
virtual void UpdatePeripheralCharacteristicValue(
|
||||
const std::string& service,
|
||||
const std::string& characteristic,
|
||||
const std::vector<uint8_t>& value,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) = 0;
|
||||
virtual void NotifyPeripheralCharacteristic(
|
||||
const std::string& service,
|
||||
const std::string& characteristic,
|
||||
const std::vector<uint8_t>& value,
|
||||
bool indicate,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) = 0;
|
||||
virtual std::optional<FlutterError> SetLogLevel(const UniversalBleLogLevel& log_level) = 0;
|
||||
|
||||
// The codec used by UniversalBlePlatformChannel.
|
||||
static const flutter::StandardMessageCodec& GetCodec();
|
||||
static const ::flutter::StandardMessageCodec& GetCodec();
|
||||
// Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binary_messenger`.
|
||||
static void SetUp(
|
||||
flutter::BinaryMessenger* binary_messenger,
|
||||
::flutter::BinaryMessenger* binary_messenger,
|
||||
UniversalBlePlatformChannel* api);
|
||||
static void SetUp(
|
||||
flutter::BinaryMessenger* binary_messenger,
|
||||
::flutter::BinaryMessenger* binary_messenger,
|
||||
UniversalBlePlatformChannel* api,
|
||||
const std::string& message_channel_suffix);
|
||||
static flutter::EncodableValue WrapError(std::string_view error_message);
|
||||
static flutter::EncodableValue WrapError(const FlutterError& error);
|
||||
static ::flutter::EncodableValue WrapError(std::string_view error_message);
|
||||
static ::flutter::EncodableValue WrapError(const FlutterError& error);
|
||||
protected:
|
||||
UniversalBlePlatformChannel() = default;
|
||||
};
|
||||
@@ -554,11 +798,11 @@ class UniversalBlePlatformChannel {
|
||||
// Generated class from Pigeon that represents Flutter messages that can be called from C++.
|
||||
class UniversalBleCallbackChannel {
|
||||
public:
|
||||
UniversalBleCallbackChannel(flutter::BinaryMessenger* binary_messenger);
|
||||
UniversalBleCallbackChannel(::flutter::BinaryMessenger* binary_messenger);
|
||||
UniversalBleCallbackChannel(
|
||||
flutter::BinaryMessenger* binary_messenger,
|
||||
::flutter::BinaryMessenger* binary_messenger,
|
||||
const std::string& message_channel_suffix);
|
||||
static const flutter::StandardMessageCodec& GetCodec();
|
||||
static const ::flutter::StandardMessageCodec& GetCodec();
|
||||
void OnAvailabilityChanged(
|
||||
int64_t state,
|
||||
std::function<void(void)>&& on_success,
|
||||
@@ -586,8 +830,24 @@ class UniversalBleCallbackChannel {
|
||||
const std::string* error,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
void OnPeripheralConnectionChanged(
|
||||
const std::string& device_id,
|
||||
bool connected,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
void OnPeripheralWrite(
|
||||
const UniversalBlePeripheralWriteEvent& event,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
void OnPeripheralSubscriptionChanged(
|
||||
const std::string& device_id,
|
||||
const std::string& service,
|
||||
const std::string& characteristic,
|
||||
bool subscribed,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
private:
|
||||
flutter::BinaryMessenger* binary_messenger_;
|
||||
::flutter::BinaryMessenger* binary_messenger_;
|
||||
std::string message_channel_suffix_;
|
||||
};
|
||||
|
||||
|
||||
@@ -120,13 +120,14 @@ void UniversalBlePlugin::DisableBluetooth(
|
||||
}
|
||||
|
||||
ErrorOr<bool>
|
||||
UniversalBlePlugin::HasPermissions(bool with_android_fine_location) {
|
||||
UniversalBlePlugin::HasPermissions(bool with_android_fine_location,
|
||||
bool with_android_bluetooth_advertise) {
|
||||
// Windows does not require runtime permissions for Bluetooth
|
||||
return true;
|
||||
}
|
||||
|
||||
void UniversalBlePlugin::RequestPermissions(
|
||||
bool with_android_fine_location,
|
||||
bool with_android_fine_location, bool with_android_bluetooth_advertise,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) {
|
||||
// Windows does not require runtime permissions for Bluetooth
|
||||
result(std::nullopt);
|
||||
@@ -444,6 +445,39 @@ void UniversalBlePlugin::RequestConnectionPriority(
|
||||
"requestConnectionPriority is not supported on Windows platform"));
|
||||
}
|
||||
|
||||
ErrorOr<bool> UniversalBlePlugin::IsPeripheralSupported() { return false; }
|
||||
|
||||
void UniversalBlePlugin::StartPeripheral(
|
||||
const UniversalBlePeripheralConfig &config,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) {
|
||||
result(create_flutter_error(
|
||||
UniversalBleErrorCode::kNotSupported,
|
||||
"BLE peripheral mode is not implemented on Windows platform yet"));
|
||||
}
|
||||
|
||||
void UniversalBlePlugin::StopPeripheral(
|
||||
std::function<void(std::optional<FlutterError> reply)> result) {
|
||||
result(std::nullopt);
|
||||
}
|
||||
|
||||
void UniversalBlePlugin::UpdatePeripheralCharacteristicValue(
|
||||
const std::string &service, const std::string &characteristic,
|
||||
const std::vector<uint8_t> &value,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) {
|
||||
result(create_flutter_error(
|
||||
UniversalBleErrorCode::kNotSupported,
|
||||
"BLE peripheral mode is not implemented on Windows platform yet"));
|
||||
}
|
||||
|
||||
void UniversalBlePlugin::NotifyPeripheralCharacteristic(
|
||||
const std::string &service, const std::string &characteristic,
|
||||
const std::vector<uint8_t> &value, bool indicate,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) {
|
||||
result(create_flutter_error(
|
||||
UniversalBleErrorCode::kNotSupported,
|
||||
"BLE peripheral mode is not implemented on Windows platform yet"));
|
||||
}
|
||||
|
||||
void UniversalBlePlugin::ReadRssi(
|
||||
const std::string &device_id,
|
||||
std::function<void(ErrorOr<int64_t> reply)> result) {
|
||||
|
||||
@@ -184,9 +184,10 @@ private:
|
||||
ErrorOr<bool> IsScanning() override;
|
||||
std::optional<FlutterError> Connect(const std::string &device_id, const bool *auto_connect) override;
|
||||
std::optional<FlutterError> Disconnect(const std::string &device_id) override;
|
||||
ErrorOr<bool> HasPermissions(bool with_android_fine_location) override;
|
||||
ErrorOr<bool> HasPermissions(bool with_android_fine_location,
|
||||
bool with_android_bluetooth_advertise) override;
|
||||
void RequestPermissions(
|
||||
bool with_android_fine_location,
|
||||
bool with_android_fine_location, bool with_android_bluetooth_advertise,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) override;
|
||||
void
|
||||
DiscoverServices(const std::string &device_id, bool with_descriptors,
|
||||
@@ -210,6 +211,20 @@ private:
|
||||
void RequestConnectionPriority(
|
||||
const std::string &device_id, int64_t priority,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) override;
|
||||
ErrorOr<bool> IsPeripheralSupported() override;
|
||||
void StartPeripheral(
|
||||
const UniversalBlePeripheralConfig &config,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) override;
|
||||
void StopPeripheral(
|
||||
std::function<void(std::optional<FlutterError> reply)> result) override;
|
||||
void UpdatePeripheralCharacteristicValue(
|
||||
const std::string &service, const std::string &characteristic,
|
||||
const std::vector<uint8_t> &value,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) override;
|
||||
void NotifyPeripheralCharacteristic(
|
||||
const std::string &service, const std::string &characteristic,
|
||||
const std::vector<uint8_t> &value, bool indicate,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) override;
|
||||
void ReadRssi(const std::string &device_id,
|
||||
std::function<void(ErrorOr<int64_t> reply)> result) override;
|
||||
void IsPaired(const std::string &device_id,
|
||||
|
||||
Reference in New Issue
Block a user