Improve windows device name discovery (#4)

* Improve windows device name discovery

* Imrove classes and folders structuring

* rename generated files

* Improve windows threads and other fixes

* More optimizations

* Cleanups

* Update .vscode/settings.json

Co-authored-by: Foti Dim <foti@navideck.com>

* Resolve comments

* Performance improvements

---------

Co-authored-by: Foti Dim <foti@navideck.com>
Co-authored-by: Foti Dim <fdimanidis@gmail.com>
This commit is contained in:
Rohit Sangwan
2024-02-02 16:40:53 +05:30
committed by GitHub
parent 2dedc0e600
commit ed3852a5c9
18 changed files with 1000 additions and 673 deletions
+14 -1
View File
@@ -1,18 +1,31 @@
{
"cSpell.words": [
"BTLE",
"bytevc",
"connnection",
"DSIMPLEBLE",
"hresult",
"hstring",
"HWND",
"Inspectable",
"LPARAM",
"LRESULT",
"microtask",
"modalias",
"navideck",
"NSUUID",
"NTDDI",
"pairable",
"rssi",
"simpleble",
"unawaited",
"UNIVERSALBLE",
"Unpair",
"Unpairing",
"unwatch",
"uuidstr"
"uuidstr",
"winrt",
"WPARAM"
],
"cmake.configureOnOpen": false,
"files.associations": {
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v13.0.0), do not edit directly.
// Autogenerated from Pigeon (v16.0.5), do not edit directly.
// See also: https://pub.dev/packages/pigeon
package com.navideck.universal_ble
@@ -31,6 +31,9 @@ private fun wrapError(exception: Throwable): List<Any?> {
}
}
private fun createConnectionError(channelName: String): FlutterError {
return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "")}
/**
* Error class for passing custom error details to Flutter via a thrown PlatformException.
* @property code The error code.
@@ -525,73 +528,83 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger)
UniversalBleCallbackChannelCodec
}
}
fun onAvailabilityChanged(stateArg: Long, callback: (Result<Unit>) -> Unit) {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged", codec)
fun onAvailabilityChanged(stateArg: Long, callback: (Result<Unit>) -> Unit)
{
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged"
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
channel.send(listOf(stateArg)) {
if (it is List<*>) {
if (it.size > 1) {
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)));
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
} else {
callback(Result.success(Unit));
callback(Result.success(Unit))
}
} else {
callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", "")));
callback(Result.failure(createConnectionError(channelName)))
}
}
}
fun onPairStateChange(deviceIdArg: String, isPairedArg: Boolean, errorArg: String?, callback: (Result<Unit>) -> Unit) {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange", codec)
fun onPairStateChange(deviceIdArg: String, isPairedArg: Boolean, errorArg: String?, callback: (Result<Unit>) -> Unit)
{
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange"
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
channel.send(listOf(deviceIdArg, isPairedArg, errorArg)) {
if (it is List<*>) {
if (it.size > 1) {
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)));
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
} else {
callback(Result.success(Unit));
callback(Result.success(Unit))
}
} else {
callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", "")));
callback(Result.failure(createConnectionError(channelName)))
}
}
}
fun onScanResult(resultArg: UniversalBleScanResult, callback: (Result<Unit>) -> Unit) {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult", codec)
fun onScanResult(resultArg: UniversalBleScanResult, callback: (Result<Unit>) -> Unit)
{
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult"
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
channel.send(listOf(resultArg)) {
if (it is List<*>) {
if (it.size > 1) {
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)));
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
} else {
callback(Result.success(Unit));
callback(Result.success(Unit))
}
} else {
callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", "")));
callback(Result.failure(createConnectionError(channelName)))
}
}
}
fun onValueChanged(deviceIdArg: String, characteristicIdArg: String, valueArg: ByteArray, callback: (Result<Unit>) -> Unit) {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged", codec)
fun onValueChanged(deviceIdArg: String, characteristicIdArg: String, valueArg: ByteArray, callback: (Result<Unit>) -> Unit)
{
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged"
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
channel.send(listOf(deviceIdArg, characteristicIdArg, valueArg)) {
if (it is List<*>) {
if (it.size > 1) {
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)));
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
} else {
callback(Result.success(Unit));
callback(Result.success(Unit))
}
} else {
callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", "")));
callback(Result.failure(createConnectionError(channelName)))
}
}
}
fun onConnectionChanged(deviceIdArg: String, stateArg: Long, callback: (Result<Unit>) -> Unit) {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged", codec)
fun onConnectionChanged(deviceIdArg: String, stateArg: Long, callback: (Result<Unit>) -> Unit)
{
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged"
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
channel.send(listOf(deviceIdArg, stateArg)) {
if (it is List<*>) {
if (it.size > 1) {
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)));
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
} else {
callback(Result.success(Unit));
callback(Result.success(Unit))
}
} else {
callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", "")));
callback(Result.failure(createConnectionError(channelName)))
}
}
}
+150 -85
View File
@@ -1,18 +1,15 @@
// Autogenerated from Pigeon (v13.0.0), do not edit directly.
// Autogenerated from Pigeon (v16.0.5), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
#if os(iOS)
import Flutter
#elseif os(macOS)
import FlutterMacOS
#else
#error("Unsupported platform.")
#endif
private func isNullish(_ value: Any?) -> Bool {
return value is NSNull || value == nil
}
#if os(iOS)
import Flutter
#elseif os(macOS)
import FlutterMacOS
#else
#error("Unsupported platform.")
#endif
private func wrapResult(_ result: Any?) -> [Any?] {
return [result]
@@ -23,16 +20,24 @@ private func wrapError(_ error: Any) -> [Any?] {
return [
flutterError.code,
flutterError.message,
flutterError.details
flutterError.details,
]
}
return [
"\(error)",
"\(type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)"
"Stacktrace: \(Thread.callStackSymbols)",
]
}
private func createConnectionError(withChannelName channelName: String) -> FlutterError {
return FlutterError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "")
}
private func isNullish(_ value: Any?) -> Bool {
return value is NSNull || value == nil
}
private func nilOrValue<T>(_ value: Any?) -> T? {
if value is NSNull { return nil }
return value as! T?
@@ -123,14 +128,14 @@ struct UniversalBleCharacteristic {
private class UniversalBlePlatformChannelCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 128:
return UniversalBleCharacteristic.fromList(self.readValue() as! [Any?])
case 129:
return UniversalBleScanResult.fromList(self.readValue() as! [Any?])
case 130:
return UniversalBleService.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
case 128:
return UniversalBleCharacteristic.fromList(self.readValue() as! [Any?])
case 129:
return UniversalBleScanResult.fromList(self.readValue() as! [Any?])
case 130:
return UniversalBleService.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
}
}
}
@@ -196,12 +201,12 @@ class UniversalBlePlatformChannelSetup {
let getBluetoothAvailabilityStateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
getBluetoothAvailabilityStateChannel.setMessageHandler { _, reply in
api.getBluetoothAvailabilityState() { result in
api.getBluetoothAvailabilityState { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
@@ -211,12 +216,12 @@ class UniversalBlePlatformChannelSetup {
let enableBluetoothChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
enableBluetoothChannel.setMessageHandler { _, reply in
api.enableBluetooth() { result in
api.enableBluetooth { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
@@ -304,10 +309,10 @@ class UniversalBlePlatformChannelSetup {
let deviceIdArg = args[0] as! String
api.discoverServices(deviceId: deviceIdArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
@@ -323,10 +328,10 @@ class UniversalBlePlatformChannelSetup {
let characteristicArg = args[2] as! String
api.readValue(deviceId: deviceIdArg, service: serviceArg, characteristic: characteristicArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
@@ -341,10 +346,10 @@ class UniversalBlePlatformChannelSetup {
let expectedMtuArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
api.requestMtu(deviceId: deviceIdArg, expectedMtu: expectedMtuArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
@@ -362,10 +367,10 @@ class UniversalBlePlatformChannelSetup {
let bleOutputPropertyArg = args[4] is Int64 ? args[4] as! Int64 : Int64(args[4] as! Int32)
api.writeValue(deviceId: deviceIdArg, service: serviceArg, characteristic: characteristicArg, value: valueArg, bleOutputProperty: bleOutputPropertyArg) { result in
switch result {
case .success:
reply(wrapResult(nil))
case .failure(let error):
reply(wrapError(error))
case .success:
reply(wrapResult(nil))
case .failure(let error):
reply(wrapError(error))
}
}
}
@@ -379,10 +384,10 @@ class UniversalBlePlatformChannelSetup {
let deviceIdArg = args[0] as! String
api.isPaired(deviceId: deviceIdArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
@@ -426,10 +431,10 @@ class UniversalBlePlatformChannelSetup {
let withServicesArg = args[0] as! [String]
api.getConnectedDevices(withServices: withServicesArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
@@ -441,10 +446,10 @@ class UniversalBlePlatformChannelSetup {
private class UniversalBleCallbackChannelCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 128:
return UniversalBleScanResult.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
case 128:
return UniversalBleScanResult.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
}
}
}
@@ -478,48 +483,108 @@ class UniversalBleCallbackChannelCodec: FlutterStandardMessageCodec {
///
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
protocol UniversalBleCallbackChannelProtocol {
func onAvailabilityChanged(state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onConnectionChanged(deviceId deviceIdArg: String, state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onAvailabilityChanged(state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void)
func onConnectionChanged(deviceId deviceIdArg: String, state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
}
class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol {
private let binaryMessenger: FlutterBinaryMessenger
init(binaryMessenger: FlutterBinaryMessenger){
init(binaryMessenger: FlutterBinaryMessenger) {
self.binaryMessenger = binaryMessenger
}
var codec: FlutterStandardMessageCodec {
return UniversalBleCallbackChannelCodec.shared
}
func onAvailabilityChanged(state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([stateArg] as [Any?]) { _ in
completion(.success(Void()))
func onAvailabilityChanged(state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([stateArg] 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(FlutterError(code: code, message: message, details: details)))
} else {
completion(.success(Void()))
}
}
}
func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, FlutterError>) -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([deviceIdArg, isPairedArg, errorArg] as [Any?]) { _ in
completion(.success(Void()))
func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result<Void, FlutterError>) -> Void) {
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([deviceIdArg, isPairedArg, errorArg] 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(FlutterError(code: code, message: message, details: details)))
} else {
completion(.success(Void()))
}
}
}
func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result<Void, FlutterError>) -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([resultArg] as [Any?]) { _ in
completion(.success(Void()))
func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result<Void, FlutterError>) -> Void) {
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([resultArg] 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(FlutterError(code: code, message: message, details: details)))
} else {
completion(.success(Void()))
}
}
}
func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([deviceIdArg, characteristicIdArg, valueArg] as [Any?]) { _ in
completion(.success(Void()))
func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void) {
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([deviceIdArg, characteristicIdArg, valueArg] 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(FlutterError(code: code, message: message, details: details)))
} else {
completion(.success(Void()))
}
}
}
func onConnectionChanged(deviceId deviceIdArg: String, state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([deviceIdArg, stateArg] as [Any?]) { _ in
completion(.success(Void()))
func onConnectionChanged(deviceId deviceIdArg: String, state stateArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([deviceIdArg, stateArg] 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(FlutterError(code: code, message: message, details: details)))
} else {
completion(.success(Void()))
}
}
}
}
+1 -1
View File
@@ -386,7 +386,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.8.3"
version: "0.8.4"
vector_math:
dependency: transitive
description:
+269 -261
View File
@@ -1,12 +1,20 @@
// Autogenerated from Pigeon (v13.0.0), do not edit directly.
// Autogenerated from Pigeon (v16.0.5), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
PlatformException _createConnectionError(String channelName) {
return PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
}
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
if (empty) {
return <Object?>[];
@@ -154,81 +162,81 @@ class UniversalBlePlatformChannel {
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
UniversalBlePlatformChannel({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;
final BinaryMessenger? _binaryMessenger;
: __pigeon_binaryMessenger = binaryMessenger;
final BinaryMessenger? __pigeon_binaryMessenger;
static const MessageCodec<Object?> codec = _UniversalBlePlatformChannelCodec();
static const MessageCodec<Object?> pigeonChannelCodec = _UniversalBlePlatformChannelCodec();
Future<int> getBluetoothAvailabilityState() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(null) as List<Object?>?;
if (replyList == null) {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(null) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
} else if (__pigeon_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as int?)!;
return (__pigeon_replyList[0] as int?)!;
}
}
Future<bool> enableBluetooth() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(null) as List<Object?>?;
if (replyList == null) {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(null) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
} else if (__pigeon_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as bool?)!;
return (__pigeon_replyList[0] as bool?)!;
}
}
Future<void> startScan() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(null) as List<Object?>?;
if (replyList == null) {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(null) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else {
return;
@@ -236,291 +244,291 @@ class UniversalBlePlatformChannel {
}
Future<void> stopScan() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(null) as List<Object?>?;
if (replyList == null) {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(null) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else {
return;
}
}
Future<void> connect(String arg_deviceId) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_deviceId]) as List<Object?>?;
if (replyList == null) {
Future<void> connect(String deviceId) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else {
return;
}
}
Future<void> disconnect(String arg_deviceId) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_deviceId]) as List<Object?>?;
if (replyList == null) {
Future<void> disconnect(String deviceId) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else {
return;
}
}
Future<void> setNotifiable(String arg_deviceId, String arg_service, String arg_characteristic, int arg_bleInputProperty) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_deviceId, arg_service, arg_characteristic, arg_bleInputProperty]) as List<Object?>?;
if (replyList == null) {
Future<void> setNotifiable(String deviceId, String service, String characteristic, int bleInputProperty) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, service, characteristic, bleInputProperty]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else {
return;
}
}
Future<List<UniversalBleService?>> discoverServices(String arg_deviceId) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_deviceId]) as List<Object?>?;
if (replyList == null) {
Future<List<UniversalBleService?>> discoverServices(String deviceId) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
} else if (__pigeon_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as List<Object?>?)!.cast<UniversalBleService?>();
return (__pigeon_replyList[0] as List<Object?>?)!.cast<UniversalBleService?>();
}
}
Future<Uint8List> readValue(String arg_deviceId, String arg_service, String arg_characteristic) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_deviceId, arg_service, arg_characteristic]) as List<Object?>?;
if (replyList == null) {
Future<Uint8List> readValue(String deviceId, String service, String characteristic) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, service, characteristic]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
} else if (__pigeon_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as Uint8List?)!;
return (__pigeon_replyList[0] as Uint8List?)!;
}
}
Future<int> requestMtu(String arg_deviceId, int arg_expectedMtu) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_deviceId, arg_expectedMtu]) as List<Object?>?;
if (replyList == null) {
Future<int> requestMtu(String deviceId, int expectedMtu) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, expectedMtu]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
} else if (__pigeon_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as int?)!;
return (__pigeon_replyList[0] as int?)!;
}
}
Future<void> writeValue(String arg_deviceId, String arg_service, String arg_characteristic, Uint8List arg_value, int arg_bleOutputProperty) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_deviceId, arg_service, arg_characteristic, arg_value, arg_bleOutputProperty]) as List<Object?>?;
if (replyList == null) {
Future<void> writeValue(String deviceId, String service, String characteristic, Uint8List value, int bleOutputProperty) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId, service, characteristic, value, bleOutputProperty]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else {
return;
}
}
Future<bool> isPaired(String arg_deviceId) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_deviceId]) as List<Object?>?;
if (replyList == null) {
Future<bool> isPaired(String deviceId) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
} else if (__pigeon_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as bool?)!;
return (__pigeon_replyList[0] as bool?)!;
}
}
Future<void> pair(String arg_deviceId) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_deviceId]) as List<Object?>?;
if (replyList == null) {
Future<void> pair(String deviceId) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else {
return;
}
}
Future<void> unPair(String arg_deviceId) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_deviceId]) as List<Object?>?;
if (replyList == null) {
Future<void> unPair(String deviceId) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[deviceId]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else {
return;
}
}
Future<List<UniversalBleScanResult?>> getConnectedDevices(List<String?> arg_withServices) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectedDevices', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_withServices]) as List<Object?>?;
if (replyList == null) {
Future<List<UniversalBleScanResult?>> getConnectedDevices(List<String?> withServices) async {
const String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectedDevices';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(<Object?>[withServices]) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
} else if (__pigeon_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as List<Object?>?)!.cast<UniversalBleScanResult?>();
return (__pigeon_replyList[0] as List<Object?>?)!.cast<UniversalBleScanResult?>();
}
}
}
@@ -550,7 +558,7 @@ class _UniversalBleCallbackChannelCodec extends StandardMessageCodec {
/// Native -> Flutter
abstract class UniversalBleCallbackChannel {
static const MessageCodec<Object?> codec = _UniversalBleCallbackChannelCodec();
static const MessageCodec<Object?> pigeonChannelCodec = _UniversalBleCallbackChannelCodec();
void onAvailabilityChanged(int state);
@@ -564,13 +572,13 @@ abstract class UniversalBleCallbackChannel {
static void setup(UniversalBleCallbackChannel? api, {BinaryMessenger? binaryMessenger}) {
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged', codec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
__pigeon_channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
@@ -589,13 +597,13 @@ abstract class UniversalBleCallbackChannel {
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange', codec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
__pigeon_channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null.');
final List<Object?> args = (message as List<Object?>?)!;
@@ -618,13 +626,13 @@ abstract class UniversalBleCallbackChannel {
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult', codec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
__pigeon_channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.');
final List<Object?> args = (message as List<Object?>?)!;
@@ -643,13 +651,13 @@ abstract class UniversalBleCallbackChannel {
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged', codec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
__pigeon_channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
@@ -674,13 +682,13 @@ abstract class UniversalBleCallbackChannel {
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged', codec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
__pigeon_channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
+2 -2
View File
@@ -12,8 +12,8 @@ import 'package:pigeon/pigeon.dart';
kotlinOptions: KotlinOptions(package: 'com.navideck.universal_ble'),
swiftOptions: SwiftOptions(),
cppOptions: CppOptions(namespace: 'universal_ble'),
cppHeaderOut: 'windows/UniversalBle.g.h',
cppSourceOut: 'windows/UniversalBle.g.cpp',
cppHeaderOut: 'windows/src/generated/universal_ble.g.h',
cppSourceOut: 'windows/src/generated/universal_ble.g.cpp',
debugGenerators: true,
),
)
+2 -4
View File
@@ -12,7 +12,7 @@ platforms:
macos:
web:
windows:
environment:
sdk: ">=3.1.3 <4.0.0"
flutter: ">=3.3.0"
@@ -30,7 +30,7 @@ dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
pigeon: ^13.0.0
pigeon: ^16.0.5
flutter:
plugin:
@@ -46,5 +46,3 @@ flutter:
sharedDarwinSource: true
windows:
pluginClass: UniversalBlePluginCApi
+24 -25
View File
@@ -6,7 +6,7 @@ include(FetchContent)
set(CPPWINRT_VERSION "2.0.220418.1")
set(PLUGIN_NAME "universal_ble_plugin")
################ NuGet intall begin ################
# ############### NuGet intall begin ################
FetchContent_Declare(nuget
URL "https://dist.nuget.org/win-x86-commandline/v6.0.0/nuget.exe"
URL_HASH SHA256=04eb6c4fe4213907e2773e1be1bbbd730e9a655a3c9c58387ce8d4a714a5b9e1
@@ -14,31 +14,33 @@ FetchContent_Declare(nuget
)
find_program(NUGET nuget)
if (NOT NUGET)
message("Nuget.exe not found, trying to download or use cached version.")
FetchContent_MakeAvailable(nuget)
set(NUGET ${nuget_SOURCE_DIR}/nuget.exe)
if(NOT NUGET)
message("Nuget.exe not found, trying to download or use cached version.")
FetchContent_MakeAvailable(nuget)
set(NUGET ${nuget_SOURCE_DIR}/nuget.exe)
endif()
execute_process(COMMAND
${NUGET} install "Microsoft.Windows.CppWinRT" -Version ${CPPWINRT_VERSION} -OutputDirectory packages
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
RESULT_VARIABLE ret)
if (NOT ret EQUAL 0)
message(FATAL_ERROR "Failed to install nuget package Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}")
${NUGET} install "Microsoft.Windows.CppWinRT" -Version ${CPPWINRT_VERSION} -OutputDirectory packages
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
RESULT_VARIABLE ret)
if(NOT ret EQUAL 0)
message(FATAL_ERROR "Failed to install nuget package Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}")
endif()
################ NuGet install end ################
# ############### NuGet install end ################
list(APPEND PLUGIN_SOURCES
"universal_ble_plugin.cpp"
"universal_ble_plugin.h"
"universal_enum.h"
"Utils.cpp"
"Utils.h"
"UniversalBle.g.cpp"
"UniversalBle.g.h"
"src/universal_ble_plugin.cpp"
"src/universal_ble_plugin.h"
"src/helper/universal_enum.h"
"src/helper/universal_ble_base.h"
"src/helper/utils.cpp"
"src/helper/utils.h"
"src/ui_thread_handler.hpp"
"src/generated/universal_ble.g.cpp"
"src/generated/universal_ble.g.h"
)
add_library(${PLUGIN_NAME} SHARED
@@ -47,11 +49,9 @@ add_library(${PLUGIN_NAME} SHARED
${PLUGIN_SOURCES}
)
apply_standard_settings(${PLUGIN_NAME})
################ NuGet import begin ################
# ############### NuGet import begin ################
set_target_properties(${PLUGIN_NAME} PROPERTIES VS_PROJECT_IMPORT
${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}/build/native/Microsoft.Windows.CppWinRT.props
)
@@ -59,8 +59,8 @@ set_target_properties(${PLUGIN_NAME} PROPERTIES VS_PROJECT_IMPORT
target_link_libraries(${PLUGIN_NAME} PRIVATE
${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}/build/native/Microsoft.Windows.CppWinRT.targets
)
################ NuGet import end ################
# ############### NuGet import end ################
set_target_properties(${PLUGIN_NAME} PROPERTIES
CXX_VISIBILITY_PRESET hidden)
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
@@ -69,7 +69,6 @@ target_include_directories(${PLUGIN_NAME} INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)
set(universal_ble_bundled_libraries
""
PARENT_SCOPE
@@ -1,9 +1,9 @@
// Autogenerated from Pigeon (v13.0.0), do not edit directly.
// Autogenerated from Pigeon (v16.0.5), do not edit directly.
// See also: https://pub.dev/packages/pigeon
#undef _HAS_EXCEPTIONS
#include "UniversalBle.g.h"
#include "universal_ble.g.h"
#include <flutter/basic_message_channel.h>
#include <flutter/binary_messenger.h>
@@ -21,6 +21,13 @@ using flutter::EncodableList;
using flutter::EncodableMap;
using flutter::EncodableValue;
FlutterError CreateConnectionError(const std::string channel_name) {
return FlutterError(
"channel-error",
"Unable to establish connection on channel: '" + channel_name + "'.",
EncodableValue(""));
}
// UniversalBleScanResult
UniversalBleScanResult::UniversalBleScanResult(const std::string& device_id)
@@ -811,22 +818,23 @@ void UniversalBleCallbackChannel::OnAvailabilityChanged(
int64_t state_arg,
std::function<void(void)>&& on_success,
std::function<void(const FlutterError&)>&& on_error) {
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged", &GetCodec());
const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged";
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, channel_name, &GetCodec());
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
EncodableValue(state_arg),
});
channel->Send(encoded_api_arguments, [on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
channel->Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
const auto& encodable_return_value = *response;
const auto* list_return_value = std::get_if<EncodableList>(&encodable_return_value);
if (list_return_value) {
if (list_return_value->size() > 1) {
on_error(FlutterError( std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
on_error(FlutterError(std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
} else {
on_success();
}
} else {
on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));
on_error(CreateConnectionError(channel_name));
}
});
}
@@ -837,24 +845,25 @@ void UniversalBleCallbackChannel::OnPairStateChange(
const std::string* error_arg,
std::function<void(void)>&& on_success,
std::function<void(const FlutterError&)>&& on_error) {
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange", &GetCodec());
const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange";
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, channel_name, &GetCodec());
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
EncodableValue(device_id_arg),
EncodableValue(is_paired_arg),
error_arg ? EncodableValue(*error_arg) : EncodableValue(),
});
channel->Send(encoded_api_arguments, [on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
channel->Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
const auto& encodable_return_value = *response;
const auto* list_return_value = std::get_if<EncodableList>(&encodable_return_value);
if (list_return_value) {
if (list_return_value->size() > 1) {
on_error(FlutterError( std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
on_error(FlutterError(std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
} else {
on_success();
}
} else {
on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));
on_error(CreateConnectionError(channel_name));
}
});
}
@@ -863,22 +872,23 @@ void UniversalBleCallbackChannel::OnScanResult(
const UniversalBleScanResult& result_arg,
std::function<void(void)>&& on_success,
std::function<void(const FlutterError&)>&& on_error) {
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult", &GetCodec());
const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult";
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, channel_name, &GetCodec());
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
CustomEncodableValue(result_arg),
});
channel->Send(encoded_api_arguments, [on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
channel->Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
const auto& encodable_return_value = *response;
const auto* list_return_value = std::get_if<EncodableList>(&encodable_return_value);
if (list_return_value) {
if (list_return_value->size() > 1) {
on_error(FlutterError( std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
on_error(FlutterError(std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
} else {
on_success();
}
} else {
on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));
on_error(CreateConnectionError(channel_name));
}
});
}
@@ -889,24 +899,25 @@ void UniversalBleCallbackChannel::OnValueChanged(
const std::vector<uint8_t>& value_arg,
std::function<void(void)>&& on_success,
std::function<void(const FlutterError&)>&& on_error) {
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged", &GetCodec());
const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged";
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, channel_name, &GetCodec());
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
EncodableValue(device_id_arg),
EncodableValue(characteristic_id_arg),
EncodableValue(value_arg),
});
channel->Send(encoded_api_arguments, [on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
channel->Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
const auto& encodable_return_value = *response;
const auto* list_return_value = std::get_if<EncodableList>(&encodable_return_value);
if (list_return_value) {
if (list_return_value->size() > 1) {
on_error(FlutterError( std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
on_error(FlutterError(std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
} else {
on_success();
}
} else {
on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));
on_error(CreateConnectionError(channel_name));
}
});
}
@@ -916,23 +927,24 @@ void UniversalBleCallbackChannel::OnConnectionChanged(
int64_t state_arg,
std::function<void(void)>&& on_success,
std::function<void(const FlutterError&)>&& on_error) {
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged", &GetCodec());
const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged";
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, channel_name, &GetCodec());
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
EncodableValue(device_id_arg),
EncodableValue(state_arg),
});
channel->Send(encoded_api_arguments, [on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
channel->Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
const auto& encodable_return_value = *response;
const auto* list_return_value = std::get_if<EncodableList>(&encodable_return_value);
if (list_return_value) {
if (list_return_value->size() > 1) {
on_error(FlutterError( std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
on_error(FlutterError(std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
} else {
on_success();
}
} else {
on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));
on_error(CreateConnectionError(channel_name));
}
});
}
@@ -1,8 +1,8 @@
// Autogenerated from Pigeon (v13.0.0), do not edit directly.
// Autogenerated from Pigeon (v16.0.5), do not edit directly.
// See also: https://pub.dev/packages/pigeon
#ifndef PIGEON_UNIVERSALBLE_G_H_
#define PIGEON_UNIVERSALBLE_G_H_
#ifndef PIGEON_UNIVERSAL_BLE_G_H_
#define PIGEON_UNIVERSAL_BLE_G_H_
#include <flutter/basic_message_channel.h>
#include <flutter/binary_messenger.h>
#include <flutter/encodable_value.h>
@@ -308,4 +308,4 @@ class UniversalBleCallbackChannel {
};
} // namespace universal_ble
#endif // PIGEON_UNIVERSALBLE_G_H_
#endif // PIGEON_UNIVERSAL_BLE_G_H_
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <winrt/Windows.Devices.Bluetooth.h>
#include <winrt/Windows.Devices.Bluetooth.Advertisement.h>
#include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
#include <winrt/Windows.Devices.Enumeration.h>
#include <winrt/Windows.Devices.Radios.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Storage.Streams.h>
namespace universal_ble
{
using namespace winrt;
using namespace winrt::Windows;
using namespace winrt::Windows::Devices;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::Storage::Streams;
using namespace winrt::Windows::Devices::Radios;
using namespace winrt::Windows::Devices::Bluetooth;
using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;
using namespace Windows::Devices::Enumeration;
}
@@ -9,11 +9,10 @@
#if WDK_NTDDI_VERSION < NTDDI_WIN10_VB
#error "Windows SDK version before 10.0.19041.0 is not supported"
#elif WDK_NTDDI_VERSION == NTDDI_WIN10_VB
// For Windows SDK version before 10.0.19041.0, remap functions to post-10.0.19041.0 versions
#define WINRT_IMPL_CoGetApartmentType WINRT_CoGetApartmentType
#endif
#define MAC_ADDRESS_STR_LENGTH (size_t)17 // Two chars per byte, 5 chars for colon
#define MAC_ADDRESS_STR_LENGTH (size_t)17
namespace universal_ble
{
@@ -29,7 +28,6 @@ namespace universal_ble
uint64_t _str_to_mac_address(std::string mac_str)
{
// TODO: Validate input - Expected Format: XX:XX:XX:XX:XX:XX
uint64_t mac_address_number = 0;
uint8_t *mac_ptr = (uint8_t *)&mac_address_number;
sscanf_s(mac_str.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &mac_ptr[5], &mac_ptr[4], &mac_ptr[3],
@@ -39,7 +37,6 @@ namespace universal_ble
winrt::guid uuid_to_guid(const std::string &uuid)
{
// TODO: Add proper cleanup / validation
std::stringstream helper;
for (int i = 0; i < uuid.length(); i++)
{
@@ -63,23 +60,18 @@ namespace universal_ble
std::string guid_to_uuid(const winrt::guid &guid)
{
std::stringstream helper;
// TODO: It might be cleaner to use snprintf instead of string streams.
for (uint32_t i = 0; i < 4; i++)
{
// * NOTE: We're performing a byte swap!
helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t *)&guid.Data1)[3 - i];
}
helper << '-';
for (uint32_t i = 0; i < 2; i++)
{
// * NOTE: We're performing a byte swap!
helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t *)&guid.Data2)[1 - i];
}
helper << '-';
for (uint32_t i = 0; i < 2; i++)
{
// * NOTE: We're performing a byte swap!
helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t *)&guid.Data3)[1 - i];
}
helper << '-';
+2 -31
View File
@@ -7,10 +7,7 @@
#include "winrt/Windows.Foundation.h"
#include "winrt/Windows.Storage.Streams.h"
#include "winrt/base.h"
#include "UniversalBle.g.h"
using namespace winrt::Windows;
using namespace winrt::Windows::Storage::Streams;
#include "universal_ble_base.h"
constexpr uint32_t TEN_SECONDS_IN_MSECS = 10000;
@@ -29,34 +26,8 @@ namespace universal_ble
std::string to_uuidstr(winrt::guid guid);
/// Structs for passing data between background to ui thread
struct ConnectionStateStruct
{
std::string deviceId;
int64_t connectionState;
ConnectionStateStruct(std::string deviceId, int64_t connectionState)
: deviceId(deviceId), connectionState(connectionState) {}
};
struct PairStateStruct
{
std::string deviceId;
bool isPaired;
std::string errorMessage;
PairStateStruct(std::string deviceId, bool isPaired, std::string errorMessage)
: deviceId(deviceId), isPaired(isPaired), errorMessage(errorMessage) {}
};
struct ValueChangeStruct
{
std::string deviceId;
std::string characteristicId;
std::vector<uint8_t> value;
ValueChangeStruct(std::string deviceId, std::string characteristicId, std::vector<uint8_t> value)
: deviceId(deviceId), characteristicId(characteristicId), value(value) {}
};
/// To call async functions synchronously
/// To call async functions synchronously
template <typename async_t>
static auto async_get(async_t const &async)
{
+79
View File
@@ -0,0 +1,79 @@
#pragma once
#include <windows.h>
#include <flutter/plugin_registrar_windows.h>
#include <algorithm>
#include <functional>
#include <optional>
#include <mutex>
class UniversalBleUiThreadHandler
{
public:
explicit UniversalBleUiThreadHandler(flutter::PluginRegistrarWindows *registrar)
: registrar_(registrar)
{
windowProcId_ = registrar_->RegisterTopLevelWindowProcDelegate(
[this](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
return HandleWindowMessage(hwnd, message, wparam, lparam);
});
}
~UniversalBleUiThreadHandler()
{
registrar_->UnregisterTopLevelWindowProcDelegate(windowProcId_);
}
UniversalBleUiThreadHandler(const UniversalBleUiThreadHandler &) = delete;
UniversalBleUiThreadHandler &operator=(const UniversalBleUiThreadHandler &) = delete;
void Post(std::function<void()> &&func)
{
std::lock_guard<std::mutex> lock(mutex_);
queuedFuncs_.emplace_back(std::move(func));
Notify();
}
private:
static const UINT kWmCallQueuedFunctions = WM_APP + 0x1d7;
void Notify()
{
if (hwnd_ != 0)
{
PostMessage(hwnd_, kWmCallQueuedFunctions, 0, reinterpret_cast<LPARAM>(this));
}
}
std::optional<LRESULT> HandleWindowMessage(
HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
if (hwnd_ == 0)
{
hwnd_ = hwnd;
Notify(); // Make sure queued functions are processed
}
if (message == kWmCallQueuedFunctions && lparam == reinterpret_cast<LPARAM>(this))
{
std::list<std::function<void()>> queuedFuncs;
{
std::lock_guard<std::mutex> lock(mutex_);
std::swap(queuedFuncs_, queuedFuncs);
}
for (auto &func : queuedFuncs)
{
func();
}
}
return std::nullopt;
}
flutter::PluginRegistrarWindows *registrar_;
int windowProcId_ = 0;
HWND hwnd_ = 0;
std::list<std::function<void()>> queuedFuncs_;
std::mutex mutex_;
};
@@ -9,16 +9,11 @@
#include <algorithm>
#include <iomanip>
#include <thread>
#include "UniversalBle.g.h"
#include "Utils.h"
#include "universal_enum.h"
#include <regex>
#define WM_AVAILABILITY_CHANGE WM_USER + 101
#define WM_PAIR_CHANGE WM_USER + 102
#define WM_SCAN_RESULT WM_USER + 103
#define WM_VALUE_CHANGE WM_USER + 104
#define WM_CONNECTION_CHANGE WM_USER + 105
#include "helper/utils.h"
#include "helper/universal_enum.h"
#include "generated/universal_ble.g.h"
namespace universal_ble
{
@@ -27,8 +22,15 @@ namespace universal_ble
using universal_ble::UniversalBlePlatformChannel;
using universal_ble::UniversalBleScanResult;
const auto isConnectableKey = L"System.Devices.Aep.Bluetooth.Le.IsConnectable";
const auto isConnectedKey = L"System.Devices.Aep.IsConnected";
const auto isPairedKey = L"System.Devices.Aep.IsPaired";
const auto isPresentKey = L"System.Devices.Aep.IsPresent";
const auto deviceAddressKey = L"System.Devices.Aep.DeviceAddress";
const auto signalStrengthKey = L"System.Devices.Aep.SignalStrength";
std::unique_ptr<UniversalBleCallbackChannel> callbackChannel;
std::map<std::string, winrt::event_token> characteristicsTokens{};
std::unordered_map<std::string, winrt::event_token> characteristicsTokens{}; // TODO: Remove the map and store the token inside the characteristic object object
union uint16_t_union
{
@@ -44,81 +46,14 @@ namespace universal_ble
registrar->AddPlugin(std::move(plugin));
}
UniversalBlePlugin::UniversalBlePlugin(flutter::PluginRegistrarWindows *registrar) : registrar_(registrar)
UniversalBlePlugin::UniversalBlePlugin(flutter::PluginRegistrarWindows *registrar)
: uiThreadHandler_(registrar)
{
if (window_proc_delegate_id_ == -1)
{
window_proc_delegate_id_ = registrar_->RegisterTopLevelWindowProcDelegate(
std::bind(
&UniversalBlePlugin::WindowProcDelegate, this,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4)
);
}
InitializeAsync();
}
UniversalBlePlugin::~UniversalBlePlugin()
{
if (window_proc_delegate_id_ != -1)
{
registrar_->UnregisterTopLevelWindowProcDelegate(
static_cast<int32_t>(window_proc_delegate_id_));
}
}
HWND UniversalBlePlugin::GetWindow()
{
return ::GetAncestor(registrar_->GetView()->GetNativeWindow(), GA_ROOT);
}
/// Background Messages Handler
std::optional<LRESULT> UniversalBlePlugin::WindowProcDelegate(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
{
switch (message)
{
case WM_SCAN_RESULT:
{
UniversalBleScanResult *scanResult = reinterpret_cast<UniversalBleScanResult *>(wp);
callbackChannel->OnScanResult(*scanResult, SuccessCallback, ErrorCallback);
delete scanResult;
return 0;
}
case WM_AVAILABILITY_CHANGE:
{
callbackChannel->OnAvailabilityChanged(static_cast<int>(wp), SuccessCallback, ErrorCallback);
return 0;
}
case WM_CONNECTION_CHANGE:
{
ConnectionStateStruct *connectionStateStruct = reinterpret_cast<ConnectionStateStruct *>(wp);
callbackChannel->OnConnectionChanged(connectionStateStruct->deviceId, connectionStateStruct->connectionState, SuccessCallback, ErrorCallback);
delete connectionStateStruct;
return 0;
}
case WM_VALUE_CHANGE:
{
ValueChangeStruct *valueChangeStruct = reinterpret_cast<ValueChangeStruct *>(wp);
callbackChannel->OnValueChanged(valueChangeStruct->deviceId, valueChangeStruct->characteristicId, valueChangeStruct->value, SuccessCallback, ErrorCallback);
delete valueChangeStruct;
return 0;
}
case WM_PAIR_CHANGE:
{
PairStateStruct *pairStateStruct = reinterpret_cast<PairStateStruct *>(wp);
callbackChannel->OnPairStateChange(pairStateStruct->deviceId, pairStateStruct->isPaired, &pairStateStruct->errorMessage, SuccessCallback, ErrorCallback);
delete pairStateStruct;
return 0;
}
}
return std::nullopt;
}
void UniversalBlePlugin::PostConnectionUpdate(uint64_t bluetoothAddress, ConnectionState connectionState)
{
ConnectionStateStruct *connectionStateStruct = new ConnectionStateStruct(_mac_address_to_str(bluetoothAddress), static_cast<int>(connectionState));
::PostMessage(GetWindow(), WM_CONNECTION_CHANGE, reinterpret_cast<WPARAM>(connectionStateStruct), 0);
}
// UniversalBlePlatformChannel implementation.
@@ -163,9 +98,16 @@ namespace universal_ble
if (!bluetoothLEWatcher)
{
bluetoothLEWatcher = BluetoothLEAdvertisementWatcher();
bluetoothLEWatcher.ScanningMode(BluetoothLEScanningMode::Active);
bluetoothLEWatcherReceivedToken = bluetoothLEWatcher.Received({this, &UniversalBlePlugin::BluetoothLEWatcher_Received});
}
bluetoothLEWatcher.Start();
setupDeviceWatcher();
DeviceWatcherStatus status = deviceWatcher.Status();
if (status != DeviceWatcherStatus::Started)
deviceWatcher.Start();
else
return FlutterError("Already scanning");
return std::nullopt;
}
else
@@ -176,6 +118,7 @@ namespace universal_ble
std::optional<FlutterError> UniversalBlePlugin::StopScan()
{
if (bluetoothRadio && bluetoothRadio.State() == RadioState::On)
{
if (bluetoothLEWatcher)
@@ -184,6 +127,7 @@ namespace universal_ble
bluetoothLEWatcher.Received(bluetoothLEWatcherReceivedToken);
}
bluetoothLEWatcher = nullptr;
disposeDeviceWatcher();
return std::nullopt;
}
else
@@ -194,12 +138,6 @@ namespace universal_ble
std::optional<FlutterError> UniversalBlePlugin::Connect(const std::string &device_id)
{
auto isConnectable = deviceConnectableStatus[_str_to_mac_address(device_id)];
if (isConnectable == false)
{
return FlutterError("Device is not connectable");
}
ConnectAsync(_str_to_mac_address(device_id));
return std::nullopt;
};
@@ -208,7 +146,10 @@ namespace universal_ble
{
auto deviceAddress = _str_to_mac_address(device_id);
CleanConnection(deviceAddress);
PostConnectionUpdate(deviceAddress, ConnectionState::disconnected);
// TODO: send disconnect event only after disconnect is complete
uiThreadHandler_.Post([deviceAddress]
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(deviceAddress), static_cast<int>(ConnectionState::disconnected), SuccessCallback, ErrorCallback); });
return std::nullopt;
};
@@ -233,6 +174,7 @@ namespace universal_ble
}
catch (...)
{
std::cout << "DiscoverServicesLog: Unknown error" << std::endl;
return result(FlutterError("Unknown error"));
}
}
@@ -249,7 +191,7 @@ namespace universal_ble
if (it == connectedDevices.end())
return FlutterError("IllegalArgument", "Unknown devicesId:" + device_id);
auto bluetoothAgent = *it->second;
gatt_characteristic_t &gatt_characteristic_holder = bluetoothAgent._fetch_characteristic(service, characteristic);
GattCharacteristicObject &gatt_characteristic_holder = bluetoothAgent._fetch_characteristic(service, characteristic);
GattCharacteristic gattCharacteristic = gatt_characteristic_holder.obj;
auto descriptorValue = GattClientCharacteristicConfigurationDescriptorValue::None;
auto properties = gattCharacteristic.CharacteristicProperties();
@@ -280,6 +222,7 @@ namespace universal_ble
}
catch (...)
{
std::cout << "SetNotifiableLog: Unknown error" << std::endl;
return FlutterError("Unknown error");
}
};
@@ -299,7 +242,7 @@ namespace universal_ble
return;
}
auto bluetoothAgent = *it->second;
gatt_characteristic_t &gatt_characteristic_holder = bluetoothAgent._fetch_characteristic(service, characteristic);
GattCharacteristicObject &gatt_characteristic_holder = bluetoothAgent._fetch_characteristic(service, characteristic);
GattCharacteristic gattCharacteristic = gatt_characteristic_holder.obj;
auto properties = gattCharacteristic.CharacteristicProperties();
if ((properties & GattCharacteristicProperties::Read) == GattCharacteristicProperties::None)
@@ -336,6 +279,7 @@ namespace universal_ble
}
catch (...)
{
std::cout << "ReadValueLog: Unknown error" << std::endl;
return result(FlutterError("Unknown error"));
}
}
@@ -357,7 +301,7 @@ namespace universal_ble
return;
}
auto bluetoothAgent = *it->second;
gatt_characteristic_t &gatt_characteristic_holder = bluetoothAgent._fetch_characteristic(service, characteristic);
GattCharacteristicObject &gatt_characteristic_holder = bluetoothAgent._fetch_characteristic(service, characteristic);
GattCharacteristic gattCharacteristic = gatt_characteristic_holder.obj;
auto properties = gattCharacteristic.CharacteristicProperties();
auto writeOption = GattWriteOption::WriteWithResponse;
@@ -407,6 +351,7 @@ namespace universal_ble
}
catch (...)
{
std::cout << "WriteValue: Unknown error" << std::endl;
result(FlutterError("Unknown error"));
}
}
@@ -449,13 +394,14 @@ namespace universal_ble
try
{
auto device = async_get(BluetoothLEDevice::FromBluetoothAddressAsync(_str_to_mac_address(device_id)));
std::cout << "PairLog: Device to be paired was found" << std::endl;
auto deviceInformation = device.DeviceInformation();
bool isPaired = deviceInformation.Pairing().IsPaired();
if (isPaired)
return FlutterError("Device is already paired");
return FlutterError("PairLog: Device is already paired");
bool canPair = deviceInformation.Pairing().CanPair();
if (!canPair)
return FlutterError("Device is not pairable");
return FlutterError("PairLog: Device is not pairable");
auto customPairing = deviceInformation.Pairing().Custom();
winrt::event_token token = customPairing.PairingRequested([this](const Enumeration::DeviceInformationCustomPairing &sender, const Enumeration::DevicePairingRequestedEventArgs &eventArgs)
@@ -466,18 +412,21 @@ namespace universal_ble
eventArgs.Accept(); });
// DevicePairingKinds => None, ConfirmOnly, DisplayPin, ProvidePin, ConfirmPinMatch, ProvidePasswordCredential
// DevicePairingProtectionLevel => Default, None, Encryption, EncryptionAndAuthentication
std::cout << "PairLog: Trying to pair" << std::endl;
auto async_c = customPairing.PairAsync(
Enumeration::DevicePairingKinds::ConfirmOnly,
Enumeration::DevicePairingProtectionLevel::None);
async_c.Completed([this, customPairing, token, device_id](IAsyncOperation<DevicePairingResult> const &sender, AsyncStatus const args)
{
auto result = sender.GetResults();
std::cout << "PairLog: Received pairing status" << std::endl;
customPairing.PairingRequested(token);
auto isPaired = result.Status() == Enumeration::DevicePairingResultStatus::Paired;
// Post to main thread
PairStateStruct *pairStateStruct = new PairStateStruct(device_id, isPaired, parsePairingFailError(result));
::PostMessage(GetWindow(), WM_PAIR_CHANGE, reinterpret_cast<WPARAM>(pairStateStruct), 0); });
// Post to main thread
std::string errorStr = parsePairingFailError(result);
uiThreadHandler_.Post([device_id, isPaired, errorStr]
{ callbackChannel->OnPairStateChange(device_id, isPaired, &errorStr, SuccessCallback, ErrorCallback); }); });
return std::nullopt;
}
catch (const FlutterError &err)
@@ -528,6 +477,31 @@ namespace universal_ble
}
/// Helper Methods
std::vector<uint8_t> parseManufacturerDataHead(BluetoothLEAdvertisement advertisement, std::string deviceId)
{
try
{
if (advertisement.ManufacturerData().Size() == 0)
{
return std::vector<uint8_t>();
}
auto manufacturerData = advertisement.ManufacturerData().GetAt(0);
// FIXME Compat with REG_DWORD_BIG_ENDIAN
uint8_t *prefix = uint16_t_union{manufacturerData.CompanyId()}.bytes;
auto result = std::vector<uint8_t>{prefix, prefix + sizeof(uint16_t_union)};
auto data = to_bytevc(manufacturerData.Data());
result.insert(result.end(), data.begin(), data.end());
return result;
}
catch (...)
{
std::cout << "Error in parsing manufacturer data: " << deviceId << std::endl;
return std::vector<uint8_t>();
}
}
winrt::fire_and_forget UniversalBlePlugin::InitializeAsync()
{
auto bluetoothAdapter = co_await BluetoothAdapter::GetDefaultAsync();
@@ -538,6 +512,209 @@ namespace universal_ble
}
}
// Send device to callback channel
// if device is already discovered in deviceWatcher then merge the scan result
void UniversalBlePlugin::pushUniversalScanResult(UniversalBleScanResult scanResult)
{
auto it = scanResults.find(scanResult.device_id());
if (it != scanResults.end())
{
UniversalBleScanResult &existingScanResult = it->second;
bool shouldUpdate = false;
if ((scanResult.name() == nullptr || scanResult.name()->empty()) && (existingScanResult.name() != nullptr && !existingScanResult.name()->empty()))
{
scanResult.set_name(*existingScanResult.name());
shouldUpdate = true;
}
if (scanResult.is_paired() == nullptr && existingScanResult.is_paired() != nullptr)
{
scanResult.set_is_paired(existingScanResult.is_paired());
shouldUpdate = true;
}
if (scanResult.manufacturer_data_head() == nullptr && existingScanResult.manufacturer_data_head() != nullptr)
{
scanResult.set_manufacturer_data_head(existingScanResult.manufacturer_data_head());
shouldUpdate = true;
}
// if nothing to update then return
if (!shouldUpdate)
return;
// update the existing scan result
existingScanResult = scanResult;
}
else
{
// if not present, insert the new scan result
scanResults.insert(std::make_pair(scanResult.device_id(), scanResult));
}
uiThreadHandler_.Post([scanResult]
{ callbackChannel->OnScanResult(scanResult, SuccessCallback, ErrorCallback); });
}
void UniversalBlePlugin::setupDeviceWatcher()
{
if (deviceWatcher != nullptr)
return;
deviceWatcher = DeviceInformation::CreateWatcher(
L"(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")",
{
deviceAddressKey,
isConnectedKey,
isPairedKey,
isPresentKey,
isConnectableKey,
signalStrengthKey,
},
DeviceInformationKind::AssociationEndpoint);
/// Device Added from DeviceWatcher
deviceWatcherAddedToken = deviceWatcher.Added([this](DeviceWatcher sender, DeviceInformation deviceInfo)
{
std::string deviceId = winrt::to_string(deviceInfo.Id());
deviceWatcherDevices.insert_or_assign(deviceId, deviceInfo);
onDeviceInfoReceived(deviceInfo);
// On Device Added
});
// Update only if device is already discovered in deviceWatcher.Added
deviceWatcherUpdatedToken = deviceWatcher.Updated([this](DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
{
std::string deviceId = winrt::to_string(deviceInfoUpdate.Id());
auto it = deviceWatcherDevices.find(deviceId);
if (it != deviceWatcherDevices.end())
{
it->second.Update(deviceInfoUpdate);
onDeviceInfoReceived(it->second);
}
// On Device Updated
});
deviceWatcherRemovedToken = deviceWatcher.Removed([this](DeviceWatcher sender, DeviceInformationUpdate args)
{
std::string deviceId = winrt::to_string(args.Id());
deviceWatcherDevices.erase(deviceId);
// On Device Removed
});
}
void UniversalBlePlugin::disposeDeviceWatcher()
{
if (deviceWatcher != nullptr)
{
if (deviceWatcher.Status() == DeviceWatcherStatus::Started)
deviceWatcher.Stop();
deviceWatcher.Added(deviceWatcherAddedToken);
deviceWatcher.Updated(deviceWatcherUpdatedToken);
deviceWatcher.Removed(deviceWatcherRemovedToken);
deviceWatcher = nullptr;
// Dispose tokens
deviceWatcherDevices.clear();
}
}
void UniversalBlePlugin::onDeviceInfoReceived(DeviceInformation deviceInfo)
{
auto properties = deviceInfo.Properties();
// Avoid devices if not connectable or if deviceAddressKey is not present
if (!(properties.HasKey(isConnectableKey) && (properties.Lookup(isConnectableKey).as<IPropertyValue>()).GetBoolean()) || !properties.HasKey(deviceAddressKey))
return;
auto bluetoothAddressPropertyValue = properties.Lookup(deviceAddressKey).as<IPropertyValue>();
std::string deviceAddress = winrt::to_string(bluetoothAddressPropertyValue.GetString());
// Update device info if already discovered in advertisementWatcher
if (scanResults.count(deviceAddress) > 0)
{
bool isPaired = deviceInfo.Pairing().IsPaired();
if (properties.HasKey(isPairedKey))
{
auto isPairedPropertyValue = properties.Lookup(isPairedKey).as<IPropertyValue>();
isPaired = isPairedPropertyValue.GetBoolean();
}
UniversalBleScanResult universalScanResult(deviceAddress);
universalScanResult.set_is_paired(isPaired);
if (!deviceInfo.Name().empty())
universalScanResult.set_name(winrt::to_string(deviceInfo.Name()));
if (properties.HasKey(signalStrengthKey))
{
auto rssiPropertyValue = properties.Lookup(signalStrengthKey).as<IPropertyValue>();
int16_t rssi = rssiPropertyValue.GetInt16();
universalScanResult.set_rssi(rssi);
}
pushUniversalScanResult(universalScanResult);
}
}
/// Advertisement received from advertisementWatcher
void UniversalBlePlugin::BluetoothLEWatcher_Received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
{
try
{
// Avoid devices if they are not connectable
if (!args.IsConnectable())
return;
auto deviceId = _mac_address_to_str(args.BluetoothAddress());
auto universalScanResult = UniversalBleScanResult(deviceId);
std::string name = winrt::to_string(args.Advertisement().LocalName());
// Use CompleteName from dataType if localName is empty
if (name.empty())
{
auto dataSection = args.Advertisement().DataSections();
for (auto &&data : dataSection)
{
auto dataBytes = to_bytevc(data.Data());
if (data.DataType() == 0x09)
{
name = std::string(dataBytes.begin(), dataBytes.end());
break;
}
}
}
if (!name.empty())
universalScanResult.set_name(name);
auto manufacturerData = parseManufacturerDataHead(args.Advertisement(), deviceId);
universalScanResult.set_manufacturer_data_head(manufacturerData);
universalScanResult.set_rssi(args.RawSignalStrengthInDBm());
// check if this device already discovered in deviceWatcher
auto it = deviceWatcherDevices.find(deviceId);
if (it != deviceWatcherDevices.end())
{
auto &deviceInfo = it->second;
auto properties = deviceInfo.Properties();
// Update Paired Status
bool isPaired = deviceInfo.Pairing().IsPaired();
if (properties.HasKey(isPairedKey))
isPaired = (properties.Lookup(isPairedKey).as<IPropertyValue>()).GetBoolean();
universalScanResult.set_is_paired(isPaired);
// Update Name
if (name.empty() && !deviceInfo.Name().empty())
universalScanResult.set_name(winrt::to_string(deviceInfo.Name()));
}
// Cache connectable status
pushUniversalScanResult(universalScanResult);
}
catch (...)
{
std::cout << "ScanResultErrorInParsing" << std::endl;
}
}
AvailabilityState UniversalBlePlugin::getAvailabilityStateFromRadio(RadioState radioState)
{
auto state = [=]() -> AvailabilityState
@@ -575,56 +752,12 @@ namespace universal_ble
}
oldRadioState = radioState;
auto state = getAvailabilityStateFromRadio(radioState);
::PostMessage(GetWindow(), WM_AVAILABILITY_CHANGE, static_cast<int>(state), 0);
uiThreadHandler_.Post([state]
{ callbackChannel->OnAvailabilityChanged(static_cast<int>(state), SuccessCallback, ErrorCallback); });
}
std::vector<uint8_t> parseManufacturerDataHead(BluetoothLEAdvertisement advertisement, std::string deviceId)
{
try
{
if (advertisement.ManufacturerData().Size() == 0)
{
return std::vector<uint8_t>();
}
auto manufacturerData = advertisement.ManufacturerData().GetAt(0);
// FIXME Compat with REG_DWORD_BIG_ENDIAN
uint8_t *prefix = uint16_t_union{manufacturerData.CompanyId()}.bytes;
auto result = std::vector<uint8_t>{prefix, prefix + sizeof(uint16_t_union)};
auto data = to_bytevc(manufacturerData.Data());
result.insert(result.end(), data.begin(), data.end());
return result;
}
catch (...)
{
std::cout << "Error in parsing manufacturer data: " << deviceId << std::endl;
return std::vector<uint8_t>();
}
}
void UniversalBlePlugin::BluetoothLEWatcher_Received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
{
try
{
auto deviceId = _mac_address_to_str(args.BluetoothAddress());
auto universalScanResult = new UniversalBleScanResult(deviceId);
hstring localName = args.Advertisement().LocalName();
if (!localName.empty())
universalScanResult->set_name(winrt::to_string(localName));
universalScanResult->set_manufacturer_data_head(parseManufacturerDataHead(args.Advertisement(), deviceId));
universalScanResult->set_rssi(args.RawSignalStrengthInDBm());
// Cache connectable status
deviceConnectableStatus[_str_to_mac_address(deviceId)] = args.IsConnectable();
::PostMessage(GetWindow(), WM_SCAN_RESULT, reinterpret_cast<WPARAM>(universalScanResult), 0);
}
catch (...)
{
std::cout << "ScanResultErrorInParsing" << std::endl;
}
}
std::string GattCommunicationStatusToString(GattCommunicationStatus status)
std::string UniversalBlePlugin::GattCommunicationStatusToString(GattCommunicationStatus status)
{
switch (status)
{
@@ -643,19 +776,32 @@ namespace universal_ble
winrt::fire_and_forget UniversalBlePlugin::ConnectAsync(uint64_t bluetoothAddress)
{
auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(bluetoothAddress);
auto servicesResult = co_await device.GetGattServicesAsync((BluetoothCacheMode::Uncached));
if (servicesResult.Status() != GattCommunicationStatus::Success)
BluetoothLEDevice device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(bluetoothAddress);
std::cout << "ConnectionLog: Device found" << std::endl;
if (!device)
{
PostConnectionUpdate(bluetoothAddress, ConnectionState::disconnected);
std::cout << "ConnectionLog: ConnectionFailed: Failed to get device" << std::endl;
uiThreadHandler_.Post([bluetoothAddress]
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), static_cast<int>(ConnectionState::disconnected), SuccessCallback, ErrorCallback); });
co_return;
}
auto servicesResult = co_await device.GetGattServicesAsync((BluetoothCacheMode::Uncached));
auto status = servicesResult.Status();
if (status != GattCommunicationStatus::Success)
{
std::cout << "ConnectionFailed: Failed to get services: " << GattCommunicationStatusToString(status) << std::endl;
uiThreadHandler_.Post([bluetoothAddress]
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), static_cast<int>(ConnectionState::disconnected), SuccessCallback, ErrorCallback); });
std::map<std::string, gatt_service_t> gatt_map_;
co_return;
}
std::cout << "ConnectionLog: Services discovered" << std::endl;
std::unordered_map<std::string, GattServiceObject> gatt_map_;
auto gatt_services = servicesResult.Services();
for (GattDeviceService &&service : gatt_services)
{
gatt_service_t gatt_service;
GattServiceObject gatt_service;
gatt_service.obj = service;
std::string service_uuid = guid_to_uuid(service.Uuid());
auto characteristics_result = co_await service.GetCharacteristicsAsync(BluetoothCacheMode::Uncached);
@@ -669,19 +815,21 @@ namespace universal_ble
auto gatt_characteristics = characteristics_result.Characteristics();
for (GattCharacteristic &&characteristic : gatt_characteristics)
{
gatt_characteristic_t gatt_characteristic;
GattCharacteristicObject gatt_characteristic;
gatt_characteristic.obj = characteristic;
std::string characteristic_uuid = guid_to_uuid(characteristic.Uuid());
gatt_service.characteristics.emplace(characteristic_uuid, std::move(gatt_characteristic));
gatt_service.characteristics.insert_or_assign(characteristic_uuid, std::move(gatt_characteristic));
}
gatt_map_.emplace(service_uuid, std::move(gatt_service));
gatt_map_.insert_or_assign(service_uuid, std::move(gatt_service));
}
auto connnectionStatusChangedToken = device.ConnectionStatusChanged({this, &UniversalBlePlugin::BluetoothLEDevice_ConnectionStatusChanged});
winrt::event_token connnectionStatusChangedToken = device.ConnectionStatusChanged({this, &UniversalBlePlugin::BluetoothLEDevice_ConnectionStatusChanged});
auto deviceAgent = std::make_unique<BluetoothDeviceAgent>(device, connnectionStatusChangedToken, gatt_map_);
auto pair = std::make_pair(bluetoothAddress, std::move(deviceAgent));
connectedDevices.insert(std::move(pair));
PostConnectionUpdate(bluetoothAddress, ConnectionState::connected);
std::cout << "ConnectionLog: Connected" << std::endl;
uiThreadHandler_.Post([bluetoothAddress]
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), static_cast<int>(ConnectionState::connected), SuccessCallback, ErrorCallback); });
}
void UniversalBlePlugin::BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, IInspectable args)
@@ -689,7 +837,9 @@ namespace universal_ble
if (sender.ConnectionStatus() == BluetoothConnectionStatus::Disconnected)
{
CleanConnection(sender.BluetoothAddress());
PostConnectionUpdate(sender.BluetoothAddress(), ConnectionState::disconnected);
auto bluetoothAddress = sender.BluetoothAddress();
uiThreadHandler_.Post([bluetoothAddress]
{ callbackChannel->OnConnectionChanged(_mac_address_to_str(bluetoothAddress), static_cast<int>(ConnectionState::disconnected), SuccessCallback, ErrorCallback); });
}
}
@@ -706,9 +856,11 @@ namespace universal_ble
auto &service = servicePair.second;
for (auto &characteristicPair : service.characteristics)
{
gatt_characteristic_t &characteristic = characteristicPair.second;
GattCharacteristicObject &characteristic = characteristicPair.second;
auto gattCharacteristic = characteristic.obj;
auto uniqTokenKey = to_uuidstr(gattCharacteristic.Uuid()) + _mac_address_to_str(gattCharacteristic.Service().Device().BluetoothAddress());
std::stringstream uniqTokenKeyStream;
uniqTokenKeyStream << to_uuidstr(gattCharacteristic.Uuid()) << _mac_address_to_str(gattCharacteristic.Service().Device().BluetoothAddress());
std::string uniqTokenKey = uniqTokenKeyStream.str();
if (characteristicsTokens.count(uniqTokenKey) != 0)
{
characteristic.obj.ValueChanged(characteristicsTokens[uniqTokenKey]);
@@ -758,12 +910,13 @@ namespace universal_ble
universalScanResult.set_name(winrt::to_string(deviceInfo.Name()));
universalScanResult.set_is_paired(deviceInfo.Pairing().IsPaired());
results.push_back(flutter::CustomEncodableValue(universalScanResult));
deviceConnectableStatus[_str_to_mac_address(deviceId)] = true;
// deviceConnectableStatus[_str_to_mac_address(deviceId)] = true;
}
result(results);
}
catch (...)
{
std::cout << "Unknown error GetConnectedDevicesAsync" << std::endl;
result(FlutterError("Unknown error"));
}
}
@@ -840,7 +993,7 @@ namespace universal_ble
catch (...)
{
result(FlutterError("DiscoverServiceError: Unknown error"));
std::cerr << "DiscoverServiceError: Unknown error" << '\n';
std::cout << "DiscoverServiceError: Unknown error" << '\n';
}
}
@@ -864,7 +1017,7 @@ namespace universal_ble
winrt::fire_and_forget UniversalBlePlugin::SetNotifiableAsync(BluetoothDeviceAgent &bluetoothDeviceAgent, const std::string &service,
const std::string &characteristic, GattClientCharacteristicConfigurationDescriptorValue descriptorValue)
{
gatt_characteristic_t &gatt_characteristic_holder = bluetoothDeviceAgent._fetch_characteristic(service, characteristic);
GattCharacteristicObject &gatt_characteristic_holder = bluetoothDeviceAgent._fetch_characteristic(service, characteristic);
GattCharacteristic gattCharacteristic = gatt_characteristic_holder.obj;
auto uuid = to_uuidstr(gattCharacteristic.Uuid());
@@ -898,7 +1051,9 @@ namespace universal_ble
}
// create uniqKey with uuid and deviceId
// TODO: store token key in gatt_characteristic_t struct instead of using map
auto uniqTokenKey = uuid + _mac_address_to_str(gattCharacteristic.Service().Device().BluetoothAddress());
std::stringstream uniqTokenKeyStream;
uniqTokenKeyStream << uuid << _mac_address_to_str(gattCharacteristic.Service().Device().BluetoothAddress());
auto uniqTokenKey = uniqTokenKeyStream.str();
// Register/UnRegister handler for the ValueChanged event.
if (descriptorValue == GattClientCharacteristicConfigurationDescriptorValue::None)
@@ -927,8 +1082,8 @@ namespace universal_ble
{
auto uuid = to_uuidstr(sender.Uuid());
auto bytes = to_bytevc(args.CharacteristicValue());
ValueChangeStruct *valueChangeStruct = new ValueChangeStruct(_mac_address_to_str(sender.Service().Device().BluetoothAddress()), uuid, bytes);
::PostMessage(GetWindow(), WM_VALUE_CHANGE, reinterpret_cast<WPARAM>(valueChangeStruct), 0);
uiThreadHandler_.Post([sender, uuid, bytes]
{ callbackChannel->OnValueChanged(_mac_address_to_str(sender.Service().Device().BluetoothAddress()), uuid, bytes, SuccessCallback, ErrorCallback); });
}
std::string UniversalBlePlugin::parsePairingFailError(Enumeration::DevicePairingResult result)
@@ -5,6 +5,7 @@
#include <flutter/plugin_registrar_windows.h>
#include <windows.h>
#include <winrt/base.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Storage.Streams.h>
@@ -15,42 +16,32 @@
#include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
#include <memory>
#include "Utils.h"
#include "UniversalBle.g.h"
#include "universal_enum.h"
#include "helper/utils.h"
#include "helper/universal_enum.h"
#include "helper/universal_ble_base.h"
#include "generated/universal_ble.g.h"
#include "ui_thread_handler.hpp"
namespace universal_ble
{
using namespace winrt;
using namespace winrt::Windows::Devices;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::Storage::Streams;
using namespace winrt::Windows::Devices::Radios;
using namespace winrt::Windows::Devices::Bluetooth;
using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;
using namespace Windows::Devices::Enumeration;
struct gatt_characteristic_t
struct GattCharacteristicObject
{
GattCharacteristic obj = nullptr;
// winrt::event_token value_changed_token;
};
struct gatt_service_t
struct GattServiceObject
{
GattDeviceService obj = nullptr;
std::map<std::string, gatt_characteristic_t> characteristics;
std::unordered_map<std::string, GattCharacteristicObject> characteristics;
};
struct BluetoothDeviceAgent
{
BluetoothLEDevice device;
winrt::event_token connnectionStatusChangedToken;
std::map<std::string, gatt_service_t> gatt_map_;
std::unordered_map<std::string, GattServiceObject> gatt_map_;
BluetoothDeviceAgent(BluetoothLEDevice device, winrt::event_token connnectionStatusChangedToken, std::map<std::string, gatt_service_t> gatt_map_)
BluetoothDeviceAgent(BluetoothLEDevice device, winrt::event_token connnectionStatusChangedToken, std::unordered_map<std::string, GattServiceObject> gatt_map_)
: device(device),
connnectionStatusChangedToken(connnectionStatusChangedToken),
gatt_map_(gatt_map_) {}
@@ -60,19 +51,13 @@ namespace universal_ble
device = nullptr;
}
gatt_characteristic_t &_fetch_characteristic(const std::string &service_uuid,
const std::string &characteristic_uuid)
GattCharacteristicObject &_fetch_characteristic(const std::string &service_uuid,
const std::string &characteristic_uuid)
{
if (gatt_map_.count(service_uuid) == 0)
{
throw FlutterError("Service not found");
}
if (gatt_map_[service_uuid].characteristics.count(characteristic_uuid) == 0)
{
throw FlutterError("Characteristic not found");
}
return gatt_map_[service_uuid].characteristics.at(characteristic_uuid);
}
};
@@ -97,19 +82,31 @@ namespace universal_ble
UniversalBlePlugin &operator=(const UniversalBlePlugin &) = delete;
flutter::PluginRegistrarWindows *registrar_;
int64_t window_proc_delegate_id_ = -1;
HWND GetWindow();
std::optional<LRESULT> WindowProcDelegate(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
winrt::fire_and_forget InitializeAsync();
UniversalBleUiThreadHandler uiThreadHandler_;
Radio bluetoothRadio{nullptr};
void Radio_StateChanged(Radio sender, IInspectable args);
RadioState oldRadioState = RadioState::Unknown;
BluetoothLEAdvertisementWatcher bluetoothLEWatcher{nullptr};
DeviceWatcher deviceWatcher{nullptr};
std::unordered_map<uint64_t, std::unique_ptr<BluetoothDeviceAgent>> connectedDevices{};
std::unordered_map<std::string, DeviceInformation> deviceWatcherDevices{};
winrt::event_token bluetoothLEWatcherReceivedToken;
winrt::event_token deviceWatcherAddedToken;
winrt::event_token deviceWatcherUpdatedToken;
winrt::event_token deviceWatcherRemovedToken;
winrt::fire_and_forget InitializeAsync();
void Radio_StateChanged(Radio sender, IInspectable args);
void setupDeviceWatcher();
void disposeDeviceWatcher();
void pushUniversalScanResult(UniversalBleScanResult scanResult);
void BluetoothLEWatcher_Received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args);
std::map<uint64_t, std::unique_ptr<BluetoothDeviceAgent>> connectedDevices{};
std::map<uint64_t, bool> deviceConnectableStatus{};
void onDeviceInfoReceived(DeviceInformation deviceInfo);
std::string GattCommunicationStatusToString(GattCommunicationStatus status);
std::unordered_map<std::string, UniversalBleScanResult> scanResults{};
winrt::event_revoker<IRadio> radioStateChangedRevoker;
winrt::fire_and_forget ConnectAsync(uint64_t bluetoothAddress);
void BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, IInspectable args);
@@ -120,7 +117,6 @@ namespace universal_ble
void GattCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args);
AvailabilityState getAvailabilityStateFromRadio(RadioState radioState);
std::string parsePairingFailError(Enumeration::DevicePairingResult result);
void PostConnectionUpdate(uint64_t bluetoothAddress, ConnectionState connectionState);
winrt::fire_and_forget GetConnectedDevicesAsync(std::vector<std::string> with_services,
std::function<void(ErrorOr<flutter::EncodableList> reply)> result);
winrt::fire_and_forget IsPairedAsync(std::string device_id, std::function<void(ErrorOr<bool> reply)> result);
+6 -5
View File
@@ -2,11 +2,12 @@
#include <flutter/plugin_registrar_windows.h>
#include "universal_ble_plugin.h"
#include "src/universal_ble_plugin.h"
void UniversalBlePluginCApiRegisterWithRegistrar(
FlutterDesktopPluginRegistrarRef registrar) {
universal_ble::UniversalBlePlugin::RegisterWithRegistrar(
flutter::PluginRegistrarManager::GetInstance()
->GetRegistrar<flutter::PluginRegistrarWindows>(registrar));
FlutterDesktopPluginRegistrarRef registrar)
{
universal_ble::UniversalBlePlugin::RegisterWithRegistrar(
flutter::PluginRegistrarManager::GetInstance()
->GetRegistrar<flutter::PluginRegistrarWindows>(registrar));
}