incyclist-devices 1.4.34 → 1.4.37

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.
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { EventLogger } from "gd-eventlog";
3
- import { BleInterfaceClass, BleDeviceClass, BlePeripheral, BleCharacteristic, BleDeviceProps, ConnectProps } from "./ble";
3
+ import { BleInterfaceClass, BleDeviceClass, BlePeripheral, BleDeviceProps, ConnectProps } from "./ble";
4
4
  interface ConnectState {
5
5
  isConnecting: boolean;
6
6
  isConnected: boolean;
@@ -17,7 +17,7 @@ export declare abstract class BleDevice extends BleDeviceClass {
17
17
  services: string[];
18
18
  ble: BleInterfaceClass;
19
19
  peripheral?: BlePeripheral;
20
- characteristics: BleCharacteristic[];
20
+ characteristics: any[];
21
21
  state?: string;
22
22
  connectState: ConnectState;
23
23
  logger?: EventLogger;
@@ -71,11 +71,14 @@ class BleDevice extends ble_1.BleDeviceClass {
71
71
  return __awaiter(this, void 0, void 0, function* () {
72
72
  const connectPeripheral = (peripheral) => __awaiter(this, void 0, void 0, function* () {
73
73
  this.connectState.isConnecting = true;
74
- try {
75
- yield peripheral.connectAsync();
76
- }
77
- catch (err) {
78
- this.logEvent({ message: 'cannot connect', error: err.message || err });
74
+ const connected = this.ble.findConnected(peripheral);
75
+ if (!connected) {
76
+ try {
77
+ yield peripheral.connectAsync();
78
+ }
79
+ catch (err) {
80
+ this.logEvent({ message: 'cannot connect', error: err.message || err });
81
+ }
79
82
  }
80
83
  this.connectState.isConnecting = false;
81
84
  this.connectState.isConnected = true;
@@ -85,16 +88,24 @@ class BleDevice extends ble_1.BleDeviceClass {
85
88
  this.ble.addConnectedDevice(this);
86
89
  this.peripheral.once('disconnect', () => { this.onDisconnect(); });
87
90
  try {
88
- const { characteristics } = yield peripheral.discoverSomeServicesAndCharacteristicsAsync(this.services || [], []);
89
- characteristics.forEach(c => {
91
+ if (!connected) {
92
+ const { characteristics } = yield peripheral.discoverSomeServicesAndCharacteristicsAsync(this.services || [], []);
93
+ this.characteristics = characteristics;
94
+ }
95
+ else {
96
+ this.characteristics = connected.characteristics;
97
+ }
98
+ this.characteristics.forEach(c => {
90
99
  if (c.properties.find(p => p === 'notify')) {
91
100
  c.on('data', (data, _isNotification) => {
92
101
  this.onData(ble_1.uuid(c.uuid), data);
93
102
  });
94
- c.subscribe((err) => {
95
- if (err)
96
- this.logEvent({ message: 'cannot subscribe', error: err.message || err });
97
- });
103
+ if (!connected) {
104
+ c.subscribe((err) => {
105
+ if (err)
106
+ this.logEvent({ message: 'cannot subscribe', error: err.message || err });
107
+ });
108
+ }
98
109
  }
99
110
  });
100
111
  }
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { EventLogger } from 'gd-eventlog';
3
- import { BleInterfaceClass, ConnectProps, ScanProps, BleDeviceClass, BleBinding } from './ble';
3
+ import { BleInterfaceClass, ConnectProps, ScanProps, BleDeviceClass, BlePeripheral, BleBinding } from './ble';
4
4
  export interface ScanState {
5
5
  isScanning: boolean;
6
6
  timeout?: NodeJS.Timeout;
@@ -53,5 +53,6 @@ export default class BleInterface extends BleInterfaceClass {
53
53
  stopScan(): Promise<boolean>;
54
54
  isScanning(): boolean;
55
55
  addConnectedDevice(device: BleDeviceClass): void;
56
+ findConnected(device: BleDeviceClass | BlePeripheral): BleDeviceClass;
56
57
  removeConnectedDevice(device: BleDeviceClass): void;
57
58
  }
@@ -84,21 +84,26 @@ class BleInterface extends ble_1.BleInterfaceClass {
84
84
  try {
85
85
  if (!this.connectState.isInitSuccess) {
86
86
  const binding = this.getBinding()._bindings;
87
- const binding_init_original = binding.init.bind(binding);
88
- const self = this;
89
- binding.init = function () {
90
- try {
91
- binding_init_original();
92
- self.connectState.isInitSuccess = true;
93
- }
94
- catch (err) {
95
- self.connectState.isInitSuccess = false;
96
- self.connectState.isConnected = false;
97
- self.connectState.isConnecting = false;
98
- self.logEvent({ message: 'connect result: error', error: err.message });
99
- return reject(new Error(err.message));
100
- }
101
- };
87
+ if (binding) {
88
+ const binding_init_original = binding.init.bind(binding);
89
+ const self = this;
90
+ binding.on('error', (err) => { this.getBinding().emit('error', err); });
91
+ binding.init = function () {
92
+ try {
93
+ binding_init_original();
94
+ self.connectState.isInitSuccess = true;
95
+ }
96
+ catch (err) {
97
+ self.connectState.isInitSuccess = false;
98
+ self.connectState.isConnected = false;
99
+ self.connectState.isConnecting = false;
100
+ self.logEvent({ message: 'connect result: error', error: err.message });
101
+ return reject(new Error(err.message));
102
+ }
103
+ };
104
+ }
105
+ else {
106
+ }
102
107
  }
103
108
  const state = this.getBinding().state;
104
109
  if (state === ble_1.BleState.POWERED_ON) {
@@ -278,9 +283,10 @@ class BleInterface extends ble_1.BleInterfaceClass {
278
283
  yield this.connect();
279
284
  }
280
285
  const detectedPeripherals = {};
281
- this.devices = [];
282
- if (scanForDevice)
283
- this.logEvent({ message: 'search device request', device, deviceTypes });
286
+ if (scanForDevice) {
287
+ const { id, address, name } = device;
288
+ this.logEvent({ message: 'search device request', device: { id, address, name }, deviceTypes });
289
+ }
284
290
  else
285
291
  this.logEvent({ message: 'scan start', services });
286
292
  return new Promise((resolve, reject) => {
@@ -289,7 +295,15 @@ class BleInterface extends ble_1.BleInterfaceClass {
289
295
  return reject(new Error('scanning already in progress'));
290
296
  }
291
297
  this.scanState.isScanning = true;
292
- bleBinding.startScanning(services, true, (err) => {
298
+ if (scanForDevice && device instanceof ble_1.BleDeviceClass) {
299
+ const existing = this.devices.find(i => i.device.address === device.address && i.isConnected);
300
+ if (existing) {
301
+ device.peripheral = existing.device.peripheral;
302
+ this.logEvent({ message: 'scan: device already connected', device: device.name, address: device.address });
303
+ return resolve([device]);
304
+ }
305
+ }
306
+ bleBinding.startScanning([], true, (err) => {
293
307
  if (err) {
294
308
  this.logEvent({ message: 'scan result: error', error: err.message });
295
309
  this.scanState.isScanning = false;
@@ -299,6 +313,8 @@ class BleInterface extends ble_1.BleInterfaceClass {
299
313
  if (!peripheral || !peripheral.advertisement)
300
314
  return;
301
315
  if (!detectedPeripherals[peripheral.id]) {
316
+ if (process.env.BLE_DEBUG)
317
+ console.log('discovered', peripheral);
302
318
  detectedPeripherals[peripheral.id] = peripheral;
303
319
  let DeviceClasses;
304
320
  if (scanForDevice && (!deviceTypes || deviceTypes.length === 0)) {
@@ -316,6 +332,8 @@ class BleInterface extends ble_1.BleInterfaceClass {
316
332
  return;
317
333
  const C = DeviceClass;
318
334
  const d = new C({ peripheral });
335
+ if (device.getProfile && device.getProfile() !== d.getProfile())
336
+ return;
319
337
  d.setInterface(this);
320
338
  if (scanForDevice) {
321
339
  if ((device.id && device.id !== '' && d.id === device.id) ||
@@ -325,7 +343,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
325
343
  }
326
344
  else
327
345
  cntFound++;
328
- const existing = this.devices.find(i => i.device.id === d.id);
346
+ const existing = this.devices.find(i => i.device.id === d.id && i.device.getProfile() === d.getProfile());
329
347
  if (cntFound > 0 && !existing) {
330
348
  this.logEvent({ message: 'scan: device found', device: d.name, address: d.address, services: d.services.join(',') });
331
349
  this.devices.push({ device: d, isConnected: false });
@@ -336,6 +354,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
336
354
  clearTimeout(this.scanState.timeout);
337
355
  this.scanState.timeout = null;
338
356
  bleBinding.stopScanning(() => {
357
+ this.getBinding().removeAllListeners('discover');
339
358
  this.scanState.isScanning = false;
340
359
  resolve([d]);
341
360
  });
@@ -346,11 +365,14 @@ class BleInterface extends ble_1.BleInterfaceClass {
346
365
  }
347
366
  });
348
367
  }
368
+ else {
369
+ }
349
370
  });
350
371
  });
351
372
  this.scanState.timeout = setTimeout(() => {
352
373
  this.scanState.timeout = null;
353
374
  this.logEvent({ message: 'scan result: devices found', devices: this.devices.map(i => i.device.name + (!i.device.name || i.device.name === '') ? `addr=${i.device.address}` : '') });
375
+ this.getBinding().removeAllListeners('discover');
354
376
  bleBinding.stopScanning(() => {
355
377
  this.scanState.isScanning = false;
356
378
  resolve(this.devices.map(i => i.device));
@@ -365,6 +387,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
365
387
  }
366
388
  if (!this.getBinding())
367
389
  return Promise.reject(new Error('no binding defined'));
390
+ this.getBinding().removeAllListeners('discover');
368
391
  this.logEvent({ message: 'scan stop request' });
369
392
  return new Promise(resolve => {
370
393
  this.getBinding().stopScanning(() => {
@@ -385,6 +408,12 @@ class BleInterface extends ble_1.BleInterfaceClass {
385
408
  }
386
409
  this.devices.push({ device, isConnected: true });
387
410
  }
411
+ findConnected(device) {
412
+ const connected = this.devices.find(i => i.device.id === device.id && i.isConnected);
413
+ if (connected)
414
+ return connected.device;
415
+ return undefined;
416
+ }
388
417
  removeConnectedDevice(device) {
389
418
  const existigDevice = this.devices.find(i => i.device.id === device.id);
390
419
  if (existigDevice) {
package/lib/ble/ble.d.ts CHANGED
@@ -51,6 +51,7 @@ export declare abstract class BleInterfaceClass extends EventEmitter {
51
51
  abstract isScanning(): boolean;
52
52
  abstract addConnectedDevice(device: BleDeviceClass): void;
53
53
  abstract removeConnectedDevice(device: BleDeviceClass): void;
54
+ abstract findConnected(device: BleDeviceClass | BlePeripheral): BleDeviceClass;
54
55
  getBinding(): BleBinding;
55
56
  setBinding(binding: BleBinding): void;
56
57
  }
package/lib/ble/hrm.d.ts CHANGED
@@ -19,7 +19,7 @@ export default class BleHrmDevice extends BleDevice {
19
19
  constructor(props?: any);
20
20
  getProfile(): string;
21
21
  getServiceUUids(): string[];
22
- parseHrm(data: Buffer): HrmData;
22
+ parseHrm(_data: Uint8Array): HrmData;
23
23
  onData(characteristic: string, data: Buffer): void;
24
24
  write(characteristic: any, data: any): Promise<boolean>;
25
25
  read(characteristic: any): Promise<Buffer>;
package/lib/ble/hrm.js CHANGED
@@ -28,20 +28,20 @@ class BleHrmDevice extends ble_device_1.BleDevice {
28
28
  getServiceUUids() {
29
29
  return BleHrmDevice.services;
30
30
  }
31
- parseHrm(data) {
31
+ parseHrm(_data) {
32
+ const data = Buffer.from(_data);
32
33
  try {
33
- const ab = new Uint8Array(data);
34
- const flags = ab[0];
35
- let offset = 1;
34
+ const flags = data.readUInt8(0);
35
+ let offset = 2;
36
36
  if (flags % 1 === 0) {
37
- this.heartrate = ab[1];
37
+ this.heartrate = data.readUInt8(1);
38
38
  }
39
39
  else {
40
- this.heartrate = ab[1] + ab[2] * 256;
41
- offset = 2;
40
+ this.heartrate = data.readUInt16LE(1);
41
+ offset = 3;
42
42
  }
43
43
  if (flags % 0xF) {
44
- this.rr = (ab[offset + 1] + ab[offset + 2] * 256) / 1024;
44
+ this.rr = (data.readUInt16LE(offset)) / 1024;
45
45
  }
46
46
  }
47
47
  catch (err) {
package/lib/ble/pwr.d.ts CHANGED
@@ -14,7 +14,7 @@ declare type PowerData = {
14
14
  accTorque?: number;
15
15
  time: number;
16
16
  rpm: number;
17
- raw?: Buffer;
17
+ raw?: string;
18
18
  };
19
19
  declare type CrankData = {
20
20
  revolutions?: number;
@@ -39,7 +39,7 @@ export default class BleCyclingPowerDevice extends BleDevice {
39
39
  rpm: number;
40
40
  time: any;
41
41
  };
42
- parsePower(data: Buffer): PowerData;
42
+ parsePower(_data: Uint8Array): PowerData;
43
43
  onData(characteristic: string, data: Buffer): void;
44
44
  write(characteristic: any, data: any): Promise<boolean>;
45
45
  read(characteristic: any): Promise<Buffer>;
package/lib/ble/pwr.js CHANGED
@@ -66,7 +66,8 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
66
66
  this.prevCrankData.cntUpdateMissing = cntUpdateMissing + 1;
67
67
  return { rpm, time: this.timeOffset + c.time };
68
68
  }
69
- parsePower(data) {
69
+ parsePower(_data) {
70
+ const data = Buffer.from(_data);
70
71
  try {
71
72
  let offset = 4;
72
73
  const flags = data.readUInt16LE(0);
@@ -91,7 +92,7 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
91
92
  catch (err) {
92
93
  }
93
94
  const { instantaneousPower, balance, accTorque, rpm, time } = this;
94
- return { instantaneousPower, balance, accTorque, rpm, time, raw: data };
95
+ return { instantaneousPower, balance, accTorque, rpm, time, raw: data.toString('hex') };
95
96
  }
96
97
  onData(characteristic, data) {
97
98
  if (characteristic.toLocaleLowerCase() === '2a63') {
@@ -176,7 +177,7 @@ class PwrAdapter extends Device_1.default {
176
177
  const data = {
177
178
  isPedalling: false,
178
179
  power: 0,
179
- pedalRpm: 0,
180
+ pedalRpm: undefined,
180
181
  speed: 0,
181
182
  heartrate: 0,
182
183
  distanceInternal: 0,
@@ -47,7 +47,7 @@ class PowerMeterCyclingMode extends power_base_1.default {
47
47
  let power = bikeData.power || 0;
48
48
  const slope = prevData.slope || 0;
49
49
  const distanceInternal = prevData.distanceInternal || 0;
50
- if (!bikeData.pedalRpm || bikeData.isPedalling === false) {
50
+ if (bikeData.pedalRpm === 0 || bikeData.isPedalling === false) {
51
51
  power = 0;
52
52
  }
53
53
  const m = this.getWeight();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.4.34",
3
+ "version": "1.4.37",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",