incyclist-devices 1.4.67 → 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.
- package/lib/ble/ble-device.d.ts +6 -0
- package/lib/ble/ble-device.js +46 -4
- package/lib/ble/ble-interface.js +2 -2
- package/lib/ble/fm.d.ts +1 -0
- package/lib/ble/fm.js +27 -21
- package/lib/ble/tacx.js +6 -6
- package/lib/ble/wahoo-kickr.js +7 -23
- package/package.json +1 -1
package/lib/ble/ble-device.d.ts
CHANGED
|
@@ -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,6 +27,7 @@ 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;
|
|
@@ -36,12 +38,16 @@ export declare abstract class BleDevice extends BleDeviceClass {
|
|
|
36
38
|
waitForConnectFinished(timeout: any): Promise<unknown>;
|
|
37
39
|
hasService(serviceUuid: any): boolean;
|
|
38
40
|
init(): Promise<boolean>;
|
|
41
|
+
initDevice(): Promise<boolean>;
|
|
39
42
|
connectPeripheral(peripheral: BlePeripheral): Promise<void>;
|
|
40
43
|
subscribeAll(conn?: BlePeripheralConnector): Promise<void>;
|
|
41
44
|
connect(props?: ConnectProps): Promise<boolean>;
|
|
42
45
|
disconnect(): Promise<boolean>;
|
|
43
46
|
abstract getProfile(): string;
|
|
44
47
|
onData(characteristic: string, data: Buffer): void;
|
|
48
|
+
timeoutCheck(): void;
|
|
49
|
+
startWorker(): void;
|
|
50
|
+
stopWorker(): void;
|
|
45
51
|
write(characteristicUuid: string, data: Buffer, withoutResponse?: boolean): Promise<ArrayBuffer>;
|
|
46
52
|
read(characteristicUuid: string): Promise<Uint8Array>;
|
|
47
53
|
getDeviceInfo(): Promise<BleDeviceInfo>;
|
package/lib/ble/ble-device.js
CHANGED
|
@@ -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;
|
|
@@ -106,11 +107,17 @@ class BleDevice extends ble_1.BleDeviceClass {
|
|
|
106
107
|
return this.services && this.services.find(s => s === serviceUuid || (0, ble_1.uuid)(serviceUuid)) !== undefined;
|
|
107
108
|
}
|
|
108
109
|
init() {
|
|
109
|
-
|
|
110
|
-
|
|
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' });
|
|
111
118
|
return this.getDeviceInfo().then(() => {
|
|
112
119
|
this.emit('deviceInfo', this.deviceInfo);
|
|
113
|
-
this.logEvent(Object.assign({ message: '
|
|
120
|
+
this.logEvent(Object.assign({ message: 'device init done' }, this.deviceInfo));
|
|
114
121
|
this.isInitialized = true;
|
|
115
122
|
return true;
|
|
116
123
|
});
|
|
@@ -223,6 +230,9 @@ class BleDevice extends ble_1.BleDeviceClass {
|
|
|
223
230
|
const { id, name, address } = this;
|
|
224
231
|
this.logEvent({ message: 'disconnect requested', device: { id, name, address } });
|
|
225
232
|
this.connectState.isDisconnecting = true;
|
|
233
|
+
if (this.workerIv) {
|
|
234
|
+
this.stopWorker();
|
|
235
|
+
}
|
|
226
236
|
if (!this.connectState.isConnecting && !this.connectState.isConnected) {
|
|
227
237
|
this.connectState.isDisconnecting = false;
|
|
228
238
|
this.logEvent({ message: 'disconnect result: success', device: { id, name, address } });
|
|
@@ -254,11 +264,43 @@ class BleDevice extends ble_1.BleDeviceClass {
|
|
|
254
264
|
}
|
|
255
265
|
}
|
|
256
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
|
+
}
|
|
257
296
|
write(characteristicUuid, data, withoutResponse = false) {
|
|
258
297
|
return __awaiter(this, void 0, void 0, function* () {
|
|
259
298
|
try {
|
|
260
299
|
const connector = this.ble.getConnector(this.peripheral);
|
|
261
300
|
const isAlreadySubscribed = connector.isSubscribed(characteristicUuid);
|
|
301
|
+
if (!withoutResponse && !this.workerIv) {
|
|
302
|
+
this.startWorker();
|
|
303
|
+
}
|
|
262
304
|
if (!withoutResponse && !isAlreadySubscribed) {
|
|
263
305
|
const connector = this.ble.getConnector(this.peripheral);
|
|
264
306
|
connector.removeAllListeners(characteristicUuid);
|
|
@@ -284,7 +326,7 @@ class BleDevice extends ble_1.BleDeviceClass {
|
|
|
284
326
|
else {
|
|
285
327
|
const writeId = this.writeQueue.length;
|
|
286
328
|
let messageDeleted = false;
|
|
287
|
-
this.writeQueue.push({ uuid: characteristicUuid.toLocaleLowerCase(), data, resolve, reject });
|
|
329
|
+
this.writeQueue.push({ uuid: characteristicUuid.toLocaleLowerCase(), data, timeout: Date.now() + 1000, resolve, reject });
|
|
288
330
|
const to = setTimeout(() => {
|
|
289
331
|
if (this.writeQueue.length > writeId && !messageDeleted)
|
|
290
332
|
this.writeQueue.splice(writeId, 1);
|
package/lib/ble/ble-interface.js
CHANGED
|
@@ -590,14 +590,14 @@ class BleInterface extends ble_1.BleInterfaceClass {
|
|
|
590
590
|
cntFound++;
|
|
591
591
|
const existing = devicesProcessed.find(device => device.id === d.id && device.getProfile() === d.getProfile());
|
|
592
592
|
if (!scanForDevice && cntFound > 0 && !existing) {
|
|
593
|
-
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(',') });
|
|
594
594
|
this.addDeviceToCache(d, peripheral.state === 'connected');
|
|
595
595
|
devicesProcessed.push(d);
|
|
596
596
|
this.emit('device', d);
|
|
597
597
|
return;
|
|
598
598
|
}
|
|
599
599
|
if (scanForDevice && cntFound > 0) {
|
|
600
|
-
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(',') });
|
|
601
601
|
this.addDeviceToCache(d, peripheral.state === 'connected');
|
|
602
602
|
devicesProcessed.push(d);
|
|
603
603
|
this.emit('device', d);
|
package/lib/ble/fm.d.ts
CHANGED
|
@@ -53,6 +53,7 @@ export default class BleFitnessMachineDevice extends BleDevice {
|
|
|
53
53
|
wheelSize: number;
|
|
54
54
|
constructor(props?: any);
|
|
55
55
|
isMatching(characteristics: string[]): boolean;
|
|
56
|
+
subscribeWriteResponse(cuuid: string): Promise<void>;
|
|
56
57
|
init(): Promise<boolean>;
|
|
57
58
|
onDisconnect(): void;
|
|
58
59
|
getProfile(): string;
|
package/lib/ble/fm.js
CHANGED
|
@@ -104,35 +104,40 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
104
104
|
const hasIndoorBike = characteristics.find(c => c === INDOOR_BIKE_DATA) !== undefined;
|
|
105
105
|
return hasStatus && hasCP && hasIndoorBike;
|
|
106
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
|
+
}
|
|
107
128
|
init() {
|
|
108
129
|
const _super = Object.create(null, {
|
|
109
|
-
|
|
130
|
+
initDevice: { get: () => super.initDevice }
|
|
110
131
|
});
|
|
111
132
|
return __awaiter(this, void 0, void 0, function* () {
|
|
112
133
|
try {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (!isAlreadySubscribed) {
|
|
116
|
-
connector.removeAllListeners(FTMS_CP);
|
|
117
|
-
let prev = undefined;
|
|
118
|
-
let prevTS = undefined;
|
|
119
|
-
connector.on(FTMS_CP, (uuid, data) => {
|
|
120
|
-
const message = data.toString('hex');
|
|
121
|
-
if (prevTS && prev && message === prev && Date.now() - prevTS < 500) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
prevTS = Date.now();
|
|
125
|
-
prev = message;
|
|
126
|
-
this.onData(uuid, data);
|
|
127
|
-
});
|
|
128
|
-
yield connector.subscribe(FTMS_CP);
|
|
129
|
-
}
|
|
130
|
-
this.logEvent({ message: 'get device info' });
|
|
131
|
-
yield _super.init.call(this);
|
|
134
|
+
yield this.subscribeWriteResponse(FTMS_CP);
|
|
135
|
+
yield _super.initDevice.call(this);
|
|
132
136
|
yield this.getFitnessMachineFeatures();
|
|
133
137
|
this.logEvent({ message: 'device info', deviceInfo: this.deviceInfo, features: this.features });
|
|
134
138
|
}
|
|
135
139
|
catch (err) {
|
|
140
|
+
this.logEvent({ message: 'error', fn: 'BleFitnessMachineDevice.init()', error: err.message || err, stack: err.stack });
|
|
136
141
|
return Promise.resolve(false);
|
|
137
142
|
}
|
|
138
143
|
});
|
|
@@ -504,7 +509,8 @@ class FmAdapter extends Device_1.default {
|
|
|
504
509
|
return (adapter.getName() === this.getName() && adapter.getProfile() === this.getProfile());
|
|
505
510
|
}
|
|
506
511
|
getProfile() {
|
|
507
|
-
|
|
512
|
+
const profile = this.device ? this.device.getProfile() : undefined;
|
|
513
|
+
return profile || 'Smart Trainer';
|
|
508
514
|
}
|
|
509
515
|
getName() {
|
|
510
516
|
return `${this.device.name}`;
|
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
|
|
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
|
-
|
|
82
|
+
initDevice: { get: () => super.initDevice }
|
|
83
83
|
});
|
|
84
84
|
return __awaiter(this, void 0, void 0, function* () {
|
|
85
85
|
try {
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
90
|
+
this.logEvent({ message: 'error', fn: 'TacxAdvancedFitnessMachineDevice.init()', error: err.message || err, stack: err.stack });
|
|
91
|
+
return false;
|
|
92
92
|
}
|
|
93
93
|
});
|
|
94
94
|
}
|
package/lib/ble/wahoo-kickr.js
CHANGED
|
@@ -62,33 +62,17 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
62
62
|
}
|
|
63
63
|
init() {
|
|
64
64
|
const _super = Object.create(null, {
|
|
65
|
-
|
|
65
|
+
initDevice: { get: () => super.initDevice }
|
|
66
66
|
});
|
|
67
67
|
return __awaiter(this, void 0, void 0, function* () {
|
|
68
68
|
try {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
connector.removeAllListeners(WAHOO_ADVANCED_TRAINER_CP);
|
|
73
|
-
let prev = undefined;
|
|
74
|
-
let prevTS = undefined;
|
|
75
|
-
connector.on(WAHOO_ADVANCED_TRAINER_CP, (uuid, data) => {
|
|
76
|
-
const message = data.toString('hex');
|
|
77
|
-
if (prevTS && prev && message === prev && Date.now() - prevTS < 500) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
prevTS = Date.now();
|
|
81
|
-
prev = message;
|
|
82
|
-
this.onData(uuid, data);
|
|
83
|
-
});
|
|
84
|
-
yield connector.subscribe(WAHOO_ADVANCED_TRAINER_CP);
|
|
85
|
-
}
|
|
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 });
|
|
69
|
+
yield this.subscribeWriteResponse(WAHOO_ADVANCED_TRAINER_CP);
|
|
70
|
+
yield _super.initDevice.call(this);
|
|
71
|
+
return true;
|
|
89
72
|
}
|
|
90
73
|
catch (err) {
|
|
91
|
-
|
|
74
|
+
this.logEvent({ message: 'error', fn: 'WahooAdvancedFitnessMachineDevice.init()', error: err.message || err, stack: err.stack });
|
|
75
|
+
return false;
|
|
92
76
|
}
|
|
93
77
|
});
|
|
94
78
|
}
|
|
@@ -195,7 +179,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
|
|
|
195
179
|
const opcode = Buffer.alloc(1);
|
|
196
180
|
opcode.writeUInt8(requestedOpCode, 0);
|
|
197
181
|
const message = Buffer.concat([opcode, data]);
|
|
198
|
-
const res = yield this.write(
|
|
182
|
+
const res = yield this.write(WAHOO_ADVANCED_TRAINER_CP, message);
|
|
199
183
|
const responseData = Buffer.from(res);
|
|
200
184
|
const result = responseData.readUInt8(0);
|
|
201
185
|
this.logEvent({ message: 'response', opCode: requestedOpCode, response: responseData.toString('hex') });
|