incyclist-devices 1.4.66 → 1.4.69

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.
@@ -9,6 +9,7 @@ interface BleDeviceConstructProps extends BleDeviceProps {
9
9
  declare type CommandQueueItem = {
10
10
  uuid: string;
11
11
  data: Buffer;
12
+ timeout: number;
12
13
  resolve: any;
13
14
  reject: any;
14
15
  };
@@ -26,21 +27,27 @@ export declare abstract class BleDevice extends BleDeviceClass {
26
27
  isInitialized: boolean;
27
28
  subscribedCharacteristics: string[];
28
29
  writeQueue: CommandQueueItem[];
30
+ workerIv: NodeJS.Timeout;
29
31
  constructor(props?: BleDeviceConstructProps);
30
32
  logEvent(event: any): void;
31
33
  setLogger(logger: EventLogger): void;
32
34
  setInterface(ble: BleInterfaceClass): void;
35
+ isMatching(characteristics: string[]): boolean;
33
36
  cleanupListeners(): void;
34
37
  onDisconnect(): void;
35
38
  waitForConnectFinished(timeout: any): Promise<unknown>;
36
39
  hasService(serviceUuid: any): boolean;
37
40
  init(): Promise<boolean>;
41
+ initDevice(): Promise<boolean>;
38
42
  connectPeripheral(peripheral: BlePeripheral): Promise<void>;
39
43
  subscribeAll(conn?: BlePeripheralConnector): Promise<void>;
40
44
  connect(props?: ConnectProps): Promise<boolean>;
41
45
  disconnect(): Promise<boolean>;
42
46
  abstract getProfile(): string;
43
47
  onData(characteristic: string, data: Buffer): void;
48
+ timeoutCheck(): void;
49
+ startWorker(): void;
50
+ stopWorker(): void;
44
51
  write(characteristicUuid: string, data: Buffer, withoutResponse?: boolean): Promise<ArrayBuffer>;
45
52
  read(characteristicUuid: string): Promise<Uint8Array>;
46
53
  getDeviceInfo(): Promise<BleDeviceInfo>;
@@ -27,6 +27,7 @@ class BleDevice extends ble_1.BleDeviceClass {
27
27
  this.subscribedCharacteristics = [];
28
28
  this.isInitialized = false;
29
29
  this.writeQueue = [];
30
+ this.workerIv = null;
30
31
  if (props.peripheral) {
31
32
  const { id, address, advertisement, state } = props.peripheral;
32
33
  this.peripheral = props.peripheral;
@@ -57,6 +58,9 @@ class BleDevice extends ble_1.BleDeviceClass {
57
58
  setInterface(ble) {
58
59
  this.ble = ble;
59
60
  }
61
+ isMatching(characteristics) {
62
+ return true;
63
+ }
60
64
  cleanupListeners() {
61
65
  if (this.characteristics === undefined) {
62
66
  this.characteristics = [];
@@ -103,11 +107,15 @@ class BleDevice extends ble_1.BleDeviceClass {
103
107
  return this.services && this.services.find(s => s === serviceUuid || (0, ble_1.uuid)(serviceUuid)) !== undefined;
104
108
  }
105
109
  init() {
106
- if (this.isInitialized)
107
- return Promise.resolve(true);
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ return yield this.initDevice();
112
+ });
113
+ }
114
+ initDevice() {
115
+ this.logEvent({ message: 'get device info' });
108
116
  return this.getDeviceInfo().then(() => {
109
117
  this.emit('deviceInfo', this.deviceInfo);
110
- this.logEvent(Object.assign({ message: 'ftms device init done' }, this.deviceInfo));
118
+ this.logEvent(Object.assign({ message: 'device init done' }, this.deviceInfo));
111
119
  this.isInitialized = true;
112
120
  return true;
113
121
  });
@@ -220,6 +228,9 @@ class BleDevice extends ble_1.BleDeviceClass {
220
228
  const { id, name, address } = this;
221
229
  this.logEvent({ message: 'disconnect requested', device: { id, name, address } });
222
230
  this.connectState.isDisconnecting = true;
231
+ if (this.workerIv) {
232
+ this.stopWorker();
233
+ }
223
234
  if (!this.connectState.isConnecting && !this.connectState.isConnected) {
224
235
  this.connectState.isDisconnecting = false;
225
236
  this.logEvent({ message: 'disconnect result: success', device: { id, name, address } });
@@ -251,11 +262,43 @@ class BleDevice extends ble_1.BleDeviceClass {
251
262
  }
252
263
  }
253
264
  }
265
+ timeoutCheck() {
266
+ const now = Date.now();
267
+ const updatedQueue = [];
268
+ let hasTimeout = false;
269
+ this.writeQueue.forEach(writeItem => {
270
+ if (writeItem.timeout && writeItem.timeout < now) {
271
+ if (writeItem.reject) {
272
+ hasTimeout = true;
273
+ writeItem.reject(new Error('timeout'));
274
+ }
275
+ }
276
+ else {
277
+ updatedQueue.push(writeItem);
278
+ }
279
+ });
280
+ if (hasTimeout)
281
+ this.writeQueue = updatedQueue;
282
+ }
283
+ startWorker() {
284
+ if (this.workerIv)
285
+ return;
286
+ this.workerIv = setInterval(() => { this.timeoutCheck(); }, 100);
287
+ }
288
+ stopWorker() {
289
+ if (!this.workerIv)
290
+ return;
291
+ clearInterval(this.workerIv);
292
+ this.workerIv = null;
293
+ }
254
294
  write(characteristicUuid, data, withoutResponse = false) {
255
295
  return __awaiter(this, void 0, void 0, function* () {
256
296
  try {
257
297
  const connector = this.ble.getConnector(this.peripheral);
258
298
  const isAlreadySubscribed = connector.isSubscribed(characteristicUuid);
299
+ if (!withoutResponse && !this.workerIv) {
300
+ this.startWorker();
301
+ }
259
302
  if (!withoutResponse && !isAlreadySubscribed) {
260
303
  const connector = this.ble.getConnector(this.peripheral);
261
304
  connector.removeAllListeners(characteristicUuid);
@@ -281,9 +324,8 @@ class BleDevice extends ble_1.BleDeviceClass {
281
324
  else {
282
325
  const writeId = this.writeQueue.length;
283
326
  let messageDeleted = false;
284
- this.writeQueue.push({ uuid: characteristicUuid.toLocaleLowerCase(), data, resolve, reject });
327
+ this.writeQueue.push({ uuid: characteristicUuid.toLocaleLowerCase(), data, timeout: Date.now() + 2500, resolve, reject });
285
328
  const to = setTimeout(() => {
286
- console.log('~~~ write timeout');
287
329
  if (this.writeQueue.length > writeId && !messageDeleted)
288
330
  this.writeQueue.splice(writeId, 1);
289
331
  this.logEvent({ message: 'writing response', err: 'timeout' });
@@ -77,6 +77,7 @@ export default class BleInterface extends BleInterfaceClass {
77
77
  getDeviceClasses(peripheral: any, props?: {
78
78
  deviceTypes?: (typeof BleDeviceClass)[];
79
79
  profile?: string;
80
+ services?: string[];
80
81
  }): (typeof BleDeviceClass)[];
81
82
  createDevice(DeviceClass: (typeof BleDeviceClass), peripheral: BlePeripheral, characteristics?: BleCharacteristic[]): any;
82
83
  connectDevice(requested: BleDeviceClass | BleDeviceDescription, timeout?: number): Promise<BleDeviceClass>;
@@ -55,7 +55,9 @@ class BleInterface extends ble_1.BleInterfaceClass {
55
55
  if (this.logger) {
56
56
  this.logger.logEvent(event);
57
57
  }
58
- console.log('~~BLE:', event);
58
+ if (process.env.BLE_DEBUG) {
59
+ console.log('~~BLE:', event);
60
+ }
59
61
  }
60
62
  onStateChange(state) {
61
63
  if (state !== ble_1.BleState.POWERED_ON) {
@@ -334,13 +336,13 @@ class BleInterface extends ble_1.BleInterfaceClass {
334
336
  }
335
337
  getDeviceClasses(peripheral, props = {}) {
336
338
  let DeviceClasses;
337
- const { deviceTypes, profile } = props;
339
+ const { deviceTypes, profile, services = peripheral.advertisement.serviceUuids } = props;
338
340
  if ((!deviceTypes || deviceTypes.length === 0)) {
339
341
  const classes = BleInterface.deviceClasses.map(c => c.Class);
340
- DeviceClasses = this.getDevicesFromServices(classes, peripheral.advertisement.serviceUuids);
342
+ DeviceClasses = this.getDevicesFromServices(classes, services);
341
343
  }
342
344
  else {
343
- DeviceClasses = this.getDevicesFromServices(deviceTypes, peripheral.advertisement.serviceUuids);
345
+ DeviceClasses = this.getDevicesFromServices(deviceTypes, services);
344
346
  }
345
347
  if (profile && DeviceClasses && DeviceClasses.length > 0) {
346
348
  DeviceClasses = DeviceClasses.filter(C => {
@@ -353,15 +355,26 @@ class BleInterface extends ble_1.BleInterfaceClass {
353
355
  return DeviceClasses;
354
356
  }
355
357
  createDevice(DeviceClass, peripheral, characteristics) {
356
- this.logEvent({ message: 'trying to create device', peripheral: peripheral.address, characteristics });
357
- const C = DeviceClass;
358
- const device = new C({ peripheral });
359
- const existingDevice = this.devices.find(i => i.device.id === device.id && i.device.getProfile() === device.getProfile());
360
- if (existingDevice)
361
- return existingDevice;
362
- device.setInterface(this);
363
- device.characteristics = characteristics;
364
- return device;
358
+ try {
359
+ const C = DeviceClass;
360
+ const device = new C({ peripheral });
361
+ const cids = characteristics ? characteristics.map(c => (0, ble_1.uuid)(c.uuid)) : [];
362
+ this.logEvent({ message: 'trying to create device', peripheral: peripheral.address, characteristics: cids, profile: device.getProfile() });
363
+ const existingDevice = this.devices.find(i => i.device.id === device.id && i.device.getProfile() === device.getProfile());
364
+ if (existingDevice)
365
+ return existingDevice;
366
+ device.setInterface(this);
367
+ if (characteristics && device.isMatching(cids)) {
368
+ device.characteristics = characteristics;
369
+ return device;
370
+ }
371
+ else {
372
+ this.logEvent({ message: 'failed to create device', peripheral: peripheral.address, profile: device.getProfile() });
373
+ }
374
+ }
375
+ catch (err) {
376
+ this.logEvent({ message: 'error', fn: '', error: err.message || err, stack: err.stack });
377
+ }
365
378
  }
366
379
  connectDevice(requested, timeout = DEFAULT_SCAN_TIMEOUT + CONNECT_TIMEOUT) {
367
380
  return __awaiter(this, void 0, void 0, function* () {
@@ -551,10 +564,12 @@ class BleInterface extends ble_1.BleInterfaceClass {
551
564
  peripheralsProcessed.push(peripheral.address);
552
565
  const characteristics = yield this.getCharacteristics(peripheral);
553
566
  const connector = this.getConnector(peripheral);
567
+ const connectedServices = connector.getServices();
568
+ const services = connectedServices ? connectedServices.map(cs => cs.uuid) : undefined;
554
569
  const connectedPeripheral = connector.getPeripheral();
555
570
  const { id, name, address, advertisement = {} } = connectedPeripheral;
556
- const DeviceClasses = this.getDeviceClasses(connectedPeripheral, { profile });
557
- this.logEvent({ message: 'BLE scan: device connected', peripheral: { id, name, address, services: advertisement.serviceUuids, classes: DeviceClasses.map(c => c.prototype.constructor.name) } });
571
+ const DeviceClasses = this.getDeviceClasses(connectedPeripheral, { profile, services });
572
+ this.logEvent({ message: 'BLE scan: device connected', peripheral: { id, name, address, services: advertisement.serviceUuids }, services, classes: DeviceClasses.map(c => c.prototype.constructor.name) });
558
573
  let cntFound = 0;
559
574
  DeviceClasses.forEach((DeviceClass) => __awaiter(this, void 0, void 0, function* () {
560
575
  if (!DeviceClass)
@@ -562,6 +577,8 @@ class BleInterface extends ble_1.BleInterfaceClass {
562
577
  if (scanForDevice && cntFound > 0)
563
578
  return;
564
579
  const d = this.createDevice(DeviceClass, peripheral, characteristics);
580
+ if (!d)
581
+ return;
565
582
  yield d.connect();
566
583
  if (scanForDevice) {
567
584
  if ((id && id !== '' && d.id === id) ||
@@ -573,14 +590,14 @@ class BleInterface extends ble_1.BleInterfaceClass {
573
590
  cntFound++;
574
591
  const existing = devicesProcessed.find(device => device.id === d.id && device.getProfile() === d.getProfile());
575
592
  if (!scanForDevice && cntFound > 0 && !existing) {
576
- this.logEvent({ message: `${opStr}: device found`, device: d.name, address: d.address, services: d.services.join(',') });
593
+ this.logEvent({ message: `${opStr}: device found`, device: d.name, profile: d.getProfile(), address: d.address, services: d.services.join(',') });
577
594
  this.addDeviceToCache(d, peripheral.state === 'connected');
578
595
  devicesProcessed.push(d);
579
596
  this.emit('device', d);
580
597
  return;
581
598
  }
582
599
  if (scanForDevice && cntFound > 0) {
583
- this.logEvent({ message: `${opStr}: device found`, device: d.name, address: d.address, services: d.services.join(',') });
600
+ this.logEvent({ message: `${opStr}: device found`, device: d.name, profile: d.getProfile(), address: d.address, services: d.services.join(',') });
584
601
  this.addDeviceToCache(d, peripheral.state === 'connected');
585
602
  devicesProcessed.push(d);
586
603
  this.emit('device', d);
package/lib/ble/fm.d.ts CHANGED
@@ -52,6 +52,8 @@ export default class BleFitnessMachineDevice extends BleDevice {
52
52
  windSpeed: number;
53
53
  wheelSize: number;
54
54
  constructor(props?: any);
55
+ isMatching(characteristics: string[]): boolean;
56
+ subscribeWriteResponse(cuuid: string): Promise<void>;
55
57
  init(): Promise<boolean>;
56
58
  onDisconnect(): void;
57
59
  getProfile(): string;
package/lib/ble/fm.js CHANGED
@@ -21,6 +21,8 @@ const power_meter_1 = __importDefault(require("../modes/power-meter"));
21
21
  const ble_st_mode_1 = __importDefault(require("./ble-st-mode"));
22
22
  const ble_erg_mode_1 = __importDefault(require("./ble-erg-mode"));
23
23
  const FTMS_CP = '2ad9';
24
+ const FTMS_STATUS = '2ada';
25
+ const INDOOR_BIKE_DATA = '2ad2';
24
26
  const cwABike = {
25
27
  race: 0.35,
26
28
  triathlon: 0.29,
@@ -94,35 +96,48 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
94
96
  this.wheelSize = 2100;
95
97
  this.data = {};
96
98
  }
99
+ isMatching(characteristics) {
100
+ if (!characteristics)
101
+ return false;
102
+ const hasStatus = characteristics.find(c => c === FTMS_STATUS) !== undefined;
103
+ const hasCP = characteristics.find(c => c === FTMS_CP) !== undefined;
104
+ const hasIndoorBike = characteristics.find(c => c === INDOOR_BIKE_DATA) !== undefined;
105
+ return hasStatus && hasCP && hasIndoorBike;
106
+ }
107
+ subscribeWriteResponse(cuuid) {
108
+ return __awaiter(this, void 0, void 0, function* () {
109
+ const connector = this.ble.getConnector(this.peripheral);
110
+ const isAlreadySubscribed = connector.isSubscribed(cuuid);
111
+ if (!isAlreadySubscribed) {
112
+ connector.removeAllListeners(cuuid);
113
+ let prev = undefined;
114
+ let prevTS = undefined;
115
+ connector.on(cuuid, (uuid, data) => {
116
+ const message = data.toString('hex');
117
+ if (prevTS && prev && message === prev && Date.now() - prevTS < 500) {
118
+ return;
119
+ }
120
+ prevTS = Date.now();
121
+ prev = message;
122
+ this.onData(uuid, data);
123
+ });
124
+ yield connector.subscribe(cuuid);
125
+ }
126
+ });
127
+ }
97
128
  init() {
98
129
  const _super = Object.create(null, {
99
- init: { get: () => super.init }
130
+ initDevice: { get: () => super.initDevice }
100
131
  });
101
132
  return __awaiter(this, void 0, void 0, function* () {
102
133
  try {
103
- const connector = this.ble.getConnector(this.peripheral);
104
- const isAlreadySubscribed = connector.isSubscribed(FTMS_CP);
105
- if (!isAlreadySubscribed) {
106
- connector.removeAllListeners(FTMS_CP);
107
- let prev = undefined;
108
- let prevTS = undefined;
109
- connector.on(FTMS_CP, (uuid, data) => {
110
- const message = data.toString('hex');
111
- if (prevTS && prev && message === prev && Date.now() - prevTS < 500) {
112
- return;
113
- }
114
- prevTS = Date.now();
115
- prev = message;
116
- this.onData(uuid, data);
117
- });
118
- yield connector.subscribe(FTMS_CP);
119
- }
120
- this.logEvent({ message: 'get device info' });
121
- yield _super.init.call(this);
134
+ yield this.subscribeWriteResponse(FTMS_CP);
135
+ yield _super.initDevice.call(this);
122
136
  yield this.getFitnessMachineFeatures();
123
137
  this.logEvent({ message: 'device info', deviceInfo: this.deviceInfo, features: this.features });
124
138
  }
125
139
  catch (err) {
140
+ this.logEvent({ message: 'error', fn: 'BleFitnessMachineDevice.init()', error: err.message || err, stack: err.stack });
126
141
  return Promise.resolve(false);
127
142
  }
128
143
  });
@@ -295,13 +310,13 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
295
310
  const uuid = characteristic.toLocaleLowerCase();
296
311
  let res = undefined;
297
312
  switch (uuid) {
298
- case '2ad2':
313
+ case INDOOR_BIKE_DATA:
299
314
  res = this.parseIndoorBikeData(data);
300
315
  break;
301
316
  case '2a37':
302
317
  res = this.parseHrm(data);
303
318
  break;
304
- case '2ada':
319
+ case FTMS_STATUS:
305
320
  res = this.parseFitnessMachineStatus(data);
306
321
  break;
307
322
  case '2a63':
@@ -409,9 +424,11 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
409
424
  }
410
425
  setIndoorBikeSimulation(windSpeed, gradient, crr, cw) {
411
426
  return __awaiter(this, void 0, void 0, function* () {
412
- if (!this.hasControl)
413
- return;
414
427
  const hasControl = yield this.requestControl();
428
+ if (!hasControl) {
429
+ this.logEvent({ message: 'setTargetInclination failed', reason: 'control is disabled' });
430
+ return;
431
+ }
415
432
  const data = Buffer.alloc(7);
416
433
  data.writeUInt8(17, 0);
417
434
  data.writeInt16LE(Math.round(windSpeed * 1000), 1);
@@ -469,7 +486,7 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
469
486
  }
470
487
  exports.default = BleFitnessMachineDevice;
471
488
  BleFitnessMachineDevice.services = ['1826'];
472
- BleFitnessMachineDevice.characteristics = ['2acc', '2ad2', '2ad6', '2ad8', '2ad9', '2ada'];
489
+ BleFitnessMachineDevice.characteristics = ['2acc', INDOOR_BIKE_DATA, '2ad6', '2ad8', FTMS_CP, FTMS_STATUS];
473
490
  ble_interface_1.default.register('BleFitnessMachineDevice', 'fm', BleFitnessMachineDevice, BleFitnessMachineDevice.services);
474
491
  class FmAdapter extends Device_1.default {
475
492
  constructor(device, protocol) {
@@ -494,7 +511,8 @@ class FmAdapter extends Device_1.default {
494
511
  return (adapter.getName() === this.getName() && adapter.getProfile() === this.getProfile());
495
512
  }
496
513
  getProfile() {
497
- return 'Smart Trainer';
514
+ const profile = this.device ? this.device.getProfile() : undefined;
515
+ return profile || 'Smart Trainer';
498
516
  }
499
517
  getName() {
500
518
  return `${this.device.name}`;
package/lib/ble/pwr.d.ts CHANGED
@@ -33,6 +33,7 @@ export default class BleCyclingPowerDevice extends BleDevice {
33
33
  currentCrankData: CrankData;
34
34
  prevCrankData: CrankData;
35
35
  constructor(props?: any);
36
+ isMatching(characteristics: string[]): boolean;
36
37
  init(): Promise<boolean>;
37
38
  getProfile(): string;
38
39
  getServiceUUids(): string[];
package/lib/ble/pwr.js CHANGED
@@ -37,6 +37,8 @@ const ble_interface_1 = __importDefault(require("./ble-interface"));
37
37
  const Device_1 = __importStar(require("../Device"));
38
38
  const gd_eventlog_1 = require("gd-eventlog");
39
39
  const power_meter_1 = __importDefault(require("../modes/power-meter"));
40
+ const CP_MEASUREMENT = '2a63';
41
+ const CP_FEATURE = '2a65';
40
42
  class BleCyclingPowerDevice extends ble_device_1.BleDevice {
41
43
  constructor(props) {
42
44
  super(props);
@@ -49,6 +51,13 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
49
51
  this.currentCrankData = undefined;
50
52
  this.prevCrankData = undefined;
51
53
  }
54
+ isMatching(characteristics) {
55
+ if (!characteristics)
56
+ return false;
57
+ const hasCPMeasurement = characteristics.find(c => c === CP_MEASUREMENT) !== undefined;
58
+ const hasCPFeature = characteristics.find(c => c === CP_FEATURE) !== undefined;
59
+ return hasCPMeasurement && hasCPFeature;
60
+ }
52
61
  init() {
53
62
  const _super = Object.create(null, {
54
63
  init: { get: () => super.init }
@@ -131,7 +140,7 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
131
140
  }
132
141
  onData(characteristic, data) {
133
142
  super.onData(characteristic, data);
134
- if (characteristic.toLocaleLowerCase() === '2a63') {
143
+ if (characteristic.toLocaleLowerCase() === CP_MEASUREMENT) {
135
144
  const res = this.parsePower(data);
136
145
  this.emit('data', res);
137
146
  }
@@ -149,7 +158,7 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
149
158
  }
150
159
  exports.default = BleCyclingPowerDevice;
151
160
  BleCyclingPowerDevice.services = ['1818'];
152
- BleCyclingPowerDevice.characteristics = ['2a63', '2a65', '2a5d', '2a3c'];
161
+ BleCyclingPowerDevice.characteristics = [CP_MEASUREMENT, CP_FEATURE, '2a5d', '2a3c'];
153
162
  ble_interface_1.default.register('BleCyclingPowerDevice', 'cp', BleCyclingPowerDevice, BleCyclingPowerDevice.services);
154
163
  class PwrAdapter extends Device_1.default {
155
164
  constructor(device, protocol) {
package/lib/ble/tacx.js CHANGED
@@ -42,7 +42,7 @@ const TACX_FE_C_TX = '6e40fec3';
42
42
  const SYNC_BYTE = 0xA4;
43
43
  const DEFAULT_CHANNEL = 5;
44
44
  const ACKNOWLEDGED_DATA = 0x4F;
45
- const PROFILE_ID = 'Tacx FE-C over BLE';
45
+ const PROFILE_ID = 'Tacx SmartTrainer';
46
46
  const cwABike = {
47
47
  race: 0.35,
48
48
  triathlon: 0.29,
@@ -79,16 +79,16 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
79
79
  }
80
80
  init() {
81
81
  const _super = Object.create(null, {
82
- init: { get: () => super.init }
82
+ initDevice: { get: () => super.initDevice }
83
83
  });
84
84
  return __awaiter(this, void 0, void 0, function* () {
85
85
  try {
86
- this.logEvent({ message: 'get device info' });
87
- yield _super.init.call(this);
88
- this.logEvent({ message: 'device info', deviceInfo: this.deviceInfo, features: this.features });
86
+ yield _super.initDevice.call(this);
87
+ return true;
89
88
  }
90
89
  catch (err) {
91
- return Promise.resolve(false);
90
+ this.logEvent({ message: 'error', fn: 'TacxAdvancedFitnessMachineDevice.init()', error: err.message || err, stack: err.stack });
91
+ return false;
92
92
  }
93
93
  });
94
94
  }
@@ -35,6 +35,7 @@ export default class WahooAdvancedFitnessMachineDevice extends BleFitnessMachine
35
35
  timeOffset: number;
36
36
  tsPrevWrite: any;
37
37
  constructor(props?: any);
38
+ isMatching(characteristics: string[]): boolean;
38
39
  init(): Promise<boolean>;
39
40
  getProfile(): string;
40
41
  getServiceUUids(): string[];
@@ -54,35 +54,25 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
54
54
  this.tsPrevWrite = undefined;
55
55
  this.data = {};
56
56
  }
57
+ isMatching(characteristics) {
58
+ if (!characteristics)
59
+ return false;
60
+ const hasWahooCP = characteristics.find(c => c === WAHOO_ADVANCED_TRAINER_CP) !== undefined;
61
+ return hasWahooCP;
62
+ }
57
63
  init() {
58
64
  const _super = Object.create(null, {
59
- init: { get: () => super.init }
65
+ initDevice: { get: () => super.initDevice }
60
66
  });
61
67
  return __awaiter(this, void 0, void 0, function* () {
62
68
  try {
63
- const connector = this.ble.getConnector(this.peripheral);
64
- const isAlreadySubscribed = connector.isSubscribed(WAHOO_ADVANCED_TRAINER_CP);
65
- if (!isAlreadySubscribed) {
66
- connector.removeAllListeners(WAHOO_ADVANCED_TRAINER_CP);
67
- let prev = undefined;
68
- let prevTS = undefined;
69
- connector.on(WAHOO_ADVANCED_TRAINER_CP, (uuid, data) => {
70
- const message = data.toString('hex');
71
- if (prevTS && prev && message === prev && Date.now() - prevTS < 500) {
72
- return;
73
- }
74
- prevTS = Date.now();
75
- prev = message;
76
- this.onData(uuid, data);
77
- });
78
- yield connector.subscribe(WAHOO_ADVANCED_TRAINER_CP);
79
- }
80
- this.logEvent({ message: 'get device info' });
81
- yield _super.init.call(this);
82
- this.logEvent({ message: 'device info', deviceInfo: this.deviceInfo, features: this.features });
69
+ yield this.subscribeWriteResponse(WAHOO_ADVANCED_TRAINER_CP);
70
+ yield _super.initDevice.call(this);
71
+ return true;
83
72
  }
84
73
  catch (err) {
85
- return Promise.resolve(false);
74
+ this.logEvent({ message: 'error', fn: 'WahooAdvancedFitnessMachineDevice.init()', error: err.message || err, stack: err.stack });
75
+ return false;
86
76
  }
87
77
  });
88
78
  }
@@ -189,7 +179,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
189
179
  const opcode = Buffer.alloc(1);
190
180
  opcode.writeUInt8(requestedOpCode, 0);
191
181
  const message = Buffer.concat([opcode, data]);
192
- const res = yield this.write(WAHOO_ADVANCED_FTMS, message);
182
+ const res = yield this.write(WAHOO_ADVANCED_TRAINER_CP, message);
193
183
  const responseData = Buffer.from(res);
194
184
  const result = responseData.readUInt8(0);
195
185
  this.logEvent({ message: 'response', opCode: requestedOpCode, response: responseData.toString('hex') });
@@ -315,7 +305,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
315
305
  }
316
306
  exports.default = WahooAdvancedFitnessMachineDevice;
317
307
  WahooAdvancedFitnessMachineDevice.services = ['a026ee0b'];
318
- WahooAdvancedFitnessMachineDevice.characteristics = ['2acc', '2ad2', '2ad6', '2ad8', '2ad9', '2ada', WAHOO_ADVANCED_FTMS, WAHOO_ADVANCED_TRAINER_CP];
308
+ WahooAdvancedFitnessMachineDevice.characteristics = ['2acc', '2ad2', '2ad6', '2ad8', '2ad9', '2ada', WAHOO_ADVANCED_TRAINER_CP];
319
309
  ble_interface_1.default.register('WahooAdvancedFitnessMachineDevice', 'wahoo-fm', WahooAdvancedFitnessMachineDevice, WahooAdvancedFitnessMachineDevice.services);
320
310
  class WahooAdvancedFmAdapter extends fm_1.FmAdapter {
321
311
  constructor(device, protocol) {
@@ -1,7 +1,7 @@
1
1
  export declare const DEFAULT_AGE = 30;
2
2
  export declare const DEFAULT_USER_WEIGHT = 75;
3
3
  export declare const DEFAULT_BIKE_WEIGHT = 10;
4
- export declare function getCockpit(c: any): "Cardio" | "Fitness" | "Vita De Luxe" | "8008" | "8008 TRS" | "8080" | "Therapie" | "8008 TRS Pro" | "8008 TRS3" | "Unknown";
4
+ export declare function getCockpit(c: any): "Cardio" | "Fitness" | "Vita De Luxe" | "8008" | "8008 TRS" | "8080" | "Therapie" | "8008 TRS Pro" | "8008 TRS3" | "ergo_lyps Cardio Pro" | "Unknown";
5
5
  export declare function getBikeType(type: any): 1 | 0;
6
6
  export declare function getGender(sex: any): 1 | 2;
7
7
  export declare function getLength(length: any): number;
@@ -24,6 +24,8 @@ function getCockpit(c) {
24
24
  return "8008 TRS Pro";
25
25
  case 160:
26
26
  return "8008 TRS3";
27
+ case 0x8D:
28
+ return "ergo_lyps Cardio Pro";
27
29
  default:
28
30
  return "Unknown";
29
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.4.66",
3
+ "version": "1.4.69",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",