incyclist-devices 2.3.37 → 2.3.39
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/antv2/base/adapter.js +5 -5
- package/lib/antv2/fe/adapter.js +2 -2
- package/lib/antv2/pwr/adapter.js +1 -1
- package/lib/base/adpater.js +2 -3
- package/lib/ble/cp/adapter.js +1 -1
- package/lib/ble/cp/sensor.js +1 -1
- package/lib/ble/fm/adapter.d.ts +1 -0
- package/lib/ble/fm/adapter.js +8 -2
- package/lib/ble/hr/sensor.js +1 -1
- package/lib/ble/utils.js +1 -1
- package/lib/ble/zwift/play/sensor.js +1 -2
- package/lib/direct-connect/base/peripheral.js +0 -1
- package/lib/direct-connect/messages/DiscoverCharacteristics.d.ts +1 -1
- package/lib/direct-connect/messages/DiscoverCharacteristics.js +3 -2
- package/lib/direct-connect/messages/DiscoverServices.d.ts +1 -1
- package/lib/direct-connect/messages/DiscoverServices.js +5 -3
- package/lib/direct-connect/messages/message.d.ts +1 -1
- package/lib/direct-connect/messages/message.js +2 -1
- package/lib/features/features.d.ts +11 -0
- package/lib/features/features.js +29 -0
- package/lib/features/index.d.ts +1 -0
- package/lib/features/index.js +17 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/modes/antble-smarttrainer.d.ts +5 -0
- package/lib/modes/antble-smarttrainer.js +82 -27
- package/lib/modes/base.d.ts +3 -0
- package/lib/modes/base.js +20 -0
- package/lib/modes/daum-erg.d.ts +1 -0
- package/lib/modes/daum-erg.js +3 -0
- package/lib/modes/daum-premium-standard.js +1 -1
- package/lib/modes/daum-smarttrainer.js +7 -7
- package/lib/modes/power-base.d.ts +1 -0
- package/lib/modes/power-base.js +7 -2
- package/lib/modes/types.d.ts +2 -2
- package/lib/modes/types.js +1 -1
- package/lib/serial/bindings/tcp.js +8 -8
- package/lib/serial/daum/DaumAdapter.js +2 -2
- package/lib/serial/daum/classic/adapter.d.ts +1 -1
- package/lib/serial/daum/classic/adapter.js +9 -10
- package/lib/serial/daum/classic/mock.js +1 -1
- package/lib/serial/daum/premium/comms.js +5 -5
- package/lib/serial/daum/premium/mock.js +1 -1
- package/lib/serial/daum/premium/utils.js +12 -12
- package/lib/serial/kettler/ergo-racer/adapter.d.ts +1 -1
- package/lib/serial/kettler/ergo-racer/adapter.js +43 -50
- package/lib/simulator/Simulator.js +1 -1
- package/lib/utils/utils.js +5 -5
- package/package.json +2 -2
package/lib/modes/base.js
CHANGED
|
@@ -71,6 +71,26 @@ class CyclingModeBase extends types_1.CyclingMode {
|
|
|
71
71
|
return prop.default;
|
|
72
72
|
return undefined;
|
|
73
73
|
}
|
|
74
|
+
updateRequired(request = {}) {
|
|
75
|
+
const prevRequest = Object.assign({}, this.prevUpdate);
|
|
76
|
+
this.prevUpdate = Object.assign({}, request);
|
|
77
|
+
if (prevRequest && !request.targetPowerDelta && !request.reset) {
|
|
78
|
+
if ((request.slope !== undefined && prevRequest.slope === request.slope) &&
|
|
79
|
+
(request.targetPower !== undefined && prevRequest.targetPower === request.targetPower)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
buildUpdate(request) {
|
|
86
|
+
if (!request) {
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
if (!this.updateRequired(request)) {
|
|
90
|
+
return {};
|
|
91
|
+
}
|
|
92
|
+
return this.sendBikeUpdate(request);
|
|
93
|
+
}
|
|
74
94
|
}
|
|
75
95
|
exports.CyclingModeBase = CyclingModeBase;
|
|
76
96
|
CyclingModeBase.config = { name: '', description: '', properties: [] };
|
package/lib/modes/daum-erg.d.ts
CHANGED
|
@@ -47,4 +47,5 @@ export default class ERGCyclingMode extends PowerBasedCyclingModeBase implements
|
|
|
47
47
|
private checkIsStarting;
|
|
48
48
|
calculateTargetPower(request: any, updateMode?: boolean): any;
|
|
49
49
|
protected checkForTempPowerAdjustments(request: UpdateRequest): void;
|
|
50
|
+
protected applyCadenceFixes(): boolean;
|
|
50
51
|
}
|
package/lib/modes/daum-erg.js
CHANGED
|
@@ -43,7 +43,7 @@ class DaumClassicCyclingMode extends power_meter_1.default {
|
|
|
43
43
|
this.distanceOffset = calculateDistance - distanceBike;
|
|
44
44
|
distanceInternal = calculateDistance;
|
|
45
45
|
}
|
|
46
|
-
data.speed = parseFloat(speed.toFixed(1));
|
|
46
|
+
data.speed = Number.parseFloat(speed.toFixed(1));
|
|
47
47
|
data.power = Math.round(power);
|
|
48
48
|
data.distanceInternal = distanceInternal;
|
|
49
49
|
data.slope = slope;
|
|
@@ -53,12 +53,11 @@ class SmartTrainerCyclingMode extends base_1.CyclingModeBase {
|
|
|
53
53
|
const minMaxStr = this.getSetting(`${source}Rings`);
|
|
54
54
|
const values = minMaxStr.split('-');
|
|
55
55
|
if (values[0] && values[1] && values[0] < values[1]) {
|
|
56
|
-
return [parseInt(values[0]), parseInt(values[1])];
|
|
56
|
+
return [Number.parseInt(values[0]), Number.parseInt(values[1])];
|
|
57
57
|
}
|
|
58
58
|
if (values[0] && values[1] && values[0] > values[1]) {
|
|
59
|
-
return [parseInt(values[1]), parseInt(values[0])];
|
|
59
|
+
return [Number.parseInt(values[1]), Number.parseInt(values[0])];
|
|
60
60
|
}
|
|
61
|
-
return;
|
|
62
61
|
}
|
|
63
62
|
sendBikeUpdate(request) {
|
|
64
63
|
const getData = () => {
|
|
@@ -70,7 +69,7 @@ class SmartTrainerCyclingMode extends base_1.CyclingModeBase {
|
|
|
70
69
|
const event = Object.assign({}, this.event);
|
|
71
70
|
if (this.data === undefined)
|
|
72
71
|
event.noData = true;
|
|
73
|
-
const slope = request.slope === undefined ? request.slope : parseFloat(request.slope.toFixed(1));
|
|
72
|
+
const slope = request.slope === undefined ? request.slope : Number.parseFloat(request.slope.toFixed(1));
|
|
74
73
|
if (slope !== undefined && (event.noData || Math.abs(slope - this.data.slope) >= 0.1))
|
|
75
74
|
event.slopeUpdate = true;
|
|
76
75
|
if (this.prevRequest === undefined)
|
|
@@ -231,7 +230,7 @@ class SmartTrainerCyclingMode extends base_1.CyclingModeBase {
|
|
|
231
230
|
const v = speed / 3.6;
|
|
232
231
|
distanceInternal += (v * duration);
|
|
233
232
|
}
|
|
234
|
-
data.speed = parseFloat(speed.toFixed(1));
|
|
233
|
+
data.speed = Number.parseFloat(speed.toFixed(1));
|
|
235
234
|
data.power = Math.round(power);
|
|
236
235
|
data.distanceInternal = distanceInternal;
|
|
237
236
|
data.distance = distance;
|
|
@@ -294,17 +293,18 @@ class SmartTrainerCyclingMode extends base_1.CyclingModeBase {
|
|
|
294
293
|
return speed;
|
|
295
294
|
}
|
|
296
295
|
calculateTargetPower(request, speed) {
|
|
296
|
+
var _a, _b;
|
|
297
297
|
const defaultPower = this.getSetting('startPower');
|
|
298
298
|
const minPower = this.getSetting('minPower');
|
|
299
299
|
const bikeType = this.getSetting('bikeType').toLowerCase();
|
|
300
300
|
const m = this.getWeight();
|
|
301
301
|
const prevData = this.data || {};
|
|
302
|
-
const slope = parseFloat((request.slope
|
|
302
|
+
const slope = Number.parseFloat(((_b = (_a = request.slope) !== null && _a !== void 0 ? _a : prevData.slope) !== null && _b !== void 0 ? _b : 0).toFixed(1));
|
|
303
303
|
let target = request.targetPower || defaultPower;
|
|
304
304
|
if (prevData.speed !== undefined || speed !== undefined) {
|
|
305
305
|
const v = speed ? speed / 3.6 : prevData.speed / 3.6;
|
|
306
306
|
const calculatedPower = calculations_1.default.calculatePower(m, v, slope, { bikeType });
|
|
307
|
-
const power = (calculatedPower
|
|
307
|
+
const power = Math.max(calculatedPower, minPower);
|
|
308
308
|
let belowMin = (calculatedPower < minPower);
|
|
309
309
|
const powerDelta = power - prevData.power || 0;
|
|
310
310
|
let target;
|
|
@@ -34,6 +34,7 @@ export default class PowerBasedCyclingModeBase extends CyclingModeBase {
|
|
|
34
34
|
bikeType: any;
|
|
35
35
|
slope: any;
|
|
36
36
|
};
|
|
37
|
+
protected applyCadenceFixes(): boolean;
|
|
37
38
|
copyBikeData(data: IncyclistBikeData, bikeData: IncyclistBikeData): IncyclistBikeData;
|
|
38
39
|
calculatePowerAndDistance(speed: number, slope: number, m: number, t: number, props?: {}): {
|
|
39
40
|
power: number;
|
package/lib/modes/power-base.js
CHANGED
|
@@ -177,6 +177,9 @@ class PowerBasedCyclingModeBase extends base_1.CyclingModeBase {
|
|
|
177
177
|
this.copyBikeData(data, bikeData);
|
|
178
178
|
return { data, prevData, prevRequest, bikeType, slope };
|
|
179
179
|
}
|
|
180
|
+
applyCadenceFixes() {
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
180
183
|
copyBikeData(data, bikeData) {
|
|
181
184
|
var _a;
|
|
182
185
|
const prevCadence = data.pedalRpm;
|
|
@@ -197,8 +200,10 @@ class PowerBasedCyclingModeBase extends base_1.CyclingModeBase {
|
|
|
197
200
|
data.slope = 0;
|
|
198
201
|
if (bikeData.isPedalling === undefined)
|
|
199
202
|
(data.isPedalling = data.pedalRpm > 0 || data.power > 0);
|
|
200
|
-
if (
|
|
201
|
-
|
|
203
|
+
if (this.applyCadenceFixes()) {
|
|
204
|
+
if (bikeData.pedalRpm === 0 && bikeData.power > 0 && prevCadence !== undefined) {
|
|
205
|
+
data.pedalRpm = prevCadence;
|
|
206
|
+
}
|
|
202
207
|
}
|
|
203
208
|
if (((_a = this.prevRequest) === null || _a === void 0 ? void 0 : _a.slope) !== undefined) {
|
|
204
209
|
data.slope = this.prevRequest.slope;
|
package/lib/modes/types.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export default interface ICyclingMode {
|
|
|
41
41
|
getProperties(): CyclingModeProperty[];
|
|
42
42
|
getProperty(name: string): CyclingModeProperty;
|
|
43
43
|
getBikeInitRequest(): UpdateRequest;
|
|
44
|
-
|
|
44
|
+
buildUpdate(request: UpdateRequest): UpdateRequest;
|
|
45
45
|
updateData(data: IncyclistBikeData): IncyclistBikeData;
|
|
46
46
|
setSettings(settings: any): any;
|
|
47
47
|
setSetting(name: string, value: any): void;
|
|
@@ -66,7 +66,7 @@ export declare class CyclingMode implements ICyclingMode {
|
|
|
66
66
|
getProperties(): CyclingModeProperty[];
|
|
67
67
|
getProperty(_name: string): CyclingModeProperty;
|
|
68
68
|
getBikeInitRequest(): UpdateRequest;
|
|
69
|
-
|
|
69
|
+
buildUpdate(_request: UpdateRequest): UpdateRequest;
|
|
70
70
|
updateData(_data: IncyclistBikeData): IncyclistBikeData;
|
|
71
71
|
setSettings(_settings: any): void;
|
|
72
72
|
setSetting(_name: string, _value: any): void;
|
package/lib/modes/types.js
CHANGED
|
@@ -38,7 +38,7 @@ function scanPort(host, port) {
|
|
|
38
38
|
try {
|
|
39
39
|
socket.destroy();
|
|
40
40
|
}
|
|
41
|
-
catch (
|
|
41
|
+
catch (_a) { }
|
|
42
42
|
socket.removeAllListeners();
|
|
43
43
|
};
|
|
44
44
|
socket.setTimeout(1000);
|
|
@@ -47,7 +47,7 @@ function scanPort(host, port) {
|
|
|
47
47
|
socket.on('ready', () => { resolve(true); cleanup(); });
|
|
48
48
|
socket.connect(port, host);
|
|
49
49
|
}
|
|
50
|
-
catch (
|
|
50
|
+
catch (_a) {
|
|
51
51
|
resolve(false);
|
|
52
52
|
}
|
|
53
53
|
});
|
|
@@ -109,10 +109,10 @@ exports.TCPBinding = {
|
|
|
109
109
|
return reject(new TypeError('"path" is not valid'));
|
|
110
110
|
host = res[0];
|
|
111
111
|
port = Number(res[1]);
|
|
112
|
-
if (isNaN(port))
|
|
112
|
+
if (Number.isNaN(port))
|
|
113
113
|
return reject(new TypeError('"path" is not valid'));
|
|
114
114
|
}
|
|
115
|
-
catch (
|
|
115
|
+
catch (_a) {
|
|
116
116
|
return reject(new TypeError('"path" is not valid'));
|
|
117
117
|
}
|
|
118
118
|
const socket = new net_1.default.Socket();
|
|
@@ -207,11 +207,11 @@ class TCPPortBinding {
|
|
|
207
207
|
if (!Buffer.isBuffer(buffer)) {
|
|
208
208
|
throw new TypeError('"buffer" is not a Buffer');
|
|
209
209
|
}
|
|
210
|
-
if (typeof offset !== 'number' || isNaN(offset)) {
|
|
211
|
-
throw new TypeError(`"offset" is not an integer got "${isNaN(offset) ? 'NaN' : typeof offset}"`);
|
|
210
|
+
if (typeof offset !== 'number' || Number.isNaN(offset)) {
|
|
211
|
+
throw new TypeError(`"offset" is not an integer got "${Number.isNaN(offset) ? 'NaN' : typeof offset}"`);
|
|
212
212
|
}
|
|
213
|
-
if (typeof length !== 'number' || isNaN(length)) {
|
|
214
|
-
throw new TypeError(`"length" is not an integer got "${isNaN(length) ? 'NaN' : typeof length}"`);
|
|
213
|
+
if (typeof length !== 'number' || Number.isNaN(length)) {
|
|
214
|
+
throw new TypeError(`"length" is not an integer got "${Number.isNaN(length) ? 'NaN' : typeof length}"`);
|
|
215
215
|
}
|
|
216
216
|
if (buffer.length < offset + length) {
|
|
217
217
|
throw new Error('buffer is too small');
|
|
@@ -508,7 +508,7 @@ class DaumAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
508
508
|
return;
|
|
509
509
|
if (!this.deviceData.isPedalling || this.deviceData.pedalRpm === 0)
|
|
510
510
|
return;
|
|
511
|
-
let bikeRequest = this.getCyclingMode().
|
|
511
|
+
let bikeRequest = this.getCyclingMode().buildUpdate({ refresh: true }) || {};
|
|
512
512
|
const prev = this.requests[this.requests.length - 1] || {};
|
|
513
513
|
if (bikeRequest.targetPower !== undefined && bikeRequest.targetPower !== prev.targetPower) {
|
|
514
514
|
this.logEvent({ message: 'add request', request: bikeRequest });
|
|
@@ -521,7 +521,7 @@ class DaumAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
521
521
|
}
|
|
522
522
|
return new Promise((resolve) => {
|
|
523
523
|
const fn = () => __awaiter(this, void 0, void 0, function* () {
|
|
524
|
-
let bikeRequest = this.getCyclingMode().
|
|
524
|
+
let bikeRequest = this.getCyclingMode().buildUpdate(request);
|
|
525
525
|
this.logEvent({ message: 'add request', request: bikeRequest });
|
|
526
526
|
this.requests.push(bikeRequest);
|
|
527
527
|
resolve(bikeRequest);
|
|
@@ -4,7 +4,7 @@ import { SerialDeviceSettings, SerialCommProps } from "../../types";
|
|
|
4
4
|
import { IncyclistBikeData, ControllerConfig } from "../../../types";
|
|
5
5
|
import Daum8008 from './comms';
|
|
6
6
|
export default class DaumClassicAdapter extends DaumAdapter<SerialDeviceSettings, DaumClassicProperties, Daum8008> {
|
|
7
|
-
static NAME
|
|
7
|
+
static readonly NAME = "Daum Classic";
|
|
8
8
|
protected static controllers: ControllerConfig;
|
|
9
9
|
protected name: string;
|
|
10
10
|
protected id: string;
|
|
@@ -41,7 +41,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
|
|
|
41
41
|
else {
|
|
42
42
|
serial = props.interface;
|
|
43
43
|
}
|
|
44
|
-
if (!serial ||
|
|
44
|
+
if (!(serial === null || serial === void 0 ? void 0 : serial.binding))
|
|
45
45
|
throw new Error(`unknonwn interface: ${ifaceName}`);
|
|
46
46
|
const path = `${port}`;
|
|
47
47
|
return { serial, path };
|
|
@@ -57,8 +57,8 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
|
|
|
57
57
|
}
|
|
58
58
|
performCheck() {
|
|
59
59
|
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
-
|
|
61
|
-
const check =
|
|
60
|
+
const info = {};
|
|
61
|
+
const check = () => __awaiter(this, void 0, void 0, function* () {
|
|
62
62
|
this.logEvent({ message: "checking device", port: this.getPort() });
|
|
63
63
|
try {
|
|
64
64
|
yield this.stop();
|
|
@@ -66,8 +66,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
|
|
|
66
66
|
this.logEvent({ message: "checking device failed", port: this.getPort(), reason: 'timeout' });
|
|
67
67
|
});
|
|
68
68
|
if (!connected) {
|
|
69
|
-
|
|
70
|
-
return;
|
|
69
|
+
return false;
|
|
71
70
|
}
|
|
72
71
|
this.stopped = false;
|
|
73
72
|
const address = yield this.getComms().getAddress();
|
|
@@ -79,14 +78,14 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
|
|
|
79
78
|
this.pause();
|
|
80
79
|
this.started = false;
|
|
81
80
|
this.logEvent({ message: "checking device success", port: this.getPort(), info });
|
|
82
|
-
|
|
81
|
+
return true;
|
|
83
82
|
}
|
|
84
83
|
catch (err) {
|
|
85
84
|
this.logEvent({ message: "checking device failed", port: this.getPort(), reason: err.message });
|
|
86
|
-
|
|
85
|
+
return false;
|
|
87
86
|
}
|
|
88
|
-
})
|
|
89
|
-
return yield (0, utils_1.waitWithTimeout)(check, 5000, () => {
|
|
87
|
+
});
|
|
88
|
+
return yield (0, utils_1.waitWithTimeout)(check(), 5000, () => {
|
|
90
89
|
this.logEvent({ message: "checking device failed", port: this.getPort(), reason: 'Timeout' });
|
|
91
90
|
return false;
|
|
92
91
|
});
|
|
@@ -128,7 +127,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
|
|
|
128
127
|
try {
|
|
129
128
|
yield this.getComms().setBikeType(bikeType.toLowerCase());
|
|
130
129
|
}
|
|
131
|
-
catch (
|
|
130
|
+
catch (_a) {
|
|
132
131
|
}
|
|
133
132
|
startState.setBikeType = true;
|
|
134
133
|
}
|
|
@@ -405,25 +405,25 @@ class Daum8i extends comms_1.default {
|
|
|
405
405
|
return __awaiter(this, void 0, void 0, function* () {
|
|
406
406
|
const powerStr = typeof power === 'string' ? Number.parseFloat(power).toFixed(2) : power.toFixed(2);
|
|
407
407
|
const str = yield this.sendStrCommand('setPower', `S23${powerStr}`);
|
|
408
|
-
return parseInt(str);
|
|
408
|
+
return Number.parseInt(str);
|
|
409
409
|
});
|
|
410
410
|
}
|
|
411
411
|
getPower() {
|
|
412
412
|
return __awaiter(this, void 0, void 0, function* () {
|
|
413
413
|
const str = yield this.sendStrCommand('getPower', 'S23');
|
|
414
|
-
return parseInt(str);
|
|
414
|
+
return Number.parseInt(str);
|
|
415
415
|
});
|
|
416
416
|
}
|
|
417
417
|
setGear(gear) {
|
|
418
418
|
return __awaiter(this, void 0, void 0, function* () {
|
|
419
419
|
const str = yield this.sendStrCommand('setGear', `M71${gear}`);
|
|
420
|
-
return parseInt(str);
|
|
420
|
+
return Number.parseInt(str);
|
|
421
421
|
});
|
|
422
422
|
}
|
|
423
423
|
getGear() {
|
|
424
424
|
return __awaiter(this, void 0, void 0, function* () {
|
|
425
425
|
const str = yield this.sendStrCommand('getGear', 'M71');
|
|
426
|
-
return parseInt(str);
|
|
426
|
+
return Number.parseInt(str);
|
|
427
427
|
});
|
|
428
428
|
}
|
|
429
429
|
sendReservedDaum8iCommand(logString, command, data) {
|
|
@@ -442,7 +442,7 @@ class Daum8i extends comms_1.default {
|
|
|
442
442
|
}
|
|
443
443
|
const cmdData = Uint8Array.from(buffer);
|
|
444
444
|
const res = yield this.sendBinaryCommand(logString || 'ReservedCommand', 'M70', (0, utils_1.bin2esc)(cmdData));
|
|
445
|
-
const resData = Uint8Array.from(res, x => x.
|
|
445
|
+
const resData = Uint8Array.from(res, x => x.codePointAt(0));
|
|
446
446
|
const cmd = (0, utils_1.esc2bin)(resData);
|
|
447
447
|
return cmd;
|
|
448
448
|
});
|
|
@@ -26,7 +26,7 @@ exports.DEBUG_LOGGER = {
|
|
|
26
26
|
logEvent: (event) => console.log(JSON.stringify(event))
|
|
27
27
|
};
|
|
28
28
|
const GS = 0x1D;
|
|
29
|
-
const GS_CHAR = String.
|
|
29
|
+
const GS_CHAR = String.fromCodePoint(GS);
|
|
30
30
|
function responseLog(str) {
|
|
31
31
|
if (str.includes(GS_CHAR)) {
|
|
32
32
|
return str.split(GS_CHAR).join('/');
|
|
@@ -177,7 +177,7 @@ function hexstr(arr, start, len) {
|
|
|
177
177
|
return str;
|
|
178
178
|
}
|
|
179
179
|
function ascii(c) {
|
|
180
|
-
return c.
|
|
180
|
+
return c.codePointAt(0);
|
|
181
181
|
}
|
|
182
182
|
function getAsciiArrayFromStr(str) {
|
|
183
183
|
if (str === undefined || str === null)
|
|
@@ -185,7 +185,7 @@ function getAsciiArrayFromStr(str) {
|
|
|
185
185
|
const n = str.length;
|
|
186
186
|
let result = [];
|
|
187
187
|
for (let i = 0; i < n; i++) {
|
|
188
|
-
result.push(str.
|
|
188
|
+
result.push(str.codePointAt(i));
|
|
189
189
|
}
|
|
190
190
|
return result;
|
|
191
191
|
}
|
|
@@ -282,16 +282,16 @@ function routeToEpp(route, date) {
|
|
|
282
282
|
}
|
|
283
283
|
function parseTrainingData(payload) {
|
|
284
284
|
const gearVal = (v) => v > 0 ? v - 1 : undefined;
|
|
285
|
-
const vals = payload.split(String.
|
|
285
|
+
const vals = payload.split(String.fromCodePoint(GS));
|
|
286
286
|
const data = {
|
|
287
|
-
time: parseInt(vals[0]),
|
|
288
|
-
heartrate: parseInt(vals[1]),
|
|
289
|
-
speed: parseFloat(vals[2]) * 3.6,
|
|
290
|
-
slope: parseFloat(vals[3]),
|
|
291
|
-
distanceInternal: parseInt(vals[4]),
|
|
292
|
-
pedalRpm: parseFloat(vals[5]),
|
|
293
|
-
power: parseInt(vals[6]),
|
|
294
|
-
gear: gearVal(parseInt(vals[10])),
|
|
287
|
+
time: Number.parseInt(vals[0]),
|
|
288
|
+
heartrate: Number.parseInt(vals[1]),
|
|
289
|
+
speed: Number.parseFloat(vals[2]) * 3.6,
|
|
290
|
+
slope: Number.parseFloat(vals[3]),
|
|
291
|
+
distanceInternal: Number.parseInt(vals[4]),
|
|
292
|
+
pedalRpm: Number.parseFloat(vals[5]),
|
|
293
|
+
power: Number.parseInt(vals[6]),
|
|
294
|
+
gear: gearVal(Number.parseInt(vals[10])),
|
|
295
295
|
};
|
|
296
296
|
data.isPedalling = (data.pedalRpm > 0);
|
|
297
297
|
return data;
|
|
@@ -25,7 +25,7 @@ export interface KettlerBikeData {
|
|
|
25
25
|
export default class KettlerRacerAdapter extends SerialIncyclistDevice<DeviceProperties> {
|
|
26
26
|
private id;
|
|
27
27
|
private iv;
|
|
28
|
-
private requests;
|
|
28
|
+
private readonly requests;
|
|
29
29
|
private internalData;
|
|
30
30
|
private kettlerData;
|
|
31
31
|
private updateBusy;
|
|
@@ -171,18 +171,13 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
171
171
|
}
|
|
172
172
|
send(logStr, message, timeout) {
|
|
173
173
|
return __awaiter(this, void 0, void 0, function* () {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
catch (err) {
|
|
182
|
-
reject(err);
|
|
183
|
-
}
|
|
174
|
+
const opened = yield this.waitForOpened();
|
|
175
|
+
if (!opened) {
|
|
176
|
+
throw (new Error('connection error'));
|
|
177
|
+
}
|
|
178
|
+
return new Promise((resolve, reject) => {
|
|
184
179
|
this.comms.send({ logStr, message, onResponse: resolve, onError: reject, timeout });
|
|
185
|
-
})
|
|
180
|
+
});
|
|
186
181
|
});
|
|
187
182
|
}
|
|
188
183
|
parseExtendedStatus(data) {
|
|
@@ -193,39 +188,39 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
193
188
|
const states = data.split('\t');
|
|
194
189
|
const result = {};
|
|
195
190
|
if (states.length === 8) {
|
|
196
|
-
const hr = parseInt(states[0]);
|
|
197
|
-
if (!isNaN(hr)) {
|
|
191
|
+
const hr = Number.parseInt(states[0]);
|
|
192
|
+
if (!Number.isNaN(hr)) {
|
|
198
193
|
result.heartrate = hr;
|
|
199
194
|
}
|
|
200
|
-
|
|
201
|
-
if (!isNaN(cadence)) {
|
|
195
|
+
const cadence = Number.parseInt(states[1]);
|
|
196
|
+
if (!Number.isNaN(cadence)) {
|
|
202
197
|
result.cadence = cadence;
|
|
203
198
|
}
|
|
204
|
-
const speed = parseInt(states[2]);
|
|
205
|
-
if (!isNaN(speed)) {
|
|
199
|
+
const speed = Number.parseInt(states[2]);
|
|
200
|
+
if (!Number.isNaN(speed)) {
|
|
206
201
|
result.speed = speed * 0.1;
|
|
207
202
|
}
|
|
208
|
-
const distance = parseInt(states[3]);
|
|
209
|
-
if (!isNaN(distance)) {
|
|
203
|
+
const distance = Number.parseInt(states[3]);
|
|
204
|
+
if (!Number.isNaN(distance)) {
|
|
210
205
|
result.distance = distance * 100;
|
|
211
206
|
}
|
|
212
|
-
const requestedPower = parseInt(states[4]);
|
|
213
|
-
if (!isNaN(requestedPower)) {
|
|
207
|
+
const requestedPower = Number.parseInt(states[4]);
|
|
208
|
+
if (!Number.isNaN(requestedPower)) {
|
|
214
209
|
result.requestedPower = requestedPower;
|
|
215
210
|
}
|
|
216
|
-
const energy = parseInt(states[5]);
|
|
217
|
-
if (!isNaN(energy)) {
|
|
211
|
+
const energy = Number.parseInt(states[5]);
|
|
212
|
+
if (!Number.isNaN(energy)) {
|
|
218
213
|
result.energy = energy;
|
|
219
214
|
}
|
|
220
215
|
const timeStr = states[6];
|
|
221
216
|
const time = timeStr.split(':');
|
|
222
|
-
const hours = parseInt(time[0]);
|
|
223
|
-
const minutes = parseInt(time[1]);
|
|
224
|
-
if (!isNaN(hours) && !isNaN(minutes)) {
|
|
217
|
+
const hours = Number.parseInt(time[0]);
|
|
218
|
+
const minutes = Number.parseInt(time[1]);
|
|
219
|
+
if (!Number.isNaN(hours) && !Number.isNaN(minutes)) {
|
|
225
220
|
result.time = hours * 60 + minutes;
|
|
226
221
|
}
|
|
227
|
-
const power = parseInt(states[7]);
|
|
228
|
-
if (!isNaN(power)) {
|
|
222
|
+
const power = Number.parseInt(states[7]);
|
|
223
|
+
if (!Number.isNaN(power)) {
|
|
229
224
|
result.power = power;
|
|
230
225
|
}
|
|
231
226
|
result.timestamp = Date.now();
|
|
@@ -234,7 +229,7 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
234
229
|
}
|
|
235
230
|
check() {
|
|
236
231
|
return __awaiter(this, void 0, void 0, function* () {
|
|
237
|
-
|
|
232
|
+
const info = {};
|
|
238
233
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
239
234
|
this.logEvent({ message: "checking device", port: this.getPort() });
|
|
240
235
|
let iv = undefined;
|
|
@@ -275,7 +270,7 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
275
270
|
return __awaiter(this, void 0, void 0, function* () {
|
|
276
271
|
const props = this.getStartProps(startProps);
|
|
277
272
|
this.logEvent({ message: 'start()' });
|
|
278
|
-
|
|
273
|
+
const info = {};
|
|
279
274
|
yield this.waitForOpened(true);
|
|
280
275
|
return (0, utils_1.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () {
|
|
281
276
|
try {
|
|
@@ -489,7 +484,7 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
489
484
|
var _a;
|
|
490
485
|
if (((_a = this.kettlerData) === null || _a === void 0 ? void 0 : _a.cadence) === 0)
|
|
491
486
|
return;
|
|
492
|
-
let bikeRequest = this.getCyclingMode().
|
|
487
|
+
let bikeRequest = this.getCyclingMode().buildUpdate({ refresh: true }) || {};
|
|
493
488
|
const prev = this.requests[this.requests.length - 1] || {};
|
|
494
489
|
if (bikeRequest.targetPower !== undefined && bikeRequest.targetPower !== prev.targetPower) {
|
|
495
490
|
this.logEvent({ message: 'add request', request: bikeRequest });
|
|
@@ -501,7 +496,7 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
501
496
|
this.data.slope = request.slope;
|
|
502
497
|
}
|
|
503
498
|
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
504
|
-
let bikeRequest = this.getCyclingMode().
|
|
499
|
+
let bikeRequest = this.getCyclingMode().buildUpdate(request);
|
|
505
500
|
this.logEvent({ message: 'add request', request: bikeRequest });
|
|
506
501
|
this.requests.push(bikeRequest);
|
|
507
502
|
resolve(bikeRequest);
|
|
@@ -519,25 +514,20 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
519
514
|
}
|
|
520
515
|
waitForOpened() {
|
|
521
516
|
return __awaiter(this, arguments, void 0, function* (retries = false) {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
opened = yield this.comms.open();
|
|
531
|
-
if (opened)
|
|
532
|
-
return true;
|
|
533
|
-
}
|
|
534
|
-
catch (err) {
|
|
535
|
-
}
|
|
536
|
-
tries++;
|
|
537
|
-
yield (0, utils_1.sleep)(500);
|
|
517
|
+
const maxTries = retries ? 3 : 1;
|
|
518
|
+
let opened = false;
|
|
519
|
+
let tries = 0;
|
|
520
|
+
while (!opened && tries < maxTries) {
|
|
521
|
+
try {
|
|
522
|
+
opened = yield this.comms.open();
|
|
523
|
+
if (opened)
|
|
524
|
+
return true;
|
|
538
525
|
}
|
|
539
|
-
|
|
526
|
+
catch (_a) { }
|
|
527
|
+
tries++;
|
|
528
|
+
yield (0, utils_1.sleep)(500);
|
|
540
529
|
}
|
|
530
|
+
return false;
|
|
541
531
|
});
|
|
542
532
|
}
|
|
543
533
|
waitForClosed() {
|
|
@@ -554,7 +544,10 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
554
544
|
resolve(true);
|
|
555
545
|
cleanup();
|
|
556
546
|
};
|
|
557
|
-
const onError = (err) => {
|
|
547
|
+
const onError = (err) => {
|
|
548
|
+
reject(err);
|
|
549
|
+
cleanup();
|
|
550
|
+
};
|
|
558
551
|
const onOpen = () => { cleanup(); };
|
|
559
552
|
this.comms.on('closed', onClose);
|
|
560
553
|
this.comms.on('opened', onOpen);
|
|
@@ -188,7 +188,7 @@ class Simulator extends adpater_1.default {
|
|
|
188
188
|
return __awaiter(this, void 0, void 0, function* () {
|
|
189
189
|
if (this.paused)
|
|
190
190
|
return;
|
|
191
|
-
return
|
|
191
|
+
return this.getCyclingMode().buildUpdate(request);
|
|
192
192
|
});
|
|
193
193
|
}
|
|
194
194
|
}
|
package/lib/utils/utils.js
CHANGED
|
@@ -73,16 +73,16 @@ function floatVal(d) {
|
|
|
73
73
|
return;
|
|
74
74
|
if (typeof d === 'number')
|
|
75
75
|
return d;
|
|
76
|
-
const res = parseFloat(d);
|
|
77
|
-
return isNaN(res) ? undefined : res;
|
|
76
|
+
const res = Number.parseFloat(d);
|
|
77
|
+
return Number.isNaN(res) ? undefined : res;
|
|
78
78
|
}
|
|
79
79
|
function intVal(d) {
|
|
80
80
|
if (d === undefined)
|
|
81
81
|
return;
|
|
82
82
|
if (typeof d === 'number')
|
|
83
83
|
return Math.floor(d);
|
|
84
|
-
const res = parseInt(d);
|
|
85
|
-
return isNaN(res) ? undefined : res;
|
|
84
|
+
const res = Number.parseInt(d);
|
|
85
|
+
return Number.isNaN(res) ? undefined : res;
|
|
86
86
|
}
|
|
87
87
|
function hexstr(arr, start, len) {
|
|
88
88
|
let str = "";
|
|
@@ -93,7 +93,7 @@ function hexstr(arr, start, len) {
|
|
|
93
93
|
endIdx = arr.length;
|
|
94
94
|
}
|
|
95
95
|
let added = 0;
|
|
96
|
-
for (
|
|
96
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
97
97
|
const hex = Math.abs(arr[i]).toString(16).toUpperCase();
|
|
98
98
|
if (added !== 0)
|
|
99
99
|
str += ' ';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "incyclist-devices",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.39",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@protobuf-ts/runtime": "^2.11.1",
|
|
6
6
|
"@serialport/bindings-interface": "^1.2.2",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"scripts": {
|
|
35
35
|
"lint": "eslint . --ext .ts",
|
|
36
36
|
"build": "tsc",
|
|
37
|
-
"test": "npx jest --coverage",
|
|
37
|
+
"test:unit": "npx jest --coverage",
|
|
38
38
|
"test:ci": "npx jest --coverage --forceExit",
|
|
39
39
|
"dev": "tsc --watch",
|
|
40
40
|
"postversion": "git push && git push --tags",
|