incyclist-devices 1.4.78 → 1.4.80
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-device.d.ts +7 -0
- package/lib/ble/ble-device.js +18 -0
- package/lib/ble/ble-interface.d.ts +1 -1
- package/lib/ble/ble-interface.js +5 -3
- package/lib/ble/ble.d.ts +2 -0
- package/lib/ble/ble.js +14 -1
- package/lib/ble/consts.d.ts +7 -0
- package/lib/ble/consts.js +10 -0
- package/lib/ble/fm.d.ts +0 -3
- package/lib/ble/fm.js +15 -14
- package/lib/ble/hrm.js +3 -0
- package/lib/ble/pwr.js +3 -0
- package/lib/ble/tacx.d.ts +3 -9
- package/lib/ble/tacx.js +23 -21
- package/lib/ble/wahoo-kickr.d.ts +2 -0
- package/lib/ble/wahoo-kickr.js +16 -4
- package/package.json +1 -1
package/lib/ble/ble-device.d.ts
CHANGED
|
@@ -13,6 +13,11 @@ declare type CommandQueueItem = {
|
|
|
13
13
|
resolve: any;
|
|
14
14
|
reject: any;
|
|
15
15
|
};
|
|
16
|
+
export interface MessageLog {
|
|
17
|
+
uuid: string;
|
|
18
|
+
timestamp: any;
|
|
19
|
+
data: string;
|
|
20
|
+
}
|
|
16
21
|
export declare abstract class BleDevice extends BleDeviceClass {
|
|
17
22
|
id: string;
|
|
18
23
|
address: string;
|
|
@@ -28,6 +33,7 @@ export declare abstract class BleDevice extends BleDeviceClass {
|
|
|
28
33
|
subscribedCharacteristics: string[];
|
|
29
34
|
writeQueue: CommandQueueItem[];
|
|
30
35
|
workerIv: NodeJS.Timeout;
|
|
36
|
+
prevMessages: MessageLog[];
|
|
31
37
|
constructor(props?: BleDeviceConstructProps);
|
|
32
38
|
logEvent(event: any): void;
|
|
33
39
|
setLogger(logger: EventLogger): void;
|
|
@@ -44,6 +50,7 @@ export declare abstract class BleDevice extends BleDeviceClass {
|
|
|
44
50
|
connect(props?: ConnectProps): Promise<boolean>;
|
|
45
51
|
disconnect(): Promise<boolean>;
|
|
46
52
|
abstract getProfile(): string;
|
|
53
|
+
checkForDuplicate(characteristic: string, data: Buffer): boolean;
|
|
47
54
|
onData(characteristic: string, data: Buffer): void;
|
|
48
55
|
timeoutCheck(): void;
|
|
49
56
|
startWorker(): void;
|
package/lib/ble/ble-device.js
CHANGED
|
@@ -28,6 +28,7 @@ class BleDevice extends ble_1.BleDeviceClass {
|
|
|
28
28
|
this.isInitialized = false;
|
|
29
29
|
this.writeQueue = [];
|
|
30
30
|
this.workerIv = null;
|
|
31
|
+
this.prevMessages = [];
|
|
31
32
|
if (props.peripheral) {
|
|
32
33
|
const { id, address, advertisement, state } = props.peripheral;
|
|
33
34
|
this.peripheral = props.peripheral;
|
|
@@ -251,6 +252,23 @@ class BleDevice extends ble_1.BleDeviceClass {
|
|
|
251
252
|
}
|
|
252
253
|
});
|
|
253
254
|
}
|
|
255
|
+
checkForDuplicate(characteristic, data) {
|
|
256
|
+
const prev = this.prevMessages.find(i => i.uuid === characteristic);
|
|
257
|
+
if (prev) {
|
|
258
|
+
if (prev.data === data.toString('hex') && prev.timestamp > Date.now() - 500) {
|
|
259
|
+
prev.timestamp = Date.now();
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
prev.data = data.toString('hex');
|
|
264
|
+
prev.timestamp = Date.now();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
this.prevMessages.push({ uuid: characteristic, timestamp: Date.now(), data: data.toString('hex') });
|
|
269
|
+
}
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
254
272
|
onData(characteristic, data) {
|
|
255
273
|
if (this.writeQueue.length > 0) {
|
|
256
274
|
const writeIdx = this.writeQueue.findIndex(i => i.uuid === characteristic.toLocaleLowerCase());
|
|
@@ -79,7 +79,7 @@ export default class BleInterface extends BleInterfaceClass {
|
|
|
79
79
|
profile?: string;
|
|
80
80
|
services?: string[];
|
|
81
81
|
}): (typeof BleDeviceClass)[];
|
|
82
|
-
createDevice(DeviceClass: (typeof BleDeviceClass), peripheral: BlePeripheral, characteristics?: BleCharacteristic[]):
|
|
82
|
+
createDevice(DeviceClass: (typeof BleDeviceClass), peripheral: BlePeripheral, characteristics?: BleCharacteristic[]): BleDeviceClass;
|
|
83
83
|
connectDevice(requested: BleDeviceClass | BleDeviceDescription, timeout?: number): Promise<BleDeviceClass>;
|
|
84
84
|
waitForScanFinished(timeout: any): Promise<unknown>;
|
|
85
85
|
scan(props: ScanProps): Promise<BleDeviceClass[]>;
|
package/lib/ble/ble-interface.js
CHANGED
|
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
16
16
|
const utils_1 = require("../utils");
|
|
17
17
|
const ble_1 = require("./ble");
|
|
18
|
+
const ble_2 = require("./ble");
|
|
18
19
|
const ble_peripheral_1 = __importDefault(require("./ble-peripheral"));
|
|
19
20
|
const CONNECT_TIMEOUT = 5000;
|
|
20
21
|
const DEFAULT_SCAN_TIMEOUT = 20000;
|
|
@@ -206,13 +207,13 @@ class BleInterface extends ble_1.BleInterfaceClass {
|
|
|
206
207
|
return types;
|
|
207
208
|
};
|
|
208
209
|
if (typeof services === 'string') {
|
|
209
|
-
return get(deviceTypes, (s) => (0,
|
|
210
|
+
return get(deviceTypes, (s) => (0, ble_2.matches)(s, services));
|
|
210
211
|
}
|
|
211
212
|
if (Array.isArray(services)) {
|
|
212
213
|
const sids = services.map(ble_1.uuid);
|
|
213
214
|
return get(deviceTypes, s => {
|
|
214
|
-
const res = sids.
|
|
215
|
-
return res;
|
|
215
|
+
const res = sids.find((s) => (0, ble_2.matches)(s, services));
|
|
216
|
+
return res !== undefined;
|
|
216
217
|
});
|
|
217
218
|
}
|
|
218
219
|
return [];
|
|
@@ -370,6 +371,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
|
|
|
370
371
|
device.setInterface(this);
|
|
371
372
|
if (characteristics && device.isMatching(cids)) {
|
|
372
373
|
device.characteristics = characteristics;
|
|
374
|
+
device.setCharacteristicUUIDs(characteristics.map(c => c.uuid));
|
|
373
375
|
return device;
|
|
374
376
|
}
|
|
375
377
|
else {
|
package/lib/ble/ble.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export declare abstract class BleDeviceClass extends EventEmitter {
|
|
|
42
42
|
abstract connect(props?: ConnectProps): Promise<boolean>;
|
|
43
43
|
abstract disconnect(): Promise<boolean>;
|
|
44
44
|
abstract getDeviceInfo(): Promise<BleDeviceInfo>;
|
|
45
|
+
setCharacteristicUUIDs(uuids: string[]): void;
|
|
45
46
|
}
|
|
46
47
|
export interface BleBinding extends EventEmitter {
|
|
47
48
|
startScanning(serviceUUIDs?: string[], allowDuplicates?: boolean, callback?: (error?: Error) => void): void;
|
|
@@ -118,3 +119,4 @@ export declare enum BleState {
|
|
|
118
119
|
POWERED_ON = "poweredOn"
|
|
119
120
|
}
|
|
120
121
|
export declare const uuid: (s: any) => any;
|
|
122
|
+
export declare const matches: (uuid1: any, uuid2: any) => boolean;
|
package/lib/ble/ble.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.uuid = exports.BleState = exports.BleInterfaceClass = exports.BleBindingWrapper = exports.BleDeviceClass = void 0;
|
|
6
|
+
exports.matches = exports.uuid = exports.BleState = exports.BleInterfaceClass = exports.BleBindingWrapper = exports.BleDeviceClass = void 0;
|
|
7
7
|
const events_1 = __importDefault(require("events"));
|
|
8
8
|
class BleDeviceClass extends events_1.default {
|
|
9
9
|
constructor() {
|
|
@@ -16,6 +16,7 @@ class BleDeviceClass extends events_1.default {
|
|
|
16
16
|
isConnected() {
|
|
17
17
|
return this.connectState.isConnected;
|
|
18
18
|
}
|
|
19
|
+
setCharacteristicUUIDs(uuids) { }
|
|
19
20
|
}
|
|
20
21
|
exports.BleDeviceClass = BleDeviceClass;
|
|
21
22
|
BleDeviceClass.services = [];
|
|
@@ -71,3 +72,15 @@ const uuid = (s) => {
|
|
|
71
72
|
}
|
|
72
73
|
};
|
|
73
74
|
exports.uuid = uuid;
|
|
75
|
+
const matches = (uuid1, uuid2) => {
|
|
76
|
+
if ((0, exports.uuid)(uuid1) === (0, exports.uuid)(uuid2))
|
|
77
|
+
return true;
|
|
78
|
+
const ul1 = uuid1.toLowerCase();
|
|
79
|
+
const ul2 = uuid2.toLowerCase();
|
|
80
|
+
if (ul1.length < ul2.length && ul2.startsWith(ul1))
|
|
81
|
+
return true;
|
|
82
|
+
if (ul1.length > ul2.length && ul1.startsWith(ul2))
|
|
83
|
+
return true;
|
|
84
|
+
return false;
|
|
85
|
+
};
|
|
86
|
+
exports.matches = matches;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const TACX_FE_C_BLE = "6e40fec1";
|
|
2
|
+
export declare const TACX_FE_C_RX = "6e40fec2";
|
|
3
|
+
export declare const TACX_FE_C_TX = "6e40fec3";
|
|
4
|
+
export declare const FTMS = "1826";
|
|
5
|
+
export declare const FTMS_CP = "2ad9";
|
|
6
|
+
export declare const FTMS_STATUS = "2ada";
|
|
7
|
+
export declare const INDOOR_BIKE_DATA = "2ad2";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.INDOOR_BIKE_DATA = exports.FTMS_STATUS = exports.FTMS_CP = exports.FTMS = exports.TACX_FE_C_TX = exports.TACX_FE_C_RX = exports.TACX_FE_C_BLE = void 0;
|
|
4
|
+
exports.TACX_FE_C_BLE = '6e40fec1';
|
|
5
|
+
exports.TACX_FE_C_RX = '6e40fec2';
|
|
6
|
+
exports.TACX_FE_C_TX = '6e40fec3';
|
|
7
|
+
exports.FTMS = '1826';
|
|
8
|
+
exports.FTMS_CP = '2ad9';
|
|
9
|
+
exports.FTMS_STATUS = '2ada';
|
|
10
|
+
exports.INDOOR_BIKE_DATA = '2ad2';
|
package/lib/ble/fm.d.ts
CHANGED
|
@@ -8,9 +8,6 @@ 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";
|
|
14
11
|
declare type PowerData = {
|
|
15
12
|
instantaneousPower?: number;
|
|
16
13
|
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 =
|
|
15
|
+
exports.FmAdapter = 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,7 @@ 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
|
-
exports.FTMS_STATUS = '2ada';
|
|
25
|
-
exports.INDOOR_BIKE_DATA = '2ad2';
|
|
23
|
+
const consts_1 = require("./consts");
|
|
26
24
|
const cwABike = {
|
|
27
25
|
race: 0.35,
|
|
28
26
|
triathlon: 0.29,
|
|
@@ -99,9 +97,10 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
99
97
|
isMatching(characteristics) {
|
|
100
98
|
if (!characteristics)
|
|
101
99
|
return false;
|
|
102
|
-
const hasStatus = characteristics.find(c => c ===
|
|
103
|
-
const hasCP = characteristics.find(c => c ===
|
|
104
|
-
const hasIndoorBike = characteristics.find(c => c ===
|
|
100
|
+
const hasStatus = characteristics.find(c => c === consts_1.FTMS_STATUS) !== undefined;
|
|
101
|
+
const hasCP = characteristics.find(c => c === consts_1.FTMS_CP) !== undefined;
|
|
102
|
+
const hasIndoorBike = characteristics.find(c => c === consts_1.INDOOR_BIKE_DATA) !== undefined;
|
|
103
|
+
const hasTacx = characteristics.find(c => c === consts_1.TACX_FE_C_RX) !== undefined && characteristics.find(c => c === consts_1.TACX_FE_C_TX) !== undefined;
|
|
105
104
|
return hasStatus && hasCP && hasIndoorBike;
|
|
106
105
|
}
|
|
107
106
|
subscribeWriteResponse(cuuid) {
|
|
@@ -131,7 +130,7 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
131
130
|
});
|
|
132
131
|
return __awaiter(this, void 0, void 0, function* () {
|
|
133
132
|
try {
|
|
134
|
-
yield this.subscribeWriteResponse(
|
|
133
|
+
yield this.subscribeWriteResponse(consts_1.FTMS_CP);
|
|
135
134
|
yield _super.initDevice.call(this);
|
|
136
135
|
yield this.getFitnessMachineFeatures();
|
|
137
136
|
this.logEvent({ message: 'device info', deviceInfo: this.deviceInfo, features: this.features });
|
|
@@ -307,22 +306,24 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
307
306
|
}
|
|
308
307
|
onData(characteristic, data) {
|
|
309
308
|
super.onData(characteristic, data);
|
|
309
|
+
const isDuplicate = this.checkForDuplicate(characteristic, data);
|
|
310
|
+
if (isDuplicate)
|
|
311
|
+
return;
|
|
310
312
|
const uuid = characteristic.toLocaleLowerCase();
|
|
311
313
|
let res = undefined;
|
|
312
314
|
switch (uuid) {
|
|
313
|
-
case
|
|
315
|
+
case consts_1.INDOOR_BIKE_DATA:
|
|
314
316
|
res = this.parseIndoorBikeData(data);
|
|
315
317
|
break;
|
|
316
318
|
case '2a37':
|
|
317
319
|
res = this.parseHrm(data);
|
|
318
320
|
break;
|
|
319
|
-
case
|
|
321
|
+
case consts_1.FTMS_STATUS:
|
|
320
322
|
res = this.parseFitnessMachineStatus(data);
|
|
321
323
|
break;
|
|
322
324
|
case '2a63':
|
|
323
325
|
case '2a5b':
|
|
324
326
|
case '347b0011-7635-408b-8918-8ff3949ce592':
|
|
325
|
-
this.logger.logEvent({ message: 'onBleData', raw: `uuid:${data.toString('hex')}` });
|
|
326
327
|
break;
|
|
327
328
|
default:
|
|
328
329
|
break;
|
|
@@ -334,7 +335,7 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
334
335
|
return __awaiter(this, void 0, void 0, function* () {
|
|
335
336
|
try {
|
|
336
337
|
this.logEvent({ message: 'fmts:write', data: data.toString('hex') });
|
|
337
|
-
const res = yield this.write(
|
|
338
|
+
const res = yield this.write(consts_1.FTMS_CP, data);
|
|
338
339
|
const responseData = Buffer.from(res);
|
|
339
340
|
const opCode = responseData.readUInt8(0);
|
|
340
341
|
const request = responseData.readUInt8(1);
|
|
@@ -485,8 +486,8 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
485
486
|
}
|
|
486
487
|
}
|
|
487
488
|
exports.default = BleFitnessMachineDevice;
|
|
488
|
-
BleFitnessMachineDevice.services = [
|
|
489
|
-
BleFitnessMachineDevice.characteristics = ['2acc',
|
|
489
|
+
BleFitnessMachineDevice.services = [consts_1.FTMS];
|
|
490
|
+
BleFitnessMachineDevice.characteristics = ['2acc', consts_1.INDOOR_BIKE_DATA, '2ad6', '2ad8', consts_1.FTMS_CP, consts_1.FTMS_STATUS];
|
|
490
491
|
ble_interface_1.default.register('BleFitnessMachineDevice', 'fm', BleFitnessMachineDevice, BleFitnessMachineDevice.services);
|
|
491
492
|
class FmAdapter extends Device_1.default {
|
|
492
493
|
constructor(device, protocol) {
|
package/lib/ble/hrm.js
CHANGED
|
@@ -52,6 +52,9 @@ class BleHrmDevice extends ble_device_1.BleDevice {
|
|
|
52
52
|
}
|
|
53
53
|
onData(characteristic, data) {
|
|
54
54
|
super.onData(characteristic, data);
|
|
55
|
+
const isDuplicate = this.checkForDuplicate(characteristic, data);
|
|
56
|
+
if (isDuplicate)
|
|
57
|
+
return;
|
|
55
58
|
if (characteristic.toLocaleLowerCase() === '2a37') {
|
|
56
59
|
const res = this.parseHrm(data);
|
|
57
60
|
this.emit('data', res);
|
package/lib/ble/pwr.js
CHANGED
|
@@ -140,6 +140,9 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
|
|
|
140
140
|
}
|
|
141
141
|
onData(characteristic, data) {
|
|
142
142
|
super.onData(characteristic, data);
|
|
143
|
+
const isDuplicate = this.checkForDuplicate(characteristic, data);
|
|
144
|
+
if (isDuplicate)
|
|
145
|
+
return;
|
|
143
146
|
if (characteristic.toLocaleLowerCase() === CP_MEASUREMENT) {
|
|
144
147
|
const res = this.parsePower(data);
|
|
145
148
|
this.emit('data', res);
|
package/lib/ble/tacx.d.ts
CHANGED
|
@@ -24,14 +24,6 @@ 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
|
-
};
|
|
35
27
|
export default class TacxAdvancedFitnessMachineDevice extends BleFitnessMachineDevice {
|
|
36
28
|
static services: string[];
|
|
37
29
|
static characteristics: string[];
|
|
@@ -42,10 +34,12 @@ export default class TacxAdvancedFitnessMachineDevice extends BleFitnessMachineD
|
|
|
42
34
|
tsPrevWrite: any;
|
|
43
35
|
data: BleFeBikeData;
|
|
44
36
|
hasFECData: boolean;
|
|
45
|
-
prevMessages: MessageLog;
|
|
46
37
|
messageCnt: number;
|
|
38
|
+
tacxRx: string;
|
|
39
|
+
tacxTx: string;
|
|
47
40
|
constructor(props?: any);
|
|
48
41
|
isMatching(characteristics: string[]): boolean;
|
|
42
|
+
setCharacteristicUUIDs(uuids: string[]): void;
|
|
49
43
|
init(): Promise<boolean>;
|
|
50
44
|
getProfile(): string;
|
|
51
45
|
getServiceUUids(): string[];
|
package/lib/ble/tacx.js
CHANGED
|
@@ -33,12 +33,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
33
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
34
|
exports.TacxBleFEAdapter = void 0;
|
|
35
35
|
const ble_interface_1 = __importDefault(require("./ble-interface"));
|
|
36
|
+
const ble_1 = require("./ble");
|
|
36
37
|
const Device_1 = require("../Device");
|
|
37
38
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
38
39
|
const fm_1 = __importStar(require("./fm"));
|
|
39
|
-
const
|
|
40
|
-
const TACX_FE_C_RX = '6e40fec2';
|
|
41
|
-
const TACX_FE_C_TX = '6e40fec3';
|
|
40
|
+
const consts_1 = require("./consts");
|
|
42
41
|
const SYNC_BYTE = 0xA4;
|
|
43
42
|
const DEFAULT_CHANNEL = 5;
|
|
44
43
|
const ACKNOWLEDGED_DATA = 0x4F;
|
|
@@ -77,14 +76,24 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
77
76
|
this.data = {};
|
|
78
77
|
this.hasFECData = false;
|
|
79
78
|
this.messageCnt = 0;
|
|
80
|
-
this.
|
|
79
|
+
this.tacxRx = consts_1.TACX_FE_C_RX;
|
|
80
|
+
this.tacxTx = consts_1.TACX_FE_C_TX;
|
|
81
81
|
}
|
|
82
82
|
isMatching(characteristics) {
|
|
83
83
|
if (!characteristics)
|
|
84
84
|
return false;
|
|
85
|
-
const hasTacxCP = characteristics.find(c => c
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
const hasTacxCP = characteristics.find(c => (0, ble_1.matches)(c, consts_1.TACX_FE_C_RX)) !== undefined &&
|
|
86
|
+
characteristics.find(c => (0, ble_1.matches)(c, consts_1.TACX_FE_C_TX)) !== undefined;
|
|
87
|
+
const hasFTMS = characteristics.find(c => (0, ble_1.matches)(c, consts_1.FTMS_CP)) !== undefined;
|
|
88
|
+
return hasTacxCP;
|
|
89
|
+
}
|
|
90
|
+
setCharacteristicUUIDs(uuids) {
|
|
91
|
+
uuids.forEach(c => {
|
|
92
|
+
if ((0, ble_1.matches)(c, consts_1.TACX_FE_C_RX))
|
|
93
|
+
this.tacxRx = c;
|
|
94
|
+
if ((0, ble_1.matches)(c, consts_1.TACX_FE_C_TX))
|
|
95
|
+
this.tacxTx = c;
|
|
96
|
+
});
|
|
88
97
|
}
|
|
89
98
|
init() {
|
|
90
99
|
const _super = Object.create(null, {
|
|
@@ -425,20 +434,13 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
425
434
|
return res;
|
|
426
435
|
}
|
|
427
436
|
onData(characteristic, data) {
|
|
437
|
+
const isDuplicate = this.checkForDuplicate(characteristic, data);
|
|
438
|
+
if (isDuplicate)
|
|
439
|
+
return;
|
|
428
440
|
try {
|
|
429
441
|
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++;
|
|
440
442
|
let res = undefined;
|
|
441
|
-
if (uuid && uuid.
|
|
443
|
+
if (uuid && (0, ble_1.matches)(uuid, this.tacxRx)) {
|
|
442
444
|
res = this.parseFECMessage(data);
|
|
443
445
|
}
|
|
444
446
|
else {
|
|
@@ -494,7 +496,7 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
494
496
|
}
|
|
495
497
|
sendMessage(message) {
|
|
496
498
|
return __awaiter(this, void 0, void 0, function* () {
|
|
497
|
-
yield this.write(
|
|
499
|
+
yield this.write(this.tacxTx, message, true);
|
|
498
500
|
return true;
|
|
499
501
|
});
|
|
500
502
|
}
|
|
@@ -646,8 +648,8 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
646
648
|
}
|
|
647
649
|
}
|
|
648
650
|
exports.default = TacxAdvancedFitnessMachineDevice;
|
|
649
|
-
TacxAdvancedFitnessMachineDevice.services = [TACX_FE_C_BLE];
|
|
650
|
-
TacxAdvancedFitnessMachineDevice.characteristics = ['2acc', '2ad2', '2ad6', '2ad8', '2ad9', '2ada', TACX_FE_C_RX, TACX_FE_C_TX];
|
|
651
|
+
TacxAdvancedFitnessMachineDevice.services = [consts_1.TACX_FE_C_BLE];
|
|
652
|
+
TacxAdvancedFitnessMachineDevice.characteristics = ['2acc', '2ad2', '2ad6', '2ad8', '2ad9', '2ada', consts_1.TACX_FE_C_RX, consts_1.TACX_FE_C_TX];
|
|
651
653
|
TacxAdvancedFitnessMachineDevice.PROFILE = PROFILE_ID;
|
|
652
654
|
ble_interface_1.default.register('TacxBleFEDevice', 'tacx-ble-fec', TacxAdvancedFitnessMachineDevice, TacxAdvancedFitnessMachineDevice.services);
|
|
653
655
|
class TacxBleFEAdapter extends fm_1.FmAdapter {
|
package/lib/ble/wahoo-kickr.d.ts
CHANGED
|
@@ -35,9 +35,11 @@ export default class WahooAdvancedFitnessMachineDevice extends BleFitnessMachine
|
|
|
35
35
|
timeOffset: number;
|
|
36
36
|
tsPrevWrite: any;
|
|
37
37
|
prevSlope: any;
|
|
38
|
+
wahooCP: string;
|
|
38
39
|
constructor(props?: any);
|
|
39
40
|
isMatching(characteristics: string[]): boolean;
|
|
40
41
|
init(): Promise<boolean>;
|
|
42
|
+
setCharacteristicUUIDs(uuids: string[]): void;
|
|
41
43
|
getProfile(): string;
|
|
42
44
|
getServiceUUids(): string[];
|
|
43
45
|
isBike(): boolean;
|
package/lib/ble/wahoo-kickr.js
CHANGED
|
@@ -33,9 +33,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
33
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
34
|
exports.WahooAdvancedFmAdapter = void 0;
|
|
35
35
|
const ble_interface_1 = __importDefault(require("./ble-interface"));
|
|
36
|
+
const ble_1 = require("./ble");
|
|
36
37
|
const Device_1 = require("../Device");
|
|
37
38
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
38
39
|
const fm_1 = __importStar(require("./fm"));
|
|
40
|
+
const consts_1 = require("./consts");
|
|
39
41
|
const WAHOO_ADVANCED_FTMS = 'a026ee0b';
|
|
40
42
|
const WAHOO_ADVANCED_TRAINER_CP = 'a026e005';
|
|
41
43
|
const cwABike = {
|
|
@@ -54,12 +56,13 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
54
56
|
this.tsPrevWrite = undefined;
|
|
55
57
|
this.prevSlope = undefined;
|
|
56
58
|
this.data = {};
|
|
59
|
+
this.wahooCP = WAHOO_ADVANCED_TRAINER_CP;
|
|
57
60
|
}
|
|
58
61
|
isMatching(characteristics) {
|
|
59
62
|
if (!characteristics)
|
|
60
63
|
return false;
|
|
61
|
-
const hasWahooCP = characteristics.find(c => c
|
|
62
|
-
const hasFTMS = characteristics.find(c => c
|
|
64
|
+
const hasWahooCP = characteristics.find(c => (0, ble_1.matches)(c, WAHOO_ADVANCED_TRAINER_CP)) !== undefined;
|
|
65
|
+
const hasFTMS = characteristics.find(c => (0, ble_1.matches)(c, consts_1.FTMS_CP)) !== undefined;
|
|
63
66
|
return hasWahooCP && !hasFTMS;
|
|
64
67
|
}
|
|
65
68
|
init() {
|
|
@@ -68,7 +71,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
68
71
|
});
|
|
69
72
|
return __awaiter(this, void 0, void 0, function* () {
|
|
70
73
|
try {
|
|
71
|
-
yield this.subscribeWriteResponse(
|
|
74
|
+
yield this.subscribeWriteResponse(this.wahooCP);
|
|
72
75
|
yield _super.initDevice.call(this);
|
|
73
76
|
return true;
|
|
74
77
|
}
|
|
@@ -78,6 +81,12 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
78
81
|
}
|
|
79
82
|
});
|
|
80
83
|
}
|
|
84
|
+
setCharacteristicUUIDs(uuids) {
|
|
85
|
+
uuids.forEach(c => {
|
|
86
|
+
if ((0, ble_1.matches)(c, WAHOO_ADVANCED_TRAINER_CP))
|
|
87
|
+
this.wahooCP = c;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
81
90
|
getProfile() {
|
|
82
91
|
return 'Wahoo Smart Trainer';
|
|
83
92
|
}
|
|
@@ -154,6 +163,9 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
154
163
|
}
|
|
155
164
|
onData(characteristic, data) {
|
|
156
165
|
super.onData(characteristic, data);
|
|
166
|
+
const isDuplicate = this.checkForDuplicate(characteristic, data);
|
|
167
|
+
if (isDuplicate)
|
|
168
|
+
return;
|
|
157
169
|
const uuid = characteristic.toLocaleLowerCase();
|
|
158
170
|
let res = undefined;
|
|
159
171
|
switch (uuid) {
|
|
@@ -181,7 +193,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
181
193
|
const opcode = Buffer.alloc(1);
|
|
182
194
|
opcode.writeUInt8(requestedOpCode, 0);
|
|
183
195
|
const message = Buffer.concat([opcode, data]);
|
|
184
|
-
const res = yield this.write(
|
|
196
|
+
const res = yield this.write(this.wahooCP, message);
|
|
185
197
|
const responseData = Buffer.from(res);
|
|
186
198
|
const result = responseData.readUInt8(0);
|
|
187
199
|
this.logEvent({ message: 'response', opCode: requestedOpCode, response: responseData.toString('hex') });
|