Implement pairing with dialog on windows (#46)

* Implement pairing with dialog on windows

* Minor fix

* Add pin pairing request for windows 10

* Implement native windows dialog for asking pin pairing

* Cleanups

* Improve pairing dialog ui

* Use PairAsync for Windows 11

* Fix OK button text

* Improve pin entry layout

Co-authored-by: Rohit Sangwan <rohitsangwan647@gmail.com>

* Dialog adjustments

* Make dialog non resizable

* Make window topmost

* Final adjustments

* Update changelog

* Release dialog resources properly

* Release dialog resources properly

* Remove duplicate import

* Minor Fix

---------

Co-authored-by: fotidim <foti@navideck.com>
This commit is contained in:
Rohit Sangwan
2024-06-11 15:58:25 +05:30
committed by GitHub
parent 2fe21962d2
commit b74191bb97
13 changed files with 418 additions and 246 deletions
+25 -1
View File
@@ -2,27 +2,50 @@
"cSpell.words": [
"bluez",
"BTLE",
"BTNHIGHLIGHT",
"bytevc",
"connnection",
"Cupertino",
"DFACE",
"DSIMPLEBLE",
"HFONT",
"HINSTANCE",
"HMENU",
"hresult",
"hstring",
"HWND",
"Inspectable",
"LOWORD",
"LPARAM",
"lpfn",
"LPOSVERSIONINFO",
"lpsz",
"LRESULT",
"MAXIMIZEBOX",
"microtask",
"MINIMIZEBOX",
"modalias",
"msix",
"navideck",
"NOMOVE",
"NOSIZE",
"NSUUID",
"NTDDI",
"ntdll",
"NTSTATUS",
"OSVERSIONINFOW",
"osvi",
"OVERLAPPEDWINDOW",
"pairable",
"PNTSTATUS",
"PRTL",
"rssi",
"SETFONT",
"SETTEXT",
"simpleble",
"subdata",
"sublist",
"THICKFRAME",
"unawaited",
"UNIVERSALBLE",
"Unpair",
@@ -30,6 +53,7 @@
"unwatch",
"uuidstr",
"winrt",
"WNDCLASS",
"WPARAM",
"ZUUID"
],
@@ -122,4 +146,4 @@
"future": "cpp",
"regex": "cpp"
}
}
}
+1
View File
@@ -1,6 +1,7 @@
## 0.9.12
* Add .perDevice queue
* Improve code level documentation
* Support "ProvidePin" pairing on Windows 10/11
## 0.9.11
* Add device name prefix filtering
@@ -1,5 +1,7 @@
// ignore_for_file: avoid_print, depend_on_referenced_packages
import 'dart:async';
import 'package:convert/convert.dart';
import 'package:expandable/expandable.dart';
import 'package:flutter/foundation.dart';
+41 -41
View File
@@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
url: "https://pub.dev"
source: hosted
version: "2.4.2"
version: "2.5.0"
async:
dependency: transitive
description:
@@ -69,26 +69,26 @@ packages:
dependency: "direct main"
description:
name: cupertino_icons
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev"
source: hosted
version: "1.0.6"
version: "1.0.8"
dbus:
dependency: transitive
description:
name: dbus
sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263"
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
url: "https://pub.dev"
source: hosted
version: "0.7.8"
version: "0.7.10"
device_info_plus:
dependency: "direct main"
description:
name: device_info_plus
sha256: "7035152271ff67b072a211152846e9f1259cf1be41e34cd3e0b5463d2d6b8419"
sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110"
url: "https://pub.dev"
source: hosted
version: "9.1.0"
version: "9.1.2"
device_info_plus_platform_interface:
dependency: transitive
description:
@@ -117,10 +117,10 @@ packages:
dependency: transitive
description:
name: ffi
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
version: "2.1.2"
file:
dependency: transitive
description:
@@ -138,10 +138,10 @@ packages:
dependency: "direct main"
description:
name: flutter_adaptive_scaffold
sha256: b3b7f8537b0af3e9982a0d1199d4d0e73b225672c867cecfb731c7f2bfc2f0f8
sha256: "794791e6fc0cc23e375d07ea987e76cf7f0eb7cd753532e45dc35b7e90575e2d"
url: "https://pub.dev"
source: hosted
version: "0.1.7+2"
version: "0.1.11"
flutter_driver:
dependency: transitive
description: flutter
@@ -164,10 +164,10 @@ packages:
dependency: transitive
description:
name: flutter_web_bluetooth
sha256: "0823eabf8643fb9adbf0d074b117a6b1357b312f6c0a34bd76cef0cd34b7df54"
sha256: "52ce64f65d7321c4bf6abfe9dac02fb888731339a5e0ad6de59fb916c20c9f02"
url: "https://pub.dev"
source: hosted
version: "0.2.2"
version: "0.2.3"
flutter_web_plugins:
dependency: transitive
description: flutter
@@ -187,34 +187,34 @@ packages:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev"
source: hosted
version: "0.6.7"
version: "0.7.1"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.dev"
source: hosted
version: "10.0.0"
version: "10.0.4"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "3.0.3"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "3.0.1"
lints:
dependency: transitive
description:
@@ -251,10 +251,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev"
source: hosted
version: "1.11.0"
version: "1.12.0"
path:
dependency: transitive
description:
@@ -307,10 +307,10 @@ packages:
dependency: transitive
description:
name: petitparser
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "5.4.0"
version: "6.0.2"
platform:
dependency: transitive
description:
@@ -323,10 +323,10 @@ packages:
dependency: transitive
description:
name: plugin_platform_interface
sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.6"
version: "2.1.8"
process:
dependency: transitive
description:
@@ -392,10 +392,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.dev"
source: hosted
version: "0.6.1"
version: "0.7.0"
typed_data:
dependency: transitive
description:
@@ -410,7 +410,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.9.10"
version: "0.9.12"
vector_math:
dependency: transitive
description:
@@ -423,10 +423,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev"
source: hosted
version: "13.0.0"
version: "14.2.1"
webdriver:
dependency: transitive
description:
@@ -439,26 +439,26 @@ packages:
dependency: transitive
description:
name: win32
sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
url: "https://pub.dev"
source: hosted
version: "5.0.9"
version: "5.5.1"
win32_registry:
dependency: transitive
description:
name: win32_registry
sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a"
sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.1.3"
xml:
dependency: transitive
description:
name: xml
sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.3.0"
version: "6.5.0"
sdks:
dart: ">=3.2.0-0 <4.0.0"
flutter: ">=3.10.0"
dart: ">=3.4.0 <4.0.0"
flutter: ">=3.19.0"
+2 -2
View File
@@ -24,7 +24,7 @@ class UniversalBle {
/// Set how commands will be executed. By default, all commands are executed in a global queue (`QueueType.global`),
/// with each command waiting for the previous one to finish.
///
///
/// [QueueType.global] will execute commands of all devices in a single queue
/// [QueueType.perDevice] will execute command of each device in separate queues
/// [QueueType.none] will execute all commands in parallel
@@ -33,7 +33,7 @@ class UniversalBle {
UniversalBlePlatform.logInfo('Queue ${queueType.name}');
}
/// Get Bluetooth availability state
/// Get Bluetooth availability state
/// To be notified of updates, set [onAvailabilityChange] listener
static Future<AvailabilityState> getBluetoothAvailabilityState() async {
return await _bleCommandQueue.executeCommand(
+87 -160
View File
@@ -15,8 +15,7 @@ PlatformException _createConnectionError(String channelName) {
);
}
List<Object?> wrapResponse(
{Object? result, PlatformException? error, bool empty = false}) {
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
if (empty) {
return <Object?>[];
}
@@ -98,8 +97,7 @@ class UniversalBleService {
result as List<Object?>;
return UniversalBleService(
uuid: result[0]! as String,
characteristics:
(result[1] as List<Object?>?)?.cast<UniversalBleCharacteristic?>(),
characteristics: (result[1] as List<Object?>?)?.cast<UniversalBleCharacteristic?>(),
);
}
}
@@ -152,8 +150,7 @@ class UniversalScanFilter {
result as List<Object?>;
return UniversalScanFilter(
withServices: (result[0] as List<Object?>?)!.cast<String?>(),
withManufacturerData: (result[1] as List<Object?>?)!
.cast<UniversalManufacturerDataFilter?>(),
withManufacturerData: (result[1] as List<Object?>?)!.cast<UniversalManufacturerDataFilter?>(),
);
}
}
@@ -216,15 +213,15 @@ class _UniversalBlePlatformChannelCodec extends StandardMessageCodec {
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
case 128:
return UniversalBleCharacteristic.decode(readValue(buffer)!);
case 129:
case 129:
return UniversalBleScanResult.decode(readValue(buffer)!);
case 130:
case 130:
return UniversalBleService.decode(readValue(buffer)!);
case 131:
case 131:
return UniversalManufacturerDataFilter.decode(readValue(buffer)!);
case 132:
case 132:
return UniversalScanFilter.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
@@ -237,23 +234,18 @@ class UniversalBlePlatformChannel {
/// Constructor for [UniversalBlePlatformChannel]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
UniversalBlePlatformChannel(
{BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
UniversalBlePlatformChannel({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
: __pigeon_binaryMessenger = binaryMessenger,
__pigeon_messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
__pigeon_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
final BinaryMessenger? __pigeon_binaryMessenger;
static const MessageCodec<Object?> pigeonChannelCodec =
_UniversalBlePlatformChannelCodec();
static const MessageCodec<Object?> pigeonChannelCodec = _UniversalBlePlatformChannelCodec();
final String __pigeon_messageChannelSuffix;
Future<int> getBluetoothAvailabilityState() async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -279,10 +271,8 @@ class UniversalBlePlatformChannel {
}
Future<bool> enableBluetooth() async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -308,10 +298,8 @@ class UniversalBlePlatformChannel {
}
Future<void> startScan(UniversalScanFilter? filter) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -332,10 +320,8 @@ class UniversalBlePlatformChannel {
}
Future<void> stopScan() async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -356,10 +342,8 @@ class UniversalBlePlatformChannel {
}
Future<void> connect(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -380,10 +364,8 @@ class UniversalBlePlatformChannel {
}
Future<void> disconnect(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -403,19 +385,15 @@ class UniversalBlePlatformChannel {
}
}
Future<void> setNotifiable(String deviceId, String service,
String characteristic, int bleInputProperty) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<void> setNotifiable(String deviceId, String service, String characteristic, int bleInputProperty) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$__pigeon_messageChannelSuffix';
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?>?;
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) {
@@ -430,10 +408,8 @@ class UniversalBlePlatformChannel {
}
Future<List<UniversalBleService?>> discoverServices(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -454,23 +430,19 @@ class UniversalBlePlatformChannel {
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (__pigeon_replyList[0] as List<Object?>?)!
.cast<UniversalBleService?>();
return (__pigeon_replyList[0] as List<Object?>?)!.cast<UniversalBleService?>();
}
}
Future<Uint8List> readValue(
String deviceId, String service, String characteristic) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<Uint8List> readValue(String deviceId, String service, String characteristic) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$__pigeon_messageChannelSuffix';
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?>?;
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) {
@@ -490,16 +462,14 @@ class UniversalBlePlatformChannel {
}
Future<int> requestMtu(String deviceId, int expectedMtu) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu$__pigeon_messageChannelSuffix';
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?>?;
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) {
@@ -518,24 +488,15 @@ class UniversalBlePlatformChannel {
}
}
Future<void> writeValue(String deviceId, String service,
String characteristic, Uint8List value, int bleOutputProperty) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<void> writeValue(String deviceId, String service, String characteristic, Uint8List value, int bleOutputProperty) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$__pigeon_messageChannelSuffix';
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?>?;
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) {
@@ -550,10 +511,8 @@ class UniversalBlePlatformChannel {
}
Future<bool> isPaired(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -579,10 +538,8 @@ class UniversalBlePlatformChannel {
}
Future<void> pair(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -603,10 +560,8 @@ class UniversalBlePlatformChannel {
}
Future<void> unPair(String deviceId) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -626,12 +581,9 @@ class UniversalBlePlatformChannel {
}
}
Future<List<UniversalBleScanResult?>> getConnectedDevices(
List<String?> withServices) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectedDevices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
Future<List<UniversalBleScanResult?>> getConnectedDevices(List<String?> withServices) async {
final String __pigeon_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectedDevices$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
@@ -652,8 +604,7 @@ class UniversalBlePlatformChannel {
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (__pigeon_replyList[0] as List<Object?>?)!
.cast<UniversalBleScanResult?>();
return (__pigeon_replyList[0] as List<Object?>?)!.cast<UniversalBleScanResult?>();
}
}
}
@@ -673,7 +624,7 @@ class _UniversalBleCallbackChannelCodec extends StandardMessageCodec {
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
case 128:
return UniversalBleScanResult.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
@@ -683,8 +634,7 @@ class _UniversalBleCallbackChannelCodec extends StandardMessageCodec {
/// Native -> Flutter
abstract class UniversalBleCallbackChannel {
static const MessageCodec<Object?> pigeonChannelCodec =
_UniversalBleCallbackChannelCodec();
static const MessageCodec<Object?> pigeonChannelCodec = _UniversalBleCallbackChannelCodec();
void onAvailabilityChanged(int state);
@@ -692,30 +642,22 @@ abstract class UniversalBleCallbackChannel {
void onScanResult(UniversalBleScanResult result);
void onValueChanged(
String deviceId, String characteristicId, Uint8List value);
void onValueChanged(String deviceId, String characteristicId, Uint8List value);
void onConnectionChanged(String deviceId, int state);
static void setUp(
UniversalBleCallbackChannel? api, {
BinaryMessenger? binaryMessenger,
String messageChannelSuffix = '',
}) {
messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
static void setUp(UniversalBleCallbackChannel? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
final int? arg_state = (args[0] as int?);
assert(arg_state != null,
@@ -725,25 +667,22 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
@@ -757,28 +696,24 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.');
final List<Object?> args = (message as List<Object?>?)!;
final UniversalBleScanResult? arg_result =
(args[0] as UniversalBleScanResult?);
final UniversalBleScanResult? arg_result = (args[0] as UniversalBleScanResult?);
assert(arg_result != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null, expected non-null UniversalBleScanResult.');
try {
@@ -786,25 +721,22 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
@@ -816,30 +748,26 @@ abstract class UniversalBleCallbackChannel {
assert(arg_value != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null Uint8List.');
try {
api.onValueChanged(
arg_deviceId!, arg_characteristicId!, arg_value!);
api.onValueChanged(arg_deviceId!, arg_characteristicId!, arg_value!);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null.');
'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_deviceId = (args[0] as String?);
assert(arg_deviceId != null,
@@ -852,9 +780,8 @@ abstract class UniversalBleCallbackChannel {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
@@ -116,18 +116,20 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
/// To set listeners
void _setupListeners() {
UniversalBleCallbackChannel.setUp(_UniversalBleCallbackHandler(
scanResult: (BleScanResult scanResult) => updateScanResult(scanResult),
availabilityChange: (AvailabilityState state) =>
onAvailabilityChange?.call(state),
connectionChanged: (String deviceId, BleConnectionState state) =>
onConnectionChanged?.call(deviceId, state),
valueChanged:
(String deviceId, String characteristicId, Uint8List value) =>
onValueChanged?.call(deviceId, characteristicId, value),
pairStateChange: (String deviceId, bool isPaired, String? error) =>
onPairingStateChange?.call(deviceId, isPaired, error),
));
UniversalBleCallbackChannel.setUp(
_UniversalBleCallbackHandler(
scanResult: (BleScanResult scanResult) => updateScanResult(scanResult),
availabilityChange: (AvailabilityState state) =>
onAvailabilityChange?.call(state),
connectionChanged: (String deviceId, BleConnectionState state) =>
onConnectionChanged?.call(deviceId, state),
valueChanged:
(String deviceId, String characteristicId, Uint8List value) =>
onValueChanged?.call(deviceId, characteristicId, value),
pairStateChange: (String deviceId, bool isPaired, String? error) =>
onPairingStateChange?.call(deviceId, isPaired, error),
),
);
}
}
+1
View File
@@ -41,6 +41,7 @@ list(APPEND PLUGIN_SOURCES
"src/ui_thread_handler.hpp"
"src/generated/universal_ble.g.cpp"
"src/generated/universal_ble.g.h"
"src/pin_entry.h"
)
add_library(${PLUGIN_NAME} SHARED
+33 -1
View File
@@ -3,7 +3,8 @@
#include <iomanip>
#include <iostream>
#include <sstream>
#include <windows.h>
#include <stdio.h>
#include <sdkddkver.h>
#if WDK_NTDDI_VERSION < NTDDI_WIN10_VB
@@ -13,6 +14,9 @@
#endif
#define MAC_ADDRESS_STR_LENGTH (size_t)17
typedef LONG NTSTATUS, *PNTSTATUS;
#define STATUS_SUCCESS (0x00000000)
typedef NTSTATUS(WINAPI *RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
namespace universal_ble
{
@@ -126,4 +130,32 @@ namespace universal_ble
return (numPtr[0] == 1);
}
bool isWindows11OrGreater()
{
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
if (!hMod)
{
std::cout << "Failed to get ntdll" << std::endl;
return false;
}
RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
if (fxPtr == nullptr)
{
std::cout << "Failed to get RtlGetVersionPtr" << std::endl;
return false;
}
RTL_OSVERSIONINFOW rove = {0};
rove.dwOSVersionInfoSize = sizeof(rove);
if (STATUS_SUCCESS != fxPtr(&rove))
{
std::cout << "Failed to get RTL_OSVERSIONINFOW" << std::endl;
return false;
}
// Windows 11 => MajorVersion = 10 and BuildNumber >= 22000
return rove.dwMajorVersion == 10 && rove.dwBuildNumber >= 22000;
}
} // namespace SimpleBLE
+1
View File
@@ -26,6 +26,7 @@ namespace universal_ble
std::string to_uuidstr(winrt::guid guid);
bool isLittleEndian();
bool isWindows11OrGreater();
/// To call async functions synchronously
template <typename async_t>
+134
View File
@@ -0,0 +1,134 @@
#pragma once
#include <windows.h>
#include <tchar.h>
namespace universal_ble
{
typedef struct SizeAndPos_s
{
int x, y, width, height;
} SizeAndPos_t;
const WORD ID_btnOK = 1;
const WORD ID_txtEdit = 4;
HWND txtEditHandle = NULL;
TCHAR textBoxText[16];
// Positions and dimensions of UI elements: X, Y, Width, Height
const SizeAndPos_t mainWindow = {150, 150, 450, 240};
const SizeAndPos_t txtEdit = {50, 40, 320, 40};
const SizeAndPos_t btnOK = {50, 100, 320, 40};
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
txtEditHandle = CreateWindow(
TEXT("Edit"), TEXT(""),
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER,
txtEdit.x, txtEdit.y, txtEdit.width, txtEdit.height,
hwnd, (HMENU)ID_txtEdit, NULL, NULL);
CreateWindow(
TEXT("Button"), TEXT("OK"),
WS_CHILD | WS_VISIBLE | BS_FLAT,
btnOK.x, btnOK.y, btnOK.width, btnOK.height,
hwnd, (HMENU)ID_btnOK, NULL, NULL);
break;
}
case WM_COMMAND:
if (LOWORD(wParam) == ID_btnOK)
{
GetWindowText(txtEditHandle, textBoxText, sizeof(textBoxText) / sizeof(TCHAR));
DestroyWindow(hwnd);
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
hstring askForPairingPin()
{
textBoxText[0] = '\0';
HINSTANCE hInstance = GetModuleHandle(NULL);
MSG msg;
WNDCLASS mainWindowClass = {0};
mainWindowClass.lpszClassName = TEXT("JRH.MainWindow");
mainWindowClass.hInstance = hInstance;
mainWindowClass.hbrBackground = GetSysColorBrush(COLOR_BTNHIGHLIGHT);
mainWindowClass.lpfnWndProc = WndProc;
mainWindowClass.hCursor = LoadCursor(0, IDC_ARROW);
// Register the window class
if (!RegisterClass(&mainWindowClass))
{
std::cout << "PinPairDialog: Failed to register window class" << std::endl;
return L"";
}
HWND hwnd = CreateWindow(
mainWindowClass.lpszClassName,
TEXT("PIN"), (WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX) | WS_VISIBLE,
mainWindow.x, mainWindow.y, mainWindow.width, mainWindow.height,
NULL, 0, hInstance, NULL);
if (hwnd == NULL)
{
std::cout << "PinPairDialog: Failed to create window" << std::endl;
return L"";
}
// After creating the window, make it topmost
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
ShowWindow(hwnd, SW_SHOW);
// Create a font with the desired size
HFONT hFont = CreateFont(
36, // Height of the font
0, // Width of the font
0, // Angle of escapement
0, // Orientation angle
FW_NORMAL, // Font weight
FALSE, // Italic attribute option
FALSE, // Underline attribute option
FALSE, // Strikeout attribute option
DEFAULT_CHARSET, // Character set identifier
OUT_DEFAULT_PRECIS, // Output precision
CLIP_DEFAULT_PRECIS, // Clipping precision
DEFAULT_QUALITY, // Output quality
DEFAULT_PITCH | FF_SWISS, // Pitch and family
TEXT("Arial") // Font name
);
// Set the font to the edit control
SendMessage(txtEditHandle, WM_SETFONT, (WPARAM)hFont, TRUE);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (msg.wParam != 0)
{
std::wcout << "PinPairDialog: Got invalid result" << std::endl;
}
DeleteObject(hFont);
DestroyWindow(hwnd);
UnregisterClass(mainWindowClass.lpszClassName, hInstance);
return winrt::to_hstring(textBoxText);
}
}
+73 -28
View File
@@ -14,6 +14,7 @@
#include "helper/utils.h"
#include "helper/universal_enum.h"
#include "generated/universal_ble.g.h"
#include "pin_entry.h"
namespace universal_ble
{
@@ -408,37 +409,24 @@ namespace universal_ble
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)
if (deviceInformation.Pairing().IsPaired())
{
return FlutterError("PairLog: Device is already paired");
bool canPair = deviceInformation.Pairing().CanPair();
if (!canPair)
}
if (!deviceInformation.Pairing().CanPair())
{
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)
{
std::cout << "PairLog: Pairing requested" << std::endl;
// eventArgs.AcceptWithPasswordCredential(nullptr, nullptr);
// eventArgs.Pin();
// Accept all pairing request
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);
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
std::string errorStr = parsePairingFailError(result);
uiThreadHandler_.Post([device_id, isPaired, errorStr]
{ callbackChannel->OnPairStateChange(device_id, isPaired, &errorStr, SuccessCallback, ErrorCallback); }); });
if (isWindows11OrGreater())
{
PairAsync(device_id, deviceInformation);
}
else
{
CustomPairAsync(device_id, deviceInformation);
}
return std::nullopt;
}
catch (const FlutterError &err)
@@ -554,6 +542,63 @@ namespace universal_ble
}
}
winrt::fire_and_forget UniversalBlePlugin::PairAsync(std::string device_id, const DeviceInformation deviceInformation)
{
try
{
auto result = co_await deviceInformation.Pairing().PairAsync();
std::cout << "PairLog: Received pairing status" << std::endl;
auto isPaired = result.Status() == Enumeration::DevicePairingResultStatus::Paired;
std::string errorStr = parsePairingFailError(result);
uiThreadHandler_.Post([device_id, isPaired, errorStr]
{ callbackChannel->OnPairStateChange(device_id, isPaired, &errorStr, SuccessCallback, ErrorCallback); });
}
catch (...)
{
std::cout << "PairLog: Unknown error" << std::endl;
}
}
winrt::fire_and_forget UniversalBlePlugin::CustomPairAsync(std::string device_id, const DeviceInformation deviceInformation)
{
try
{
auto customPairing = deviceInformation.Pairing().Custom();
winrt::event_token token = customPairing.PairingRequested({this, &UniversalBlePlugin::PairingRequestedHandler});
std::cout << "PairLog: Trying to pair" << std::endl;
DevicePairingProtectionLevel protectionLevel = deviceInformation.Pairing().ProtectionLevel();
// DevicePairingKinds => None, ConfirmOnly, DisplayPin, ProvidePin, ConfirmPinMatch, ProvidePasswordCredential
auto result = co_await customPairing.PairAsync(DevicePairingKinds::ConfirmOnly | DevicePairingKinds::ProvidePin, protectionLevel);
std::cout << "PairLog: Got Pair Result" << std::endl;
DevicePairingResultStatus status = result.Status();
customPairing.PairingRequested(token);
auto isPaired = status == Enumeration::DevicePairingResultStatus::Paired;
std::string errorStr = parsePairingFailError(result);
uiThreadHandler_.Post([device_id, isPaired, errorStr]
{ callbackChannel->OnPairStateChange(device_id, isPaired, &errorStr, SuccessCallback, ErrorCallback); });
}
catch (...)
{
std::cout << "PairLog Error: Pairing Failed" << std::endl;
}
}
void UniversalBlePlugin::PairingRequestedHandler(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs eventArgs)
{
std::cout << "PairLog: Got PairingRequest" << std::endl;
DevicePairingKinds kind = eventArgs.PairingKind();
if (kind != DevicePairingKinds::ProvidePin)
{
eventArgs.Accept();
return;
}
std::cout << "PairLog: Trying to get pin from user" << std::endl;
hstring pin = askForPairingPin();
std::wcout << "PairLog: Got Pin: " << pin.c_str() << std::endl;
eventArgs.Accept(pin);
}
// Send device to callback channel
// if device is already discovered in deviceWatcher then merge the scan result
void UniversalBlePlugin::pushUniversalScanResult(UniversalBleScanResult scanResult, bool isConnectable)
+4 -1
View File
@@ -114,7 +114,7 @@ namespace universal_ble
void DiscoverServicesAsync(BluetoothDeviceAgent &bluetoothDeviceAgent, std::function<void(ErrorOr<flutter::EncodableList> reply)>);
winrt::fire_and_forget SetNotifiableAsync(BluetoothDeviceAgent &bluetoothDeviceAgent, const std::string &service,
const std::string &characteristic, GattClientCharacteristicConfigurationDescriptorValue descriptorValue,
std::function<void(std::optional<FlutterError> reply)> result );
std::function<void(std::optional<FlutterError> reply)> result);
void GattCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args);
AvailabilityState getAvailabilityStateFromRadio(RadioState radioState);
std::string parsePairingFailError(Enumeration::DevicePairingResult result);
@@ -125,6 +125,9 @@ namespace universal_ble
const std::vector<uint8_t> &value,
std::function<void(std::optional<FlutterError> reply)> result);
bool filterByManufacturerData(IVector<BluetoothLEManufacturerData> deviceManufactureData);
winrt::fire_and_forget PairAsync(std::string device_id, const DeviceInformation deviceInformation);
winrt::fire_and_forget CustomPairAsync(std::string device_id, const DeviceInformation deviceInformation);
void PairingRequestedHandler(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs eventArgs);
// UniversalBlePlatformChannel implementation.
void GetBluetoothAvailabilityState(std::function<void(ErrorOr<int64_t> reply)> result) override;