incyclist-devices 1.4.65 → 1.4.68

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;
@@ -47,7 +48,9 @@ class BleDevice extends ble_1.BleDeviceClass {
47
48
  if (this.logger) {
48
49
  this.logger.logEvent(event);
49
50
  }
50
- console.log('~~~BLE:', event);
51
+ if (process.env.BLE_DEBUG) {
52
+ console.log('~~~BLE:', event);
53
+ }
51
54
  }
52
55
  setLogger(logger) {
53
56
  this.logger = logger;
@@ -55,6 +58,9 @@ class BleDevice extends ble_1.BleDeviceClass {
55
58
  setInterface(ble) {
56
59
  this.ble = ble;
57
60
  }
61
+ isMatching(characteristics) {
62
+ return true;
63
+ }
58
64
  cleanupListeners() {
59
65
  if (this.characteristics === undefined) {
60
66
  this.characteristics = [];
@@ -101,11 +107,17 @@ class BleDevice extends ble_1.BleDeviceClass {
101
107
  return this.services && this.services.find(s => s === serviceUuid || (0, ble_1.uuid)(serviceUuid)) !== undefined;
102
108
  }
103
109
  init() {
104
- if (this.isInitialized)
105
- return Promise.resolve(true);
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ if (this.isInitialized)
112
+ return Promise.resolve(true);
113
+ return yield this.initDevice();
114
+ });
115
+ }
116
+ initDevice() {
117
+ this.logEvent({ message: 'get device info' });
106
118
  return this.getDeviceInfo().then(() => {
107
119
  this.emit('deviceInfo', this.deviceInfo);
108
- this.logEvent(Object.assign({ message: 'ftms device init done' }, this.deviceInfo));
120
+ this.logEvent(Object.assign({ message: 'device init done' }, this.deviceInfo));
109
121
  this.isInitialized = true;
110
122
  return true;
111
123
  });
@@ -218,6 +230,9 @@ class BleDevice extends ble_1.BleDeviceClass {
218
230
  const { id, name, address } = this;
219
231
  this.logEvent({ message: 'disconnect requested', device: { id, name, address } });
220
232
  this.connectState.isDisconnecting = true;
233
+ if (this.workerIv) {
234
+ this.stopWorker();
235
+ }
221
236
  if (!this.connectState.isConnecting && !this.connectState.isConnected) {
222
237
  this.connectState.isDisconnecting = false;
223
238
  this.logEvent({ message: 'disconnect result: success', device: { id, name, address } });
@@ -244,20 +259,51 @@ class BleDevice extends ble_1.BleDeviceClass {
244
259
  if (writeIdx !== -1) {
245
260
  const writeItem = this.writeQueue[writeIdx];
246
261
  this.writeQueue.splice(writeIdx, 1);
247
- console.log('~~~ write queue', this.writeQueue);
248
262
  if (writeItem.resolve)
249
263
  writeItem.resolve(data);
250
264
  }
251
265
  }
252
266
  }
267
+ timeoutCheck() {
268
+ const now = Date.now();
269
+ const updatedQueue = [];
270
+ let hasTimeout = false;
271
+ this.writeQueue.forEach(writeItem => {
272
+ if (writeItem.timeout && writeItem.timeout > now) {
273
+ if (writeItem.reject) {
274
+ hasTimeout = true;
275
+ writeItem.reject(new Error('timeout'));
276
+ }
277
+ }
278
+ else {
279
+ updatedQueue.push(writeItem);
280
+ }
281
+ });
282
+ if (hasTimeout)
283
+ this.writeQueue = updatedQueue;
284
+ }
285
+ startWorker() {
286
+ if (this.workerIv)
287
+ return;
288
+ this.workerIv = setInterval(() => { this.timeoutCheck(); }, 100);
289
+ }
290
+ stopWorker() {
291
+ if (!this.workerIv)
292
+ return;
293
+ clearInterval(this.workerIv);
294
+ this.workerIv = null;
295
+ }
253
296
  write(characteristicUuid, data, withoutResponse = false) {
254
297
  return __awaiter(this, void 0, void 0, function* () {
255
298
  try {
256
299
  const connector = this.ble.getConnector(this.peripheral);
257
300
  const isAlreadySubscribed = connector.isSubscribed(characteristicUuid);
258
- console.log('~~~ write ', characteristicUuid, data.toString('hex'), isAlreadySubscribed, this.subscribedCharacteristics);
301
+ if (!withoutResponse && !this.workerIv) {
302
+ this.startWorker();
303
+ }
259
304
  if (!withoutResponse && !isAlreadySubscribed) {
260
305
  const connector = this.ble.getConnector(this.peripheral);
306
+ connector.removeAllListeners(characteristicUuid);
261
307
  connector.on(characteristicUuid, (uuid, data) => {
262
308
  this.onData(uuid, data);
263
309
  });
@@ -280,14 +326,13 @@ class BleDevice extends ble_1.BleDeviceClass {
280
326
  else {
281
327
  const writeId = this.writeQueue.length;
282
328
  let messageDeleted = false;
283
- this.writeQueue.push({ uuid: characteristicUuid.toLocaleLowerCase(), data, resolve, reject });
329
+ this.writeQueue.push({ uuid: characteristicUuid.toLocaleLowerCase(), data, timeout: Date.now() + 1000, resolve, reject });
284
330
  const to = setTimeout(() => {
285
- console.log('~~~ write timeout');
286
331
  if (this.writeQueue.length > writeId && !messageDeleted)
287
332
  this.writeQueue.splice(writeId, 1);
288
333
  this.logEvent({ message: 'writing response', err: 'timeout' });
289
334
  reject(new Error('timeout'));
290
- }, 1000);
335
+ }, 5000);
291
336
  this.logEvent({ message: 'writing' });
292
337
  characteristic.write(data, withoutResponse, (err) => {
293
338
  clearTimeout(to);
@@ -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);
@@ -31,7 +31,9 @@ class BlePeripheralConnector {
31
31
  if (this.logger) {
32
32
  this.logger.logEvent(event);
33
33
  }
34
- console.log('~~~BLE:', event);
34
+ if (process.env.BLE_DEBUG) {
35
+ console.log('~~~BLE:', event);
36
+ }
35
37
  }
36
38
  connect() {
37
39
  return __awaiter(this, void 0, void 0, function* () {
@@ -110,7 +112,6 @@ class BlePeripheralConnector {
110
112
  try {
111
113
  yield this.subscribe(c.uuid);
112
114
  subscribed.push(c.uuid);
113
- this.state.subscribed.push(c.uuid);
114
115
  }
115
116
  catch (err) {
116
117
  this.logEvent({ message: 'cannot subscribe', peripheral: this.peripheral.address, characteristic: c.uuid, error: err.message || err });
@@ -137,6 +138,7 @@ class BlePeripheralConnector {
137
138
  reject(new Error('Characteristic not found'));
138
139
  return;
139
140
  }
141
+ characteristic.removeAllListeners('data');
140
142
  characteristic.on('data', (data, _isNotification) => {
141
143
  this.onData(characteristicUuid, data);
142
144
  });
@@ -149,8 +151,10 @@ class BlePeripheralConnector {
149
151
  this.logEvent({ message: 'subscribe result', characteristic: characteristicUuid, error: err });
150
152
  if (err)
151
153
  reject(err);
152
- else
154
+ else {
155
+ this.state.subscribed.push(characteristicUuid);
153
156
  resolve(true);
157
+ }
154
158
  });
155
159
  }
156
160
  catch (err) {
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,18 +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
- this.logEvent({ message: 'get device info' });
104
- yield _super.init.call(this);
134
+ yield this.subscribeWriteResponse(FTMS_CP);
135
+ yield _super.initDevice.call(this);
105
136
  yield this.getFitnessMachineFeatures();
106
137
  this.logEvent({ message: 'device info', deviceInfo: this.deviceInfo, features: this.features });
107
138
  }
108
139
  catch (err) {
140
+ this.logEvent({ message: 'error', fn: 'BleFitnessMachineDevice.init()', error: err.message || err, stack: err.stack });
109
141
  return Promise.resolve(false);
110
142
  }
111
143
  });
@@ -278,13 +310,13 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
278
310
  const uuid = characteristic.toLocaleLowerCase();
279
311
  let res = undefined;
280
312
  switch (uuid) {
281
- case '2ad2':
313
+ case INDOOR_BIKE_DATA:
282
314
  res = this.parseIndoorBikeData(data);
283
315
  break;
284
316
  case '2a37':
285
317
  res = this.parseHrm(data);
286
318
  break;
287
- case '2ada':
319
+ case FTMS_STATUS:
288
320
  res = this.parseFitnessMachineStatus(data);
289
321
  break;
290
322
  case '2a63':
@@ -452,7 +484,7 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
452
484
  }
453
485
  exports.default = BleFitnessMachineDevice;
454
486
  BleFitnessMachineDevice.services = ['1826'];
455
- BleFitnessMachineDevice.characteristics = ['2acc', '2ad2', '2ad6', '2ad8', '2ad9', '2ada'];
487
+ BleFitnessMachineDevice.characteristics = ['2acc', INDOOR_BIKE_DATA, '2ad6', '2ad8', FTMS_CP, FTMS_STATUS];
456
488
  ble_interface_1.default.register('BleFitnessMachineDevice', 'fm', BleFitnessMachineDevice, BleFitnessMachineDevice.services);
457
489
  class FmAdapter extends Device_1.default {
458
490
  constructor(device, protocol) {
@@ -477,7 +509,8 @@ class FmAdapter extends Device_1.default {
477
509
  return (adapter.getName() === this.getName() && adapter.getProfile() === this.getProfile());
478
510
  }
479
511
  getProfile() {
480
- return 'Smart Trainer';
512
+ const profile = this.device ? this.device.getProfile() : undefined;
513
+ return profile || 'Smart Trainer';
481
514
  }
482
515
  getName() {
483
516
  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[];
@@ -36,7 +36,7 @@ const ble_interface_1 = __importDefault(require("./ble-interface"));
36
36
  const Device_1 = require("../Device");
37
37
  const gd_eventlog_1 = require("gd-eventlog");
38
38
  const fm_1 = __importStar(require("./fm"));
39
- const WAHOO_ADVANCED_FTMS = 'a026e005';
39
+ const WAHOO_ADVANCED_FTMS = 'a026e00b';
40
40
  const WAHOO_ADVANCED_TRAINER_CP = 'a026e037';
41
41
  const cwABike = {
42
42
  race: 0.35,
@@ -54,18 +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
- this.logEvent({ message: 'get device info' });
64
- yield _super.init.call(this);
65
- 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;
66
72
  }
67
73
  catch (err) {
68
- return Promise.resolve(false);
74
+ this.logEvent({ message: 'error', fn: 'WahooAdvancedFitnessMachineDevice.init()', error: err.message || err, stack: err.stack });
75
+ return false;
69
76
  }
70
77
  });
71
78
  }
@@ -172,7 +179,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
172
179
  const opcode = Buffer.alloc(1);
173
180
  opcode.writeUInt8(requestedOpCode, 0);
174
181
  const message = Buffer.concat([opcode, data]);
175
- const res = yield this.write(WAHOO_ADVANCED_FTMS, message);
182
+ const res = yield this.write(WAHOO_ADVANCED_TRAINER_CP, message);
176
183
  const responseData = Buffer.from(res);
177
184
  const result = responseData.readUInt8(0);
178
185
  this.logEvent({ message: 'response', opCode: requestedOpCode, response: responseData.toString('hex') });
@@ -298,7 +305,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
298
305
  }
299
306
  exports.default = WahooAdvancedFitnessMachineDevice;
300
307
  WahooAdvancedFitnessMachineDevice.services = ['a026ee0b'];
301
- 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];
302
309
  ble_interface_1.default.register('WahooAdvancedFitnessMachineDevice', 'wahoo-fm', WahooAdvancedFitnessMachineDevice, WahooAdvancedFitnessMachineDevice.services);
303
310
  class WahooAdvancedFmAdapter extends fm_1.FmAdapter {
304
311
  constructor(device, protocol) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.4.65",
3
+ "version": "1.4.68",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",