incyclist-devices 1.1.0 → 1.3.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/LICENSE +21 -0
- package/lib/CyclingMode.d.ts +72 -0
- package/lib/CyclingMode.js +66 -0
- package/lib/Device.d.ts +48 -10
- package/lib/Device.js +9 -8
- package/lib/DeviceProtocol.d.ts +40 -12
- package/lib/DeviceProtocol.js +16 -16
- package/lib/DeviceRegistry.d.ts +4 -4
- package/lib/DeviceRegistry.js +10 -10
- package/lib/DeviceSupport.d.ts +4 -3
- package/lib/DeviceSupport.js +32 -8
- package/lib/ant/AntAdapter.d.ts +11 -2
- package/lib/ant/AntAdapter.js +30 -1
- package/lib/ant/AntScanner.d.ts +17 -6
- package/lib/ant/AntScanner.js +406 -135
- package/lib/ant/antfe/AntFEAdapter.d.ts +12 -8
- package/lib/ant/antfe/AntFEAdapter.js +404 -182
- package/lib/ant/anthrm/AntHrmAdapter.d.ts +4 -2
- package/lib/ant/anthrm/AntHrmAdapter.js +72 -25
- package/lib/ant/utils.js +2 -1
- package/lib/calculations.d.ts +12 -13
- package/lib/calculations.js +88 -125
- package/lib/daum/DaumAdapter.d.ts +29 -6
- package/lib/daum/DaumAdapter.js +219 -96
- package/lib/daum/ERGCyclingMode.d.ts +28 -0
- package/lib/daum/ERGCyclingMode.js +207 -0
- package/lib/daum/PowerMeterCyclingMode.d.ts +18 -0
- package/lib/daum/PowerMeterCyclingMode.js +79 -0
- package/lib/daum/SmartTrainerCyclingMode.d.ts +41 -0
- package/lib/daum/SmartTrainerCyclingMode.js +344 -0
- package/lib/daum/classic/DaumClassicAdapter.d.ts +3 -1
- package/lib/daum/classic/DaumClassicAdapter.js +46 -32
- package/lib/daum/classic/DaumClassicCyclingMode.d.ts +13 -0
- package/lib/daum/classic/DaumClassicCyclingMode.js +98 -0
- package/lib/daum/classic/DaumClassicProtocol.d.ts +5 -3
- package/lib/daum/classic/DaumClassicProtocol.js +39 -6
- package/lib/daum/classic/ERGCyclingMode.d.ts +23 -0
- package/lib/daum/classic/ERGCyclingMode.js +171 -0
- package/lib/daum/classic/bike.d.ts +41 -37
- package/lib/daum/classic/bike.js +86 -53
- package/lib/daum/classic/utils.d.ts +3 -3
- package/lib/daum/classic/utils.js +16 -10
- package/lib/daum/indoorbike.d.ts +2 -1
- package/lib/daum/indoorbike.js +23 -21
- package/lib/daum/premium/DaumPremiumAdapter.d.ts +2 -2
- package/lib/daum/premium/DaumPremiumAdapter.js +30 -20
- package/lib/daum/premium/DaumPremiumProtocol.d.ts +11 -2
- package/lib/daum/premium/DaumPremiumProtocol.js +49 -8
- package/lib/daum/premium/bike.d.ts +63 -52
- package/lib/daum/premium/bike.js +258 -207
- package/lib/daum/premium/tcpserial.d.ts +18 -14
- package/lib/daum/premium/tcpserial.js +50 -20
- package/lib/daum/premium/utils.d.ts +2 -2
- package/lib/simulator/Simulator.d.ts +13 -7
- package/lib/simulator/Simulator.js +62 -21
- package/lib/utils.d.ts +3 -1
- package/lib/utils.js +39 -18
- package/package.json +12 -11
- package/lib/ant/AntScanner.unit.tests.d.ts +0 -1
- package/lib/ant/AntScanner.unit.tests.js +0 -25
- package/lib/ant/antfe/AntFEProcessor.d.ts +0 -40
- package/lib/ant/antfe/AntFEProcessor.js +0 -238
- package/lib/ant/antfe/AntHrmProtocol.d.ts +0 -9
- package/lib/ant/antfe/AntHrmProtocol.js +0 -30
- package/lib/ant/antfe/bike.d.ts +0 -47
- package/lib/ant/antfe/bike.js +0 -602
- package/lib/ant/anthrm/anthrm.d.ts +0 -33
- package/lib/ant/anthrm/anthrm.js +0 -523
- package/lib/simulator/Simulator.unit.tests.d.ts +0 -1
- package/lib/simulator/Simulator.unit.tests.js +0 -79
|
@@ -8,18 +8,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
13
|
-
const AntAdapter_1 = require("../AntAdapter");
|
|
16
|
+
const AntAdapter_1 = __importDefault(require("../AntAdapter"));
|
|
14
17
|
const utils_1 = require("../utils");
|
|
15
18
|
const utils_2 = require("../../utils");
|
|
16
19
|
const floatVal = (d) => d ? parseFloat(d) : d;
|
|
17
20
|
const intVal = (d) => d ? parseInt(d) : d;
|
|
18
|
-
const
|
|
21
|
+
const hex = (v) => Math.abs(v).toString(16).toUpperCase();
|
|
22
|
+
const TIMEOUT_ACK = 5000;
|
|
23
|
+
const TIMEOUT_START = 10000;
|
|
24
|
+
const TIMEOUT_ATTACH = 3000;
|
|
25
|
+
const DEFAULT_USER_WEIGHT = 75;
|
|
26
|
+
const DEFAULT_BIKE_WEIGHT = 12.75;
|
|
19
27
|
class AntFEAdapter extends AntAdapter_1.default {
|
|
20
28
|
constructor(DeviceID, port, stick, protocol) {
|
|
21
29
|
super(protocol);
|
|
22
30
|
this.logger = new gd_eventlog_1.EventLogger('Ant+FE');
|
|
31
|
+
this.logger.logEvent({ message: 'Ant+FE Adapter created', DeviceID, port });
|
|
23
32
|
this.deviceID = DeviceID;
|
|
24
33
|
this.port = port;
|
|
25
34
|
this.stick = stick;
|
|
@@ -28,13 +37,14 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
28
37
|
};
|
|
29
38
|
this.data = {};
|
|
30
39
|
this.started = false;
|
|
40
|
+
this.starting = false;
|
|
31
41
|
this.connected = false;
|
|
32
42
|
}
|
|
33
43
|
isBike() { return true; }
|
|
34
|
-
isHrm() { return this.deviceData.
|
|
44
|
+
isHrm() { return this.deviceData.HeartRate !== undefined; }
|
|
35
45
|
isPower() { return true; }
|
|
36
|
-
|
|
37
|
-
return
|
|
46
|
+
getProfile() {
|
|
47
|
+
return 'Smart Trainer';
|
|
38
48
|
}
|
|
39
49
|
getName() {
|
|
40
50
|
return `Ant+FE ${this.deviceID}`;
|
|
@@ -42,14 +52,22 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
42
52
|
getDisplayName() {
|
|
43
53
|
const { DeviceID, ManId, ComputedHeartRate } = this.deviceData;
|
|
44
54
|
const hrmStr = ComputedHeartRate ? ` (${ComputedHeartRate})` : '';
|
|
45
|
-
return `${utils_1.getBrand(ManId)} FE ${DeviceID}${hrmStr}`;
|
|
55
|
+
return `${(0, utils_1.getBrand)(ManId)} FE ${DeviceID}${hrmStr}`;
|
|
56
|
+
}
|
|
57
|
+
onAttached() {
|
|
58
|
+
this.logger.logEvent({ message: 'Device connected' });
|
|
59
|
+
this.connected = true;
|
|
46
60
|
}
|
|
47
61
|
onDeviceData(deviceData) {
|
|
62
|
+
if (!this.started || this.isStopped())
|
|
63
|
+
return;
|
|
48
64
|
this.deviceData = deviceData;
|
|
49
65
|
try {
|
|
50
66
|
if (this.onDataFn && !(this.ignoreHrm && this.ignoreBike && this.ignorePower) && !this.paused) {
|
|
51
67
|
if (!this.lastUpdate || (Date.now() - this.lastUpdate) > this.updateFrequency) {
|
|
52
|
-
|
|
68
|
+
this.logger.logEvent({ message: 'onDeviceData', data: deviceData });
|
|
69
|
+
this.data = this.updateData(this.data, deviceData);
|
|
70
|
+
const data = this.transformData(this.data);
|
|
53
71
|
this.onDataFn(data);
|
|
54
72
|
this.lastUpdate = Date.now();
|
|
55
73
|
}
|
|
@@ -60,36 +78,48 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
60
78
|
}
|
|
61
79
|
onDeviceEvent(data) {
|
|
62
80
|
try {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
if (stick.currentCmd !== undefined && data.message === 1 && data.code === 5) {
|
|
66
|
-
stick.currentCmd.response = { success: true };
|
|
81
|
+
const cmdInfo = this.currentCmd;
|
|
82
|
+
if (!cmdInfo)
|
|
67
83
|
return;
|
|
84
|
+
const msg = cmdInfo.msg.readUInt8(2);
|
|
85
|
+
const Constants = this.getProtocol().getAnt().Constants;
|
|
86
|
+
const { expectedResponse } = cmdInfo;
|
|
87
|
+
if (data.message === msg) {
|
|
88
|
+
if (expectedResponse === undefined && data.code === Constants.EVENT_TRANSFER_TX_COMPLETED) {
|
|
89
|
+
this.currentCmd.response = { success: true, message: hex(data.message), code: hex(data.code) };
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (expectedResponse === undefined && data.code !== Constants.EVENT_TRANSFER_TX_COMPLETED) {
|
|
93
|
+
this.currentCmd.response = { success: false, message: hex(data.message), code: hex(data.code) };
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
68
96
|
}
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
97
|
+
if (data.message === 1) {
|
|
98
|
+
if (expectedResponse !== undefined && data.code === expectedResponse) {
|
|
99
|
+
this.currentCmd.response = { success: true, message: hex(data.message), code: hex(data.code) };
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (expectedResponse === undefined && (data.code === Constants.EVENT_TRANSFER_TX_COMPLETED || data.code === 3)) {
|
|
103
|
+
this.currentCmd.response = { success: true, message: hex(data.message), code: hex(data.code) };
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (data.code === Constants.EVENT_TRANSFER_TX_FAILED || data.code === Constants.EVENT_CHANNEL_COLLISION) {
|
|
107
|
+
this.currentCmd.response = { success: false, message: hex(data.message), code: hex(data.code) };
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
72
110
|
}
|
|
73
|
-
if (
|
|
111
|
+
if (this.currentCmd !== undefined && data.message === Constants.MESSAGE_CHANNEL_ACKNOWLEDGED_DATA && data.code === 31) {
|
|
74
112
|
this.logger.log("could not send (TRANSFER_IN_PROGRESS)");
|
|
113
|
+
this.currentCmd.response = { success: false, message: hex(data.message), code: hex(data.code) };
|
|
75
114
|
return;
|
|
76
115
|
}
|
|
77
|
-
this.logger.logEvent({ message: "Incoming Event ", event: data });
|
|
116
|
+
this.logger.logEvent({ message: "Incoming Event ", event: { message: hex(data.message), code: hex(data.code) } });
|
|
78
117
|
}
|
|
79
118
|
catch (err) {
|
|
80
|
-
this.logger.logEvent({ message: 'Error', fn: 'parseEvent', data:
|
|
119
|
+
this.logger.logEvent({ message: 'Error', fn: 'parseEvent', event: { message: hex(data.message), code: hex(data.code) }, error: err.message || err });
|
|
81
120
|
}
|
|
82
121
|
}
|
|
83
122
|
updateData(data, deviceData) {
|
|
84
|
-
let DeviceID = deviceData.DeviceID;
|
|
85
|
-
let type = deviceData.EquipmentType;
|
|
86
|
-
let state = deviceData.State;
|
|
87
|
-
if (DeviceID === this.deviceID && type !== undefined && state !== "OFF") {
|
|
88
|
-
this.connected = true;
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
return {};
|
|
92
|
-
}
|
|
93
123
|
if (data.distanceOffs === undefined)
|
|
94
124
|
data.distanceOffs = 0;
|
|
95
125
|
data.speed = (deviceData.VirtualSpeed !== undefined ? deviceData.VirtualSpeed : deviceData.RealSpeed) * 3.6;
|
|
@@ -97,21 +127,19 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
97
127
|
data.power = (deviceData.InstantaneousPower !== undefined ? deviceData.InstantaneousPower : data.power);
|
|
98
128
|
data.pedalRpm = (deviceData.Cadence !== undefined ? deviceData.Cadence : data.pedalRpm);
|
|
99
129
|
data.heartrate = (deviceData.HeartRate !== undefined ? deviceData.HeartRate : data.heartrate);
|
|
100
|
-
if (deviceData.Distance !== undefined) {
|
|
130
|
+
if (deviceData.Distance !== undefined && deviceData.Distance !== 0) {
|
|
101
131
|
data.distanceInternal = deviceData.Distance - data.distanceOffs;
|
|
102
132
|
data.distance = data.distanceInternal / 1000;
|
|
103
133
|
}
|
|
104
|
-
|
|
105
|
-
this.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
this.data.distanceInternal = undefined;
|
|
112
|
-
this.data.distanceOffs = deviceData.Distance !== undefined ? deviceData.Distance : 0;
|
|
134
|
+
else {
|
|
135
|
+
if (this.lastUpdate && deviceData.Cadence !== undefined && deviceData.Cadence > 0 && data.speed) {
|
|
136
|
+
const t = (Date.now() - this.lastUpdate) / 1000;
|
|
137
|
+
const prevDistance = data.distanceInternal || 0;
|
|
138
|
+
data.distanceInternal = Math.round(data.speed / 3.6 * t) + prevDistance;
|
|
139
|
+
data.distance = data.distanceInternal / 1000;
|
|
140
|
+
}
|
|
113
141
|
}
|
|
114
|
-
return
|
|
142
|
+
return data;
|
|
115
143
|
}
|
|
116
144
|
transformData(bikeData) {
|
|
117
145
|
if (bikeData === undefined)
|
|
@@ -143,57 +171,193 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
143
171
|
return data;
|
|
144
172
|
}
|
|
145
173
|
start(props) {
|
|
174
|
+
const _super = Object.create(null, {
|
|
175
|
+
start: { get: () => super.start }
|
|
176
|
+
});
|
|
146
177
|
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
+
yield _super.start.call(this, props);
|
|
147
179
|
this.logger.logEvent({ message: 'start()' });
|
|
148
|
-
const
|
|
180
|
+
const args = props || {};
|
|
149
181
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
150
|
-
if (this.ignoreHrm && this.ignoreBike && this.ignorePower)
|
|
151
|
-
|
|
182
|
+
if (this.ignoreHrm && this.ignoreBike && this.ignorePower) {
|
|
183
|
+
this.logger.logEvent({ message: 'start() not done: bike disabled' });
|
|
184
|
+
return resolve(false);
|
|
185
|
+
}
|
|
186
|
+
if (this.starting) {
|
|
187
|
+
this.logger.logEvent({ message: 'start() not done: bike starting' });
|
|
188
|
+
return resolve(false);
|
|
189
|
+
}
|
|
190
|
+
if (this.started) {
|
|
191
|
+
this.logger.logEvent({ message: 'start() done: bike was already started' });
|
|
192
|
+
this.startWorker();
|
|
193
|
+
return resolve(true);
|
|
194
|
+
}
|
|
195
|
+
this.starting = true;
|
|
152
196
|
const Ant = this.getProtocol().getAnt();
|
|
153
197
|
const protocol = this.getProtocol();
|
|
154
|
-
|
|
155
|
-
|
|
198
|
+
let start = Date.now();
|
|
199
|
+
let timeout = start + (args.timeout || TIMEOUT_ATTACH);
|
|
200
|
+
const ivAttach = setInterval(() => {
|
|
201
|
+
if (Date.now() > timeout) {
|
|
202
|
+
clearInterval(ivAttach);
|
|
203
|
+
this.starting = false;
|
|
204
|
+
reject(new Error('timeout'));
|
|
205
|
+
}
|
|
206
|
+
if (this.isStopped()) {
|
|
207
|
+
clearInterval(ivAttach);
|
|
208
|
+
this.starting = false;
|
|
209
|
+
reject(new Error('stopped'));
|
|
210
|
+
}
|
|
211
|
+
}, 100);
|
|
212
|
+
try {
|
|
213
|
+
if (!this.connected) {
|
|
214
|
+
this.logger.logEvent({ message: 'attach device ...' });
|
|
215
|
+
yield protocol.attachSensors(this, Ant.FitnessEquipmentSensor, 'fitnessData');
|
|
216
|
+
}
|
|
217
|
+
clearInterval(ivAttach);
|
|
156
218
|
this.startWorker();
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
219
|
+
const tsStart = Date.now();
|
|
220
|
+
const iv = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
221
|
+
if (this.connected) {
|
|
222
|
+
clearInterval(iv);
|
|
223
|
+
let status = {
|
|
224
|
+
trackResistanceSent: false,
|
|
225
|
+
userSent: false,
|
|
226
|
+
};
|
|
227
|
+
(0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () {
|
|
228
|
+
if (this.isStopped())
|
|
229
|
+
resolve(false);
|
|
230
|
+
try {
|
|
231
|
+
if (!status.trackResistanceSent) {
|
|
232
|
+
yield this.sendTrackResistance(0.0);
|
|
233
|
+
status.trackResistanceSent = true;
|
|
234
|
+
}
|
|
235
|
+
if (!status.userSent) {
|
|
236
|
+
yield this.sendUserConfiguration(args.userWeight || DEFAULT_USER_WEIGHT, args.bikeWeight || DEFAULT_BIKE_WEIGHT, args.wheelDiameter, args.gearRatio);
|
|
237
|
+
status.userSent = true;
|
|
238
|
+
}
|
|
239
|
+
this.started = true;
|
|
240
|
+
this.starting = false;
|
|
241
|
+
resolve(true);
|
|
242
|
+
}
|
|
243
|
+
catch (err) {
|
|
244
|
+
throw (new Error(`could not start device, reason:${err.message || err}`));
|
|
245
|
+
}
|
|
246
|
+
}), 5, 1500)
|
|
247
|
+
.catch(err => {
|
|
248
|
+
this.logger.logEvent({ message: 'start() error', error: err.message || err });
|
|
249
|
+
this.starting = false;
|
|
250
|
+
reject(err);
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
else if ((Date.now() - tsStart) > TIMEOUT_START) {
|
|
254
|
+
clearInterval(iv);
|
|
255
|
+
try {
|
|
256
|
+
yield protocol.detachSensor(this);
|
|
257
|
+
}
|
|
258
|
+
catch (err) { }
|
|
259
|
+
this.started = false;
|
|
260
|
+
this.starting = false;
|
|
261
|
+
reject(new Error('could not start device, reason:timeout'));
|
|
262
|
+
}
|
|
263
|
+
}), 50);
|
|
264
|
+
}
|
|
265
|
+
catch (err) {
|
|
266
|
+
this.logger.logEvent({ message: 'start() error', error: err.message });
|
|
267
|
+
this.starting = false;
|
|
268
|
+
reject(new Error(`could not start device, reason:${err.message}`));
|
|
269
|
+
}
|
|
162
270
|
}));
|
|
163
271
|
});
|
|
164
272
|
}
|
|
165
273
|
stop() {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
274
|
+
const _super = Object.create(null, {
|
|
275
|
+
stop: { get: () => super.stop }
|
|
276
|
+
});
|
|
277
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
278
|
+
yield _super.stop.call(this);
|
|
279
|
+
this.logger.logEvent({ message: 'stop()' });
|
|
280
|
+
this.stopWorker();
|
|
281
|
+
const Messages = this.getProtocol().getAnt().Messages;
|
|
171
282
|
const stick = this.stick;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
resolve(true);
|
|
176
|
-
this.started
|
|
177
|
-
|
|
283
|
+
const channel = this.channel;
|
|
284
|
+
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
285
|
+
this.starting = false;
|
|
286
|
+
return resolve(true);
|
|
287
|
+
if (!this.started && !this.connected)
|
|
288
|
+
return resolve(false);
|
|
289
|
+
try {
|
|
290
|
+
stick.write(Messages.openChannel(channel));
|
|
291
|
+
const protocol = this.getProtocol();
|
|
292
|
+
yield protocol.detachSensor(this);
|
|
293
|
+
this.started = false;
|
|
294
|
+
this.connected = false;
|
|
295
|
+
this.logger.logEvent({ message: 'stop() finished' });
|
|
296
|
+
resolve(true);
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
this.connected = false;
|
|
300
|
+
this.logger.logEvent({ message: 'stop() error', error: err.message });
|
|
301
|
+
reject(err);
|
|
302
|
+
}
|
|
303
|
+
}));
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
sendUpdate(request) {
|
|
307
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
308
|
+
this.logger.logEvent({ message: "sendBikeUpdate():", request });
|
|
178
309
|
try {
|
|
179
|
-
|
|
180
|
-
|
|
310
|
+
const isReset = (!request || request.reset || Object.keys(request).length === 0);
|
|
311
|
+
if (request.slope !== undefined) {
|
|
312
|
+
yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTrackResistance(request.slope); }), 2, 100);
|
|
313
|
+
}
|
|
314
|
+
if (request.targetPower !== undefined) {
|
|
315
|
+
yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(request.targetPower); }), 2, 100);
|
|
316
|
+
}
|
|
317
|
+
else if (request.maxPower !== undefined) {
|
|
318
|
+
if (this.data.power && this.data.power > request.maxPower)
|
|
319
|
+
yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(request.maxPower); }), 2, 100);
|
|
320
|
+
}
|
|
321
|
+
else if (request.minPower !== undefined) {
|
|
322
|
+
if (this.data.power && this.data.power < request.minPower)
|
|
323
|
+
yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(request.minPower); }), 2, 100);
|
|
324
|
+
}
|
|
181
325
|
}
|
|
182
326
|
catch (err) {
|
|
183
|
-
|
|
327
|
+
this.logger.logEvent({ message: 'sendBikeUpdate() error', error: err.message });
|
|
184
328
|
}
|
|
185
|
-
})
|
|
329
|
+
});
|
|
186
330
|
}
|
|
187
|
-
send(msg, logStr, callback) {
|
|
188
|
-
if (this.workerId === undefined)
|
|
331
|
+
send(msg, logStr, callback, expectedResponse) {
|
|
332
|
+
if (this.workerId === undefined) {
|
|
189
333
|
return;
|
|
190
|
-
|
|
334
|
+
}
|
|
335
|
+
this.queue.enqueue({ msg, logStr, callback, expectedResponse });
|
|
336
|
+
}
|
|
337
|
+
sendAsync(msg, logStr, expectedResponse) {
|
|
338
|
+
return new Promise((resolve, reject) => {
|
|
339
|
+
this.send(msg, logStr, (res, err) => {
|
|
340
|
+
if (err)
|
|
341
|
+
return reject(err);
|
|
342
|
+
resolve(res);
|
|
343
|
+
}, expectedResponse);
|
|
344
|
+
});
|
|
191
345
|
}
|
|
192
346
|
startWorker() {
|
|
347
|
+
this.logger.logEvent({ message: 'startWorker()' });
|
|
193
348
|
if (this.queue === undefined) {
|
|
194
349
|
this.queue = new utils_2.Queue();
|
|
195
350
|
}
|
|
196
|
-
|
|
351
|
+
if (this.workerId)
|
|
352
|
+
return;
|
|
353
|
+
this.workerId = setInterval(() => {
|
|
354
|
+
try {
|
|
355
|
+
this.sendFromQueue();
|
|
356
|
+
}
|
|
357
|
+
catch (err) {
|
|
358
|
+
this.logger.logEvent({ message: 'sendFromQueue error', error: err.message });
|
|
359
|
+
}
|
|
360
|
+
}, 10);
|
|
197
361
|
}
|
|
198
362
|
stopWorker() {
|
|
199
363
|
if (!this.workerId)
|
|
@@ -203,8 +367,9 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
203
367
|
this.workerId = undefined;
|
|
204
368
|
}
|
|
205
369
|
sendFromQueue() {
|
|
206
|
-
if (this.queue === undefined
|
|
370
|
+
if (this.queue === undefined) {
|
|
207
371
|
return;
|
|
372
|
+
}
|
|
208
373
|
if (this.currentCmd !== undefined) {
|
|
209
374
|
const cmdInfo = this.currentCmd;
|
|
210
375
|
if (this.currentCmd.response === undefined) {
|
|
@@ -217,147 +382,204 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
217
382
|
this.logger.logEvent({ message: 'timeout', cmd: logStr, timeout: `${timeout}ms` });
|
|
218
383
|
this.currentCmd = undefined;
|
|
219
384
|
if (callback !== undefined) {
|
|
220
|
-
callback(undefined,
|
|
385
|
+
callback(undefined, new Error('timeout'));
|
|
221
386
|
}
|
|
222
387
|
}
|
|
223
388
|
}
|
|
224
389
|
else {
|
|
225
390
|
const { callback, response, logStr } = cmdInfo;
|
|
226
|
-
this.logger.logEvent({ message: "response: ", cmd: logStr, response
|
|
391
|
+
this.logger.logEvent({ message: "response: ", cmd: logStr, response });
|
|
227
392
|
this.currentCmd = undefined;
|
|
228
393
|
if (callback !== undefined) {
|
|
394
|
+
if (response && response.success === false) {
|
|
395
|
+
callback(undefined, new Error(`ANT error ${response.code}`));
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
229
398
|
callback(response);
|
|
230
399
|
}
|
|
231
400
|
}
|
|
232
401
|
}
|
|
233
402
|
else {
|
|
403
|
+
if (this.queue.isEmpty())
|
|
404
|
+
return;
|
|
234
405
|
this.currentCmd = this.queue.dequeue();
|
|
235
406
|
this.currentCmd.tsStart = Date.now();
|
|
236
407
|
const { msg, logStr } = this.currentCmd;
|
|
237
|
-
this.logger.logEvent({ message: "sending", cmd: logStr, msg: utils_2.hexstr(msg), queueSize: this.queue.size() });
|
|
238
|
-
this.stick
|
|
408
|
+
this.logger.logEvent({ message: "sending", cmd: logStr, msg: (0, utils_2.hexstr)(msg), queueSize: this.queue.size() });
|
|
409
|
+
if (this.stick)
|
|
410
|
+
this.stick.write(msg);
|
|
239
411
|
}
|
|
240
412
|
}
|
|
241
413
|
sendUserConfiguration(userWeight, bikeWeight, wheelDiameter, gearRatio) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
414
|
+
return new Promise((resolve, reject) => {
|
|
415
|
+
if (!this.connected)
|
|
416
|
+
reject(new Error('not connected'));
|
|
417
|
+
if (!this.queue)
|
|
418
|
+
this.startWorker();
|
|
419
|
+
var payload = [];
|
|
420
|
+
payload.push(this.channel);
|
|
421
|
+
const logStr = `sendUserConfiguration(${userWeight},${bikeWeight},${wheelDiameter},${gearRatio})`;
|
|
422
|
+
var m = userWeight === undefined ? 0xFFFF : userWeight;
|
|
423
|
+
var mb = bikeWeight === undefined ? 0xFFF : bikeWeight;
|
|
424
|
+
var d = wheelDiameter === undefined ? 0xFF : wheelDiameter;
|
|
425
|
+
var gr = gearRatio === undefined ? 0x00 : gearRatio;
|
|
426
|
+
var dOffset = 0xFF;
|
|
427
|
+
if (m !== 0xFFFF)
|
|
428
|
+
m = Math.trunc(m * 100);
|
|
429
|
+
if (mb !== 0xFFF)
|
|
430
|
+
mb = Math.trunc(mb * 20);
|
|
431
|
+
if (d !== 0xFF) {
|
|
432
|
+
d = d * 1000;
|
|
433
|
+
dOffset = d % 10;
|
|
434
|
+
d = Math.trunc(d / 10);
|
|
435
|
+
}
|
|
436
|
+
if (gr !== 0x00) {
|
|
437
|
+
gr = Math.trunc(gr / 0.03);
|
|
438
|
+
}
|
|
439
|
+
payload.push(0x37);
|
|
440
|
+
payload.push(m & 0xFF);
|
|
441
|
+
payload.push((m >> 8) & 0xFF);
|
|
442
|
+
payload.push(0xFF);
|
|
443
|
+
payload.push(((mb & 0xF) << 4) | (dOffset & 0xF));
|
|
444
|
+
payload.push((mb >> 4) & 0xF);
|
|
445
|
+
payload.push(d & 0xFF);
|
|
446
|
+
payload.push(gr & 0xFF);
|
|
447
|
+
const Messages = this.protocol.getAnt().Messages;
|
|
448
|
+
let msg = Messages.acknowledgedData(payload);
|
|
449
|
+
this.send(msg, logStr, (res, err) => {
|
|
450
|
+
if (err)
|
|
451
|
+
return reject(err);
|
|
452
|
+
resolve(res);
|
|
453
|
+
});
|
|
454
|
+
});
|
|
273
455
|
}
|
|
274
456
|
sendBasicResistance(resistance) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
457
|
+
return new Promise((resolve, reject) => {
|
|
458
|
+
if (!this.connected)
|
|
459
|
+
reject(new Error('not connected'));
|
|
460
|
+
if (!this.queue)
|
|
461
|
+
this.startWorker();
|
|
462
|
+
var payload = [];
|
|
463
|
+
payload.push(this.channel);
|
|
464
|
+
const logStr = `sendBasicResistance(${resistance})`;
|
|
465
|
+
var res = resistance === undefined ? 0 : resistance;
|
|
466
|
+
res = res / 0.5;
|
|
467
|
+
payload.push(0x30);
|
|
468
|
+
payload.push(0xFF);
|
|
469
|
+
payload.push(0xFF);
|
|
470
|
+
payload.push(0xFF);
|
|
471
|
+
payload.push(0xFF);
|
|
472
|
+
payload.push(0xFF);
|
|
473
|
+
payload.push(0xFF);
|
|
474
|
+
payload.push(res & 0xFF);
|
|
475
|
+
const Messages = this.protocol.getAnt().Messages;
|
|
476
|
+
let msg = Messages.acknowledgedData(payload);
|
|
477
|
+
this.send(msg, logStr, (res, err) => {
|
|
478
|
+
if (err)
|
|
479
|
+
return reject(err);
|
|
480
|
+
resolve(res);
|
|
481
|
+
});
|
|
482
|
+
});
|
|
291
483
|
}
|
|
292
484
|
sendTargetPower(power) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
485
|
+
return new Promise((resolve, reject) => {
|
|
486
|
+
if (!this.connected)
|
|
487
|
+
reject(new Error('not connected'));
|
|
488
|
+
if (!this.queue)
|
|
489
|
+
this.startWorker();
|
|
490
|
+
var payload = [];
|
|
491
|
+
payload.push(this.channel);
|
|
492
|
+
const logStr = `sendTargetPower(${power})`;
|
|
493
|
+
var p = power === undefined ? 0x00 : power;
|
|
494
|
+
p = p * 4;
|
|
495
|
+
payload.push(0x31);
|
|
496
|
+
payload.push(0xFF);
|
|
497
|
+
payload.push(0xFF);
|
|
498
|
+
payload.push(0xFF);
|
|
499
|
+
payload.push(0xFF);
|
|
500
|
+
payload.push(0xFF);
|
|
501
|
+
payload.push(p & 0xFF);
|
|
502
|
+
payload.push((p >> 8) & 0xFF);
|
|
503
|
+
const Messages = this.protocol.getAnt().Messages;
|
|
504
|
+
let msg = Messages.acknowledgedData(payload);
|
|
505
|
+
this.send(msg, logStr, (res, err) => {
|
|
506
|
+
if (err)
|
|
507
|
+
return reject(err);
|
|
508
|
+
resolve(res);
|
|
509
|
+
});
|
|
510
|
+
});
|
|
309
511
|
}
|
|
310
512
|
sendWindResistance(windCoeff, windSpeed, draftFactor) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
513
|
+
return new Promise((resolve, reject) => {
|
|
514
|
+
if (!this.connected)
|
|
515
|
+
reject(new Error('not connected'));
|
|
516
|
+
if (!this.queue)
|
|
517
|
+
this.startWorker();
|
|
518
|
+
var payload = [];
|
|
519
|
+
payload.push(this.channel);
|
|
520
|
+
const logStr = `sendWindResistance(${windCoeff},${windSpeed},${draftFactor})`;
|
|
521
|
+
var wc = windCoeff === undefined ? 0xFF : windCoeff;
|
|
522
|
+
var ws = windSpeed === undefined ? 0xFF : windSpeed;
|
|
523
|
+
var df = draftFactor === undefined ? 0xFF : draftFactor;
|
|
524
|
+
if (wc !== 0xFF) {
|
|
525
|
+
wc = Math.trunc(wc / 0.01);
|
|
526
|
+
}
|
|
527
|
+
if (ws !== 0xFF) {
|
|
528
|
+
ws = Math.trunc(ws + 127);
|
|
529
|
+
}
|
|
530
|
+
if (df !== 0xFF) {
|
|
531
|
+
df = Math.trunc(df / 0.01);
|
|
532
|
+
}
|
|
533
|
+
payload.push(0x32);
|
|
534
|
+
payload.push(0xFF);
|
|
535
|
+
payload.push(0xFF);
|
|
536
|
+
payload.push(0xFF);
|
|
537
|
+
payload.push(0xFF);
|
|
538
|
+
payload.push(wc & 0xFF);
|
|
539
|
+
payload.push(ws & 0xFF);
|
|
540
|
+
payload.push(df & 0xFF);
|
|
541
|
+
const Messages = this.protocol.getAnt().Messages;
|
|
542
|
+
let msg = Messages.acknowledgedData(payload);
|
|
543
|
+
this.send(msg, logStr, (res, err) => {
|
|
544
|
+
if (err)
|
|
545
|
+
return reject(err);
|
|
546
|
+
resolve(res);
|
|
547
|
+
});
|
|
548
|
+
});
|
|
337
549
|
}
|
|
338
550
|
sendTrackResistance(slope, rrCoeff) {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
rr =
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
551
|
+
return new Promise((resolve, reject) => {
|
|
552
|
+
if (!this.connected)
|
|
553
|
+
reject(new Error('not connected'));
|
|
554
|
+
if (!this.queue)
|
|
555
|
+
this.startWorker();
|
|
556
|
+
var payload = [];
|
|
557
|
+
payload.push(this.channel);
|
|
558
|
+
const logStr = `sendTrackResistance(${slope},${rrCoeff})`;
|
|
559
|
+
var s = slope === undefined ? 0xFFFF : slope;
|
|
560
|
+
var rr = rrCoeff === undefined ? 0xFF : rrCoeff;
|
|
561
|
+
if (s !== 0xFFFF) {
|
|
562
|
+
s = Math.trunc((s + 200) / 0.01);
|
|
563
|
+
}
|
|
564
|
+
if (rr !== 0xFF) {
|
|
565
|
+
rr = Math.trunc(rr / 0.00005);
|
|
566
|
+
}
|
|
567
|
+
payload.push(0x33);
|
|
568
|
+
payload.push(0xFF);
|
|
569
|
+
payload.push(0xFF);
|
|
570
|
+
payload.push(0xFF);
|
|
571
|
+
payload.push(0xFF);
|
|
572
|
+
payload.push(s & 0xFF);
|
|
573
|
+
payload.push((s >> 8) & 0xFF);
|
|
574
|
+
payload.push(rr & 0xFF);
|
|
575
|
+
const Messages = this.protocol.getAnt().Messages;
|
|
576
|
+
let msg = Messages.acknowledgedData(payload);
|
|
577
|
+
this.send(msg, logStr, (res, err) => {
|
|
578
|
+
if (err)
|
|
579
|
+
return reject(err);
|
|
580
|
+
resolve(res);
|
|
581
|
+
});
|
|
582
|
+
});
|
|
361
583
|
}
|
|
362
584
|
}
|
|
363
585
|
exports.default = AntFEAdapter;
|