incyclist-devices 1.4.76 → 1.4.78

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.
@@ -316,7 +316,7 @@ class BleDevice extends ble_1.BleDeviceClass {
316
316
  return;
317
317
  }
318
318
  if (withoutResponse) {
319
- this.logEvent({ message: 'writing' });
319
+ this.logEvent({ message: 'writing', data: data.toString('hex'), withoutResponse });
320
320
  characteristic.write(data, withoutResponse);
321
321
  resolve(new ArrayBuffer(0));
322
322
  return;
@@ -55,9 +55,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
55
55
  if (this.logger) {
56
56
  this.logger.logEvent(event);
57
57
  }
58
- if (process.env.BLE_DEBUG) {
59
- console.log('~~BLE:', event);
60
- }
58
+ console.log('~~BLE:', event);
61
59
  }
62
60
  onStateChange(state) {
63
61
  if (state !== ble_1.BleState.POWERED_ON) {
@@ -583,9 +581,12 @@ class BleInterface extends ble_1.BleInterfaceClass {
583
581
  if (scanForDevice && cntFound > 0)
584
582
  return;
585
583
  const d = this.createDevice(DeviceClass, peripheral, characteristics);
586
- if (!d)
584
+ if (!d) {
585
+ this.logEvent({ message: `${opStr}: could not create device `, DeviceClass });
587
586
  return;
587
+ }
588
588
  try {
589
+ this.logEvent({ message: `${opStr}: connecting `, device: d.name, profile: d.getProfile(), address: d.address });
589
590
  yield d.connect();
590
591
  }
591
592
  catch (err) {
@@ -31,9 +31,7 @@ class BlePeripheralConnector {
31
31
  if (this.logger) {
32
32
  this.logger.logEvent(event);
33
33
  }
34
- if (process.env.BLE_DEBUG) {
35
- console.log('~~~BLE:', event);
36
- }
34
+ console.log('~~~BLE:', event);
37
35
  }
38
36
  connect() {
39
37
  return __awaiter(this, void 0, void 0, function* () {
@@ -132,15 +130,15 @@ class BlePeripheralConnector {
132
130
  this.logEvent({ message: 'subscribe', characteristic: characteristicUuid, characteristics: this.characteristics.map(c => ({ characteristic: c.uuid, uuid: (0, ble_1.uuid)(c.uuid) })) });
133
131
  return new Promise((resolve, reject) => {
134
132
  try {
135
- const characteristic = this.characteristics.find(c => c.uuid === characteristicUuid || (0, ble_1.uuid)(c.uuid) === characteristicUuid);
136
- this.logEvent({ message: 'subscribe', peripheral: this.peripheral.address, characteristic: characteristic.uuid, uuid: (0, ble_1.uuid)(characteristic.uuid) });
133
+ const characteristic = this.characteristics.find(c => (0, ble_1.uuid)(c.uuid) === (0, ble_1.uuid)(characteristicUuid) || (0, ble_1.uuid)(c.uuid) === (0, ble_1.uuid)(characteristicUuid));
137
134
  if (!characteristic) {
138
135
  reject(new Error('Characteristic not found'));
139
136
  return;
140
137
  }
138
+ this.logEvent({ message: 'subscribe', peripheral: this.peripheral.address, characteristic: characteristic.uuid, uuid: (0, ble_1.uuid)(characteristic.uuid) });
141
139
  characteristic.removeAllListeners('data');
142
140
  characteristic.on('data', (data, _isNotification) => {
143
- this.onData(characteristicUuid, data);
141
+ this.onData((0, ble_1.uuid)(characteristicUuid), data);
144
142
  });
145
143
  const to = setTimeout(() => {
146
144
  this.logEvent({ message: 'subscribe result', characteristic: characteristicUuid, error: 'timeout' });
@@ -163,18 +161,18 @@ class BlePeripheralConnector {
163
161
  });
164
162
  }
165
163
  onData(characteristicUuid, data) {
166
- this.emitter.emit(characteristicUuid, characteristicUuid, data);
164
+ this.emitter.emit((0, ble_1.uuid)(characteristicUuid), characteristicUuid, data);
167
165
  }
168
166
  on(characteristicUuid, callback) {
169
167
  if (callback)
170
- this.emitter.on(characteristicUuid, callback);
168
+ this.emitter.on((0, ble_1.uuid)(characteristicUuid), callback);
171
169
  }
172
170
  off(characteristicUuid, callback) {
173
171
  if (callback)
174
- this.emitter.off(characteristicUuid, callback);
172
+ this.emitter.off((0, ble_1.uuid)(characteristicUuid), callback);
175
173
  }
176
174
  removeAllListeners(characteristicUuid) {
177
- this.emitter.removeAllListeners(characteristicUuid);
175
+ this.emitter.removeAllListeners((0, ble_1.uuid)(characteristicUuid));
178
176
  }
179
177
  getState() {
180
178
  return this.peripheral.state;
package/lib/ble/ble.js CHANGED
@@ -65,7 +65,7 @@ const uuid = (s) => {
65
65
  if (s.includes('-')) {
66
66
  const parts = s.split('-');
67
67
  const uuidNo = parseInt('0x' + parts[0]);
68
- return uuidNo.toString(16);
68
+ return uuidNo.toString(16).toLowerCase();
69
69
  }
70
70
  return s;
71
71
  }
package/lib/ble/tacx.d.ts CHANGED
@@ -24,6 +24,14 @@ declare type CrankData = {
24
24
  time?: number;
25
25
  cntUpdateMissing?: number;
26
26
  };
27
+ declare type MessageInfo = {
28
+ message: string;
29
+ ts: number;
30
+ uuid: string;
31
+ };
32
+ declare type MessageLog = {
33
+ [uuid: string]: MessageInfo;
34
+ };
27
35
  export default class TacxAdvancedFitnessMachineDevice extends BleFitnessMachineDevice {
28
36
  static services: string[];
29
37
  static characteristics: string[];
@@ -34,6 +42,8 @@ export default class TacxAdvancedFitnessMachineDevice extends BleFitnessMachineD
34
42
  tsPrevWrite: any;
35
43
  data: BleFeBikeData;
36
44
  hasFECData: boolean;
45
+ prevMessages: MessageLog;
46
+ messageCnt: number;
37
47
  constructor(props?: any);
38
48
  isMatching(characteristics: string[]): boolean;
39
49
  init(): Promise<boolean>;
@@ -44,9 +54,13 @@ export default class TacxAdvancedFitnessMachineDevice extends BleFitnessMachineD
44
54
  isHrm(): boolean;
45
55
  requestControl(): Promise<boolean>;
46
56
  parseCrankData(crankData: any): {
57
+ rpm?: undefined;
58
+ time?: undefined;
59
+ } | {
47
60
  rpm: number;
48
61
  time: any;
49
62
  };
63
+ parseCSC(_data: Buffer): IndoorBikeData;
50
64
  parsePower(_data: Buffer): IndoorBikeData;
51
65
  resetState(): void;
52
66
  parseFEState(capStateBF: number): void;
package/lib/ble/tacx.js CHANGED
@@ -76,6 +76,8 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
76
76
  this.tsPrevWrite = undefined;
77
77
  this.data = {};
78
78
  this.hasFECData = false;
79
+ this.messageCnt = 0;
80
+ this.prevMessages = {};
79
81
  }
80
82
  isMatching(characteristics) {
81
83
  if (!characteristics)
@@ -120,8 +122,10 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
120
122
  });
121
123
  }
122
124
  parseCrankData(crankData) {
123
- if (!this.prevCrankData)
124
- this.prevCrankData = { revolutions: 0, time: 0, cntUpdateMissing: -1 };
125
+ if (!this.prevCrankData) {
126
+ this.prevCrankData = Object.assign(Object.assign({}, crankData), { cntUpdateMissing: -1 });
127
+ return {};
128
+ }
125
129
  const c = this.currentCrankData = crankData;
126
130
  const p = this.prevCrankData;
127
131
  let rpm = this.data.cadence;
@@ -150,7 +154,29 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
150
154
  this.prevCrankData.cntUpdateMissing = cntUpdateMissing + 1;
151
155
  return { rpm, time: this.timeOffset + c.time };
152
156
  }
157
+ parseCSC(_data) {
158
+ this.logEvent({ message: 'BLE CSC message', data: _data.toString('hex') });
159
+ const data = Buffer.from(_data);
160
+ let offset = 0;
161
+ const flags = data.readUInt8(offset);
162
+ offset++;
163
+ if (flags & 0x01) {
164
+ offset += 6;
165
+ }
166
+ if (flags & 0x02) {
167
+ const crankData = {
168
+ revolutions: data.readUInt16LE(offset),
169
+ time: data.readUInt16LE(offset + 2)
170
+ };
171
+ const { rpm, time } = this.parseCrankData(crankData);
172
+ this.data.cadence = rpm;
173
+ this.data.time = time;
174
+ offset += 4;
175
+ }
176
+ return this.data;
177
+ }
153
178
  parsePower(_data) {
179
+ this.logEvent({ message: 'BLE CSP message', data: _data.toString('hex') });
154
180
  const data = Buffer.from(_data);
155
181
  try {
156
182
  let offset = 4;
@@ -174,6 +200,7 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
174
200
  }
175
201
  }
176
202
  catch (err) {
203
+ this.logEvent({ message: 'error', fn: 'parsePower()', error: err.message || err, stack: err.stack });
177
204
  }
178
205
  const { instantaneousPower, cadence, time } = this.data;
179
206
  return { instantaneousPower, cadence, time, raw: data.toString('hex') };
@@ -349,6 +376,8 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
349
376
  break;
350
377
  }
351
378
  this.parseFEState(flagStateBF);
379
+ if (power !== undefined && cadence !== undefined)
380
+ this.hasFECData = true;
352
381
  return this.data;
353
382
  }
354
383
  parseProductInformation(data) {
@@ -374,26 +403,40 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
374
403
  }
375
404
  const len = data.readUInt8(1);
376
405
  const messageId = data.readUInt8(4);
377
- this.hasFECData = true;
378
406
  let res;
379
- switch (messageId) {
380
- case ANTMessages.generalFE:
381
- res = this.parseGeneralFE(data.slice(4, len + 3));
382
- break;
383
- case ANTMessages.trainerData:
384
- res = this.parseTrainerData(data.slice(4, len + 3));
385
- break;
386
- case ANTMessages.productInformation:
387
- res = this.parseProductInformation(data.slice(4, len + 3));
388
- break;
407
+ try {
408
+ switch (messageId) {
409
+ case ANTMessages.generalFE:
410
+ res = this.parseGeneralFE(data.slice(4, len + 3));
411
+ break;
412
+ case ANTMessages.trainerData:
413
+ res = this.parseTrainerData(data.slice(4, len + 3));
414
+ break;
415
+ case ANTMessages.productInformation:
416
+ res = this.parseProductInformation(data.slice(4, len + 3));
417
+ break;
418
+ }
419
+ if (res)
420
+ res.raw = data.toString('hex');
421
+ }
422
+ catch (err) {
423
+ this.logEvent({ message: 'error', fn: 'parseFECMessage()', error: err.message || err, stack: err.stack });
389
424
  }
390
- res.raw = data.toString('hex');
391
425
  return res;
392
426
  }
393
427
  onData(characteristic, data) {
394
428
  try {
395
- super.onData(characteristic, data);
396
429
  const uuid = characteristic.toLocaleLowerCase();
430
+ const message = data.toString('hex');
431
+ const ts = Date.now();
432
+ if (this.prevMessages[uuid]) {
433
+ const prev = this.prevMessages[uuid];
434
+ if (prev.message === message && prev.ts > ts - 500) {
435
+ return;
436
+ }
437
+ }
438
+ this.prevMessages[uuid] = { uuid, ts, message };
439
+ this.messageCnt++;
397
440
  let res = undefined;
398
441
  if (uuid && uuid.startsWith(TACX_FE_C_RX)) {
399
442
  res = this.parseFECMessage(data);
@@ -411,6 +454,10 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
411
454
  case '2a37':
412
455
  res = this.parseHrm(data);
413
456
  break;
457
+ case '2a5b':
458
+ if (!this.hasFECData)
459
+ res = this.parseCSC(data);
460
+ break;
414
461
  case '2ada':
415
462
  if (!this.hasFECData)
416
463
  res = this.parseFitnessMachineStatus(data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.4.76",
3
+ "version": "1.4.78",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",