Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Pair Method for Windows #116

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions quick_blue/lib/quick_blue.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class QuickBlue {

static void connect(String deviceId) => _platform.connect(deviceId);

static void pair(String deviceId) => _platform.pair(deviceId);

static void disconnect(String deviceId) => _platform.disconnect(deviceId);

static void setConnectionHandler(OnConnectionChanged? onConnectionChanged) {
Expand Down
4 changes: 4 additions & 0 deletions quick_blue/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ dependencies:
quick_blue_linux: ^0.2.0-dev.0
convert: ^3.0.0

dependency_overrides:
quick_blue_platform_interface:
path: ../quick_blue_platform_interface

dev_dependencies:
flutter_test:
sdk: flutter
Expand Down
10 changes: 9 additions & 1 deletion quick_blue_example/lib/PeripheralDetailPage.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:io';
import 'dart:typed_data';

import 'package:convert/convert.dart';
Expand Down Expand Up @@ -46,7 +47,7 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
}

void _handleConnectionChange(String deviceId, BlueConnectionState state) {
print('_handleConnectionChange $deviceId, $state');
print('_handleConnectionChange $deviceId, ${state.value}');
}

void _handleServiceDiscovery(String deviceId, String serviceId, List<String> characteristicIds) {
Expand Down Expand Up @@ -80,6 +81,13 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
QuickBlue.connect(widget.deviceId);
},
),
if(Platform.isWindows)
RaisedButton(
child: Text('pair'),
onPressed: () {
QuickBlue.pair(widget.deviceId);
},
),
RaisedButton(
child: Text('disconnect'),
onPressed: () {
Expand Down
6 changes: 6 additions & 0 deletions quick_blue_linux/lib/quick_blue_linux.dart
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ class QuickBlueLinux extends QuickBluePlatform {
// TODO: implement requestMtu
throw UnimplementedError();
}

@override
void pair(String deviceId) {
// TODO: implement pair
throw UnimplementedError();
}
}

extension BlueZDeviceExtension on BlueZDevice {
Expand Down
4 changes: 4 additions & 0 deletions quick_blue_linux/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ dependencies:
collection: ^1.15.0
logging: ^1.0.2

dependency_overrides:
quick_blue_platform_interface:
path: ../quick_blue_platform_interface

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for here. There is a dependency_overrides in quick_blue_example

dev_dependencies:
flutter_test:
sdk: flutter
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/services.dart';
Expand Down Expand Up @@ -140,4 +141,12 @@ class MethodChannelQuickBlue extends QuickBluePlatform {
}).then((_) => _log('requestMtu invokeMethod success'));
return await _mtuConfigController.stream.first;
}

@override
void pair(String deviceId) {
if(!Platform.isWindows)throw UnimplementedError();
_method.invokeMethod('pair', {
'deviceId': deviceId,
}).then((_) => _log('pair invokeMethod success'));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ abstract class QuickBluePlatform extends PlatformInterface {

void disconnect(String deviceId);

void pair(String deviceId);

OnConnectionChanged? onConnectionChanged;

void discoverServices(String deviceId);
Expand Down
33 changes: 32 additions & 1 deletion quick_blue_windows/windows/quick_blue_windows_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#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 <flutter/method_channel.h>
#include <flutter/basic_message_channel.h>
Expand Down Expand Up @@ -36,6 +37,7 @@ 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 winrt::Windows::Devices::Enumeration;

using flutter::EncodableValue;
using flutter::EncodableMap;
Expand Down Expand Up @@ -152,7 +154,9 @@ class QuickBlueWindowsPlugin : public flutter::Plugin, public flutter::StreamHan
std::map<uint64_t, std::unique_ptr<BluetoothDeviceAgent>> connectedDevices{};

winrt::fire_and_forget ConnectAsync(uint64_t bluetoothAddress);
winrt::fire_and_forget PairAsync(uint64_t bluetoothAddress, DevicePairingProtectionLevel level);
void BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, IInspectable args);
void BluetoothLEDevice_PairingRequested(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args);
void CleanConnection(uint64_t bluetoothAddress);
winrt::fire_and_forget DiscoverServicesAsync(BluetoothDeviceAgent &bluetoothDeviceAgent);
winrt::fire_and_forget SetNotifiableAsync(BluetoothDeviceAgent& bluetoothDeviceAgent, std::string service, std::string characteristic, std::string bleInputProperty);
Expand Down Expand Up @@ -241,7 +245,12 @@ void QuickBlueWindowsPlugin::HandleMethodCall(
auto deviceId = std::get<std::string>(args[EncodableValue("deviceId")]);
ConnectAsync(std::stoull(deviceId));
result->Success(nullptr);
} else if (method_name.compare("disconnect") == 0) {
}else if (method_name.compare("pair") == 0) {
auto args = std::get<EncodableMap>(*method_call.arguments());
auto deviceId = std::get<std::string>(args[EncodableValue("deviceId")]);
PairAsync(std::stoull(deviceId), DevicePairingProtectionLevel::Encryption);
result->Success(nullptr);
}else if (method_name.compare("disconnect") == 0) {
auto args = std::get<EncodableMap>(*method_call.arguments());
auto deviceId = std::get<std::string>(args[EncodableValue("deviceId")]);
CleanConnection(std::stoull(deviceId));
Expand Down Expand Up @@ -380,6 +389,24 @@ std::unique_ptr<flutter::StreamHandlerError<EncodableValue>> QuickBlueWindowsPlu
return nullptr;
}

winrt::fire_and_forget QuickBlueWindowsPlugin::PairAsync(uint64_t bluetoothAddress, DevicePairingProtectionLevel level) {
auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(bluetoothAddress);
if(device != nullptr) {
if(device.DeviceInformation().Pairing().CanPair()) {
try {
device.DeviceInformation().Pairing().Custom().PairingRequested({ this, &QuickBlueWindowsPlugin::BluetoothLEDevice_PairingRequested });
auto result = co_await device.DeviceInformation().Pairing().Custom().PairAsync(DevicePairingKinds::ConfirmOnly, DevicePairingProtectionLevel::Encryption);
if(result.Status() != DevicePairingResultStatus::Paired && result.Status() != DevicePairingResultStatus::AlreadyPaired) {
OutputDebugString((L"PairAsync error: " + winrt::to_hstring((int32_t)result.Status()) + L"\n").c_str());
}
} catch(winrt::hresult_error const& ex) {
OutputDebugString((L"PairAsync " + ex.message() + L"\n").c_str());
}
}
}
co_return;
}

winrt::fire_and_forget QuickBlueWindowsPlugin::ConnectAsync(uint64_t bluetoothAddress) {
auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(bluetoothAddress);
auto servicesResult = co_await device.GetGattServicesAsync();
Expand All @@ -402,6 +429,10 @@ winrt::fire_and_forget QuickBlueWindowsPlugin::ConnectAsync(uint64_t bluetoothAd
});
}

void QuickBlueWindowsPlugin::BluetoothLEDevice_PairingRequested(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args) {
args.Accept();
}

void QuickBlueWindowsPlugin::BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, IInspectable args) {
OutputDebugString((L"ConnectionStatusChanged " + winrt::to_hstring((int32_t)sender.ConnectionStatus()) + L"\n").c_str());
if (sender.ConnectionStatus() == BluetoothConnectionStatus::Disconnected) {
Expand Down