incyclist-devices 1.4.22 → 1.4.25
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/CyclingMode.js +0 -1
- package/lib/Device.js +0 -1
- package/lib/DeviceProtocol.d.ts +1 -0
- package/lib/DeviceProtocol.js +1 -1
- package/lib/DeviceSupport.js +8 -21
- package/lib/ant/AntAdapter.js +0 -1
- package/lib/ant/AntScanner.js +10 -21
- package/lib/ant/antfe/AntFEAdapter.js +7 -7
- package/lib/ant/anthrm/AntHrmAdapter.js +1 -1
- package/lib/ant/antpwr/AntPWRAdapter.d.ts +24 -0
- package/lib/ant/antpwr/AntPWRAdapter.js +252 -0
- package/lib/ant/antpwr/pwr-adapter.d.ts +48 -0
- package/lib/ant/antpwr/pwr-adapter.js +259 -0
- package/lib/ant/utils.js +1 -3
- package/lib/calculations.js +2 -4
- package/lib/daum/DaumAdapter.d.ts +2 -2
- package/lib/daum/DaumAdapter.js +31 -39
- package/lib/daum/DaumPowerMeterCyclingMode.d.ts +8 -0
- package/lib/daum/DaumPowerMeterCyclingMode.js +21 -0
- package/lib/daum/ERGCyclingMode.d.ts +3 -6
- package/lib/daum/ERGCyclingMode.js +15 -27
- package/lib/daum/SmartTrainerCyclingMode.js +0 -1
- package/lib/daum/classic/DaumClassicAdapter.js +2 -2
- package/lib/daum/classic/DaumClassicProtocol.js +7 -19
- package/lib/daum/classic/bike.js +26 -26
- package/lib/daum/classic/utils.js +0 -1
- package/lib/daum/constants.js +0 -1
- package/lib/daum/premium/DaumClassicCyclingMode.d.ts +2 -2
- package/lib/daum/premium/DaumClassicCyclingMode.js +2 -2
- package/lib/daum/premium/DaumPremiumAdapter.js +2 -2
- package/lib/daum/premium/DaumPremiumProtocol.js +7 -19
- package/lib/daum/premium/bike.js +17 -18
- package/lib/daum/premium/utils.js +0 -1
- package/lib/kettler/comms.js +1 -2
- package/lib/kettler/ergo-racer/adapter.js +10 -22
- package/lib/kettler/ergo-racer/modes/power-meter.d.ts +2 -2
- package/lib/kettler/ergo-racer/modes/power-meter.js +12 -4
- package/lib/kettler/ergo-racer/protocol.js +7 -19
- package/lib/modes/power-base.d.ts +20 -0
- package/lib/modes/power-base.js +60 -0
- package/lib/modes/power-meter.d.ts +20 -0
- package/lib/modes/power-meter.js +70 -0
- package/lib/modes/simulator.d.ts +27 -0
- package/lib/modes/simulator.js +118 -0
- package/lib/simulator/Simulator.js +10 -23
- package/lib/simulator/simulator-mode.js +4 -4
- package/lib/types/route.js +0 -1
- package/lib/types/user.js +0 -1
- package/lib/utils.js +1 -3
- package/package.json +1 -1
|
@@ -1,23 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
-
}) : (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
o[k2] = m[k];
|
|
8
|
-
}));
|
|
9
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
-
}) : function(o, v) {
|
|
12
|
-
o["default"] = v;
|
|
13
|
-
});
|
|
14
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
-
if (mod && mod.__esModule) return mod;
|
|
16
|
-
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
-
__setModuleDefault(result, mod);
|
|
19
|
-
return result;
|
|
20
|
-
};
|
|
21
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -27,6 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
27
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
9
|
});
|
|
29
10
|
};
|
|
11
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
12
|
+
if (mod && mod.__esModule) return mod;
|
|
13
|
+
var result = {};
|
|
14
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
15
|
+
result["default"] = mod;
|
|
16
|
+
return result;
|
|
17
|
+
};
|
|
30
18
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
19
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
20
|
};
|
package/lib/daum/classic/bike.js
CHANGED
|
@@ -52,9 +52,9 @@ class Daum8008 {
|
|
|
52
52
|
}
|
|
53
53
|
getUserWeight() {
|
|
54
54
|
if (this.settings && this.settings.user && this.settings.user.weight)
|
|
55
|
-
return
|
|
55
|
+
return utils_1.getWeight(this.settings.user.weight);
|
|
56
56
|
else
|
|
57
|
-
return
|
|
57
|
+
return utils_1.getWeight();
|
|
58
58
|
}
|
|
59
59
|
getBikeWeight() {
|
|
60
60
|
if (this.settings && this.settings.weight) {
|
|
@@ -274,7 +274,7 @@ class Daum8008 {
|
|
|
274
274
|
};
|
|
275
275
|
this.queue.enqueue(cmdInfo);
|
|
276
276
|
if (this.queue.size() > 1)
|
|
277
|
-
this.logger.logEvent({ message: "sendCommand:adding:", cmd: logStr, hex:
|
|
277
|
+
this.logger.logEvent({ message: "sendCommand:adding:", cmd: logStr, hex: utils_1.hexstr(payload), queueSize: this.queue.size() });
|
|
278
278
|
if (this.bikeCmdWorker === undefined) {
|
|
279
279
|
this.startWorker();
|
|
280
280
|
}
|
|
@@ -293,7 +293,7 @@ class Daum8008 {
|
|
|
293
293
|
const parser = serialPort.pipe(new ByteLength({ length: expected }));
|
|
294
294
|
parser.on('data', (data) => {
|
|
295
295
|
let duration = Date.now() - this.cmdStart;
|
|
296
|
-
this.logger.logEvent({ message: "sendCommand:received:", duration, hex:
|
|
296
|
+
this.logger.logEvent({ message: "sendCommand:received:", duration, hex: utils_1.hexstr(data), port: this.getPort() });
|
|
297
297
|
serialPort.unpipe();
|
|
298
298
|
if (callbackErr !== undefined) {
|
|
299
299
|
if (data[0] !== payload[0]) {
|
|
@@ -306,7 +306,7 @@ class Daum8008 {
|
|
|
306
306
|
callback(data);
|
|
307
307
|
done();
|
|
308
308
|
});
|
|
309
|
-
this.logger.logEvent({ message: "sendCommand:sending:", cmd: logStr, hex:
|
|
309
|
+
this.logger.logEvent({ message: "sendCommand:sending:", cmd: logStr, hex: utils_1.hexstr(payload), port: this.getPort() });
|
|
310
310
|
this.cmdCurrent.start = this.cmdStart = Date.now();
|
|
311
311
|
serialPort.write(payload);
|
|
312
312
|
}
|
|
@@ -321,53 +321,53 @@ class Daum8008 {
|
|
|
321
321
|
this.sendDaum8008Command(`checkCockpit(${bikeNo})`, [0x10, bikeNo], 3, (data) => resolve({ bike: data[1], version: data[2] }), (status, err) => {
|
|
322
322
|
if (status === 408)
|
|
323
323
|
return resolve({ bike: bikeNo, version: undefined });
|
|
324
|
-
reject(
|
|
324
|
+
reject(utils_1.buildError(status, err));
|
|
325
325
|
});
|
|
326
326
|
});
|
|
327
327
|
}
|
|
328
328
|
getAddress() {
|
|
329
329
|
return new Promise((resolve, reject) => {
|
|
330
|
-
this.sendDaum8008Command(`getAddress()`, [0x11], 2, (data) => resolve({ bike: data[1] }), (status, err) => reject(
|
|
330
|
+
this.sendDaum8008Command(`getAddress()`, [0x11], 2, (data) => resolve({ bike: data[1] }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
331
331
|
});
|
|
332
332
|
}
|
|
333
333
|
getVersion(bikeNo = 0) {
|
|
334
334
|
return new Promise((resolve, reject) => {
|
|
335
|
-
this.sendDaum8008Command(`getVersion(${bikeNo})`, [0x73, bikeNo], 11, (data) => resolve({ bike: data[1], serialNo:
|
|
335
|
+
this.sendDaum8008Command(`getVersion(${bikeNo})`, [0x73, bikeNo], 11, (data) => resolve({ bike: data[1], serialNo: utils_1.hexstr(data, 2, 8), cockpit: utils_1.getCockpit(data[10]) }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
336
336
|
});
|
|
337
337
|
}
|
|
338
338
|
resetDevice(bikeNo = 0) {
|
|
339
339
|
return new Promise((resolve, reject) => {
|
|
340
|
-
this.sendDaum8008Command(`resetDevice(${bikeNo})`, [0x12, bikeNo], 2, (data) => resolve({}), (status, err) => reject(
|
|
340
|
+
this.sendDaum8008Command(`resetDevice(${bikeNo})`, [0x12, bikeNo], 2, (data) => resolve({}), (status, err) => reject(utils_1.buildError(status, err)));
|
|
341
341
|
});
|
|
342
342
|
}
|
|
343
343
|
startProg(bikeNo = 0) {
|
|
344
344
|
return new Promise((resolve, reject) => {
|
|
345
|
-
this.sendDaum8008Command(`startProg(${bikeNo})`, [0x21, bikeNo], 3, (data) => resolve({ bike: data[1], pedalling: data[2] > 0 }), (status, err) => reject(
|
|
345
|
+
this.sendDaum8008Command(`startProg(${bikeNo})`, [0x21, bikeNo], 3, (data) => resolve({ bike: data[1], pedalling: data[2] > 0 }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
346
346
|
});
|
|
347
347
|
}
|
|
348
348
|
stopProg(bikeNo = 0) {
|
|
349
349
|
return new Promise((resolve, reject) => {
|
|
350
|
-
this.sendDaum8008Command(`stopProg(${bikeNo})`, [0x22, bikeNo], 3, (data) => resolve({ bike: data[1], pedalling: data[2] !== 0 }), (status, err) => reject(
|
|
350
|
+
this.sendDaum8008Command(`stopProg(${bikeNo})`, [0x22, bikeNo], 3, (data) => resolve({ bike: data[1], pedalling: data[2] !== 0 }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
351
351
|
});
|
|
352
352
|
}
|
|
353
353
|
setProg(progNo = 0, bikeNo = 0) {
|
|
354
354
|
return new Promise((resolve, reject) => {
|
|
355
|
-
this.sendDaum8008Command(`setProg(${bikeNo},${progNo})`, [0x23, bikeNo, progNo], 4, (data) => resolve({ bike: data[1], progNo: data[2], pedalling: data[3] !== 0 }), (status, err) => reject(
|
|
355
|
+
this.sendDaum8008Command(`setProg(${bikeNo},${progNo})`, [0x23, bikeNo, progNo], 4, (data) => resolve({ bike: data[1], progNo: data[2], pedalling: data[3] !== 0 }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
356
356
|
});
|
|
357
357
|
}
|
|
358
358
|
setBikeType(bikeType, bikeNo = 0) {
|
|
359
|
-
const bikeVal =
|
|
359
|
+
const bikeVal = utils_1.getBikeType(bikeType);
|
|
360
360
|
return new Promise((resolve, reject) => {
|
|
361
|
-
this.sendDaum8008Command(`setBikeType(${bikeNo},${bikeType})`, [0x69, bikeNo, 0, 0, bikeVal], 3, (data) => resolve({}), (status, err) => reject(
|
|
361
|
+
this.sendDaum8008Command(`setBikeType(${bikeNo},${bikeType})`, [0x69, bikeNo, 0, 0, bikeVal], 3, (data) => resolve({}), (status, err) => reject(utils_1.buildError(status, err)));
|
|
362
362
|
});
|
|
363
363
|
}
|
|
364
364
|
setPerson(user = {}, bikeNo = 0) {
|
|
365
365
|
const age = user.age !== undefined ? user.age : utils_1.DEFAULT_AGE;
|
|
366
|
-
const gender =
|
|
367
|
-
const length =
|
|
366
|
+
const gender = utils_1.getGender(user.sex);
|
|
367
|
+
const length = utils_1.getLength(user.length);
|
|
368
368
|
const maxPower = this.settings.maxPower === undefined ? 800 : this.settings.maxPower;
|
|
369
369
|
const mUser = user.weight || this.getUserWeight();
|
|
370
|
-
const weight =
|
|
370
|
+
const weight = utils_1.getWeight(mUser) + this.getBikeWeight();
|
|
371
371
|
var cmd = [0x24, bikeNo, 0];
|
|
372
372
|
cmd.push(age);
|
|
373
373
|
cmd.push(gender);
|
|
@@ -390,26 +390,26 @@ class Daum8008 {
|
|
|
390
390
|
if (data[i] === 0 || data[i] === 80)
|
|
391
391
|
return;
|
|
392
392
|
}
|
|
393
|
-
reject(
|
|
393
|
+
reject(utils_1.buildError(512, 'illegal response'));
|
|
394
394
|
ok = false;
|
|
395
395
|
}
|
|
396
396
|
});
|
|
397
397
|
if (ok)
|
|
398
398
|
resolve({ bike: data[1], age, gender, length, weight });
|
|
399
|
-
}, (status, err) => reject(
|
|
399
|
+
}, (status, err) => reject(utils_1.buildError(status, err)));
|
|
400
400
|
});
|
|
401
401
|
}
|
|
402
402
|
runData(bikeNo = 0) {
|
|
403
403
|
return new Promise((resolve, reject) => {
|
|
404
404
|
this.sendDaum8008Command(`runData(${bikeNo})`, [0x40, bikeNo], 19, (data) => {
|
|
405
405
|
try {
|
|
406
|
-
const parsed =
|
|
406
|
+
const parsed = utils_1.parseRunData(data);
|
|
407
407
|
resolve(parsed);
|
|
408
408
|
}
|
|
409
409
|
catch (e) {
|
|
410
|
-
reject(
|
|
410
|
+
reject(utils_1.buildError(500, e));
|
|
411
411
|
}
|
|
412
|
-
}, (status, err) => reject(
|
|
412
|
+
}, (status, err) => reject(utils_1.buildError(status, err)));
|
|
413
413
|
});
|
|
414
414
|
}
|
|
415
415
|
setGear(gear, bikeNo = 0) {
|
|
@@ -419,7 +419,7 @@ class Daum8008 {
|
|
|
419
419
|
if (gear > 28)
|
|
420
420
|
gearVal = 28;
|
|
421
421
|
return new Promise((resolve, reject) => {
|
|
422
|
-
this.sendDaum8008Command(`setGear(${bikeNo},${gearVal})`, [0x53, bikeNo, gearVal], 3, (data) => resolve({ bike: data[1], gear: data[2] }), (status, err) => reject(
|
|
422
|
+
this.sendDaum8008Command(`setGear(${bikeNo},${gearVal})`, [0x53, bikeNo, gearVal], 3, (data) => resolve({ bike: data[1], gear: data[2] }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
423
423
|
});
|
|
424
424
|
}
|
|
425
425
|
setPower(power, bikeNo = 0) {
|
|
@@ -434,7 +434,7 @@ class Daum8008 {
|
|
|
434
434
|
if (power > 800)
|
|
435
435
|
powerRequest = 800;
|
|
436
436
|
const powerVal = Math.round(powerRequest / 5);
|
|
437
|
-
this.sendDaum8008Command(`setPower(${bikeNo},${power})`, [0x51, bikeNo, powerVal], 3, (data) => resolve({ bike: data[1], power: (data[2] * 5) }), (status, err) => reject(
|
|
437
|
+
this.sendDaum8008Command(`setPower(${bikeNo},${power})`, [0x51, bikeNo, powerVal], 3, (data) => resolve({ bike: data[1], power: (data[2] * 5) }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
438
438
|
});
|
|
439
439
|
}
|
|
440
440
|
setSlope(slope, bikeNo = 0) {
|
|
@@ -444,12 +444,12 @@ class Daum8008 {
|
|
|
444
444
|
return;
|
|
445
445
|
}
|
|
446
446
|
const cmd = [0x55, bikeNo];
|
|
447
|
-
const arr =
|
|
447
|
+
const arr = utils_1.Float32ToIntArray(slope);
|
|
448
448
|
cmd.push(arr[3]);
|
|
449
449
|
cmd.push(arr[2]);
|
|
450
450
|
cmd.push(arr[1]);
|
|
451
451
|
cmd.push(arr[0]);
|
|
452
|
-
this.sendDaum8008Command(`setSlope(${bikeNo},${slope})`, cmd, 6, (data) => resolve({ bike: data[1], slope: slope }), (status, err) => reject(
|
|
452
|
+
this.sendDaum8008Command(`setSlope(${bikeNo},${slope})`, cmd, 6, (data) => resolve({ bike: data[1], slope: slope }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
453
453
|
});
|
|
454
454
|
}
|
|
455
455
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Float32ToIntArray = exports.Float32ToHex = exports.hexstr = exports.buildError = exports.parseRunData = exports.getWeight = exports.getLength = exports.getGender = exports.getBikeType = exports.getCockpit = exports.DEFAULT_BIKE_WEIGHT = exports.DEFAULT_USER_WEIGHT = exports.DEFAULT_AGE = void 0;
|
|
4
3
|
exports.DEFAULT_AGE = 30;
|
|
5
4
|
exports.DEFAULT_USER_WEIGHT = 75;
|
|
6
5
|
exports.DEFAULT_BIKE_WEIGHT = 10;
|
package/lib/daum/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import CyclingMode, { CyclingModeProperty, IncyclistBikeData, Settings, UpdateRequest } from "../../CyclingMode";
|
|
2
2
|
import DaumAdapter from "../DaumAdapter";
|
|
3
|
-
import
|
|
4
|
-
export default class DaumClassicCyclingMode extends
|
|
3
|
+
import DaumPowerMeterCyclingMode from "../DaumPowerMeterCyclingMode";
|
|
4
|
+
export default class DaumClassicCyclingMode extends DaumPowerMeterCyclingMode implements CyclingMode {
|
|
5
5
|
constructor(adapter: DaumAdapter, props?: Settings);
|
|
6
6
|
getName(): string;
|
|
7
7
|
getDescription(): string;
|
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
7
7
|
const CyclingMode_1 = require("../../CyclingMode");
|
|
8
|
-
const
|
|
8
|
+
const DaumPowerMeterCyclingMode_1 = __importDefault(require("../DaumPowerMeterCyclingMode"));
|
|
9
9
|
const config = {
|
|
10
10
|
name: "Daum Classic",
|
|
11
11
|
description: "The device calculates speed and power based on slope. Incyclist will not modify any values recived from the device\nThis mode will not respect maximum power and/or workout limits",
|
|
@@ -13,7 +13,7 @@ const config = {
|
|
|
13
13
|
{ key: 'bikeType', name: 'Bike Type', description: '', type: CyclingMode_1.CyclingModeProperyType.SingleSelect, options: ['Race', 'Mountain'], default: 'Race' },
|
|
14
14
|
]
|
|
15
15
|
};
|
|
16
|
-
class DaumClassicCyclingMode extends
|
|
16
|
+
class DaumClassicCyclingMode extends DaumPowerMeterCyclingMode_1.default {
|
|
17
17
|
constructor(adapter, props) {
|
|
18
18
|
super(adapter, props);
|
|
19
19
|
this.logger = adapter ? adapter.logger : undefined;
|
|
@@ -72,7 +72,7 @@ class DaumPremiumDevice extends DaumAdapter_1.default {
|
|
|
72
72
|
const route = opts.route;
|
|
73
73
|
var info = {};
|
|
74
74
|
this.initData();
|
|
75
|
-
return
|
|
75
|
+
return utils_1.runWithRetries(() => __awaiter(this, void 0, void 0, function* () {
|
|
76
76
|
if (this.isStopped())
|
|
77
77
|
return;
|
|
78
78
|
try {
|
|
@@ -98,7 +98,7 @@ class DaumPremiumDevice extends DaumAdapter_1.default {
|
|
|
98
98
|
info.person = yield this.bike.setPerson(user);
|
|
99
99
|
}
|
|
100
100
|
if (!this.getCyclingMode().getModeProperty('eppSupport')) {
|
|
101
|
-
const gear = yield this.bike.setGear(this.
|
|
101
|
+
const gear = yield this.bike.setGear(this.cyclingData.gear || (opts.gear || 10));
|
|
102
102
|
return gear;
|
|
103
103
|
}
|
|
104
104
|
return;
|
|
@@ -1,23 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
-
}) : (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
o[k2] = m[k];
|
|
8
|
-
}));
|
|
9
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
-
}) : function(o, v) {
|
|
12
|
-
o["default"] = v;
|
|
13
|
-
});
|
|
14
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
-
if (mod && mod.__esModule) return mod;
|
|
16
|
-
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
-
__setModuleDefault(result, mod);
|
|
19
|
-
return result;
|
|
20
|
-
};
|
|
21
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -27,6 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
27
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
9
|
});
|
|
29
10
|
};
|
|
11
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
12
|
+
if (mod && mod.__esModule) return mod;
|
|
13
|
+
var result = {};
|
|
14
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
15
|
+
result["default"] = mod;
|
|
16
|
+
return result;
|
|
17
|
+
};
|
|
30
18
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
19
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
20
|
};
|
package/lib/daum/premium/bike.js
CHANGED
|
@@ -12,7 +12,6 @@ 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.Daum8iSerial = exports.Daum8iTcp = void 0;
|
|
16
15
|
const constants_1 = require("../constants");
|
|
17
16
|
const tcpserial_1 = __importDefault(require("./tcpserial"));
|
|
18
17
|
const utils_1 = require("./utils");
|
|
@@ -408,7 +407,7 @@ class Daum8i {
|
|
|
408
407
|
incoming = bufferData;
|
|
409
408
|
}
|
|
410
409
|
const response = [...incoming];
|
|
411
|
-
this.logger.logEvent({ message: 'sendCommand:RECV', data:
|
|
410
|
+
this.logger.logEvent({ message: 'sendCommand:RECV', data: utils_1.hexstr(response) });
|
|
412
411
|
for (let i = 0; i < incoming.length; i++) {
|
|
413
412
|
const getRemaining = () => {
|
|
414
413
|
let remaining = '';
|
|
@@ -441,11 +440,11 @@ class Daum8i {
|
|
|
441
440
|
}
|
|
442
441
|
else if (c === 0x17) {
|
|
443
442
|
const remaining = getRemaining();
|
|
444
|
-
this.logger.logEvent({ message: "sendCommand:received:", duration: Date.now() - this.state.sending.tsRequest, port: portName, cmd: `${cmd} [${
|
|
443
|
+
this.logger.logEvent({ message: "sendCommand:received:", duration: Date.now() - this.state.sending.tsRequest, port: portName, cmd: `${cmd} [${utils_1.hexstr(cmd)}]`, remaining: utils_1.hexstr(remaining) });
|
|
445
444
|
this.state.waitingForEnd = false;
|
|
446
445
|
const cmdStr = cmd.substring(0, cmd.length - 2);
|
|
447
446
|
const checksumExtracted = cmd.slice(-2);
|
|
448
|
-
const checksumCalculated =
|
|
447
|
+
const checksumCalculated = utils_1.checkSum(utils_1.getAsciiArrayFromStr(cmdStr), []);
|
|
449
448
|
if (checksumExtracted === checksumCalculated) {
|
|
450
449
|
this.sendACK();
|
|
451
450
|
if (this.state.sending && this.state.sending.responseCheckIv) {
|
|
@@ -487,8 +486,8 @@ class Daum8i {
|
|
|
487
486
|
this.state.busy = true;
|
|
488
487
|
}
|
|
489
488
|
else {
|
|
490
|
-
const message =
|
|
491
|
-
this.logger.logEvent({ message: 'sendCommand:waiting', port: this.portName, cmd: command, hex:
|
|
489
|
+
const message = utils_1.buildMessage(command, payload);
|
|
490
|
+
this.logger.logEvent({ message: 'sendCommand:waiting', port: this.portName, cmd: command, hex: utils_1.hexstr(message) });
|
|
492
491
|
const busyWait = () => {
|
|
493
492
|
return new Promise((done) => {
|
|
494
493
|
let start = Date.now();
|
|
@@ -509,7 +508,7 @@ class Daum8i {
|
|
|
509
508
|
};
|
|
510
509
|
const res = yield busyWait();
|
|
511
510
|
if (!res) {
|
|
512
|
-
this.logger.logEvent({ message: 'sendCommand:busy timeout', port: this.portName, cmd: command, hex:
|
|
511
|
+
this.logger.logEvent({ message: 'sendCommand:busy timeout', port: this.portName, cmd: command, hex: utils_1.hexstr(message), duration: Date.now() - tsRequest });
|
|
513
512
|
return reject(new Error('BUSY timeout'));
|
|
514
513
|
}
|
|
515
514
|
this.state.busy = true;
|
|
@@ -527,10 +526,10 @@ class Daum8i {
|
|
|
527
526
|
const portName = this.portName;
|
|
528
527
|
this.state.received = [];
|
|
529
528
|
try {
|
|
530
|
-
const message =
|
|
529
|
+
const message = utils_1.buildMessage(command, payload);
|
|
531
530
|
const start = Date.now();
|
|
532
531
|
const timeout = start + this.getTimeoutValue();
|
|
533
|
-
this.logger.logEvent({ message: "sendCommand:sending:", port: this.portName, cmd: command, hex:
|
|
532
|
+
this.logger.logEvent({ message: "sendCommand:sending:", port: this.portName, cmd: command, hex: utils_1.hexstr(message) });
|
|
534
533
|
this.state.writeBusy = true;
|
|
535
534
|
if (!this.connected || port === undefined) {
|
|
536
535
|
this.logger.logEvent({ message: "sendCommand:error: not connected", port: this.portName });
|
|
@@ -590,10 +589,10 @@ class Daum8i {
|
|
|
590
589
|
buffer.writeUInt16LE(0, 2);
|
|
591
590
|
}
|
|
592
591
|
const cmdData = Uint8Array.from(buffer);
|
|
593
|
-
return this.sendDaum8iCommand('M70', cmdType,
|
|
592
|
+
return this.sendDaum8iCommand('M70', cmdType, utils_1.bin2esc(cmdData))
|
|
594
593
|
.then((res) => {
|
|
595
594
|
const resData = Uint8Array.from(res, x => x.charCodeAt(0));
|
|
596
|
-
const cmd =
|
|
595
|
+
const cmd = utils_1.esc2bin(resData);
|
|
597
596
|
return cmd;
|
|
598
597
|
});
|
|
599
598
|
}
|
|
@@ -618,7 +617,7 @@ class Daum8i {
|
|
|
618
617
|
else if (str === '7')
|
|
619
618
|
deviceType = 'lyps';
|
|
620
619
|
else
|
|
621
|
-
throw (new Error(`unknown device type ${typeof str === 'string' ?
|
|
620
|
+
throw (new Error(`unknown device type ${typeof str === 'string' ? utils_1.ascii(str.charAt(0)) : str}`));
|
|
622
621
|
return deviceType;
|
|
623
622
|
});
|
|
624
623
|
}
|
|
@@ -633,7 +632,7 @@ class Daum8i {
|
|
|
633
632
|
else if (str === '2')
|
|
634
633
|
deviceType = constants_1.ACTUAL_BIKE_TYPE.MOUNTAIN;
|
|
635
634
|
else {
|
|
636
|
-
throw (new Error(`unknown actual device type ${typeof str === 'string' ?
|
|
635
|
+
throw (new Error(`unknown actual device type ${typeof str === 'string' ? utils_1.ascii(str.charAt(0)) : str}`));
|
|
637
636
|
}
|
|
638
637
|
this.state.actualBikeType = deviceType;
|
|
639
638
|
return deviceType;
|
|
@@ -675,12 +674,12 @@ class Daum8i {
|
|
|
675
674
|
getTrainingData() {
|
|
676
675
|
return this.sendDaum8iCommand('X70', 'AF', [])
|
|
677
676
|
.then((data) => {
|
|
678
|
-
const td =
|
|
677
|
+
const td = utils_1.parseTrainingData(data);
|
|
679
678
|
return td;
|
|
680
679
|
});
|
|
681
680
|
}
|
|
682
681
|
setLoadControl(enabled) {
|
|
683
|
-
const val = enabled ?
|
|
682
|
+
const val = enabled ? utils_1.ascii('1') : utils_1.ascii('0');
|
|
684
683
|
return this.sendDaum8iCommand('S20', 'BF', [val])
|
|
685
684
|
.then((data) => {
|
|
686
685
|
const res = data === '1';
|
|
@@ -714,7 +713,7 @@ class Daum8i {
|
|
|
714
713
|
setPerson(person) {
|
|
715
714
|
const { sex, age, length, weight } = person;
|
|
716
715
|
this.logger.logEvent({ message: 'setPerson() request', sex, age, length, weight });
|
|
717
|
-
return this.sendReservedDaum8iCommand(utils_1.ReservedCommands.PERSON_SET, 'BF',
|
|
716
|
+
return this.sendReservedDaum8iCommand(utils_1.ReservedCommands.PERSON_SET, 'BF', utils_1.getPersonData(person))
|
|
718
717
|
.then((res) => {
|
|
719
718
|
const buffer = Buffer.from(res);
|
|
720
719
|
const success = buffer.readInt16LE(0) === utils_1.ReservedCommands.PERSON_SET;
|
|
@@ -738,9 +737,9 @@ class Daum8i {
|
|
|
738
737
|
}
|
|
739
738
|
programUploadStart(bikeType, route) {
|
|
740
739
|
const payload = Buffer.alloc(40);
|
|
741
|
-
const epp = route ?
|
|
740
|
+
const epp = route ? utils_1.routeToEpp(route) : undefined;
|
|
742
741
|
const eppLength = epp ? epp.length : 0;
|
|
743
|
-
const bikeTypeVal =
|
|
742
|
+
const bikeTypeVal = utils_1.getBikeType(bikeType);
|
|
744
743
|
const wBits = route.lapMode ? DS_BITS_ENDLESS_RACE : DS_BITS_OFF;
|
|
745
744
|
payload.writeInt32LE(0, 0);
|
|
746
745
|
payload.writeInt8(bikeTypeVal, 4);
|
|
@@ -3,7 +3,6 @@ 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.getPersonData = exports.parseTrainingData = exports.routeToEpp = exports.getBikeType = exports.BikeType = exports.ReservedCommands = exports.Int32ToIntArray = exports.Int16ToIntArray = exports.Float32ToIntArray = exports.Float32ToHex = exports.getAsciiArrayFromStr = exports.asciiArrayToString = exports.charArrayToString = exports.ascii = exports.append = exports.getHex = exports.hexstr = exports.getMessageData = exports.buildMessage = exports.checkSum = exports.esc2bin = exports.bin2esc = void 0;
|
|
7
6
|
const win32filetime_1 = __importDefault(require("win32filetime"));
|
|
8
7
|
const sum = (arr) => arr.reduce((a, b) => a + b, 0);
|
|
9
8
|
function bin2esc(arr) {
|
package/lib/kettler/comms.js
CHANGED
|
@@ -12,7 +12,6 @@ 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.SendState = exports.SerialCommsState = void 0;
|
|
16
15
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
17
16
|
const utils_1 = require("../utils");
|
|
18
17
|
const events_1 = __importDefault(require("events"));
|
|
@@ -194,7 +193,7 @@ class KettlerSerialComms extends events_1.default {
|
|
|
194
193
|
write(cmd) {
|
|
195
194
|
this.sendState = SendState.Sending;
|
|
196
195
|
const { logStr, message, timeout = (this.settings.timeout || DEFAULT_RCV_TIMEOUT) } = cmd;
|
|
197
|
-
const msg = typeof message === 'string' ? message :
|
|
196
|
+
const msg = typeof message === 'string' ? message : utils_1.hexstr(message);
|
|
198
197
|
const onError = (err) => {
|
|
199
198
|
this.logger.logEvent({ message: "sendCommand:error:", cmd: logStr, error: err.message, port: this.getPort() });
|
|
200
199
|
if (cmd.onError)
|
|
@@ -1,23 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
-
}) : (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
o[k2] = m[k];
|
|
8
|
-
}));
|
|
9
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
-
}) : function(o, v) {
|
|
12
|
-
o["default"] = v;
|
|
13
|
-
});
|
|
14
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
-
if (mod && mod.__esModule) return mod;
|
|
16
|
-
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
-
__setModuleDefault(result, mod);
|
|
19
|
-
return result;
|
|
20
|
-
};
|
|
21
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -27,6 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
27
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
9
|
});
|
|
29
10
|
};
|
|
11
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
12
|
+
if (mod && mod.__esModule) return mod;
|
|
13
|
+
var result = {};
|
|
14
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
15
|
+
result["default"] = mod;
|
|
16
|
+
return result;
|
|
17
|
+
};
|
|
30
18
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
19
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
20
|
};
|
|
@@ -35,7 +23,7 @@ const Device_1 = __importStar(require("../../Device"));
|
|
|
35
23
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
36
24
|
const comms_1 = __importDefault(require("../comms"));
|
|
37
25
|
const utils_1 = require("../../utils");
|
|
38
|
-
const power_meter_1 = __importDefault(require("
|
|
26
|
+
const power_meter_1 = __importDefault(require("../../modes/power-meter"));
|
|
39
27
|
class KettlerRacerAdapter extends Device_1.default {
|
|
40
28
|
constructor(protocol, settings) {
|
|
41
29
|
super(protocol);
|
|
@@ -300,7 +288,7 @@ class KettlerRacerAdapter extends Device_1.default {
|
|
|
300
288
|
this.logger.logEvent({ message: 'start()' });
|
|
301
289
|
var info = {};
|
|
302
290
|
yield this.waitForOpened(true);
|
|
303
|
-
return
|
|
291
|
+
return utils_1.runWithRetries(() => __awaiter(this, void 0, void 0, function* () {
|
|
304
292
|
try {
|
|
305
293
|
if (!info.checkDone) {
|
|
306
294
|
info.checkDone = yield this.check();
|
|
@@ -585,7 +573,7 @@ class KettlerRacerAdapter extends Device_1.default {
|
|
|
585
573
|
if (!retries) {
|
|
586
574
|
return new Promise((resolve, reject) => run(resolve, reject));
|
|
587
575
|
}
|
|
588
|
-
return
|
|
576
|
+
return utils_1.runWithRetries(() => {
|
|
589
577
|
return new Promise((resolve, reject) => run(resolve, reject));
|
|
590
578
|
}, 3, 1000);
|
|
591
579
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { EventLogger } from 'gd-eventlog';
|
|
2
2
|
import CyclingMode, { CyclingModeProperty, IncyclistBikeData, Settings, UpdateRequest, CyclingModeBase } from '../../../CyclingMode';
|
|
3
|
-
import
|
|
3
|
+
import { DeviceAdapter } from '../../../Device';
|
|
4
4
|
export default class PowerMeterCyclingMode extends CyclingModeBase implements CyclingMode {
|
|
5
5
|
logger: EventLogger;
|
|
6
6
|
data: IncyclistBikeData;
|
|
7
7
|
prevRequest: UpdateRequest;
|
|
8
8
|
prevUpdateTS: number;
|
|
9
9
|
hasBikeUpdate: boolean;
|
|
10
|
-
constructor(adapter:
|
|
10
|
+
constructor(adapter: DeviceAdapter, props?: Settings);
|
|
11
11
|
getName(): string;
|
|
12
12
|
getDescription(): string;
|
|
13
13
|
getProperties(): CyclingModeProperty[];
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
7
7
|
const CyclingMode_1 = require("../../../CyclingMode");
|
|
8
|
+
const Device_1 = require("../../../Device");
|
|
8
9
|
const calculations_1 = __importDefault(require("../../../calculations"));
|
|
9
10
|
const config = {
|
|
10
11
|
name: 'PowerMeter',
|
|
@@ -16,7 +17,8 @@ class PowerMeterCyclingMode extends CyclingMode_1.CyclingModeBase {
|
|
|
16
17
|
super(adapter, props);
|
|
17
18
|
this.prevUpdateTS = 0;
|
|
18
19
|
this.hasBikeUpdate = false;
|
|
19
|
-
|
|
20
|
+
const a = adapter;
|
|
21
|
+
this.logger = (a && a.getLogger) ? a.getLogger() : undefined;
|
|
20
22
|
if (!this.logger)
|
|
21
23
|
this.logger = new gd_eventlog_1.EventLogger('PowerMeter');
|
|
22
24
|
}
|
|
@@ -56,10 +58,16 @@ class PowerMeterCyclingMode extends CyclingMode_1.CyclingModeBase {
|
|
|
56
58
|
power = 0;
|
|
57
59
|
}
|
|
58
60
|
let ts = Date.now();
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
let v = speed / 3.6;
|
|
61
|
+
const a = this.adapter;
|
|
62
|
+
const m = a.getWeight ? a.getWeight() : Device_1.DEFAULT_BIKE_WEIGHT + Device_1.DEFAULT_USER_WEIGHT;
|
|
62
63
|
let duration = this.prevUpdateTS === 0 ? 0 : ((ts - this.prevUpdateTS) / 1000);
|
|
64
|
+
const vPrev = (prevData.speed || 0) / 3.6;
|
|
65
|
+
const EkinPrev = 1 / 2 * m * vPrev * vPrev;
|
|
66
|
+
let powerRequired = calculations_1.default.calculatePower(m, vPrev, prevData.slope || 0);
|
|
67
|
+
const powerDelta = powerRequired - power;
|
|
68
|
+
const Ekin = EkinPrev - powerDelta * duration;
|
|
69
|
+
const v = Math.sqrt(2 * Ekin / m);
|
|
70
|
+
speed = v * 3.6;
|
|
63
71
|
distanceInternal += Math.round(v * duration);
|
|
64
72
|
data.speed = parseFloat(speed.toFixed(1));
|
|
65
73
|
data.power = Math.round(power);
|
|
@@ -1,23 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
-
}) : (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
o[k2] = m[k];
|
|
8
|
-
}));
|
|
9
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
-
}) : function(o, v) {
|
|
12
|
-
o["default"] = v;
|
|
13
|
-
});
|
|
14
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
-
if (mod && mod.__esModule) return mod;
|
|
16
|
-
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
-
__setModuleDefault(result, mod);
|
|
19
|
-
return result;
|
|
20
|
-
};
|
|
21
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -27,6 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
27
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
9
|
});
|
|
29
10
|
};
|
|
11
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
12
|
+
if (mod && mod.__esModule) return mod;
|
|
13
|
+
var result = {};
|
|
14
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
15
|
+
result["default"] = mod;
|
|
16
|
+
return result;
|
|
17
|
+
};
|
|
30
18
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
19
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
20
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { IncyclistBikeData, Settings, CyclingModeBase } from '../CyclingMode';
|
|
2
|
+
import { DeviceAdapter } from '../Device';
|
|
3
|
+
import { EventLogger } from 'gd-eventlog';
|
|
4
|
+
export default class PowerBasedCyclingModeBase extends CyclingModeBase {
|
|
5
|
+
data: IncyclistBikeData;
|
|
6
|
+
prevUpdateTS: number;
|
|
7
|
+
logger: EventLogger;
|
|
8
|
+
constructor(adapter: DeviceAdapter, props?: Settings);
|
|
9
|
+
initLogger(defaultLogName: any): void;
|
|
10
|
+
getWeight(): any;
|
|
11
|
+
getTimeSinceLastUpdate(): number;
|
|
12
|
+
calculateSpeedAndDistance(power: number, slope: number, m: number, t: number, props?: {}): {
|
|
13
|
+
speed: number;
|
|
14
|
+
distance: number;
|
|
15
|
+
};
|
|
16
|
+
calculatePowerAndDistance(speed: number, slope: number, m: number, t: number, props?: {}): {
|
|
17
|
+
power: number;
|
|
18
|
+
distance: number;
|
|
19
|
+
};
|
|
20
|
+
}
|