incyclist-devices 1.4.71 → 1.4.74
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.
- package/lib/ble/ble-interface.js +18 -7
- package/lib/ble/fm.d.ts +3 -0
- package/lib/ble/fm.js +12 -12
- package/lib/ble/tacx.d.ts +9 -1
- package/lib/ble/tacx.js +64 -29
- package/lib/ble/wahoo-kickr.js +4 -2
- package/package.json +1 -1
package/lib/ble/ble-interface.js
CHANGED
|
@@ -198,18 +198,24 @@ class BleInterface extends ble_1.BleInterfaceClass {
|
|
|
198
198
|
return [];
|
|
199
199
|
}
|
|
200
200
|
const get = (deviceTypes, fnCompare) => {
|
|
201
|
-
|
|
201
|
+
const types = deviceTypes.filter(DeviceType => {
|
|
202
202
|
const C = DeviceType;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
let found = false;
|
|
204
|
+
if (C.services)
|
|
205
|
+
found = C.services.find((s) => fnCompare(s));
|
|
206
|
+
return found;
|
|
206
207
|
});
|
|
208
|
+
return types;
|
|
207
209
|
};
|
|
208
210
|
if (typeof services === 'string') {
|
|
209
|
-
return get(deviceTypes, (s) => s === (0, ble_1.uuid)(services));
|
|
211
|
+
return get(deviceTypes, (s) => (0, ble_1.uuid)(s) === (0, ble_1.uuid)(services));
|
|
210
212
|
}
|
|
211
213
|
if (Array.isArray(services)) {
|
|
212
|
-
|
|
214
|
+
const sids = services.map(ble_1.uuid);
|
|
215
|
+
return get(deviceTypes, s => {
|
|
216
|
+
const res = sids.includes((0, ble_1.uuid)(s));
|
|
217
|
+
return res;
|
|
218
|
+
});
|
|
213
219
|
}
|
|
214
220
|
return [];
|
|
215
221
|
}
|
|
@@ -579,7 +585,12 @@ class BleInterface extends ble_1.BleInterfaceClass {
|
|
|
579
585
|
const d = this.createDevice(DeviceClass, peripheral, characteristics);
|
|
580
586
|
if (!d)
|
|
581
587
|
return;
|
|
582
|
-
|
|
588
|
+
try {
|
|
589
|
+
yield d.connect();
|
|
590
|
+
}
|
|
591
|
+
catch (err) {
|
|
592
|
+
this.logEvent({ message: 'error', fn: 'onPeripheralFound()', error: err.message || err, stack: err.stack });
|
|
593
|
+
}
|
|
583
594
|
if (scanForDevice) {
|
|
584
595
|
if ((id && id !== '' && d.id === id) ||
|
|
585
596
|
(address && address !== '' && d.address === address) ||
|
package/lib/ble/fm.d.ts
CHANGED
|
@@ -8,6 +8,9 @@ import { DeviceProtocol } from '../DeviceProtocol';
|
|
|
8
8
|
import { EventLogger } from 'gd-eventlog';
|
|
9
9
|
import CyclingMode from '../CyclingMode';
|
|
10
10
|
import { IncyclistBikeData } from '../CyclingMode';
|
|
11
|
+
export declare const FTMS_CP = "2ad9";
|
|
12
|
+
export declare const FTMS_STATUS = "2ada";
|
|
13
|
+
export declare const INDOOR_BIKE_DATA = "2ad2";
|
|
11
14
|
declare type PowerData = {
|
|
12
15
|
instantaneousPower?: number;
|
|
13
16
|
balance?: number;
|
package/lib/ble/fm.js
CHANGED
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.FmAdapter = void 0;
|
|
15
|
+
exports.FmAdapter = exports.INDOOR_BIKE_DATA = exports.FTMS_STATUS = exports.FTMS_CP = void 0;
|
|
16
16
|
const ble_device_1 = require("./ble-device");
|
|
17
17
|
const ble_interface_1 = __importDefault(require("./ble-interface"));
|
|
18
18
|
const Device_1 = __importDefault(require("../Device"));
|
|
@@ -20,9 +20,9 @@ const gd_eventlog_1 = require("gd-eventlog");
|
|
|
20
20
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
exports.FTMS_CP = '2ad9';
|
|
24
|
+
exports.FTMS_STATUS = '2ada';
|
|
25
|
+
exports.INDOOR_BIKE_DATA = '2ad2';
|
|
26
26
|
const cwABike = {
|
|
27
27
|
race: 0.35,
|
|
28
28
|
triathlon: 0.29,
|
|
@@ -99,9 +99,9 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
99
99
|
isMatching(characteristics) {
|
|
100
100
|
if (!characteristics)
|
|
101
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;
|
|
102
|
+
const hasStatus = characteristics.find(c => c === exports.FTMS_STATUS) !== undefined;
|
|
103
|
+
const hasCP = characteristics.find(c => c === exports.FTMS_CP) !== undefined;
|
|
104
|
+
const hasIndoorBike = characteristics.find(c => c === exports.INDOOR_BIKE_DATA) !== undefined;
|
|
105
105
|
return hasStatus && hasCP && hasIndoorBike;
|
|
106
106
|
}
|
|
107
107
|
subscribeWriteResponse(cuuid) {
|
|
@@ -131,7 +131,7 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
131
131
|
});
|
|
132
132
|
return __awaiter(this, void 0, void 0, function* () {
|
|
133
133
|
try {
|
|
134
|
-
yield this.subscribeWriteResponse(FTMS_CP);
|
|
134
|
+
yield this.subscribeWriteResponse(exports.FTMS_CP);
|
|
135
135
|
yield _super.initDevice.call(this);
|
|
136
136
|
yield this.getFitnessMachineFeatures();
|
|
137
137
|
this.logEvent({ message: 'device info', deviceInfo: this.deviceInfo, features: this.features });
|
|
@@ -310,13 +310,13 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
310
310
|
const uuid = characteristic.toLocaleLowerCase();
|
|
311
311
|
let res = undefined;
|
|
312
312
|
switch (uuid) {
|
|
313
|
-
case INDOOR_BIKE_DATA:
|
|
313
|
+
case exports.INDOOR_BIKE_DATA:
|
|
314
314
|
res = this.parseIndoorBikeData(data);
|
|
315
315
|
break;
|
|
316
316
|
case '2a37':
|
|
317
317
|
res = this.parseHrm(data);
|
|
318
318
|
break;
|
|
319
|
-
case FTMS_STATUS:
|
|
319
|
+
case exports.FTMS_STATUS:
|
|
320
320
|
res = this.parseFitnessMachineStatus(data);
|
|
321
321
|
break;
|
|
322
322
|
case '2a63':
|
|
@@ -334,7 +334,7 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
334
334
|
return __awaiter(this, void 0, void 0, function* () {
|
|
335
335
|
try {
|
|
336
336
|
this.logEvent({ message: 'fmts:write', data: data.toString('hex') });
|
|
337
|
-
const res = yield this.write(FTMS_CP, data);
|
|
337
|
+
const res = yield this.write(exports.FTMS_CP, data);
|
|
338
338
|
const responseData = Buffer.from(res);
|
|
339
339
|
const opCode = responseData.readUInt8(0);
|
|
340
340
|
const request = responseData.readUInt8(1);
|
|
@@ -486,7 +486,7 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
486
486
|
}
|
|
487
487
|
exports.default = BleFitnessMachineDevice;
|
|
488
488
|
BleFitnessMachineDevice.services = ['1826'];
|
|
489
|
-
BleFitnessMachineDevice.characteristics = ['2acc', INDOOR_BIKE_DATA, '2ad6', '2ad8', FTMS_CP, FTMS_STATUS];
|
|
489
|
+
BleFitnessMachineDevice.characteristics = ['2acc', exports.INDOOR_BIKE_DATA, '2ad6', '2ad8', exports.FTMS_CP, exports.FTMS_STATUS];
|
|
490
490
|
ble_interface_1.default.register('BleFitnessMachineDevice', 'fm', BleFitnessMachineDevice, BleFitnessMachineDevice.services);
|
|
491
491
|
class FmAdapter extends Device_1.default {
|
|
492
492
|
constructor(device, protocol) {
|
package/lib/ble/tacx.d.ts
CHANGED
|
@@ -13,6 +13,11 @@ interface BleFeBikeData extends IndoorBikeData {
|
|
|
13
13
|
AccumulatedPower?: number;
|
|
14
14
|
TrainerStatus?: number;
|
|
15
15
|
TargetStatus?: 'OnTarget' | 'LowSpeed' | 'HighSpeed';
|
|
16
|
+
HwVersion?: number;
|
|
17
|
+
ManId?: number;
|
|
18
|
+
ModelNum?: number;
|
|
19
|
+
SwVersion?: number;
|
|
20
|
+
SerialNumber?: number;
|
|
16
21
|
}
|
|
17
22
|
declare type CrankData = {
|
|
18
23
|
revolutions?: number;
|
|
@@ -30,12 +35,14 @@ export default class TacxAdvancedFitnessMachineDevice extends BleFitnessMachineD
|
|
|
30
35
|
data: BleFeBikeData;
|
|
31
36
|
hasFECData: boolean;
|
|
32
37
|
constructor(props?: any);
|
|
38
|
+
isMatching(characteristics: string[]): boolean;
|
|
33
39
|
init(): Promise<boolean>;
|
|
34
40
|
getProfile(): string;
|
|
35
41
|
getServiceUUids(): string[];
|
|
36
42
|
isBike(): boolean;
|
|
37
43
|
isPower(): boolean;
|
|
38
44
|
isHrm(): boolean;
|
|
45
|
+
requestControl(): Promise<boolean>;
|
|
39
46
|
parseCrankData(crankData: any): {
|
|
40
47
|
rpm: number;
|
|
41
48
|
time: any;
|
|
@@ -45,8 +52,9 @@ export default class TacxAdvancedFitnessMachineDevice extends BleFitnessMachineD
|
|
|
45
52
|
parseFEState(capStateBF: number): void;
|
|
46
53
|
parseGeneralFE(data: Buffer): BleFeBikeData;
|
|
47
54
|
parseTrainerData(data: Buffer): BleFeBikeData;
|
|
55
|
+
parseProductInformation(data: Buffer): BleFeBikeData;
|
|
48
56
|
parseFECMessage(_data: Buffer): BleFeBikeData;
|
|
49
|
-
onData(characteristic: string, data: Buffer):
|
|
57
|
+
onData(characteristic: string, data: Buffer): any;
|
|
50
58
|
getChecksum(message: any[]): number;
|
|
51
59
|
buildMessage(payload?: number[], msgID?: number): Buffer;
|
|
52
60
|
sendMessage(message: Buffer): Promise<boolean>;
|
package/lib/ble/tacx.js
CHANGED
|
@@ -77,6 +77,13 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
77
77
|
this.data = {};
|
|
78
78
|
this.hasFECData = false;
|
|
79
79
|
}
|
|
80
|
+
isMatching(characteristics) {
|
|
81
|
+
if (!characteristics)
|
|
82
|
+
return false;
|
|
83
|
+
const hasTacxCP = characteristics.find(c => c === TACX_FE_C_RX) !== undefined && characteristics.find(c => c === TACX_FE_C_TX) !== undefined;
|
|
84
|
+
const hasFTMS = characteristics.find(c => c === fm_1.FTMS_CP) !== undefined;
|
|
85
|
+
return hasTacxCP && !hasFTMS;
|
|
86
|
+
}
|
|
80
87
|
init() {
|
|
81
88
|
const _super = Object.create(null, {
|
|
82
89
|
initDevice: { get: () => super.initDevice }
|
|
@@ -107,6 +114,11 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
107
114
|
isHrm() {
|
|
108
115
|
return this.hasService('180d');
|
|
109
116
|
}
|
|
117
|
+
requestControl() {
|
|
118
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
119
|
+
return true;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
110
122
|
parseCrankData(crankData) {
|
|
111
123
|
if (!this.prevCrankData)
|
|
112
124
|
this.prevCrankData = { revolutions: 0, time: 0, cntUpdateMissing: -1 };
|
|
@@ -339,8 +351,22 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
339
351
|
this.parseFEState(flagStateBF);
|
|
340
352
|
return this.data;
|
|
341
353
|
}
|
|
354
|
+
parseProductInformation(data) {
|
|
355
|
+
const swRevSup = data.readUInt8(2);
|
|
356
|
+
const swRevMain = data.readUInt8(3);
|
|
357
|
+
const serial = data.readInt32LE(4);
|
|
358
|
+
this.data.SwVersion = swRevMain;
|
|
359
|
+
if (swRevSup !== 0xFF) {
|
|
360
|
+
this.data.SwVersion += swRevSup / 1000;
|
|
361
|
+
}
|
|
362
|
+
if (serial !== 0xFFFFFFFF) {
|
|
363
|
+
this.data.SerialNumber = serial;
|
|
364
|
+
}
|
|
365
|
+
return this.data;
|
|
366
|
+
}
|
|
342
367
|
parseFECMessage(_data) {
|
|
343
368
|
const data = Buffer.from(_data);
|
|
369
|
+
this.logEvent({ message: 'FE-C message', data: data.toString('hex') });
|
|
344
370
|
const c = data.readUInt8(0);
|
|
345
371
|
if (c !== SYNC_BYTE) {
|
|
346
372
|
this.logEvent({ message: 'SYNC missing', raw: data.toString('hex') });
|
|
@@ -352,45 +378,54 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
352
378
|
let res;
|
|
353
379
|
switch (messageId) {
|
|
354
380
|
case ANTMessages.generalFE:
|
|
355
|
-
res = this.parseGeneralFE(data.slice(4, len +
|
|
381
|
+
res = this.parseGeneralFE(data.slice(4, len + 3));
|
|
356
382
|
break;
|
|
357
383
|
case ANTMessages.trainerData:
|
|
358
|
-
res = this.parseTrainerData(data.slice(4, len +
|
|
384
|
+
res = this.parseTrainerData(data.slice(4, len + 3));
|
|
385
|
+
break;
|
|
386
|
+
case ANTMessages.productInformation:
|
|
387
|
+
res = this.parseProductInformation(data.slice(4, len + 3));
|
|
359
388
|
break;
|
|
360
389
|
}
|
|
361
390
|
res.raw = data.toString('hex');
|
|
362
391
|
return res;
|
|
363
392
|
}
|
|
364
393
|
onData(characteristic, data) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
394
|
+
try {
|
|
395
|
+
super.onData(characteristic, data);
|
|
396
|
+
const uuid = characteristic.toLocaleLowerCase();
|
|
397
|
+
let res = undefined;
|
|
398
|
+
if (uuid && uuid.startsWith(TACX_FE_C_RX)) {
|
|
399
|
+
res = this.parseFECMessage(data);
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
switch (uuid) {
|
|
403
|
+
case '2a63':
|
|
404
|
+
if (!this.hasFECData)
|
|
405
|
+
res = this.parsePower(data);
|
|
406
|
+
break;
|
|
407
|
+
case '2ad2':
|
|
408
|
+
if (!this.hasFECData)
|
|
409
|
+
res = this.parseIndoorBikeData(data);
|
|
410
|
+
break;
|
|
411
|
+
case '2a37':
|
|
412
|
+
res = this.parseHrm(data);
|
|
413
|
+
break;
|
|
414
|
+
case '2ada':
|
|
415
|
+
if (!this.hasFECData)
|
|
416
|
+
res = this.parseFitnessMachineStatus(data);
|
|
417
|
+
break;
|
|
418
|
+
default:
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
390
421
|
}
|
|
422
|
+
if (res)
|
|
423
|
+
this.emit('data', res);
|
|
424
|
+
return res;
|
|
425
|
+
}
|
|
426
|
+
catch (err) {
|
|
427
|
+
this.logEvent({ message: 'error', fn: 'tacx.onData()', error: err.message || err, stack: err.stack });
|
|
391
428
|
}
|
|
392
|
-
if (res)
|
|
393
|
-
this.emit('data', res);
|
|
394
429
|
}
|
|
395
430
|
getChecksum(message) {
|
|
396
431
|
let checksum = 0;
|
package/lib/ble/wahoo-kickr.js
CHANGED
|
@@ -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 = '
|
|
39
|
+
const WAHOO_ADVANCED_FTMS = 'a026ee0b';
|
|
40
40
|
const WAHOO_ADVANCED_TRAINER_CP = 'a026e005';
|
|
41
41
|
const cwABike = {
|
|
42
42
|
race: 0.35,
|
|
@@ -59,6 +59,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
59
59
|
if (!characteristics)
|
|
60
60
|
return false;
|
|
61
61
|
const hasWahooCP = characteristics.find(c => c === WAHOO_ADVANCED_TRAINER_CP) !== undefined;
|
|
62
|
+
const hasFTMS = characteristics.find(c => c === fm_1.FTMS_CP) !== undefined;
|
|
62
63
|
return hasWahooCP;
|
|
63
64
|
}
|
|
64
65
|
init() {
|
|
@@ -267,8 +268,9 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
267
268
|
setSimGrade(slope) {
|
|
268
269
|
return __awaiter(this, void 0, void 0, function* () {
|
|
269
270
|
const value = (Math.min(1, Math.max(-1, slope)) + 1.0) * 65535 / 2.0;
|
|
271
|
+
const slopeVal = Math.floor(value);
|
|
270
272
|
const data = Buffer.alloc(2);
|
|
271
|
-
data.writeInt16LE(
|
|
273
|
+
data.writeInt16LE(slopeVal, 0);
|
|
272
274
|
const res = yield this.writeWahooFtmsMessage(70, data);
|
|
273
275
|
return res;
|
|
274
276
|
});
|