incyclist-devices 2.3.28 → 2.3.31
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/types.d.ts +1 -1
- package/lib/base/adpater.d.ts +2 -0
- package/lib/base/adpater.js +24 -11
- package/lib/ble/base/adapter.js +2 -1
- package/lib/ble/base/interface.d.ts +1 -0
- package/lib/ble/base/interface.js +29 -4
- package/lib/ble/base/peripheral.d.ts +3 -2
- package/lib/ble/base/peripheral.js +62 -38
- package/lib/ble/base/sensor.d.ts +2 -0
- package/lib/ble/base/sensor.js +16 -4
- package/lib/ble/fm/adapter.js +10 -8
- package/lib/ble/index.js +2 -0
- package/lib/ble/types.d.ts +4 -2
- package/lib/ble/zwift/click/adapter.d.ts +19 -0
- package/lib/ble/zwift/click/adapter.js +74 -0
- package/lib/ble/zwift/click/index.d.ts +2 -0
- package/lib/ble/zwift/click/index.js +18 -0
- package/lib/ble/zwift/click/sensor.d.ts +40 -0
- package/lib/ble/zwift/click/sensor.js +221 -0
- package/lib/ble/zwift/play/adapter.d.ts +19 -0
- package/lib/ble/zwift/play/adapter.js +76 -0
- package/lib/ble/zwift/play/index.d.ts +2 -0
- package/lib/ble/zwift/play/index.js +18 -0
- package/lib/ble/zwift/play/sensor.d.ts +43 -0
- package/lib/ble/zwift/play/sensor.js +246 -0
- package/lib/modes/antble-smarttrainer.d.ts +22 -3
- package/lib/modes/antble-smarttrainer.js +226 -3
- package/lib/modes/daum-classic-standard.d.ts +2 -1
- package/lib/modes/daum-classic-standard.js +6 -0
- package/lib/modes/power-base.js +17 -3
- package/lib/modes/types.d.ts +1 -0
- package/lib/serial/daum/DaumAdapter.d.ts +1 -0
- package/lib/serial/daum/DaumAdapter.js +14 -0
- package/lib/types/adapter.d.ts +1 -0
- package/lib/types/capabilities.d.ts +2 -1
- package/lib/types/capabilities.js +1 -0
- package/lib/types/data.d.ts +2 -0
- package/lib/utils/calculations.d.ts +1 -0
- package/lib/utils/calculations.js +13 -1
- package/lib/utils/utils.js +33 -26
- package/package.json +22 -10
|
@@ -1,13 +1,52 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
39
|
const types_1 = require("./types");
|
|
7
40
|
const power_base_1 = __importDefault(require("./power-base"));
|
|
41
|
+
const calculations_1 = __importStar(require("../utils/calculations"));
|
|
8
42
|
class SmartTrainerCyclingMode extends power_base_1.default {
|
|
9
43
|
constructor(adapter, props) {
|
|
10
44
|
super(adapter, props);
|
|
45
|
+
this.gearDelta = 0;
|
|
46
|
+
this.gearRatios = [
|
|
47
|
+
0.75, 0.87, 0.99, 1.11, 1.23, 1.38, 1.53, 1.68, 1.86, 2.04, 2.22, 2.40,
|
|
48
|
+
2.61, 2.82, 3.03, 3.24, 3.49, 3.74, 3.99, 4.24, 4.54, 4.84, 5.14, 5.49
|
|
49
|
+
];
|
|
11
50
|
this.initLogger('SmartTrainerMode');
|
|
12
51
|
}
|
|
13
52
|
getBikeInitRequest() {
|
|
@@ -23,7 +62,20 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
23
62
|
return this.prevRequest;
|
|
24
63
|
}
|
|
25
64
|
}
|
|
26
|
-
|
|
65
|
+
getConfig() {
|
|
66
|
+
const config = super.getConfig();
|
|
67
|
+
let virtshift = config.properties.find(p => p.key === 'virtshift');
|
|
68
|
+
if (!virtshift) {
|
|
69
|
+
virtshift = { key: 'virtshift', name: 'Virtual Shifting', description: 'Enable virtual shifting', type: types_1.CyclingModeProperyType.SingleSelect, options: ['Disabled', 'Enabled', 'Mixed'], default: 'Disabled' };
|
|
70
|
+
config.properties.push(virtshift);
|
|
71
|
+
}
|
|
72
|
+
if (this.adapter.supportsVirtualShifting()) {
|
|
73
|
+
virtshift.default = 'Enabled';
|
|
74
|
+
virtshift.options = ['Disabled', 'Enabled'];
|
|
75
|
+
}
|
|
76
|
+
return config;
|
|
77
|
+
}
|
|
78
|
+
checkSlopeNoShiftig(request, newRequest = {}) {
|
|
27
79
|
if (request.slope !== undefined) {
|
|
28
80
|
const targetSlope = newRequest.slope = parseFloat(request.slope.toFixed(1));
|
|
29
81
|
this.data.slope = newRequest.slope;
|
|
@@ -36,6 +88,116 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
36
88
|
}
|
|
37
89
|
}
|
|
38
90
|
}
|
|
91
|
+
checkSlopeWithAdapterShifting(request, newRequest = {}) {
|
|
92
|
+
return this.checkSlopeNoShiftig(request, newRequest);
|
|
93
|
+
}
|
|
94
|
+
getSlopeDelta() {
|
|
95
|
+
return this.gearDelta * 0.5;
|
|
96
|
+
}
|
|
97
|
+
checkSlopeWithSlopeDelta(request, newRequest = {}) {
|
|
98
|
+
if (request.slope !== undefined) {
|
|
99
|
+
const targetSlope = newRequest.slope = parseFloat(request.slope.toFixed(1));
|
|
100
|
+
this.data.slope = newRequest.slope;
|
|
101
|
+
const requestedSlope = targetSlope + this.getSlopeDelta();
|
|
102
|
+
try {
|
|
103
|
+
const slopeAdj = requestedSlope >= 0 ? this.getSetting('slopeAdj') : this.getSetting('slopeAdjDown');
|
|
104
|
+
newRequest.slope = slopeAdj !== undefined ? requestedSlope * slopeAdj / 100 : requestedSlope;
|
|
105
|
+
}
|
|
106
|
+
catch (_a) {
|
|
107
|
+
console.error('# Error calculating requested slope');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
checkSlopeWithSimulatedShifting(request, newRequest = {}) {
|
|
112
|
+
var _a, _b, _c, _d;
|
|
113
|
+
if (this.gear === undefined) {
|
|
114
|
+
return this.checkSlopeNoShiftig(request, newRequest);
|
|
115
|
+
}
|
|
116
|
+
if (request.slope !== undefined) {
|
|
117
|
+
const prev = (_a = this.data.slope) !== null && _a !== void 0 ? _a : 0;
|
|
118
|
+
this.data.slope = parseFloat(request.slope.toFixed(1));
|
|
119
|
+
delete request.slope;
|
|
120
|
+
delete newRequest.slope;
|
|
121
|
+
this.simSlope = this.data.slope;
|
|
122
|
+
try {
|
|
123
|
+
const slopeAdj = this.simSlope >= 0 ? this.getSetting('slopeAdj') : this.getSetting('slopeAdjDown');
|
|
124
|
+
if (slopeAdj !== undefined)
|
|
125
|
+
this.simSlope = this.simSlope * slopeAdj / 100;
|
|
126
|
+
}
|
|
127
|
+
catch (_e) {
|
|
128
|
+
}
|
|
129
|
+
if (this.data.slope === prev) {
|
|
130
|
+
newRequest.targetPower = this.simPower;
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
const virtualSpeed = (0, calculations_1.calculateVirtualSpeed)(this.data.pedalRpm, this.gearRatios[this.gear - 1]);
|
|
135
|
+
const m = (_c = (_b = this.adapter) === null || _b === void 0 ? void 0 : _b.getWeight()) !== null && _c !== void 0 ? _c : 85;
|
|
136
|
+
this.simPower = calculations_1.default.calculatePower(m, virtualSpeed, (_d = this.simSlope) !== null && _d !== void 0 ? _d : 0);
|
|
137
|
+
newRequest.targetPower = this.simPower;
|
|
138
|
+
}
|
|
139
|
+
if (this.simPower < 0)
|
|
140
|
+
this.simPower = 0;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
newRequest.targetPower = this.simPower;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
checkSlope(request, newRequest = {}) {
|
|
147
|
+
const virtshiftMode = this.getVirtualShiftMode();
|
|
148
|
+
switch (virtshiftMode) {
|
|
149
|
+
case 'SlopeDelta':
|
|
150
|
+
this.checkSlopeWithSlopeDelta(request, newRequest);
|
|
151
|
+
break;
|
|
152
|
+
case 'Simulated':
|
|
153
|
+
this.checkSlopeWithSimulatedShifting(request, newRequest);
|
|
154
|
+
break;
|
|
155
|
+
case 'Adapter':
|
|
156
|
+
this.checkSlopeWithAdapterShifting(request, newRequest);
|
|
157
|
+
break;
|
|
158
|
+
case 'Disabled':
|
|
159
|
+
default:
|
|
160
|
+
this.checkSlopeNoShiftig(request, newRequest);
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
checkGearChange(request, newRequest = {}) {
|
|
165
|
+
var _a, _b, _c, _d;
|
|
166
|
+
const virtshiftMode = this.getVirtualShiftMode();
|
|
167
|
+
switch (virtshiftMode) {
|
|
168
|
+
case 'SlopeDelta':
|
|
169
|
+
if (request.gearDelta !== undefined) {
|
|
170
|
+
this.gearDelta += request.gearDelta;
|
|
171
|
+
request.slope = this.data.slope;
|
|
172
|
+
delete request.gearDelta;
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
175
|
+
case 'Simulated':
|
|
176
|
+
if (request.gearDelta !== undefined) {
|
|
177
|
+
if (this.gear === undefined) {
|
|
178
|
+
this.gear = 10 + request.gearDelta;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
this.gear += request.gearDelta;
|
|
182
|
+
}
|
|
183
|
+
if (this.gear < 1) {
|
|
184
|
+
this.gear = 1;
|
|
185
|
+
}
|
|
186
|
+
if (this.gear > this.gearRatios.length) {
|
|
187
|
+
this.gear = this.gearRatios.length;
|
|
188
|
+
}
|
|
189
|
+
delete request.gearDelta;
|
|
190
|
+
const virtualSpeed = (0, calculations_1.calculateVirtualSpeed)(this.data.pedalRpm, this.gearRatios[this.gear - 1]);
|
|
191
|
+
const m = (_b = (_a = this.adapter) === null || _a === void 0 ? void 0 : _a.getWeight()) !== null && _b !== void 0 ? _b : 85;
|
|
192
|
+
this.simPower = calculations_1.default.calculatePower(m, virtualSpeed, (_d = (_c = this.simSlope) !== null && _c !== void 0 ? _c : this.data.slope) !== null && _d !== void 0 ? _d : 0);
|
|
193
|
+
}
|
|
194
|
+
break;
|
|
195
|
+
case 'Adapter':
|
|
196
|
+
case 'Disabled':
|
|
197
|
+
default:
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
39
201
|
checkEmptyRequest(newRequest) {
|
|
40
202
|
if (Object.keys(newRequest).length === 0) {
|
|
41
203
|
if (this.prevRequest) {
|
|
@@ -44,14 +206,56 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
44
206
|
}
|
|
45
207
|
}
|
|
46
208
|
}
|
|
209
|
+
getVirtualShiftMode() {
|
|
210
|
+
const virtshiftMode = this.getSetting('virtshift');
|
|
211
|
+
if (virtshiftMode === 'Disabled') {
|
|
212
|
+
return 'Disabled';
|
|
213
|
+
}
|
|
214
|
+
if (this.adapter.supportsVirtualShifting()) {
|
|
215
|
+
if (virtshiftMode === 'Enabled') {
|
|
216
|
+
return 'Adapter';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
return virtshiftMode === 'Mixed' ? 'SlopeDelta' : 'Simulated';
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
updateData(bikeData, log) {
|
|
224
|
+
var _a, _b, _c, _d;
|
|
225
|
+
const prev = Object.assign({}, this.data);
|
|
226
|
+
const data = super.updateData(bikeData, log);
|
|
227
|
+
const mode = this.getVirtualShiftMode();
|
|
228
|
+
let virtualSpeed;
|
|
229
|
+
data.gearStr = this.getGearString();
|
|
230
|
+
if (mode !== 'Simulated') {
|
|
231
|
+
return data;
|
|
232
|
+
}
|
|
233
|
+
if (data.power > 0 && !this.tsStart) {
|
|
234
|
+
this.tsStart = Date.now();
|
|
235
|
+
}
|
|
236
|
+
if (this.gear === undefined && this.tsStart && data.power > 0 && (Date.now() - this.tsStart > 3000)) {
|
|
237
|
+
this.setInitialGear(data);
|
|
238
|
+
data.gearStr = this.getGearString();
|
|
239
|
+
}
|
|
240
|
+
else if (this.gear !== undefined) {
|
|
241
|
+
if (prev.power !== data.power || prev.pedalRpm !== data.pedalRpm) {
|
|
242
|
+
virtualSpeed = (0, calculations_1.calculateVirtualSpeed)(data.pedalRpm, this.gearRatios[this.gear - 1]);
|
|
243
|
+
const m = (_b = (_a = this.adapter) === null || _a === void 0 ? void 0 : _a.getWeight()) !== null && _b !== void 0 ? _b : 85;
|
|
244
|
+
this.simPower = calculations_1.default.calculatePower(m, virtualSpeed, (_d = (_c = this.simSlope) !== null && _c !== void 0 ? _c : data.slope) !== null && _d !== void 0 ? _d : 0);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return data;
|
|
248
|
+
}
|
|
47
249
|
sendBikeUpdate(incoming) {
|
|
48
250
|
this.logger.logEvent({ message: "processing update request", request: incoming, prev: this.prevRequest, data: this.getData() });
|
|
49
251
|
let newRequest = {};
|
|
50
252
|
const request = Object.assign({}, incoming);
|
|
51
253
|
try {
|
|
52
254
|
const req = this.checkForResetOrEmpty(request);
|
|
53
|
-
if (req)
|
|
255
|
+
if (req) {
|
|
54
256
|
return req;
|
|
257
|
+
}
|
|
258
|
+
this.checkGearChange(request, newRequest);
|
|
55
259
|
this.checkSlope(request, newRequest);
|
|
56
260
|
this.checkEmptyRequest(newRequest);
|
|
57
261
|
this.prevRequest = JSON.parse(JSON.stringify(newRequest));
|
|
@@ -62,6 +266,25 @@ class SmartTrainerCyclingMode extends power_base_1.default {
|
|
|
62
266
|
}
|
|
63
267
|
return newRequest;
|
|
64
268
|
}
|
|
269
|
+
setInitialGear(data) {
|
|
270
|
+
var _a, _b;
|
|
271
|
+
const m = (_b = (_a = this.adapter) === null || _a === void 0 ? void 0 : _a.getWeight()) !== null && _b !== void 0 ? _b : 85;
|
|
272
|
+
const virtualSpeeds = this.gearRatios.map(r => (0, calculations_1.calculateVirtualSpeed)(data.pedalRpm, r));
|
|
273
|
+
const requiredPowers = virtualSpeeds.map(v => { var _a; return calculations_1.default.calculatePower(m, v, (_a = data.slope) !== null && _a !== void 0 ? _a : 0); });
|
|
274
|
+
const deltas = requiredPowers.map((p, i) => ({ gear: i + 1, delta: Math.abs(p - data.power) }));
|
|
275
|
+
deltas.sort((a, b) => a.delta - b.delta);
|
|
276
|
+
this.gear = deltas[0].gear;
|
|
277
|
+
}
|
|
278
|
+
getGearString() {
|
|
279
|
+
const mode = this.getVirtualShiftMode();
|
|
280
|
+
if (mode === "Disabled")
|
|
281
|
+
return undefined;
|
|
282
|
+
if (this.gear === undefined || this.gear === null)
|
|
283
|
+
return '';
|
|
284
|
+
if (mode === "SlopeDelta")
|
|
285
|
+
return this.gear > 0 ? `+${this.gear}` : `${this.gear}`;
|
|
286
|
+
return this.gear.toString();
|
|
287
|
+
}
|
|
65
288
|
}
|
|
66
289
|
SmartTrainerCyclingMode.config = {
|
|
67
290
|
name: "Smart Trainer",
|
|
@@ -70,7 +293,7 @@ SmartTrainerCyclingMode.config = {
|
|
|
70
293
|
properties: [
|
|
71
294
|
{ key: 'bikeType', name: 'Bike Type', description: '', type: types_1.CyclingModeProperyType.SingleSelect, options: ['Race', 'Mountain', 'Triathlon'], default: 'Race' },
|
|
72
295
|
{ key: 'slopeAdj', name: 'Bike Reality Factor', description: 'Percentage of slope that should be sent to the SmartTrainer. Should be used in case the slopes are feeling too hard', type: types_1.CyclingModeProperyType.Integer, default: 100, min: 0, max: 200 },
|
|
73
|
-
{ key: 'slopeAdjDown', name: 'Bike Reality Factor downhill', description: 'Percentage of slope that should be sent during downhill sections. Should be used to avoid spinning out', type: types_1.CyclingModeProperyType.Integer, default: 50, min: 0, max: 100 }
|
|
296
|
+
{ key: 'slopeAdjDown', name: 'Bike Reality Factor downhill', description: 'Percentage of slope that should be sent during downhill sections. Should be used to avoid spinning out', type: types_1.CyclingModeProperyType.Integer, default: 50, min: 0, max: 100 },
|
|
74
297
|
]
|
|
75
298
|
};
|
|
76
299
|
exports.default = SmartTrainerCyclingMode;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import ICyclingMode, { Settings, UpdateRequest } from "./types";
|
|
1
|
+
import ICyclingMode, { CyclingModeConfig, Settings, UpdateRequest } from "./types";
|
|
2
2
|
import { IncyclistBikeData } from "../types";
|
|
3
3
|
import SmartTrainerCyclingMode from "./antble-smarttrainer";
|
|
4
4
|
import { IncyclistDeviceAdapter } from "../base/adpater";
|
|
@@ -11,6 +11,7 @@ export default class DaumClassicCyclingMode extends SmartTrainerCyclingMode impl
|
|
|
11
11
|
event: DaumClassicEvent;
|
|
12
12
|
constructor(adapter: IncyclistDeviceAdapter, props?: Settings);
|
|
13
13
|
getBikeInitRequest(): UpdateRequest;
|
|
14
|
+
getConfig(): CyclingModeConfig;
|
|
14
15
|
checkForResetOrEmpty(request: UpdateRequest): UpdateRequest | undefined;
|
|
15
16
|
protected updateSpeedAndDistance(_power: number, _slope: any, _bikeType: any, data: IncyclistBikeData, prevData: any): number;
|
|
16
17
|
}
|
|
@@ -25,6 +25,12 @@ class DaumClassicCyclingMode extends antble_smarttrainer_1.default {
|
|
|
25
25
|
getBikeInitRequest() {
|
|
26
26
|
return { slope: 0 };
|
|
27
27
|
}
|
|
28
|
+
getConfig() {
|
|
29
|
+
if (this.localConfig)
|
|
30
|
+
return this.localConfig;
|
|
31
|
+
let cm = this.constructor;
|
|
32
|
+
return cm.config;
|
|
33
|
+
}
|
|
28
34
|
checkForResetOrEmpty(request) {
|
|
29
35
|
if (!request || request.reset) {
|
|
30
36
|
this.prevRequest = {};
|
package/lib/modes/power-base.js
CHANGED
|
@@ -54,10 +54,12 @@ class PowerBasedCyclingModeBase extends base_1.CyclingModeBase {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
checkRefresh(request, newRequest) {
|
|
57
|
+
var _a;
|
|
57
58
|
if (request.refresh && request.targetPower === undefined) {
|
|
58
59
|
delete request.refresh;
|
|
59
|
-
if (this.prevRequest)
|
|
60
|
-
newRequest.targetPower = this.prevRequest.targetPower;
|
|
60
|
+
if (this.prevRequest) {
|
|
61
|
+
newRequest.targetPower = (_a = this.prevRequest.targetPower) !== null && _a !== void 0 ? _a : this.data.power;
|
|
62
|
+
}
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
checkTargetPowerSet(request, newRequest) {
|
|
@@ -73,9 +75,19 @@ class PowerBasedCyclingModeBase extends base_1.CyclingModeBase {
|
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
checkSlope(request) {
|
|
78
|
+
var _a;
|
|
76
79
|
if (request.slope !== undefined) {
|
|
77
80
|
this.data.slope = request.slope;
|
|
78
81
|
delete request.slope;
|
|
82
|
+
if (request.targetPower === undefined && request.minPower === undefined && request.maxPower === undefined) {
|
|
83
|
+
if (this.prevRequest) {
|
|
84
|
+
this.prevRequest.targetPower = (_a = this.prevRequest.targetPower) !== null && _a !== void 0 ? _a : (this.data.power || undefined);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
this.prevRequest = { targetPower: this.data.power || undefined };
|
|
88
|
+
}
|
|
89
|
+
request.refresh = this.prevRequest.targetPower !== undefined;
|
|
90
|
+
}
|
|
79
91
|
}
|
|
80
92
|
}
|
|
81
93
|
checkEmptyRequest(newRequest) {
|
|
@@ -213,8 +225,10 @@ class PowerBasedCyclingModeBase extends base_1.CyclingModeBase {
|
|
|
213
225
|
const request = Object.assign({}, incoming);
|
|
214
226
|
try {
|
|
215
227
|
const req = this.checkForResetOrEmpty(request);
|
|
216
|
-
if (req)
|
|
228
|
+
if (req) {
|
|
229
|
+
delete req.refresh;
|
|
217
230
|
return req;
|
|
231
|
+
}
|
|
218
232
|
this.checkSlope(request);
|
|
219
233
|
this.checkForTempPowerAdjustments(request);
|
|
220
234
|
this.checkTargetPowerSet(request, newRequest);
|
package/lib/modes/types.d.ts
CHANGED
|
@@ -61,5 +61,6 @@ export default class DaumAdapter<S extends SerialDeviceSettings, P extends Devic
|
|
|
61
61
|
sendRequest(request: any): Promise<any>;
|
|
62
62
|
refreshRequests(): void;
|
|
63
63
|
processClientRequest(request: any): Promise<UpdateRequest>;
|
|
64
|
+
protected reset(): void;
|
|
64
65
|
getDeviceInfo(): Promise<any>;
|
|
65
66
|
}
|
|
@@ -529,6 +529,20 @@ class DaumAdapter extends adapter_1.SerialIncyclistDevice {
|
|
|
529
529
|
fn();
|
|
530
530
|
});
|
|
531
531
|
}
|
|
532
|
+
reset() {
|
|
533
|
+
if (this.iv) {
|
|
534
|
+
const { sync, update, emitter } = this.iv;
|
|
535
|
+
if (sync)
|
|
536
|
+
clearInterval(sync);
|
|
537
|
+
if (update)
|
|
538
|
+
clearInterval(update);
|
|
539
|
+
if (emitter)
|
|
540
|
+
emitter.removeAllListeners();
|
|
541
|
+
}
|
|
542
|
+
if (this.internalEmitter) {
|
|
543
|
+
this.internalEmitter.removeAllListeners();
|
|
544
|
+
}
|
|
545
|
+
}
|
|
532
546
|
getDeviceInfo() {
|
|
533
547
|
return __awaiter(this, void 0, void 0, function* () {
|
|
534
548
|
throw new Error('Method not implemented.');
|
package/lib/types/adapter.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export interface IAdapter extends EventEmitter, IBike, ISensor {
|
|
|
34
34
|
getName(): string;
|
|
35
35
|
getID(): string;
|
|
36
36
|
getUniqueName(): string;
|
|
37
|
+
supportsVirtualShifting(): boolean;
|
|
37
38
|
getDisplayName(): string;
|
|
38
39
|
getSettings(): DeviceSettings;
|
|
39
40
|
isSame(adapter: IAdapter): boolean;
|
|
@@ -8,4 +8,5 @@ var IncyclistCapability;
|
|
|
8
8
|
IncyclistCapability["Cadence"] = "cadence";
|
|
9
9
|
IncyclistCapability["HeartRate"] = "heartrate";
|
|
10
10
|
IncyclistCapability["Control"] = "control";
|
|
11
|
+
IncyclistCapability["AppControl"] = "app_control";
|
|
11
12
|
})(IncyclistCapability || (exports.IncyclistCapability = IncyclistCapability = {}));
|
package/lib/types/data.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type IncyclistAdapterData = {
|
|
|
6
6
|
heartrate?: number;
|
|
7
7
|
distance?: number;
|
|
8
8
|
timestamp?: number;
|
|
9
|
+
gearStr?: string;
|
|
9
10
|
deviceTime?: number;
|
|
10
11
|
deviceDistanceCounter?: number;
|
|
11
12
|
internalDistanceCounter?: number;
|
|
@@ -19,5 +20,6 @@ export type IncyclistBikeData = {
|
|
|
19
20
|
distanceInternal?: number;
|
|
20
21
|
time?: number;
|
|
21
22
|
gear?: number;
|
|
23
|
+
gearStr?: string;
|
|
22
24
|
slope?: number;
|
|
23
25
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.IllegalArgumentException = void 0;
|
|
3
|
+
exports.calculateVirtualSpeed = exports.IllegalArgumentException = void 0;
|
|
4
4
|
exports.solveCubic = solveCubic;
|
|
5
5
|
const g = 9.80665;
|
|
6
6
|
const rho = 1.2041;
|
|
@@ -103,6 +103,18 @@ class C {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
exports.default = C;
|
|
106
|
+
const calculateVirtualSpeed = (rpm, gearRatio, wheelCirc = 2125) => {
|
|
107
|
+
if (rpm === undefined || rpm === null || rpm < 0)
|
|
108
|
+
throw new IllegalArgumentException("rpm must be a positive number");
|
|
109
|
+
if (!gearRatio || gearRatio < 0)
|
|
110
|
+
throw new IllegalArgumentException("gearRatio must be a positive number");
|
|
111
|
+
if (!wheelCirc || wheelCirc < 0)
|
|
112
|
+
throw new IllegalArgumentException("wheelCirc must be a positive number");
|
|
113
|
+
let distRotation = wheelCirc * gearRatio / 1000;
|
|
114
|
+
let speed = rpm * distRotation * 60 / 1000;
|
|
115
|
+
return speed / 3.6;
|
|
116
|
+
};
|
|
117
|
+
exports.calculateVirtualSpeed = calculateVirtualSpeed;
|
|
106
118
|
function acosh(x) {
|
|
107
119
|
return Math.log(x + Math.sqrt(x * x - 1.0));
|
|
108
120
|
}
|
package/lib/utils/utils.js
CHANGED
|
@@ -26,39 +26,46 @@ const resolveNextTick = () => {
|
|
|
26
26
|
};
|
|
27
27
|
exports.resolveNextTick = resolveNextTick;
|
|
28
28
|
function runWithRetries(fn, maxRetries, timeBetween) {
|
|
29
|
-
return
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
busy = true;
|
|
41
|
-
const data = yield fn();
|
|
42
|
-
clearInterval(iv);
|
|
43
|
-
iv = undefined;
|
|
44
|
-
busy = false;
|
|
45
|
-
return resolve(data);
|
|
29
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
let iv;
|
|
31
|
+
const res = yield new Promise((resolve, reject) => {
|
|
32
|
+
let retries = 0;
|
|
33
|
+
let tLastFailure = undefined;
|
|
34
|
+
let busy = false;
|
|
35
|
+
iv = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
const tNow = Date.now();
|
|
37
|
+
if (busy) {
|
|
38
|
+
return;
|
|
46
39
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
if (tLastFailure === undefined || tNow - tLastFailure > timeBetween) {
|
|
41
|
+
try {
|
|
42
|
+
busy = true;
|
|
43
|
+
const data = yield fn();
|
|
51
44
|
clearInterval(iv);
|
|
52
45
|
iv = undefined;
|
|
53
46
|
busy = false;
|
|
54
|
-
return
|
|
47
|
+
return resolve(data);
|
|
55
48
|
}
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
catch (err) {
|
|
50
|
+
tLastFailure = Date.now();
|
|
51
|
+
retries++;
|
|
52
|
+
if (retries >= maxRetries) {
|
|
53
|
+
clearInterval(iv);
|
|
54
|
+
iv = undefined;
|
|
55
|
+
busy = false;
|
|
56
|
+
return reject(err);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
busy = false;
|
|
60
|
+
}
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
|
-
}
|
|
61
|
-
})
|
|
63
|
+
}), 50);
|
|
64
|
+
});
|
|
65
|
+
if (iv) {
|
|
66
|
+
clearInterval(iv);
|
|
67
|
+
}
|
|
68
|
+
return res;
|
|
62
69
|
});
|
|
63
70
|
}
|
|
64
71
|
function floatVal(d) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "incyclist-devices",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.31",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@serialport/bindings-interface": "^1.2.2",
|
|
6
6
|
"@serialport/parser-byte-length": "^9.0.1",
|
|
@@ -16,15 +16,16 @@
|
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"@serialport/binding-mock": "^10.2.2",
|
|
18
18
|
"@serialport/bindings-cpp": "^10.8.0",
|
|
19
|
-
"@stoprocent/noble": "^
|
|
20
|
-
"@types/jest": "^
|
|
21
|
-
"@types/node": "^
|
|
19
|
+
"@stoprocent/noble": "^2.3.5",
|
|
20
|
+
"@types/jest": "^30.0.0",
|
|
21
|
+
"@types/node": "^24.3.1",
|
|
22
|
+
"@typescript-eslint/eslint-plugin": "^8.43.0",
|
|
23
|
+
"@typescript-eslint/parser": "^8.43.0",
|
|
22
24
|
"bonjour-service": "^1.3.0",
|
|
23
|
-
"eslint": "^
|
|
24
|
-
"
|
|
25
|
-
"jest": "^29.
|
|
26
|
-
"
|
|
27
|
-
"typescript": "^5.8.3"
|
|
25
|
+
"eslint": "^9.35.0",
|
|
26
|
+
"jest": "^30.1.3",
|
|
27
|
+
"ts-jest": "^29.4.1",
|
|
28
|
+
"typescript": "^5.9.2"
|
|
28
29
|
},
|
|
29
30
|
"scripts": {
|
|
30
31
|
"lint": "eslint . --ext .ts",
|
|
@@ -43,7 +44,18 @@
|
|
|
43
44
|
"lib": "./src"
|
|
44
45
|
},
|
|
45
46
|
"eslintConfig": {
|
|
46
|
-
"extends":
|
|
47
|
+
"extends": [
|
|
48
|
+
"eslint:recommended",
|
|
49
|
+
"plugin:@typescript-eslint/recommended"
|
|
50
|
+
],
|
|
51
|
+
"parser": "@typescript-eslint/parser",
|
|
52
|
+
"parserOptions": {
|
|
53
|
+
"ecmaVersion": "latest",
|
|
54
|
+
"sourceType": "module"
|
|
55
|
+
},
|
|
56
|
+
"plugins": [
|
|
57
|
+
"@typescript-eslint"
|
|
58
|
+
],
|
|
47
59
|
"rules": {
|
|
48
60
|
"jsx-a11y/anchor-is-valid": [
|
|
49
61
|
"off"
|