@ledgerhq/hw-transport-web-ble 6.27.13 → 6.27.14-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/lib/TransportWebBLE.js +207 -363
- package/lib/TransportWebBLE.js.map +1 -1
- package/lib/monitorCharacteristic.js +17 -19
- package/lib/monitorCharacteristic.js.map +1 -1
- package/lib/types.d.ts +2 -2
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +1 -1
- package/lib-es/TransportWebBLE.js +196 -353
- package/lib-es/TransportWebBLE.js.map +1 -1
- package/lib-es/monitorCharacteristic.js +14 -16
- package/lib-es/monitorCharacteristic.js.map +1 -1
- package/lib-es/types.d.ts +2 -2
- package/lib-es/types.d.ts.map +1 -1
- package/package.json +6 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @ledgerhq/hw-transport-web-ble
|
|
2
2
|
|
|
3
|
+
## 6.27.14-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`87d2349fd8`](https://github.com/LedgerHQ/ledger-live/commit/87d2349fd835e5deb39d1ee8dfcf3539f4195472)]:
|
|
8
|
+
- @ledgerhq/errors@6.12.5-next.0
|
|
9
|
+
- @ledgerhq/devices@8.0.2-next.0
|
|
10
|
+
- @ledgerhq/hw-transport@6.28.3-next.0
|
|
11
|
+
|
|
3
12
|
## 6.27.13
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/lib/TransportWebBLE.js
CHANGED
|
@@ -1,19 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
if (typeof b !== "function" && b !== null)
|
|
11
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
-
extendStatics(d, b);
|
|
13
|
-
function __() { this.constructor = d; }
|
|
14
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
-
};
|
|
16
|
-
})();
|
|
17
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
18
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -23,206 +8,130 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
23
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
9
|
});
|
|
25
10
|
};
|
|
26
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
27
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
28
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
29
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
30
|
-
function step(op) {
|
|
31
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
32
|
-
while (_) try {
|
|
33
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
34
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
35
|
-
switch (op[0]) {
|
|
36
|
-
case 0: case 1: t = op; break;
|
|
37
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
38
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
39
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
40
|
-
default:
|
|
41
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
42
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
43
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
44
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
45
|
-
if (t[2]) _.ops.pop();
|
|
46
|
-
_.trys.pop(); continue;
|
|
47
|
-
}
|
|
48
|
-
op = body.call(thisArg, _);
|
|
49
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
50
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
54
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
55
|
-
if (!m) return o;
|
|
56
|
-
var i = m.call(o), r, ar = [], e;
|
|
57
|
-
try {
|
|
58
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
59
|
-
}
|
|
60
|
-
catch (error) { e = { error: error }; }
|
|
61
|
-
finally {
|
|
62
|
-
try {
|
|
63
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
64
|
-
}
|
|
65
|
-
finally { if (e) throw e.error; }
|
|
66
|
-
}
|
|
67
|
-
return ar;
|
|
68
|
-
};
|
|
69
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
70
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
71
13
|
};
|
|
72
|
-
|
|
14
|
+
var _a;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
73
16
|
/* eslint-disable prefer-template */
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
17
|
+
const hw_transport_1 = __importDefault(require("@ledgerhq/hw-transport"));
|
|
18
|
+
const errors_1 = require("@ledgerhq/errors");
|
|
19
|
+
const devices_1 = require("@ledgerhq/devices");
|
|
20
|
+
const sendAPDU_1 = require("@ledgerhq/devices/ble/sendAPDU");
|
|
21
|
+
const receiveAPDU_1 = require("@ledgerhq/devices/ble/receiveAPDU");
|
|
22
|
+
const logs_1 = require("@ledgerhq/logs");
|
|
23
|
+
const rxjs_1 = require("rxjs");
|
|
24
|
+
const operators_1 = require("rxjs/operators");
|
|
25
|
+
const monitorCharacteristic_1 = require("./monitorCharacteristic");
|
|
26
|
+
const requiresBluetooth = () => {
|
|
84
27
|
// $FlowFixMe
|
|
85
|
-
|
|
28
|
+
const { bluetooth } = navigator;
|
|
86
29
|
if (typeof bluetooth === "undefined") {
|
|
87
30
|
throw new Error("web bluetooth not supported");
|
|
88
31
|
}
|
|
89
32
|
return bluetooth;
|
|
90
33
|
};
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
observer.next(available);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
return function () {
|
|
105
|
-
unsubscribed = true;
|
|
106
|
-
bluetooth.removeEventListener("availabilitychanged", onAvailabilityChanged);
|
|
107
|
-
};
|
|
108
|
-
});
|
|
109
|
-
};
|
|
110
|
-
var transportsCache = {};
|
|
111
|
-
var requestDeviceParam = function () { return ({
|
|
112
|
-
filters: (0, devices_1.getBluetoothServiceUuids)().map(function (uuid) { return ({
|
|
113
|
-
services: [uuid]
|
|
114
|
-
}); })
|
|
115
|
-
}); };
|
|
116
|
-
var retrieveService = function (device) { return __awaiter(void 0, void 0, void 0, function () {
|
|
117
|
-
var _a, service, infos;
|
|
118
|
-
return __generator(this, function (_b) {
|
|
119
|
-
switch (_b.label) {
|
|
120
|
-
case 0:
|
|
121
|
-
if (!device.gatt)
|
|
122
|
-
throw new Error("bluetooth gatt not found");
|
|
123
|
-
return [4 /*yield*/, device.gatt.getPrimaryServices()];
|
|
124
|
-
case 1:
|
|
125
|
-
_a = __read.apply(void 0, [_b.sent(), 1]), service = _a[0];
|
|
126
|
-
if (!service)
|
|
127
|
-
throw new Error("bluetooth service not found");
|
|
128
|
-
infos = (0, devices_1.getInfosForServiceUuid)(service.uuid);
|
|
129
|
-
if (!infos)
|
|
130
|
-
throw new Error("bluetooth service infos not found");
|
|
131
|
-
return [2 /*return*/, [service, infos]];
|
|
34
|
+
const availability = () => rxjs_1.Observable.create((observer) => {
|
|
35
|
+
const bluetooth = requiresBluetooth();
|
|
36
|
+
const onAvailabilityChanged = (e) => {
|
|
37
|
+
observer.next(e.value);
|
|
38
|
+
};
|
|
39
|
+
bluetooth.addEventListener("availabilitychanged", onAvailabilityChanged);
|
|
40
|
+
let unsubscribed = false;
|
|
41
|
+
bluetooth.getAvailability().then((available) => {
|
|
42
|
+
if (!unsubscribed) {
|
|
43
|
+
observer.next(available);
|
|
132
44
|
}
|
|
133
45
|
});
|
|
134
|
-
|
|
46
|
+
return () => {
|
|
47
|
+
unsubscribed = true;
|
|
48
|
+
bluetooth.removeEventListener("availabilitychanged", onAvailabilityChanged);
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
const transportsCache = {};
|
|
52
|
+
const requestDeviceParam = () => ({
|
|
53
|
+
filters: (0, devices_1.getBluetoothServiceUuids)().map((uuid) => ({
|
|
54
|
+
services: [uuid],
|
|
55
|
+
})),
|
|
56
|
+
});
|
|
57
|
+
const retrieveService = (device) => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
|
+
if (!device.gatt)
|
|
59
|
+
throw new Error("bluetooth gatt not found");
|
|
60
|
+
const [service] = yield device.gatt.getPrimaryServices();
|
|
61
|
+
if (!service)
|
|
62
|
+
throw new Error("bluetooth service not found");
|
|
63
|
+
const infos = (0, devices_1.getInfosForServiceUuid)(service.uuid);
|
|
64
|
+
if (!infos)
|
|
65
|
+
throw new Error("bluetooth service infos not found");
|
|
66
|
+
return [service, infos];
|
|
67
|
+
});
|
|
135
68
|
function open(deviceOrId, needsReconnect) {
|
|
136
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (transportsCache[deviceOrId]) {
|
|
143
|
-
(0, logs_1.log)("ble-verbose", "Transport in cache, using that.");
|
|
144
|
-
return [2 /*return*/, transportsCache[deviceOrId]];
|
|
145
|
-
}
|
|
146
|
-
bluetooth = requiresBluetooth();
|
|
147
|
-
return [4 /*yield*/, bluetooth.requestDevice(requestDeviceParam())];
|
|
148
|
-
case 1:
|
|
149
|
-
// TODO instead we should "query" the device by its ID
|
|
150
|
-
device = _c.sent();
|
|
151
|
-
return [3 /*break*/, 3];
|
|
152
|
-
case 2:
|
|
153
|
-
device = deviceOrId;
|
|
154
|
-
_c.label = 3;
|
|
155
|
-
case 3:
|
|
156
|
-
if (!!device.gatt.connected) return [3 /*break*/, 5];
|
|
157
|
-
(0, logs_1.log)("ble-verbose", "not connected. connecting...");
|
|
158
|
-
return [4 /*yield*/, device.gatt.connect()];
|
|
159
|
-
case 4:
|
|
160
|
-
_c.sent();
|
|
161
|
-
_c.label = 5;
|
|
162
|
-
case 5: return [4 /*yield*/, retrieveService(device)];
|
|
163
|
-
case 6:
|
|
164
|
-
_a = __read.apply(void 0, [_c.sent(), 2]), service = _a[0], infos = _a[1];
|
|
165
|
-
deviceModel = infos.deviceModel, writeUuid = infos.writeUuid, notifyUuid = infos.notifyUuid;
|
|
166
|
-
return [4 /*yield*/, Promise.all([
|
|
167
|
-
service.getCharacteristic(writeUuid),
|
|
168
|
-
service.getCharacteristic(notifyUuid),
|
|
169
|
-
])];
|
|
170
|
-
case 7:
|
|
171
|
-
_b = __read.apply(void 0, [_c.sent(), 2]), writeC = _b[0], notifyC = _b[1];
|
|
172
|
-
notifyObservable = (0, monitorCharacteristic_1.monitorCharacteristic)(notifyC).pipe((0, operators_1.tap)(function (value) {
|
|
173
|
-
(0, logs_1.log)("ble-frame", "<= " + value.toString("hex"));
|
|
174
|
-
}), (0, operators_1.share)());
|
|
175
|
-
notif = notifyObservable.subscribe();
|
|
176
|
-
transport = new BluetoothTransport(device, writeC, notifyObservable, deviceModel);
|
|
177
|
-
if (!device.gatt.connected) {
|
|
178
|
-
throw new errors_1.DisconnectedDevice();
|
|
179
|
-
}
|
|
180
|
-
// eslint-disable-next-line require-atomic-updates
|
|
181
|
-
transportsCache[transport.id] = transport;
|
|
182
|
-
onDisconnect = function (e) {
|
|
183
|
-
console.log("onDisconnect!", e);
|
|
184
|
-
delete transportsCache[transport.id];
|
|
185
|
-
transport.notYetDisconnected = false;
|
|
186
|
-
notif.unsubscribe();
|
|
187
|
-
device.removeEventListener("gattserverdisconnected", onDisconnect);
|
|
188
|
-
(0, logs_1.log)("ble-verbose", "BleTransport(".concat(transport.id, ") disconnected"));
|
|
189
|
-
transport.emit("disconnect", e);
|
|
190
|
-
};
|
|
191
|
-
device.addEventListener("gattserverdisconnected", onDisconnect);
|
|
192
|
-
beforeMTUTime = Date.now();
|
|
193
|
-
_c.label = 8;
|
|
194
|
-
case 8:
|
|
195
|
-
_c.trys.push([8, , 10, 14]);
|
|
196
|
-
return [4 /*yield*/, transport.inferMTU()];
|
|
197
|
-
case 9:
|
|
198
|
-
_c.sent();
|
|
199
|
-
return [3 /*break*/, 14];
|
|
200
|
-
case 10:
|
|
201
|
-
afterMTUTime = Date.now();
|
|
202
|
-
// workaround for #279: we need to open() again if we come the first time here,
|
|
203
|
-
// to make sure we do a disconnect() after the first pairing time
|
|
204
|
-
// because of a firmware bug
|
|
205
|
-
if (afterMTUTime - beforeMTUTime < 1000) {
|
|
206
|
-
needsReconnect = false; // (optim) there is likely no new pairing done because mtu answer was fast.
|
|
207
|
-
}
|
|
208
|
-
if (!needsReconnect) return [3 /*break*/, 13];
|
|
209
|
-
return [4 /*yield*/, device.gatt.disconnect()];
|
|
210
|
-
case 11:
|
|
211
|
-
_c.sent();
|
|
212
|
-
// necessary time for the bonding workaround
|
|
213
|
-
return [4 /*yield*/, new Promise(function (s) { return setTimeout(s, 4000); })];
|
|
214
|
-
case 12:
|
|
215
|
-
// necessary time for the bonding workaround
|
|
216
|
-
_c.sent();
|
|
217
|
-
_c.label = 13;
|
|
218
|
-
case 13: return [7 /*endfinally*/];
|
|
219
|
-
case 14:
|
|
220
|
-
if (needsReconnect) {
|
|
221
|
-
return [2 /*return*/, open(device, false)];
|
|
222
|
-
}
|
|
223
|
-
return [2 /*return*/, transport];
|
|
69
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
let device;
|
|
71
|
+
if (typeof deviceOrId === "string") {
|
|
72
|
+
if (transportsCache[deviceOrId]) {
|
|
73
|
+
(0, logs_1.log)("ble-verbose", "Transport in cache, using that.");
|
|
74
|
+
return transportsCache[deviceOrId];
|
|
224
75
|
}
|
|
225
|
-
|
|
76
|
+
const bluetooth = requiresBluetooth();
|
|
77
|
+
// TODO instead we should "query" the device by its ID
|
|
78
|
+
device = yield bluetooth.requestDevice(requestDeviceParam());
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
device = deviceOrId;
|
|
82
|
+
}
|
|
83
|
+
if (!device.gatt.connected) {
|
|
84
|
+
(0, logs_1.log)("ble-verbose", "not connected. connecting...");
|
|
85
|
+
yield device.gatt.connect();
|
|
86
|
+
}
|
|
87
|
+
const [service, infos] = yield retrieveService(device);
|
|
88
|
+
const { deviceModel, writeUuid, notifyUuid } = infos;
|
|
89
|
+
const [writeC, notifyC] = yield Promise.all([
|
|
90
|
+
service.getCharacteristic(writeUuid),
|
|
91
|
+
service.getCharacteristic(notifyUuid),
|
|
92
|
+
]);
|
|
93
|
+
const notifyObservable = (0, monitorCharacteristic_1.monitorCharacteristic)(notifyC).pipe((0, operators_1.tap)((value) => {
|
|
94
|
+
(0, logs_1.log)("ble-frame", "<= " + value.toString("hex"));
|
|
95
|
+
}), (0, operators_1.share)());
|
|
96
|
+
const notif = notifyObservable.subscribe();
|
|
97
|
+
const transport = new BluetoothTransport(device, writeC, notifyObservable, deviceModel);
|
|
98
|
+
if (!device.gatt.connected) {
|
|
99
|
+
throw new errors_1.DisconnectedDevice();
|
|
100
|
+
}
|
|
101
|
+
// eslint-disable-next-line require-atomic-updates
|
|
102
|
+
transportsCache[transport.id] = transport;
|
|
103
|
+
const onDisconnect = (e) => {
|
|
104
|
+
console.log("onDisconnect!", e);
|
|
105
|
+
delete transportsCache[transport.id];
|
|
106
|
+
transport.notYetDisconnected = false;
|
|
107
|
+
notif.unsubscribe();
|
|
108
|
+
device.removeEventListener("gattserverdisconnected", onDisconnect);
|
|
109
|
+
(0, logs_1.log)("ble-verbose", `BleTransport(${transport.id}) disconnected`);
|
|
110
|
+
transport.emit("disconnect", e);
|
|
111
|
+
};
|
|
112
|
+
device.addEventListener("gattserverdisconnected", onDisconnect);
|
|
113
|
+
const beforeMTUTime = Date.now();
|
|
114
|
+
try {
|
|
115
|
+
yield transport.inferMTU();
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
const afterMTUTime = Date.now();
|
|
119
|
+
// workaround for #279: we need to open() again if we come the first time here,
|
|
120
|
+
// to make sure we do a disconnect() after the first pairing time
|
|
121
|
+
// because of a firmware bug
|
|
122
|
+
if (afterMTUTime - beforeMTUTime < 1000) {
|
|
123
|
+
needsReconnect = false; // (optim) there is likely no new pairing done because mtu answer was fast.
|
|
124
|
+
}
|
|
125
|
+
if (needsReconnect) {
|
|
126
|
+
yield device.gatt.disconnect();
|
|
127
|
+
// necessary time for the bonding workaround
|
|
128
|
+
yield new Promise((s) => setTimeout(s, 4000));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (needsReconnect) {
|
|
132
|
+
return open(device, false);
|
|
133
|
+
}
|
|
134
|
+
return transport;
|
|
226
135
|
});
|
|
227
136
|
}
|
|
228
137
|
/**
|
|
@@ -230,200 +139,135 @@ function open(deviceOrId, needsReconnect) {
|
|
|
230
139
|
* @example
|
|
231
140
|
* import BluetoothTransport from "@ledgerhq/hw-transport-web-ble";
|
|
232
141
|
*/
|
|
233
|
-
|
|
234
|
-
__extends(BluetoothTransport, _super);
|
|
235
|
-
function BluetoothTransport(device, writeCharacteristic, notifyObservable, deviceModel) {
|
|
236
|
-
var _this = _super.call(this) || this;
|
|
237
|
-
_this.mtuSize = 20;
|
|
238
|
-
_this.notYetDisconnected = true;
|
|
239
|
-
_this.write = function (buffer) { return __awaiter(_this, void 0, void 0, function () {
|
|
240
|
-
return __generator(this, function (_b) {
|
|
241
|
-
switch (_b.label) {
|
|
242
|
-
case 0:
|
|
243
|
-
(0, logs_1.log)("ble-frame", "=> " + buffer.toString("hex"));
|
|
244
|
-
return [4 /*yield*/, this.writeCharacteristic.writeValue(buffer)];
|
|
245
|
-
case 1:
|
|
246
|
-
_b.sent();
|
|
247
|
-
return [2 /*return*/];
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
}); };
|
|
251
|
-
_this.id = device.id;
|
|
252
|
-
_this.device = device;
|
|
253
|
-
_this.writeCharacteristic = writeCharacteristic;
|
|
254
|
-
_this.notifyObservable = notifyObservable;
|
|
255
|
-
_this.deviceModel = deviceModel;
|
|
256
|
-
(0, logs_1.log)("ble-verbose", "BleTransport(".concat(String(_this.id), ") new instance"));
|
|
257
|
-
return _this;
|
|
258
|
-
}
|
|
142
|
+
class BluetoothTransport extends hw_transport_1.default {
|
|
259
143
|
/**
|
|
260
144
|
* Scan for Ledger Bluetooth devices.
|
|
261
145
|
* On this web implementation, it only emits ONE device, the one that was selected in the UI (if any).
|
|
262
146
|
*/
|
|
263
|
-
|
|
147
|
+
static listen(observer) {
|
|
264
148
|
(0, logs_1.log)("ble-verbose", "listen...");
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
bluetooth.requestDevice(requestDeviceParam()).then(
|
|
149
|
+
let unsubscribed;
|
|
150
|
+
const bluetooth = requiresBluetooth();
|
|
151
|
+
bluetooth.requestDevice(requestDeviceParam()).then((device) => {
|
|
268
152
|
if (!unsubscribed) {
|
|
269
153
|
observer.next({
|
|
270
154
|
type: "add",
|
|
271
|
-
descriptor: device
|
|
155
|
+
descriptor: device,
|
|
272
156
|
});
|
|
273
157
|
observer.complete();
|
|
274
158
|
}
|
|
275
|
-
},
|
|
159
|
+
}, (error) => {
|
|
276
160
|
observer.error(new errors_1.TransportOpenUserCancelled(error.message));
|
|
277
161
|
});
|
|
278
162
|
function unsubscribe() {
|
|
279
163
|
unsubscribed = true;
|
|
280
164
|
}
|
|
281
165
|
return {
|
|
282
|
-
unsubscribe
|
|
166
|
+
unsubscribe,
|
|
283
167
|
};
|
|
284
|
-
}
|
|
168
|
+
}
|
|
285
169
|
/**
|
|
286
170
|
* open a bluetooth device.
|
|
287
171
|
*/
|
|
288
|
-
|
|
289
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
290
|
-
return
|
|
291
|
-
return [2 /*return*/, open(deviceOrId, true)];
|
|
292
|
-
});
|
|
172
|
+
static open(deviceOrId) {
|
|
173
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
174
|
+
return open(deviceOrId, true);
|
|
293
175
|
});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
(0, logs_1.log)("ble-error", "inferMTU got " + String(e_1));
|
|
318
|
-
this.device.gatt.disconnect();
|
|
319
|
-
throw e_1;
|
|
320
|
-
case 3: return [2 /*return*/];
|
|
321
|
-
}
|
|
322
|
-
});
|
|
323
|
-
}); })];
|
|
324
|
-
case 1:
|
|
325
|
-
_b.sent();
|
|
326
|
-
if (mtu > 23) {
|
|
327
|
-
mtuSize = mtu - 3;
|
|
328
|
-
(0, logs_1.log)("ble-verbose", "BleTransport(".concat(String(this.id), ") mtu set to ").concat(String(mtuSize)));
|
|
329
|
-
this.mtuSize = mtuSize;
|
|
330
|
-
}
|
|
331
|
-
return [2 /*return*/, this.mtuSize];
|
|
176
|
+
}
|
|
177
|
+
constructor(device, writeCharacteristic, notifyObservable, deviceModel) {
|
|
178
|
+
super();
|
|
179
|
+
this.mtuSize = 20;
|
|
180
|
+
this.notYetDisconnected = true;
|
|
181
|
+
this.write = (buffer) => __awaiter(this, void 0, void 0, function* () {
|
|
182
|
+
(0, logs_1.log)("ble-frame", "=> " + buffer.toString("hex"));
|
|
183
|
+
yield this.writeCharacteristic.writeValue(buffer);
|
|
184
|
+
});
|
|
185
|
+
this.id = device.id;
|
|
186
|
+
this.device = device;
|
|
187
|
+
this.writeCharacteristic = writeCharacteristic;
|
|
188
|
+
this.notifyObservable = notifyObservable;
|
|
189
|
+
this.deviceModel = deviceModel;
|
|
190
|
+
(0, logs_1.log)("ble-verbose", `BleTransport(${String(this.id)}) new instance`);
|
|
191
|
+
}
|
|
192
|
+
inferMTU() {
|
|
193
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
194
|
+
let mtu = 23;
|
|
195
|
+
yield this.exchangeAtomicImpl(() => __awaiter(this, void 0, void 0, function* () {
|
|
196
|
+
try {
|
|
197
|
+
mtu =
|
|
198
|
+
(yield (0, rxjs_1.merge)(this.notifyObservable.pipe((0, operators_1.first)((buffer) => buffer.readUInt8(0) === 0x08), (0, operators_1.map)((buffer) => buffer.readUInt8(5))), (0, rxjs_1.defer)(() => (0, rxjs_1.from)(this.write(Buffer.from([0x08, 0, 0, 0, 0])))).pipe((0, operators_1.ignoreElements)())).toPromise()) + 3;
|
|
332
199
|
}
|
|
333
|
-
|
|
200
|
+
catch (e) {
|
|
201
|
+
(0, logs_1.log)("ble-error", "inferMTU got " + String(e));
|
|
202
|
+
this.device.gatt.disconnect();
|
|
203
|
+
throw e;
|
|
204
|
+
}
|
|
205
|
+
}));
|
|
206
|
+
if (mtu > 23) {
|
|
207
|
+
const mtuSize = mtu - 3;
|
|
208
|
+
(0, logs_1.log)("ble-verbose", `BleTransport(${String(this.id)}) mtu set to ${String(mtuSize)}`);
|
|
209
|
+
this.mtuSize = mtuSize;
|
|
210
|
+
}
|
|
211
|
+
return this.mtuSize;
|
|
334
212
|
});
|
|
335
|
-
}
|
|
213
|
+
}
|
|
336
214
|
/**
|
|
337
215
|
* Exchange with the device using APDU protocol.
|
|
338
216
|
* @param apdu
|
|
339
217
|
* @returns a promise of apdu response
|
|
340
218
|
*/
|
|
341
|
-
|
|
342
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
case 0:
|
|
352
|
-
_b.trys.push([0, 2, , 3]);
|
|
353
|
-
msgIn = apdu.toString("hex");
|
|
354
|
-
(0, logs_1.log)("apdu", "=> ".concat(msgIn));
|
|
355
|
-
return [4 /*yield*/, (0, rxjs_1.merge)(this.notifyObservable.pipe(receiveAPDU_1.receiveAPDU), (0, sendAPDU_1.sendAPDU)(this.write, apdu, this.mtuSize)).toPromise()];
|
|
356
|
-
case 1:
|
|
357
|
-
data = _b.sent();
|
|
358
|
-
msgOut = data.toString("hex");
|
|
359
|
-
(0, logs_1.log)("apdu", "<= ".concat(msgOut));
|
|
360
|
-
return [2 /*return*/, data];
|
|
361
|
-
case 2:
|
|
362
|
-
e_2 = _b.sent();
|
|
363
|
-
(0, logs_1.log)("ble-error", "exchange got " + String(e_2));
|
|
364
|
-
if (this.notYetDisconnected) {
|
|
365
|
-
// in such case we will always disconnect because something is bad.
|
|
366
|
-
this.device.gatt.disconnect();
|
|
367
|
-
}
|
|
368
|
-
throw e_2;
|
|
369
|
-
case 3: return [2 /*return*/];
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
}); })];
|
|
373
|
-
case 1:
|
|
374
|
-
b = _b.sent();
|
|
375
|
-
return [2 /*return*/, b];
|
|
219
|
+
exchange(apdu) {
|
|
220
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
221
|
+
const b = yield this.exchangeAtomicImpl(() => __awaiter(this, void 0, void 0, function* () {
|
|
222
|
+
try {
|
|
223
|
+
const msgIn = apdu.toString("hex");
|
|
224
|
+
(0, logs_1.log)("apdu", `=> ${msgIn}`);
|
|
225
|
+
const data = yield (0, rxjs_1.merge)(this.notifyObservable.pipe(receiveAPDU_1.receiveAPDU), (0, sendAPDU_1.sendAPDU)(this.write, apdu, this.mtuSize)).toPromise();
|
|
226
|
+
const msgOut = data.toString("hex");
|
|
227
|
+
(0, logs_1.log)("apdu", `<= ${msgOut}`);
|
|
228
|
+
return data;
|
|
376
229
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
switch (_b.label) {
|
|
385
|
-
case 0:
|
|
386
|
-
if (!this.exchangeBusyPromise) return [3 /*break*/, 2];
|
|
387
|
-
return [4 /*yield*/, this.exchangeBusyPromise];
|
|
388
|
-
case 1:
|
|
389
|
-
_b.sent();
|
|
390
|
-
_b.label = 2;
|
|
391
|
-
case 2: return [2 /*return*/];
|
|
230
|
+
catch (e) {
|
|
231
|
+
(0, logs_1.log)("ble-error", "exchange got " + String(e));
|
|
232
|
+
if (this.notYetDisconnected) {
|
|
233
|
+
// in such case we will always disconnect because something is bad.
|
|
234
|
+
this.device.gatt.disconnect();
|
|
235
|
+
}
|
|
236
|
+
throw e;
|
|
392
237
|
}
|
|
393
|
-
});
|
|
238
|
+
}));
|
|
239
|
+
return b;
|
|
394
240
|
});
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
.then(function () { return true; }, function () { return false; });
|
|
402
|
-
};
|
|
403
|
-
/**
|
|
404
|
-
* observe event with { available: bool, type: string }
|
|
405
|
-
* (available is generic, type is specific)
|
|
406
|
-
* an event is emit once and then each time it changes
|
|
407
|
-
*/
|
|
408
|
-
BluetoothTransport.observeAvailability = function (observer) {
|
|
409
|
-
return availability().subscribe(observer);
|
|
410
|
-
};
|
|
411
|
-
BluetoothTransport.list = function () { return Promise.resolve([]); };
|
|
412
|
-
/**
|
|
413
|
-
* globally disconnect a bluetooth device by its id.
|
|
414
|
-
*/
|
|
415
|
-
BluetoothTransport.disconnect = function (id) { return __awaiter(void 0, void 0, void 0, function () {
|
|
416
|
-
var transport;
|
|
417
|
-
return __generator(_a, function (_b) {
|
|
418
|
-
(0, logs_1.log)("ble-verbose", "user disconnect(".concat(id, ")"));
|
|
419
|
-
transport = transportsCache[id];
|
|
420
|
-
if (transport) {
|
|
421
|
-
transport.device.gatt.disconnect();
|
|
241
|
+
}
|
|
242
|
+
setScrambleKey() { }
|
|
243
|
+
close() {
|
|
244
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
245
|
+
if (this.exchangeBusyPromise) {
|
|
246
|
+
yield this.exchangeBusyPromise;
|
|
422
247
|
}
|
|
423
|
-
return [2 /*return*/];
|
|
424
248
|
});
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
exports.default = BluetoothTransport;
|
|
252
|
+
_a = BluetoothTransport;
|
|
253
|
+
BluetoothTransport.isSupported = () => Promise.resolve()
|
|
254
|
+
.then(requiresBluetooth)
|
|
255
|
+
.then(() => true, () => false);
|
|
256
|
+
/**
|
|
257
|
+
* observe event with { available: bool, type: string }
|
|
258
|
+
* (available is generic, type is specific)
|
|
259
|
+
* an event is emit once and then each time it changes
|
|
260
|
+
*/
|
|
261
|
+
BluetoothTransport.observeAvailability = (observer) => availability().subscribe(observer);
|
|
262
|
+
BluetoothTransport.list = () => Promise.resolve([]);
|
|
263
|
+
/**
|
|
264
|
+
* globally disconnect a bluetooth device by its id.
|
|
265
|
+
*/
|
|
266
|
+
BluetoothTransport.disconnect = (id) => __awaiter(void 0, void 0, void 0, function* () {
|
|
267
|
+
(0, logs_1.log)("ble-verbose", `user disconnect(${id})`);
|
|
268
|
+
const transport = transportsCache[id];
|
|
269
|
+
if (transport) {
|
|
270
|
+
transport.device.gatt.disconnect();
|
|
271
|
+
}
|
|
272
|
+
});
|
|
429
273
|
//# sourceMappingURL=TransportWebBLE.js.map
|