incyclist-devices 1.4.79 → 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/fm.js +3 -1
- 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 +19 -15
- package/lib/ble/wahoo-kickr.d.ts +2 -0
- package/lib/ble/wahoo-kickr.js +15 -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;
|
package/lib/ble/fm.js
CHANGED
|
@@ -306,6 +306,9 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
306
306
|
}
|
|
307
307
|
onData(characteristic, data) {
|
|
308
308
|
super.onData(characteristic, data);
|
|
309
|
+
const isDuplicate = this.checkForDuplicate(characteristic, data);
|
|
310
|
+
if (isDuplicate)
|
|
311
|
+
return;
|
|
309
312
|
const uuid = characteristic.toLocaleLowerCase();
|
|
310
313
|
let res = undefined;
|
|
311
314
|
switch (uuid) {
|
|
@@ -321,7 +324,6 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
321
324
|
case '2a63':
|
|
322
325
|
case '2a5b':
|
|
323
326
|
case '347b0011-7635-408b-8918-8ff3949ce592':
|
|
324
|
-
this.logger.logEvent({ message: 'onBleData', raw: `uuid:${data.toString('hex')}` });
|
|
325
327
|
break;
|
|
326
328
|
default:
|
|
327
329
|
break;
|
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,6 +33,7 @@ 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"));
|
|
@@ -75,15 +76,25 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
75
76
|
this.data = {};
|
|
76
77
|
this.hasFECData = false;
|
|
77
78
|
this.messageCnt = 0;
|
|
78
|
-
this.
|
|
79
|
+
this.tacxRx = consts_1.TACX_FE_C_RX;
|
|
80
|
+
this.tacxTx = consts_1.TACX_FE_C_TX;
|
|
79
81
|
}
|
|
80
82
|
isMatching(characteristics) {
|
|
81
83
|
if (!characteristics)
|
|
82
84
|
return false;
|
|
83
|
-
const hasTacxCP = characteristics.find(c =>
|
|
84
|
-
|
|
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;
|
|
85
88
|
return hasTacxCP;
|
|
86
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
|
+
});
|
|
97
|
+
}
|
|
87
98
|
init() {
|
|
88
99
|
const _super = Object.create(null, {
|
|
89
100
|
initDevice: { get: () => super.initDevice }
|
|
@@ -423,20 +434,13 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
423
434
|
return res;
|
|
424
435
|
}
|
|
425
436
|
onData(characteristic, data) {
|
|
437
|
+
const isDuplicate = this.checkForDuplicate(characteristic, data);
|
|
438
|
+
if (isDuplicate)
|
|
439
|
+
return;
|
|
426
440
|
try {
|
|
427
441
|
const uuid = characteristic.toLocaleLowerCase();
|
|
428
|
-
const message = data.toString('hex');
|
|
429
|
-
const ts = Date.now();
|
|
430
|
-
if (this.prevMessages[uuid]) {
|
|
431
|
-
const prev = this.prevMessages[uuid];
|
|
432
|
-
if (prev.message === message && prev.ts > ts - 500) {
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
this.prevMessages[uuid] = { uuid, ts, message };
|
|
437
|
-
this.messageCnt++;
|
|
438
442
|
let res = undefined;
|
|
439
|
-
if (uuid &&
|
|
443
|
+
if (uuid && (0, ble_1.matches)(uuid, this.tacxRx)) {
|
|
440
444
|
res = this.parseFECMessage(data);
|
|
441
445
|
}
|
|
442
446
|
else {
|
|
@@ -492,7 +496,7 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
492
496
|
}
|
|
493
497
|
sendMessage(message) {
|
|
494
498
|
return __awaiter(this, void 0, void 0, function* () {
|
|
495
|
-
yield this.write(
|
|
499
|
+
yield this.write(this.tacxTx, message, true);
|
|
496
500
|
return true;
|
|
497
501
|
});
|
|
498
502
|
}
|
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,6 +33,7 @@ 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"));
|
|
@@ -55,12 +56,13 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
55
56
|
this.tsPrevWrite = undefined;
|
|
56
57
|
this.prevSlope = undefined;
|
|
57
58
|
this.data = {};
|
|
59
|
+
this.wahooCP = WAHOO_ADVANCED_TRAINER_CP;
|
|
58
60
|
}
|
|
59
61
|
isMatching(characteristics) {
|
|
60
62
|
if (!characteristics)
|
|
61
63
|
return false;
|
|
62
|
-
const hasWahooCP = characteristics.find(c => c
|
|
63
|
-
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;
|
|
64
66
|
return hasWahooCP && !hasFTMS;
|
|
65
67
|
}
|
|
66
68
|
init() {
|
|
@@ -69,7 +71,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
69
71
|
});
|
|
70
72
|
return __awaiter(this, void 0, void 0, function* () {
|
|
71
73
|
try {
|
|
72
|
-
yield this.subscribeWriteResponse(
|
|
74
|
+
yield this.subscribeWriteResponse(this.wahooCP);
|
|
73
75
|
yield _super.initDevice.call(this);
|
|
74
76
|
return true;
|
|
75
77
|
}
|
|
@@ -79,6 +81,12 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
79
81
|
}
|
|
80
82
|
});
|
|
81
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
|
+
}
|
|
82
90
|
getProfile() {
|
|
83
91
|
return 'Wahoo Smart Trainer';
|
|
84
92
|
}
|
|
@@ -155,6 +163,9 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
155
163
|
}
|
|
156
164
|
onData(characteristic, data) {
|
|
157
165
|
super.onData(characteristic, data);
|
|
166
|
+
const isDuplicate = this.checkForDuplicate(characteristic, data);
|
|
167
|
+
if (isDuplicate)
|
|
168
|
+
return;
|
|
158
169
|
const uuid = characteristic.toLocaleLowerCase();
|
|
159
170
|
let res = undefined;
|
|
160
171
|
switch (uuid) {
|
|
@@ -182,7 +193,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
182
193
|
const opcode = Buffer.alloc(1);
|
|
183
194
|
opcode.writeUInt8(requestedOpCode, 0);
|
|
184
195
|
const message = Buffer.concat([opcode, data]);
|
|
185
|
-
const res = yield this.write(
|
|
196
|
+
const res = yield this.write(this.wahooCP, message);
|
|
186
197
|
const responseData = Buffer.from(res);
|
|
187
198
|
const result = responseData.readUInt8(0);
|
|
188
199
|
this.logEvent({ message: 'response', opCode: requestedOpCode, response: responseData.toString('hex') });
|