incyclist-devices 1.4.35 → 1.4.38

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,22 +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.on('error', (err) => { this.getBinding().emit('error', err); });
90
- binding.init = function () {
91
- try {
92
- binding_init_original();
93
- self.connectState.isInitSuccess = true;
94
- }
95
- catch (err) {
96
- self.connectState.isInitSuccess = false;
97
- self.connectState.isConnected = false;
98
- self.connectState.isConnecting = false;
99
- self.logEvent({ message: 'connect result: error', error: err.message });
100
- return reject(new Error(err.message));
101
- }
102
- };
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
+ }
103
107
  }
104
108
  const state = this.getBinding().state;
105
109
  if (state === ble_1.BleState.POWERED_ON) {
@@ -279,9 +283,10 @@ class BleInterface extends ble_1.BleInterfaceClass {
279
283
  yield this.connect();
280
284
  }
281
285
  const detectedPeripherals = {};
282
- this.devices = [];
283
- if (scanForDevice)
284
- 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
+ }
285
290
  else
286
291
  this.logEvent({ message: 'scan start', services });
287
292
  return new Promise((resolve, reject) => {
@@ -290,7 +295,15 @@ class BleInterface extends ble_1.BleInterfaceClass {
290
295
  return reject(new Error('scanning already in progress'));
291
296
  }
292
297
  this.scanState.isScanning = true;
293
- 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) => {
294
307
  if (err) {
295
308
  this.logEvent({ message: 'scan result: error', error: err.message });
296
309
  this.scanState.isScanning = false;
@@ -300,6 +313,8 @@ class BleInterface extends ble_1.BleInterfaceClass {
300
313
  if (!peripheral || !peripheral.advertisement)
301
314
  return;
302
315
  if (!detectedPeripherals[peripheral.id]) {
316
+ if (process.env.BLE_DEBUG)
317
+ console.log('discovered', peripheral);
303
318
  detectedPeripherals[peripheral.id] = peripheral;
304
319
  let DeviceClasses;
305
320
  if (scanForDevice && (!deviceTypes || deviceTypes.length === 0)) {
@@ -317,6 +332,8 @@ class BleInterface extends ble_1.BleInterfaceClass {
317
332
  return;
318
333
  const C = DeviceClass;
319
334
  const d = new C({ peripheral });
335
+ if (device && device.getProfile && device.getProfile() !== d.getProfile())
336
+ return;
320
337
  d.setInterface(this);
321
338
  if (scanForDevice) {
322
339
  if ((device.id && device.id !== '' && d.id === device.id) ||
@@ -326,7 +343,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
326
343
  }
327
344
  else
328
345
  cntFound++;
329
- 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());
330
347
  if (cntFound > 0 && !existing) {
331
348
  this.logEvent({ message: 'scan: device found', device: d.name, address: d.address, services: d.services.join(',') });
332
349
  this.devices.push({ device: d, isConnected: false });
@@ -337,6 +354,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
337
354
  clearTimeout(this.scanState.timeout);
338
355
  this.scanState.timeout = null;
339
356
  bleBinding.stopScanning(() => {
357
+ this.getBinding().removeAllListeners('discover');
340
358
  this.scanState.isScanning = false;
341
359
  resolve([d]);
342
360
  });
@@ -347,11 +365,14 @@ class BleInterface extends ble_1.BleInterfaceClass {
347
365
  }
348
366
  });
349
367
  }
368
+ else {
369
+ }
350
370
  });
351
371
  });
352
372
  this.scanState.timeout = setTimeout(() => {
353
373
  this.scanState.timeout = null;
354
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');
355
376
  bleBinding.stopScanning(() => {
356
377
  this.scanState.isScanning = false;
357
378
  resolve(this.devices.map(i => i.device));
@@ -366,6 +387,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
366
387
  }
367
388
  if (!this.getBinding())
368
389
  return Promise.reject(new Error('no binding defined'));
390
+ this.getBinding().removeAllListeners('discover');
369
391
  this.logEvent({ message: 'scan stop request' });
370
392
  return new Promise(resolve => {
371
393
  this.getBinding().stopScanning(() => {
@@ -386,6 +408,12 @@ class BleInterface extends ble_1.BleInterfaceClass {
386
408
  }
387
409
  this.devices.push({ device, isConnected: true });
388
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
+ }
389
417
  removeConnectedDevice(device) {
390
418
  const existigDevice = this.devices.find(i => i.device.id === device.id);
391
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.35",
3
+ "version": "1.4.38",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",