-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathledger_ble_connection_manager.dart
More file actions
127 lines (105 loc) · 3.49 KB
/
ledger_ble_connection_manager.dart
File metadata and controls
127 lines (105 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import 'dart:async';
import 'package:ledger_flutter/ledger_flutter.dart';
class LedgerBleConnectionManager extends BleConnectionManager {
/// Ledger Nano X service id
static const serviceId = '13D63400-2C97-0004-0000-4C6564676572';
final _bleManager = FlutterReactiveBle();
final LedgerOptions _options;
final PermissionRequestCallback? onPermissionRequest;
final _connectedDevices = <LedgerDevice, GattGateway>{};
LedgerBleConnectionManager({
required LedgerOptions options,
this.onPermissionRequest,
}) : _options = options;
@override
Future<void> connect(
LedgerDevice device, {
LedgerOptions? options,
}) async {
// Check for permissions
final granted = (await onPermissionRequest?.call(status)) ?? true;
if (!granted) {
return;
}
// There are numerous issues on the Android BLE stack that leave it hanging
// when you try to connect to a device that is not in range.
// To work around this issue use the method connectToAdvertisingDevice to
// first scan for the device and only if it is found connect to it.
final c = Completer();
StreamSubscription? subscription;
await disconnect(device);
subscription = _bleManager.connectToDevice(
id: device.id,
connectionTimeout:
options?.connectionTimeout ?? _options.connectionTimeout,
)
.listen(
(state) async {
if (state.connectionState == DeviceConnectionState.connected) {
final services = await _bleManager.discoverServices(device.id);
final ledger = DiscoveredLedger(
device: device,
subscription: subscription,
services: services,
);
final gateway = LedgerGattGateway(
bleManager: _bleManager,
ledger: ledger,
mtu: options?.mtu ?? _options.mtu,
);
await gateway.start();
_connectedDevices[device] = gateway;
c.complete();
}
if (state.connectionState == DeviceConnectionState.disconnected) {
await disconnect(device);
}
},
onError: (ex) async {
await disconnect(device);
c.completeError(ex);
},
);
return c.future;
}
@override
Future<T> sendOperation<T>(
LedgerDevice device,
LedgerOperation<T> operation,
LedgerTransformer? transformer,
) async {
final d = _connectedDevices[device];
if (d == null) {
throw LedgerException(message: 'Unable to send request.');
}
return d.sendOperation<T>(
operation,
transformer: transformer,
);
}
/// Returns the current status of the BLE subsystem of the host device.
@override
BleStatus get status => _bleManager.status;
/// A stream providing the host device BLE subsystem status updates.
@override
Stream<BleStatus> get statusStateChanges => _bleManager.statusStream;
/// Get a list of connected [LedgerDevice]s.
@override
List<LedgerDevice> get devices => _connectedDevices.keys.toList();
/// A stream providing connection updates for all the connected BLE devices.
@override
Stream<ConnectionStateUpdate> get deviceStateChanges =>
_bleManager.connectedDeviceStream;
@override
Future<void> disconnect(LedgerDevice device) async {
_connectedDevices[device]?.disconnect();
_connectedDevices.remove(device);
}
@override
Future<void> dispose() async {
for (var subscription in _connectedDevices.values) {
await subscription.disconnect();
}
_connectedDevices.clear();
}
}