incyclist-devices 2.3.0-beta.19 → 2.3.0-beta.20

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.
Files changed (43) hide show
  1. package/README.MD +55 -0
  2. package/lib/ble/adapter-factory.d.ts +24 -20
  3. package/lib/ble/adapter-factory.js +36 -13
  4. package/lib/ble/base/comms.d.ts +74 -2
  5. package/lib/ble/base/comms.js +596 -3
  6. package/lib/ble/ble-interface.d.ts +4 -7
  7. package/lib/ble/ble-interface.js +2 -16
  8. package/lib/ble/ble-peripheral.d.ts +0 -1
  9. package/lib/ble/ble-peripheral.js +11 -7
  10. package/lib/ble/characteristics/csc/features.d.ts +10 -0
  11. package/lib/ble/characteristics/csc/features.js +19 -0
  12. package/lib/ble/characteristics/csc/measurement.d.ts +33 -0
  13. package/lib/ble/characteristics/csc/measurement.js +109 -0
  14. package/lib/ble/characteristics/types.d.ts +6 -0
  15. package/lib/ble/characteristics/types.js +2 -0
  16. package/lib/ble/consts.d.ts +1 -0
  17. package/lib/ble/consts.js +2 -1
  18. package/lib/ble/cp/comm.d.ts +1 -1
  19. package/lib/ble/cp/comm.js +2 -2
  20. package/lib/ble/csc/adapter.d.ts +17 -0
  21. package/lib/ble/csc/adapter.js +66 -0
  22. package/lib/ble/csc/index.d.ts +3 -0
  23. package/lib/ble/csc/index.js +19 -0
  24. package/lib/ble/csc/sensor.d.ts +21 -0
  25. package/lib/ble/csc/sensor.js +64 -0
  26. package/lib/ble/csc/types.d.ts +6 -0
  27. package/lib/ble/csc/types.js +2 -0
  28. package/lib/ble/elite/comms.d.ts +1 -1
  29. package/lib/ble/elite/comms.js +2 -2
  30. package/lib/ble/fm/comms.d.ts +1 -1
  31. package/lib/ble/fm/comms.js +3 -3
  32. package/lib/ble/hr/comm.d.ts +1 -1
  33. package/lib/ble/hr/comm.js +2 -2
  34. package/lib/ble/index.js +2 -0
  35. package/lib/ble/tacx/comms.d.ts +1 -1
  36. package/lib/ble/tacx/comms.js +2 -2
  37. package/lib/ble/tacx/sensor.js +1 -1
  38. package/lib/ble/types.d.ts +1 -1
  39. package/lib/ble/utils.d.ts +1 -0
  40. package/lib/ble/utils.js +5 -1
  41. package/lib/ble/wahoo/comms.d.ts +1 -1
  42. package/lib/ble/wahoo/comms.js +2 -2
  43. package/package.json +1 -1
@@ -1,6 +1,599 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
2
14
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BleSensor = void 0;
4
- class BleSensor {
15
+ exports.BleComms = void 0;
16
+ const events_1 = __importDefault(require("events"));
17
+ const gd_eventlog_1 = require("gd-eventlog");
18
+ const utils_1 = require("../../utils/utils");
19
+ const ble_interface_1 = __importDefault(require("../ble-interface"));
20
+ const utils_2 = require("../utils");
21
+ const CONNECT_WAIT_TIMEOUT = 10000;
22
+ const BLE_TIMEOUT = 1000;
23
+ class BleComms extends events_1.default {
24
+ constructor(props) {
25
+ super();
26
+ this.characteristics = [];
27
+ this.deviceInfo = {};
28
+ this.connectState = { isConnecting: false, isConnected: false, isDisconnecting: false };
29
+ this.id = props.id;
30
+ this.address = props.address;
31
+ this.name = props.name;
32
+ this.services = props.services;
33
+ this.ble = ble_interface_1.default.getInstance();
34
+ this.characteristics = [];
35
+ this.subscribedCharacteristics = [];
36
+ this.isInitialized = false;
37
+ this.writeQueue = [];
38
+ this.workerIv = null;
39
+ this.prevMessages = [];
40
+ this.paused = false;
41
+ if (props.peripheral) {
42
+ const { id, address, advertisement, state } = props.peripheral;
43
+ this.peripheral = props.peripheral;
44
+ this.id = id;
45
+ this.address = address;
46
+ this.name = advertisement.localName;
47
+ this.services = advertisement.serviceUuids;
48
+ this.state = state;
49
+ }
50
+ if (props.logger) {
51
+ this.logger = props.logger;
52
+ }
53
+ else if (props.log !== false) {
54
+ this.logger = new gd_eventlog_1.EventLogger('BleDevice');
55
+ }
56
+ }
57
+ getConnectState() {
58
+ return this.connectState;
59
+ }
60
+ isConnected() {
61
+ return this.connectState.isConnected;
62
+ }
63
+ pause() {
64
+ this.ble.pauseLogging();
65
+ this.paused = true;
66
+ }
67
+ resume() {
68
+ this.paused = false;
69
+ this.ble.resumeLogging();
70
+ }
71
+ getServiceUUids() {
72
+ throw new Error("Method not implemented.");
73
+ }
74
+ getProfile() {
75
+ throw new Error("Method not implemented.");
76
+ }
77
+ getProtocol() {
78
+ throw new Error("Method not implemented.");
79
+ }
80
+ getSettings() {
81
+ const { id, address, name } = this;
82
+ return { id, name, address, interface: 'ble', protocol: this.getProtocol() };
83
+ }
84
+ getServices() {
85
+ return this.services;
86
+ }
87
+ logEvent(event) {
88
+ if (this.paused)
89
+ return;
90
+ if (this.logger) {
91
+ this.logger.logEvent(event);
92
+ }
93
+ const w = global.window;
94
+ if ((w === null || w === void 0 ? void 0 : w.DEVICE_DEBUG) || process.env.BLE_DEBUG) {
95
+ console.log('~~~ BLE', event);
96
+ }
97
+ }
98
+ setLogger(logger) {
99
+ this.logger = logger;
100
+ }
101
+ setInterface(ble) {
102
+ this.ble = ble;
103
+ }
104
+ static isMatching(characteristics) {
105
+ return true;
106
+ }
107
+ reset() {
108
+ if (this.connectState.isConnecting)
109
+ this.ble.stopConnectSensor();
110
+ }
111
+ cleanupListeners() {
112
+ if (this.characteristics === undefined) {
113
+ this.characteristics = [];
114
+ }
115
+ else {
116
+ if (this.peripheral) {
117
+ const connector = this.ble.peripheralCache.getConnector(this.peripheral);
118
+ this.characteristics.forEach(c => {
119
+ connector.removeAllListeners((0, utils_2.uuid)(c.uuid));
120
+ });
121
+ }
122
+ else {
123
+ this.characteristics = [];
124
+ }
125
+ }
126
+ }
127
+ onDisconnect() {
128
+ return __awaiter(this, void 0, void 0, function* () {
129
+ this.logEvent({ message: 'device disconnected', address: this.address, profile: this.getProfile() });
130
+ this.state = "disconnected";
131
+ const wasConnecting = this.connectState.isConnecting;
132
+ this.connectState.isConnecting = false;
133
+ this.connectState.isConnected = false;
134
+ if (!this.connectState.isDisconnecting) {
135
+ this.peripheral.state = 'disconnected';
136
+ this.cleanupListeners();
137
+ this.subscribedCharacteristics = [];
138
+ this.ble.onDisconnect(this.peripheral);
139
+ if (wasConnecting) {
140
+ this.emit('connection-failed');
141
+ }
142
+ else {
143
+ this.connect({ reconnect: true });
144
+ }
145
+ }
146
+ });
147
+ }
148
+ waitForConnectFinished(timeout) {
149
+ const waitStart = Date.now();
150
+ const waitTimeout = waitStart + timeout;
151
+ return new Promise((resolve, reject) => {
152
+ const waitIv = setInterval(() => {
153
+ try {
154
+ if (this.connectState.isConnecting && Date.now() > waitTimeout) {
155
+ clearInterval(waitIv);
156
+ return reject(new Error('connection already in progress'));
157
+ }
158
+ if (!this.connectState.isConnecting) {
159
+ clearInterval(waitIv);
160
+ return resolve(true);
161
+ }
162
+ }
163
+ catch (err) {
164
+ this.logEvent({ message: 'error', fn: '', error: err.message, stack: err.stack });
165
+ }
166
+ }, 100);
167
+ });
168
+ }
169
+ hasService(serviceUuid) {
170
+ return this.services && this.services.find(s => s === serviceUuid || (0, utils_2.uuid)(serviceUuid)) !== undefined;
171
+ }
172
+ init() {
173
+ return __awaiter(this, void 0, void 0, function* () {
174
+ return yield this.initDevice();
175
+ });
176
+ }
177
+ initDevice() {
178
+ this.logEvent({ message: 'get device info' });
179
+ return this.getDeviceInfo().then((info) => {
180
+ this.emit('deviceInfo', info);
181
+ this.logEvent(Object.assign({ message: 'device init done' }, info));
182
+ this.isInitialized = true;
183
+ return true;
184
+ });
185
+ }
186
+ connectPeripheral(peripheral) {
187
+ return __awaiter(this, void 0, void 0, function* () {
188
+ this.connectState.isConnecting = true;
189
+ let disconnectSignalled = false;
190
+ return new Promise((done) => __awaiter(this, void 0, void 0, function* () {
191
+ try {
192
+ const connector = this.ble.peripheralCache.getConnector(peripheral);
193
+ const disconnectHandler = () => {
194
+ this.logEvent({ message: 'device disconnected', address: this.address, profile: this.getProfile() });
195
+ this.state = "disconnected";
196
+ disconnectSignalled = true;
197
+ this.cleanupListeners();
198
+ this.subscribedCharacteristics = [];
199
+ this.connectState.isConnecting = false;
200
+ this.connectState.isConnected = false;
201
+ this.ble.onDisconnect(this.peripheral);
202
+ done(false);
203
+ };
204
+ connector.removeAllListeners('disconnect');
205
+ connector.once('disconnect', disconnectHandler);
206
+ yield connector.connect();
207
+ if (disconnectSignalled)
208
+ return;
209
+ const initialized = yield connector.initialize();
210
+ if (!initialized || disconnectSignalled)
211
+ return done(false);
212
+ yield this.subscribeAll(connector);
213
+ if (disconnectSignalled)
214
+ return done(false);
215
+ this.connectState.isConnected = true;
216
+ this.state = "connected";
217
+ this.emit('connected');
218
+ connector.removeAllListeners('disconnect');
219
+ connector.on('disconnect', this.onDisconnect.bind(this));
220
+ const success = yield this.init();
221
+ done(success);
222
+ return;
223
+ }
224
+ catch (err) {
225
+ this.logEvent({ message: 'Error', fn: 'connectPeripheral()', error: err.message, stack: err.stack });
226
+ }
227
+ this.connectState.isConnecting = false;
228
+ if (disconnectSignalled)
229
+ return;
230
+ done(true);
231
+ }));
232
+ });
233
+ }
234
+ subscribeMultiple(characteristics, conn) {
235
+ this.logEvent({ message: 'subscribe', characteristics });
236
+ return new Promise(resolve => {
237
+ try {
238
+ const connector = conn || this.ble.peripheralCache.getConnector(this.peripheral);
239
+ const subscribeSingle = (c) => {
240
+ connector.removeAllListeners(c);
241
+ connector.on(c, (uuid, data) => {
242
+ this.onData(uuid, data);
243
+ });
244
+ return connector.subscribe(c).then(res => {
245
+ this.subscribedCharacteristics.push(c);
246
+ return res;
247
+ }).catch(err => {
248
+ this.logEvent({ message: 'subscription failed', characteristic: c, error: err.message });
249
+ });
250
+ };
251
+ const promises = characteristics
252
+ .filter(c => {
253
+ if (this.characteristics) {
254
+ const existing = this.characteristics.find(rc => rc.uuid === c || (0, utils_2.uuid)(rc.uuid) === c);
255
+ if (!existing)
256
+ return false;
257
+ }
258
+ const isAlreadySubscribed = connector.isSubscribed(c);
259
+ return !isAlreadySubscribed;
260
+ })
261
+ .map(c => subscribeSingle(c));
262
+ Promise.all(promises).then(() => resolve());
263
+ }
264
+ catch (err) {
265
+ this.logEvent({ message: 'Error', fn: 'subscribeMultiple()', error: err.message, stack: err.stack });
266
+ }
267
+ });
268
+ }
269
+ subscribeAll(conn) {
270
+ return __awaiter(this, void 0, void 0, function* () {
271
+ try {
272
+ const connector = conn || this.ble.peripheralCache.getConnector(this.peripheral);
273
+ const subscribed = yield connector.subscribeAll((uuid, data) => { this.onData(uuid, data); });
274
+ subscribed.forEach(c => this.subscribedCharacteristics.push(c));
275
+ }
276
+ catch (err) {
277
+ this.logEvent({ message: 'Error', fn: 'subscribeAll()', error: err.message, stack: err.stack });
278
+ }
279
+ });
280
+ }
281
+ unsubscribeAll(conn) {
282
+ const connector = conn || this.ble.peripheralCache.getConnector(this.peripheral);
283
+ connector.unsubscribeAll();
284
+ }
285
+ connect(props) {
286
+ return __awaiter(this, void 0, void 0, function* () {
287
+ this.ble.resumeLogging();
288
+ if (!this.ble.isConnected()) {
289
+ try {
290
+ yield this.ble.connect();
291
+ if (!this.ble.isConnected())
292
+ return false;
293
+ }
294
+ catch (err) {
295
+ return false;
296
+ }
297
+ }
298
+ yield (0, utils_1.sleep)(Math.random() * 100);
299
+ yield this.ble.waitForSensorConnectionFinish();
300
+ this.ble.startConnectSensor();
301
+ const { reconnect } = props || {};
302
+ try {
303
+ this.logEvent({ message: reconnect ? 'reconnect' : 'connect', name: this.name, id: this.id, address: this.peripheral ? this.peripheral.address : this.address, state: this.connectState });
304
+ if (!reconnect && this.connectState.isConnecting) {
305
+ yield this.waitForConnectFinished(CONNECT_WAIT_TIMEOUT);
306
+ }
307
+ if (this.connectState.isConnected) {
308
+ try {
309
+ yield this.subscribeAll();
310
+ yield this.init();
311
+ }
312
+ catch (err) {
313
+ this.logEvent({ message: 'cannot reconnect', error: err.message || err });
314
+ this.ble.stopConnectSensor();
315
+ return false;
316
+ }
317
+ this.ble.stopConnectSensor();
318
+ return true;
319
+ }
320
+ this.connectState.isConnecting = true;
321
+ if (!this.peripheral) {
322
+ const { id, name, address } = this;
323
+ try {
324
+ this.peripheral = this.ble.peripheralCache.getPeripheral({ id, name, address });
325
+ const connector = this.ble.peripheralCache.getConnector(this.peripheral);
326
+ if (!connector) {
327
+ }
328
+ }
329
+ catch (err) {
330
+ this.logEvent({ message: 'error', fn: 'connect()', error: err.message, stack: err.stack });
331
+ }
332
+ }
333
+ if (this.peripheral) {
334
+ const { id, address, advertisement } = this.peripheral;
335
+ const name = advertisement === null || advertisement === void 0 ? void 0 : advertisement.localName;
336
+ this.logEvent({ message: 'connect requested', mode: 'peripheral', device: { id, name, address: address } });
337
+ const connected = yield this.connectPeripheral(this.peripheral);
338
+ this.logEvent({ message: 'connect result: ', connected, mode: 'peripheral', device: { id, name, address } });
339
+ this.connectState.isConnecting = false;
340
+ this.connectState.isConnected = connected;
341
+ this.ble.stopConnectSensor();
342
+ return connected;
343
+ }
344
+ else {
345
+ const { id, name, address } = this;
346
+ let error;
347
+ if (this.address || this.id || this.name) {
348
+ this.logEvent({ message: 'connect requested', mode: 'device', device: { id, name, address } });
349
+ try {
350
+ if (this.ble.isScanning()) {
351
+ yield this.ble.stopScan();
352
+ }
353
+ const peripheral = yield this.ble.scanForDevice(this, {});
354
+ if (peripheral) {
355
+ this.peripheral = peripheral;
356
+ const connected = yield this.connectPeripheral(this.peripheral);
357
+ this.logEvent({ message: 'connect result: ', connected, mode: 'device', device: { id, name, address } });
358
+ this.connectState.isConnecting = false;
359
+ this.connectState.isConnected = connected;
360
+ this.ble.stopConnectSensor();
361
+ return connected;
362
+ }
363
+ }
364
+ catch (err) {
365
+ error = err;
366
+ }
367
+ }
368
+ this.logEvent({ message: 'connect result: failure', mode: 'device', device: { id, name, address }, error: error.message });
369
+ this.connectState.isConnecting = false;
370
+ this.connectState.isConnected = false;
371
+ this.ble.stopConnectSensor();
372
+ return false;
373
+ }
374
+ }
375
+ catch (err) {
376
+ this.connectState.isConnecting = false;
377
+ this.connectState.isConnected = false;
378
+ this.logEvent({ message: 'connect result: error', error: err.message, stack: err.stack });
379
+ this.ble.stopConnectSensor();
380
+ return false;
381
+ }
382
+ });
383
+ }
384
+ disconnect() {
385
+ return __awaiter(this, void 0, void 0, function* () {
386
+ const { id, name, address } = this;
387
+ this.logEvent({ message: 'disconnect requested', device: { id, name, address } });
388
+ this.ble.pauseLogging();
389
+ this.connectState.isDisconnecting = true;
390
+ if (this.workerIv) {
391
+ this.stopWorker();
392
+ }
393
+ if (!this.connectState.isConnecting && !this.connectState.isConnected) {
394
+ this.connectState.isDisconnecting = false;
395
+ this.connectState.isConnecting = false;
396
+ this.connectState.isConnected = false;
397
+ this.logEvent({ message: 'disconnect result: success', device: { id, name, address } });
398
+ return true;
399
+ }
400
+ if (this.connectState.isConnecting) {
401
+ this.cleanupListeners();
402
+ setTimeout(() => { this.connectState.isDisconnecting = false; }, 1000);
403
+ this.logEvent({ message: 'disconnect result: unclear - connect ongoing', device: { id, name, address } });
404
+ this.connectState.isConnecting = false;
405
+ this.connectState.isConnected = false;
406
+ return true;
407
+ }
408
+ if (this.connectState.isConnected) {
409
+ this.cleanupListeners();
410
+ this.unsubscribeAll();
411
+ this.logEvent({ message: 'disconnect result: success', device: { id, name, address } });
412
+ this.connectState.isDisconnecting = false;
413
+ this.connectState.isConnecting = false;
414
+ this.connectState.isConnected = false;
415
+ return true;
416
+ }
417
+ });
418
+ }
419
+ checkForDuplicate(characteristic, data) {
420
+ const prev = this.prevMessages.find(i => i.uuid === characteristic);
421
+ if (prev) {
422
+ if (prev.data === data.toString('hex') && prev.timestamp > Date.now() - 500) {
423
+ prev.timestamp = Date.now();
424
+ return true;
425
+ }
426
+ else {
427
+ prev.data = data.toString('hex');
428
+ prev.timestamp = Date.now();
429
+ }
430
+ }
431
+ else {
432
+ this.prevMessages.push({ uuid: characteristic, timestamp: Date.now(), data: data.toString('hex') });
433
+ }
434
+ return false;
435
+ }
436
+ onData(characteristic, _data) {
437
+ const data = Buffer.from(_data);
438
+ const isDuplicate = this.checkForDuplicate(characteristic, data);
439
+ if (isDuplicate) {
440
+ return false;
441
+ }
442
+ this.logEvent({ message: 'got data', characteristic, data: data.toString('hex'), writeQueue: this.writeQueue.length });
443
+ if (this.writeQueue.length > 0) {
444
+ const writeIdx = this.writeQueue.findIndex(i => (0, utils_2.matches)(i.uuid, characteristic));
445
+ if (writeIdx !== -1) {
446
+ const writeItem = this.writeQueue[writeIdx];
447
+ this.writeQueue.splice(writeIdx, 1);
448
+ if (writeItem.resolve)
449
+ writeItem.resolve(data);
450
+ return false;
451
+ }
452
+ }
453
+ return true;
454
+ }
455
+ timeoutCheck() {
456
+ const now = Date.now();
457
+ const updatedQueue = [];
458
+ let hasTimeout = false;
459
+ this.writeQueue.forEach(writeItem => {
460
+ if (writeItem.timeout && writeItem.timeout < now) {
461
+ if (writeItem.reject) {
462
+ hasTimeout = true;
463
+ writeItem.reject(new Error('timeout'));
464
+ }
465
+ }
466
+ else {
467
+ updatedQueue.push(writeItem);
468
+ }
469
+ });
470
+ if (hasTimeout)
471
+ this.writeQueue = updatedQueue;
472
+ }
473
+ startWorker() {
474
+ if (this.workerIv)
475
+ return;
476
+ this.workerIv = setInterval(() => { this.timeoutCheck(); }, 100);
477
+ }
478
+ stopWorker() {
479
+ if (!this.workerIv)
480
+ return;
481
+ clearInterval(this.workerIv);
482
+ this.workerIv = null;
483
+ }
484
+ write(characteristicUuid, data, props) {
485
+ return __awaiter(this, void 0, void 0, function* () {
486
+ if (!this.isConnected())
487
+ throw new Error('not connected');
488
+ try {
489
+ const { withoutResponse, timeout } = props || {};
490
+ let fireAndForget = withoutResponse;
491
+ const connector = this.ble.peripheralCache.getConnector(this.peripheral);
492
+ const isAlreadySubscribed = connector.isSubscribed(characteristicUuid);
493
+ if (!withoutResponse && !this.workerIv) {
494
+ this.startWorker();
495
+ }
496
+ if (!withoutResponse && !isAlreadySubscribed) {
497
+ const connector = this.ble.peripheralCache.getConnector(this.peripheral);
498
+ connector.removeAllListeners(characteristicUuid);
499
+ connector.on(characteristicUuid, (uuid, data) => {
500
+ this.onData(uuid, data);
501
+ });
502
+ this.logEvent({ message: 'write:subscribing ', characteristic: characteristicUuid });
503
+ try {
504
+ yield connector.subscribe(characteristicUuid);
505
+ this.subscribedCharacteristics.push(characteristicUuid);
506
+ }
507
+ catch (err) {
508
+ this.logEvent({ message: 'write:subscribing failed', characteristic: characteristicUuid, error: err.message });
509
+ fireAndForget = true;
510
+ }
511
+ }
512
+ return new Promise((resolve, reject) => {
513
+ const characteristic = this.characteristics.find(c => c.uuid === characteristicUuid || (0, utils_2.uuid)(c.uuid) === characteristicUuid);
514
+ if (!characteristic) {
515
+ this.logEvent({ message: 'write: Characteristic not found', characteristicUuid, characteristics: this.characteristics.map(c => c.uuid) });
516
+ reject(new Error(`Characteristic not found`));
517
+ return;
518
+ }
519
+ if (fireAndForget) {
520
+ this.logEvent({ message: 'writing', data: data.toString('hex'), withoutResponse: 'true' });
521
+ characteristic.write(data, true);
522
+ resolve(new ArrayBuffer(0));
523
+ return;
524
+ }
525
+ else {
526
+ const writeId = this.writeQueue.length;
527
+ let messageDeleted = false;
528
+ const writeTimeout = timeout !== undefined ? timeout : BLE_TIMEOUT;
529
+ this.writeQueue.push({ uuid: characteristicUuid.toLocaleLowerCase(), data, timeout: Date.now() + writeTimeout, resolve, reject });
530
+ const to = setTimeout(() => {
531
+ if (this.writeQueue.length > writeId && !messageDeleted)
532
+ this.writeQueue.splice(writeId, 1);
533
+ this.logEvent({ message: 'writing response', err: 'timeout' });
534
+ reject(new Error('timeout'));
535
+ }, 5000);
536
+ this.logEvent({ message: 'writing' });
537
+ characteristic.write(data, withoutResponse, (err) => {
538
+ clearTimeout(to);
539
+ this.logEvent({ message: 'writing response', err });
540
+ if (err) {
541
+ this.writeQueue.splice(writeId, 1);
542
+ messageDeleted = true;
543
+ reject(err);
544
+ }
545
+ });
546
+ }
547
+ });
548
+ }
549
+ catch (err) {
550
+ this.logEvent({ message: 'error', fn: 'write', error: err.message || err, stack: err.stack });
551
+ }
552
+ });
553
+ }
554
+ read(characteristicUuid) {
555
+ return new Promise((resolve, reject) => {
556
+ if (!this.isConnected())
557
+ return reject(new Error('not connected'));
558
+ const characteristic = this.characteristics.find(c => c.uuid === characteristicUuid || (0, utils_2.uuid)(c.uuid) === characteristicUuid);
559
+ if (!characteristic) {
560
+ this.logEvent({ message: 'read: Characteristic not found', characteristicUuid, characteristics: this.characteristics.map(c => c.uuid) });
561
+ reject(new Error('Characteristic not found'));
562
+ return;
563
+ }
564
+ characteristic.read((err, data) => {
565
+ if (err && data instanceof Error)
566
+ reject(err);
567
+ else if (data instanceof Error)
568
+ reject(data);
569
+ else
570
+ resolve(data);
571
+ });
572
+ });
573
+ }
574
+ getDeviceInfo() {
575
+ return __awaiter(this, void 0, void 0, function* () {
576
+ const info = this.deviceInfo;
577
+ const readValue = (c) => __awaiter(this, void 0, void 0, function* () {
578
+ try {
579
+ const b = yield this.read(c);
580
+ const buffer = b ? Buffer.from(b) : undefined;
581
+ return buffer ? buffer.toString() : undefined;
582
+ }
583
+ catch (_a) {
584
+ return undefined;
585
+ }
586
+ });
587
+ info.model = info.model || (yield readValue('2a24'));
588
+ info.serialNo = info.serialNo || (yield readValue('2a25'));
589
+ info.fwRevision = info.fwRevision || (yield readValue('2a26'));
590
+ info.hwRevision = info.hwRevision || (yield readValue('2a27'));
591
+ info.swRevision = info.swRevision || (yield readValue('2a28'));
592
+ info.manufacturer = info.manufacturer || (yield readValue('2a29'));
593
+ this.deviceInfo = info;
594
+ return info;
595
+ });
596
+ }
5
597
  }
6
- exports.BleSensor = BleSensor;
598
+ exports.BleComms = BleComms;
599
+ BleComms.services = [];
@@ -1,8 +1,8 @@
1
1
  import { EventLogger } from 'gd-eventlog';
2
2
  import BleAdapterFactory from './adapter-factory';
3
- import { BleInterfaceProps, BlePeripheral, BleDeviceSettings, BleProtocol, BleBinding, BleInterfaceState, BleScanProps, BleCharacteristic, IBleInterface } from './types';
3
+ import { BleInterfaceProps, BlePeripheral, BleDeviceSettings, BleProtocol, BleBinding, BleInterfaceState, BleScanProps, BleCharacteristic } from './types';
4
4
  import { BleComms } from './base/comms';
5
- import { IncyclistScanProps } from '../types';
5
+ import { IncyclistInterface, IncyclistScanProps } from '../types';
6
6
  import BlePeripheralCache from './peripheral-cache';
7
7
  import EventEmitter from 'events';
8
8
  export interface ScanState {
@@ -31,7 +31,7 @@ export interface BleDeviceClassInfo {
31
31
  services: string[];
32
32
  id: string;
33
33
  }
34
- export default class BleInterface extends EventEmitter implements IBleInterface {
34
+ export default class BleInterface extends EventEmitter implements IncyclistInterface {
35
35
  scanState: ScanState;
36
36
  connectState: ConnectState;
37
37
  peripheralCache: BlePeripheralCache;
@@ -62,8 +62,7 @@ export default class BleInterface extends EventEmitter implements IBleInterface
62
62
  pauseLogging(debugOnly?: boolean): void;
63
63
  resumeLogging(): void;
64
64
  protected isDebugEnabled(): boolean;
65
- logEvent(event: any): void;
66
- logError(err: Error, fn: string, args?: any): void;
65
+ protected logEvent(event: any): void;
67
66
  protected onStateChange(state: BleInterfaceState): void;
68
67
  protected onError(err: any): void;
69
68
  connect(to?: number): Promise<boolean>;
@@ -80,8 +79,6 @@ export default class BleInterface extends EventEmitter implements IBleInterface
80
79
  }): Promise<any>;
81
80
  scanForDevice(comms: BleComms, props: IncyclistScanProps): Promise<BlePeripheral>;
82
81
  scan(props?: BleScanProps): Promise<BleDeviceSettings[]>;
83
- protected legacyScan(props?: BleScanProps): Promise<BleDeviceSettings[]>;
84
82
  stopScan(): Promise<boolean>;
85
83
  isScanning(): boolean;
86
- getLogger(): EventLogger;
87
84
  }
@@ -118,10 +118,6 @@ class BleInterface extends events_1.default {
118
118
  console.log('~~~ BLE', event);
119
119
  }
120
120
  }
121
- logError(err, fn, args) {
122
- const logInfo = args || {};
123
- this.logEvent(Object.assign(Object.assign({ message: 'Error', fn }, logInfo), { error: err.message, stack: err.stack }));
124
- }
125
121
  onStateChange(state) {
126
122
  if (state !== 'poweredOn') {
127
123
  this.logEvent({ message: 'Ble disconnected', });
@@ -146,12 +142,10 @@ class BleInterface extends events_1.default {
146
142
  this.resumeLogging();
147
143
  const timeout = this.props.timeout || to || 2000;
148
144
  const connect = new Promise((resolve, reject) => {
149
- this.logEvent({ message: 'Ble connect request', timeout });
145
+ this.logEvent({ message: 'Ble connect request' });
150
146
  if (!this.getBinding())
151
147
  return reject(new Error('no binding defined'));
152
- this.connectState.isConnecting = true;
153
148
  this.connectState.timeout = setTimeout(() => {
154
- console.log('connect timeout');
155
149
  this.connectState.isConnected = false;
156
150
  this.connectState.isConnecting = false;
157
151
  this.connectState.timeout = null;
@@ -500,13 +494,8 @@ class BleInterface extends events_1.default {
500
494
  }
501
495
  scan() {
502
496
  return __awaiter(this, arguments, void 0, function* (props = {}) {
503
- return yield this.legacyScan(props);
504
- });
505
- }
506
- legacyScan() {
507
- return __awaiter(this, arguments, void 0, function* (props = {}) {
508
- this.resumeLogging();
509
497
  this.logEvent({ message: 'starting scan ..' });
498
+ this.resumeLogging();
510
499
  const { timeout, protocol, protocols } = props;
511
500
  const requestedProtocols = protocols || [];
512
501
  if (protocol && !requestedProtocols.find(p => p === protocol))
@@ -629,8 +618,5 @@ class BleInterface extends events_1.default {
629
618
  isScanning() {
630
619
  return this.scanState.isScanning === true;
631
620
  }
632
- getLogger() {
633
- return this.logger;
634
- }
635
621
  }
636
622
  exports.default = BleInterface;