incyclist-devices 2.4.3 → 2.4.5
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.
|
@@ -32,7 +32,9 @@ export default class SmartTrainerCyclingMode extends PowerBasedCyclingModeBase i
|
|
|
32
32
|
protected tsStart: number;
|
|
33
33
|
protected simPower: number;
|
|
34
34
|
protected simSlope: number;
|
|
35
|
+
protected maintainPower: number;
|
|
35
36
|
protected prevData: any;
|
|
37
|
+
protected prevEkin: number;
|
|
36
38
|
protected readonly gearRatios: number[];
|
|
37
39
|
constructor(adapter: IAdapter, props?: any);
|
|
38
40
|
getBikeInitRequest(): UpdateRequest;
|
|
@@ -45,7 +47,7 @@ export default class SmartTrainerCyclingMode extends PowerBasedCyclingModeBase i
|
|
|
45
47
|
protected checkSlopeWithSimulatedShifting(request: UpdateRequest, newRequest?: UpdateRequest): void;
|
|
46
48
|
checkSlope(request: UpdateRequest, newRequest?: UpdateRequest): void;
|
|
47
49
|
checkCadenceChange(request: UpdateRequest, newRequest?: UpdateRequest): void;
|
|
48
|
-
calculateSimulatedPower(
|
|
50
|
+
calculateSimulatedPower(changed?: string): void;
|
|
49
51
|
checkGearChange(request: UpdateRequest, newRequest?: UpdateRequest): void;
|
|
50
52
|
protected verifySimPower(): void;
|
|
51
53
|
protected checkEmptyRequest(newRequest: UpdateRequest): void;
|
|
@@ -89,14 +89,14 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
89
89
|
config.properties.push(virtshift);
|
|
90
90
|
}
|
|
91
91
|
if (!virtshift && virtShiftEnabled && this.adapter.supportsVirtualShifting()) {
|
|
92
|
-
|
|
93
|
-
virtshift.options = [
|
|
92
|
+
const options = [
|
|
94
93
|
'Disabled',
|
|
95
94
|
{ key: 'Incyclist', display: 'App only (beta)' },
|
|
96
95
|
{ key: 'Mixed', display: 'App + Bike' },
|
|
97
96
|
{ key: 'SmartTrainer', display: 'SmartTreiner (beta)' }
|
|
98
97
|
];
|
|
99
|
-
virtshift
|
|
98
|
+
virtshift = { key: 'virtshift', name: 'Virtual Shifting', description: 'Enable virtual shifting', type: types_1.CyclingModeProperyType.SingleSelect, options, default: 'Mixed' };
|
|
99
|
+
config.properties.push(virtshift);
|
|
100
100
|
}
|
|
101
101
|
if (virtshift && !startGear) {
|
|
102
102
|
startGear = { key: 'startGear', name: 'Initial Gear', description: 'Initial Gear', type: types_1.CyclingModeProperyType.Integer, default: 12, min: 1, max: 24, condition: (s) => (s === null || s === void 0 ? void 0 : s.virtshift) === 'Incyclist' || (s === null || s === void 0 ? void 0 : s.virtshift) === 'SmartTrainer' };
|
|
@@ -141,7 +141,9 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
checkSlopeWithSimulatedShifting(request, newRequest = {}) {
|
|
144
|
-
var _a
|
|
144
|
+
var _a;
|
|
145
|
+
if (this.simPower)
|
|
146
|
+
return;
|
|
145
147
|
if (this.gear === undefined) {
|
|
146
148
|
this.checkSlopeNoShiftig(request, newRequest);
|
|
147
149
|
return;
|
|
@@ -161,36 +163,9 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
161
163
|
if (slopeAdj !== undefined)
|
|
162
164
|
this.simSlope = this.simSlope * slopeAdj / 100;
|
|
163
165
|
}
|
|
164
|
-
catch (
|
|
165
|
-
}
|
|
166
|
-
const virtualSpeed = (0, calculations_1.calculateVirtualSpeed)(this.data.pedalRpm, this.gearRatios[this.gear - 1]);
|
|
167
|
-
const m = (_c = (_b = this.adapter) === null || _b === void 0 ? void 0 : _b.getWeight()) !== null && _c !== void 0 ? _c : 85;
|
|
168
|
-
const vCurrent = this.data.speed * 1000 / 3600;
|
|
169
|
-
const eKinCurrent = m * vCurrent * vCurrent / 2;
|
|
170
|
-
const newPower = calculations_1.default.calculatePower(m, virtualSpeed, (_d = this.simSlope) !== null && _d !== void 0 ? _d : 0);
|
|
171
|
-
const prevPower = this.data.power;
|
|
172
|
-
if (this.data.speed < 10 && this.data.isPedalling && (this.data.slope < 1 || this.data.speed === 0)) {
|
|
173
|
-
this.simPower = Math.max(newPower, prevPower);
|
|
174
|
-
console.log('# set simulated power', { power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, prevPower, newPower });
|
|
175
|
-
this.logger.logEvent({ message: 'set simulated power', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, prevPower, newPower });
|
|
176
|
-
}
|
|
177
|
-
else if (this.data.slope === prev && newPower < prevPower) {
|
|
178
|
-
this.simPower = prevPower;
|
|
179
|
-
console.log('# set simulated power:', { power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, prevPower, newPower });
|
|
180
|
-
this.logger.logEvent({ message: 'set simulated power', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, prevPower, newPower });
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
const powerDiff = newPower - prevPower;
|
|
184
|
-
const vTarget = virtualSpeed * 1000 / 3600;
|
|
185
|
-
const eKinTarget = m * vTarget * vTarget / 2;
|
|
186
|
-
const eKinPrev = eKinCurrent;
|
|
187
|
-
const delta = eKinTarget - eKinPrev;
|
|
188
|
-
const eKinAfter1sec = eKinPrev - powerDiff * 1;
|
|
189
|
-
const vAfter1sec = Math.sqrt(2 * eKinAfter1sec / m) * 3600 / 1000;
|
|
190
|
-
this.simPower = calculations_1.default.calculatePower(m, vAfter1sec / 3.6, (_e = this.simSlope) !== null && _e !== void 0 ? _e : 0);
|
|
191
|
-
console.log('# set simulated power (Ekin):', { power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, eKinPrev, eKinTarget, delta, prevPower, newPower });
|
|
192
|
-
this.logger.logEvent({ message: 'set simulated power (Ekin)', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, eKinPrev, eKinTarget, delta, prevPower, newPower });
|
|
166
|
+
catch (_b) {
|
|
193
167
|
}
|
|
168
|
+
this.calculateSimulatedPower('slope');
|
|
194
169
|
this.verifySimPower();
|
|
195
170
|
}
|
|
196
171
|
newRequest.targetPower = this.simPower;
|
|
@@ -224,39 +199,53 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
224
199
|
}
|
|
225
200
|
if (this.data.pedalRpm !== this.prevData.pedalRpm) {
|
|
226
201
|
console.log('# cadence changed ', { cadence: this.data.pedalRpm, prevCadence: this.prevData.pedalRpm });
|
|
227
|
-
this.
|
|
202
|
+
this.logger.logEvent({ message: 'cadence changed', cadence: this.data.pedalRpm, prevCadence: this.prevData.pedalRpm });
|
|
203
|
+
this.calculateSimulatedPower('cadence');
|
|
228
204
|
delete request.slope;
|
|
229
205
|
}
|
|
230
206
|
}
|
|
231
|
-
calculateSimulatedPower(
|
|
232
|
-
var _a, _b, _c, _d;
|
|
207
|
+
calculateSimulatedPower(changed) {
|
|
208
|
+
var _a, _b, _c, _d, _e;
|
|
209
|
+
if (this.simPower)
|
|
210
|
+
return;
|
|
233
211
|
const m = (_b = (_a = this.adapter) === null || _a === void 0 ? void 0 : _a.getWeight()) !== null && _b !== void 0 ? _b : 85;
|
|
234
212
|
const vCurrent = this.data.speed * 1000 / 3600;
|
|
235
213
|
const eKinCurrent = m * vCurrent * vCurrent / 2;
|
|
236
214
|
if (this.data.pedalRpm > 0) {
|
|
237
|
-
const virtualSpeed = (0, calculations_1.calculateVirtualSpeed)(this.data.pedalRpm, this.gearRatios[this.gear - 1]);
|
|
238
|
-
const
|
|
215
|
+
const virtualSpeed = (0, calculations_1.calculateVirtualSpeed)(this.data.pedalRpm, this.gearRatios[this.gear - 1]) * 3.6;
|
|
216
|
+
const v = virtualSpeed / 3.6;
|
|
217
|
+
const newPower = calculations_1.default.calculatePower(m, virtualSpeed / 3.6, (_c = this.simSlope) !== null && _c !== void 0 ? _c : 0);
|
|
239
218
|
const prevPower = this.data.power;
|
|
240
|
-
if (this.
|
|
219
|
+
if (!this.prevEkin && this.data.isPedalling) {
|
|
241
220
|
this.simPower = Math.max(newPower, prevPower);
|
|
221
|
+
this.prevEkin = m * v * v / 2;
|
|
242
222
|
console.log('# set simulated power (starting)', { power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, prevPower, newPower });
|
|
243
223
|
this.logger.logEvent({ message: 'set simulated power (starting)', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, prevPower, newPower });
|
|
244
224
|
}
|
|
225
|
+
else if (changed === 'gear') {
|
|
226
|
+
this.simPower = newPower;
|
|
227
|
+
this.prevEkin = m * v * v / 2;
|
|
228
|
+
console.log('# set simulated power (gear change)', { power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, prevPower, newPower });
|
|
229
|
+
this.logger.logEvent({ message: 'set simulated power (gear change)', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, prevPower, newPower });
|
|
230
|
+
}
|
|
245
231
|
else {
|
|
246
232
|
const powerDiff = newPower - prevPower;
|
|
247
233
|
const vTarget = virtualSpeed * 1000 / 3600;
|
|
248
234
|
const eKinTarget = m * vTarget * vTarget / 2;
|
|
249
|
-
const eKinPrev =
|
|
235
|
+
const eKinPrev = (_d = this.prevEkin) !== null && _d !== void 0 ? _d : 0;
|
|
250
236
|
const delta = eKinTarget - eKinPrev;
|
|
251
|
-
const eKinAfter1sec = eKinPrev
|
|
252
|
-
const vAfter1sec = Math.sqrt(
|
|
253
|
-
this.simPower = calculations_1.default.calculatePower(m, vAfter1sec
|
|
237
|
+
const eKinAfter1sec = eKinPrev + powerDiff * 1;
|
|
238
|
+
const vAfter1sec = Math.sqrt(eKinAfter1sec / m * 2);
|
|
239
|
+
this.simPower = calculations_1.default.calculatePower(m, vAfter1sec, (_e = this.simSlope) !== null && _e !== void 0 ? _e : 0);
|
|
254
240
|
console.log('# set simulated power (Ekin):', { power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, eKinPrev, eKinTarget, delta, prevPower, newPower });
|
|
255
241
|
this.logger.logEvent({ message: 'set simulated power (Ekin)', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, eKinPrev, eKinTarget, delta, prevPower, newPower });
|
|
256
242
|
}
|
|
257
243
|
}
|
|
258
244
|
else {
|
|
259
245
|
delete this.simPower;
|
|
246
|
+
if (this.data.speed < 5) {
|
|
247
|
+
delete this.prevEkin;
|
|
248
|
+
}
|
|
260
249
|
}
|
|
261
250
|
}
|
|
262
251
|
checkGearChange(request, newRequest = {}) {
|
|
@@ -271,12 +260,13 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
271
260
|
break;
|
|
272
261
|
case 'Simulated':
|
|
273
262
|
if (request.gearDelta !== undefined) {
|
|
263
|
+
const oldGear = this.gear;
|
|
274
264
|
if (this.gear === undefined) {
|
|
275
|
-
const initialGear = this.getSetting('startGear');
|
|
276
|
-
this.gear = initialGear + request.gearDelta;
|
|
265
|
+
const initialGear = Number(this.getSetting('startGear'));
|
|
266
|
+
this.gear = initialGear + Number(request.gearDelta);
|
|
277
267
|
}
|
|
278
268
|
else {
|
|
279
|
-
this.gear += request.gearDelta;
|
|
269
|
+
this.gear += Number(request.gearDelta);
|
|
280
270
|
}
|
|
281
271
|
if (this.gear < 1) {
|
|
282
272
|
this.gear = 1;
|
|
@@ -285,7 +275,9 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
285
275
|
this.gear = this.gearRatios.length;
|
|
286
276
|
}
|
|
287
277
|
delete request.gearDelta;
|
|
288
|
-
|
|
278
|
+
console.log('# gear changed');
|
|
279
|
+
this.logger.logEvent({ message: 'gear changed', gear: this.gear, oldGear });
|
|
280
|
+
this.calculateSimulatedPower('gear');
|
|
289
281
|
if (this.simPower !== undefined) {
|
|
290
282
|
this.adapter.sendUpdate({ targetPower: this.simPower }).then(() => { });
|
|
291
283
|
}
|
|
@@ -310,7 +302,7 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
310
302
|
}
|
|
311
303
|
else if (request.gearDelta !== undefined) {
|
|
312
304
|
if (this.gear === undefined) {
|
|
313
|
-
const initialGear = this.getSetting('startGear');
|
|
305
|
+
const initialGear = Number(this.getSetting('startGear'));
|
|
314
306
|
this.gear = initialGear + request.gearDelta;
|
|
315
307
|
}
|
|
316
308
|
else {
|
|
@@ -327,7 +319,7 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
327
319
|
}
|
|
328
320
|
else {
|
|
329
321
|
if (this.gear === undefined) {
|
|
330
|
-
const initialGear = this.getSetting('startGear');
|
|
322
|
+
const initialGear = Number(this.getSetting('startGear'));
|
|
331
323
|
this.gear = initialGear + request.gearDelta;
|
|
332
324
|
}
|
|
333
325
|
newRequest.gearRatio = this.gearRatios[this.gear];
|
|
@@ -358,29 +350,35 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
358
350
|
}
|
|
359
351
|
}
|
|
360
352
|
getVirtualShiftMode() {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
353
|
+
try {
|
|
354
|
+
if (!this.getFeatureToogle().has('VirtualShifting')) {
|
|
355
|
+
return 'Disabled';
|
|
356
|
+
}
|
|
357
|
+
const virtshiftMode = this.getSetting('virtshift');
|
|
358
|
+
if (virtshiftMode === 'Disabled') {
|
|
359
|
+
return 'Disabled';
|
|
360
|
+
}
|
|
361
|
+
else if (virtshiftMode === 'Incyclist') {
|
|
362
|
+
return 'Simulated';
|
|
363
|
+
}
|
|
364
|
+
else if (virtshiftMode === 'SmartTrainer') {
|
|
365
|
+
return 'Adapter';
|
|
366
|
+
}
|
|
367
|
+
else if (virtshiftMode === 'Mixed') {
|
|
368
|
+
return 'SlopeDelta';
|
|
369
|
+
}
|
|
370
|
+
else if (virtshiftMode === 'Enabled') {
|
|
371
|
+
return this.adapter.supportsVirtualShifting() ? 'Adapter' : 'Simulated';
|
|
372
|
+
}
|
|
376
373
|
}
|
|
377
|
-
|
|
378
|
-
|
|
374
|
+
catch (err) {
|
|
375
|
+
this.logger.logEvent({ message: 'error', fn: 'getVirtualShiftMode', error: err.message, stack: err.stack });
|
|
379
376
|
}
|
|
380
377
|
return 'Disabled';
|
|
381
378
|
}
|
|
382
379
|
updateData(bikeData, log) {
|
|
383
380
|
var _a;
|
|
381
|
+
console.log('# update data', bikeData);
|
|
384
382
|
const prev = this.prevData = Object.assign({}, this.data);
|
|
385
383
|
const data = super.updateData(bikeData, log);
|
|
386
384
|
const mode = this.getVirtualShiftMode();
|
|
@@ -393,9 +391,10 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
393
391
|
this.tsStart = Date.now();
|
|
394
392
|
}
|
|
395
393
|
if (this.gear === undefined && this.tsStart && data.power > 0 && (Date.now() - this.tsStart > 3000)) {
|
|
396
|
-
this.gear = (_a = this.getSetting('startGear')) !== null && _a !== void 0 ? _a : 0;
|
|
394
|
+
this.gear = (_a = Number(this.getSetting('startGear'))) !== null && _a !== void 0 ? _a : 0;
|
|
397
395
|
data.gearStr = this.getGearString();
|
|
398
396
|
}
|
|
397
|
+
console.log('# data updated', data);
|
|
399
398
|
return data;
|
|
400
399
|
}
|
|
401
400
|
getData() {
|
|
@@ -411,9 +410,11 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
411
410
|
return super.updateRequired(request);
|
|
412
411
|
}
|
|
413
412
|
sendBikeUpdate(incoming) {
|
|
413
|
+
console.log('# bike update request', incoming);
|
|
414
414
|
this.logger.logEvent({ message: "processing update request", request: incoming, prev: this.prevRequest, data: this.getData() });
|
|
415
415
|
let newRequest = {};
|
|
416
416
|
const request = Object.assign({}, incoming);
|
|
417
|
+
delete this.simPower;
|
|
417
418
|
try {
|
|
418
419
|
const req = this.checkForResetOrEmpty(request);
|
|
419
420
|
if (req) {
|
|
@@ -432,21 +433,21 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
432
433
|
return newRequest;
|
|
433
434
|
}
|
|
434
435
|
getGearString() {
|
|
435
|
-
var _a, _b, _c, _d;
|
|
436
|
+
var _a, _b, _c, _d, _e;
|
|
436
437
|
const mode = this.getVirtualShiftMode();
|
|
437
438
|
if (mode === "Disabled")
|
|
438
439
|
return undefined;
|
|
439
440
|
if (mode === 'Simulated') {
|
|
440
|
-
this.gear = (
|
|
441
|
+
this.gear = (_a = this.gear) !== null && _a !== void 0 ? _a : Number((_b = this.getSetting('startGear')) !== null && _b !== void 0 ? _b : 0);
|
|
441
442
|
return this.gear.toString();
|
|
442
443
|
}
|
|
443
444
|
if (mode === "SlopeDelta")
|
|
444
445
|
return this.gearDelta > 0 ? `+${this.gearDelta}` : `${this.gearDelta}`;
|
|
445
446
|
if (mode === 'Adapter') {
|
|
446
|
-
this.gear = (_c = this.gear) !== null && _c !== void 0 ? _c : this.getSetting('startGear');
|
|
447
|
+
this.gear = (_c = this.gear) !== null && _c !== void 0 ? _c : Number((_d = this.getSetting('startGear')) !== null && _d !== void 0 ? _d : 1);
|
|
447
448
|
return this.gear.toString();
|
|
448
449
|
}
|
|
449
|
-
return (
|
|
450
|
+
return (_e = this.gear) === null || _e === void 0 ? void 0 : _e.toString();
|
|
450
451
|
}
|
|
451
452
|
getFeatureToogle() {
|
|
452
453
|
return (0, features_1.useFeatureToggle)();
|