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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/lib/CyclingMode.d.ts +72 -0
  3. package/lib/CyclingMode.js +66 -0
  4. package/lib/Device.d.ts +48 -10
  5. package/lib/Device.js +9 -8
  6. package/lib/DeviceProtocol.d.ts +40 -12
  7. package/lib/DeviceProtocol.js +16 -16
  8. package/lib/DeviceRegistry.d.ts +4 -4
  9. package/lib/DeviceRegistry.js +10 -10
  10. package/lib/DeviceSupport.d.ts +4 -3
  11. package/lib/DeviceSupport.js +32 -8
  12. package/lib/ant/AntAdapter.d.ts +11 -2
  13. package/lib/ant/AntAdapter.js +30 -1
  14. package/lib/ant/AntScanner.d.ts +17 -6
  15. package/lib/ant/AntScanner.js +406 -135
  16. package/lib/ant/antfe/AntFEAdapter.d.ts +12 -8
  17. package/lib/ant/antfe/AntFEAdapter.js +404 -182
  18. package/lib/ant/anthrm/AntHrmAdapter.d.ts +4 -2
  19. package/lib/ant/anthrm/AntHrmAdapter.js +72 -25
  20. package/lib/ant/utils.js +2 -1
  21. package/lib/calculations.d.ts +12 -13
  22. package/lib/calculations.js +88 -125
  23. package/lib/daum/DaumAdapter.d.ts +29 -6
  24. package/lib/daum/DaumAdapter.js +219 -96
  25. package/lib/daum/ERGCyclingMode.d.ts +28 -0
  26. package/lib/daum/ERGCyclingMode.js +207 -0
  27. package/lib/daum/PowerMeterCyclingMode.d.ts +18 -0
  28. package/lib/daum/PowerMeterCyclingMode.js +79 -0
  29. package/lib/daum/SmartTrainerCyclingMode.d.ts +41 -0
  30. package/lib/daum/SmartTrainerCyclingMode.js +344 -0
  31. package/lib/daum/classic/DaumClassicAdapter.d.ts +3 -1
  32. package/lib/daum/classic/DaumClassicAdapter.js +46 -32
  33. package/lib/daum/classic/DaumClassicCyclingMode.d.ts +13 -0
  34. package/lib/daum/classic/DaumClassicCyclingMode.js +98 -0
  35. package/lib/daum/classic/DaumClassicProtocol.d.ts +5 -3
  36. package/lib/daum/classic/DaumClassicProtocol.js +39 -6
  37. package/lib/daum/classic/ERGCyclingMode.d.ts +23 -0
  38. package/lib/daum/classic/ERGCyclingMode.js +171 -0
  39. package/lib/daum/classic/bike.d.ts +41 -37
  40. package/lib/daum/classic/bike.js +86 -53
  41. package/lib/daum/classic/utils.d.ts +3 -3
  42. package/lib/daum/classic/utils.js +16 -10
  43. package/lib/daum/indoorbike.d.ts +2 -1
  44. package/lib/daum/indoorbike.js +23 -21
  45. package/lib/daum/premium/DaumPremiumAdapter.d.ts +2 -2
  46. package/lib/daum/premium/DaumPremiumAdapter.js +30 -20
  47. package/lib/daum/premium/DaumPremiumProtocol.d.ts +11 -2
  48. package/lib/daum/premium/DaumPremiumProtocol.js +49 -8
  49. package/lib/daum/premium/bike.d.ts +63 -52
  50. package/lib/daum/premium/bike.js +258 -207
  51. package/lib/daum/premium/tcpserial.d.ts +18 -14
  52. package/lib/daum/premium/tcpserial.js +50 -20
  53. package/lib/daum/premium/utils.d.ts +2 -2
  54. package/lib/simulator/Simulator.d.ts +13 -7
  55. package/lib/simulator/Simulator.js +62 -21
  56. package/lib/utils.d.ts +3 -1
  57. package/lib/utils.js +39 -18
  58. package/package.json +12 -11
  59. package/lib/ant/AntScanner.unit.tests.d.ts +0 -1
  60. package/lib/ant/AntScanner.unit.tests.js +0 -25
  61. package/lib/ant/antfe/AntFEProcessor.d.ts +0 -40
  62. package/lib/ant/antfe/AntFEProcessor.js +0 -238
  63. package/lib/ant/antfe/AntHrmProtocol.d.ts +0 -9
  64. package/lib/ant/antfe/AntHrmProtocol.js +0 -30
  65. package/lib/ant/antfe/bike.d.ts +0 -47
  66. package/lib/ant/antfe/bike.js +0 -602
  67. package/lib/ant/anthrm/anthrm.d.ts +0 -33
  68. package/lib/ant/anthrm/anthrm.js +0 -523
  69. package/lib/simulator/Simulator.unit.tests.d.ts +0 -1
  70. 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 TIMEOUT_ACK = 500;
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.ComputedHeartRate !== undefined; }
44
+ isHrm() { return this.deviceData.HeartRate !== undefined; }
35
45
  isPower() { return true; }
36
- getID() {
37
- return this.deviceID;
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
- const data = this.updateData(this.data, deviceData);
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 Constants = this.getProtocol().getAnt();
64
- let stick = this.stick;
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 (stick.currentCmd !== undefined && data.message === 1 && data.code === 6) {
70
- stick.currentCmd.response = { success: false };
71
- return;
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 (stick.currentCmd !== undefined && data.message === Constants.MESSAGE_CHANNEL_ACKNOWLEDGED_DATA && data.code === 31) {
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: utils_2.hexstr(data), error: err.message });
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
- if (!this.data.hasStarted) {
105
- this.data.power = undefined;
106
- this.data.slope = undefined;
107
- this.data.heartrate = undefined;
108
- this.data.pedalRpm = undefined;
109
- this.data.speed = undefined;
110
- this.data.distance = undefined;
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 deviceData;
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 opts = props || {};
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
- resolve(false);
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
- protocol.attachSensors(this, Ant.FitnessEquipmentSensor, 'fitnessData')
155
- .then(() => {
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
- this.sendUserConfiguration(opts.userWeight || 75, opts.bikeWeight || 10, opts.wheelDiameter, opts.gearRatio);
158
- this.started = true;
159
- resolve(true);
160
- })
161
- .catch(err => reject(err));
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
- this.logger.logEvent({ message: 'stop()' });
167
- this.stopWorker();
168
- return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
169
- if (!this.started)
170
- return resolve(false);
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
- if (stick === undefined)
173
- return resolve(false);
174
- stick.once('shutdown', () => {
175
- resolve(true);
176
- this.started = false;
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
- stick.detach_all();
180
- setTimeout(() => { stick.close(); }, 1000);
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
- reject(err);
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
- this.queue.enqueue({ msg, logStr, callback: callback });
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
- this.workerId = setInterval(() => { this.sendFromQueue(); }, 100);
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 || this.queue.isEmpty())
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, { error: "timeout" });
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: utils_2.hexstr(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.write(msg);
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
- var payload = [];
243
- payload.push(this.channel);
244
- const logStr = `sendUserConfiguration(${userWeight},${bikeWeight},${wheelDiameter},${gearRatio})`;
245
- var m = userWeight === undefined ? 0xFFFF : userWeight;
246
- var mb = bikeWeight === undefined ? 0xFFF : bikeWeight;
247
- var d = wheelDiameter === undefined ? 0xFF : wheelDiameter;
248
- var gr = gearRatio === undefined ? 0x00 : gearRatio;
249
- var dOffset = 0xFF;
250
- if (m !== 0xFFFF)
251
- m = Math.trunc(m * 100);
252
- if (mb !== 0xFFF)
253
- mb = Math.trunc(mb * 20);
254
- if (d !== 0xFF) {
255
- d = d * 1000;
256
- dOffset = d % 10;
257
- d = Math.trunc(d / 10);
258
- }
259
- if (gr !== 0x00) {
260
- gr = Math.trunc(gr / 0.03);
261
- }
262
- payload.push(0x37);
263
- payload.push(m & 0xFF);
264
- payload.push((m >> 8) & 0xFF);
265
- payload.push(0xFF);
266
- payload.push(((mb & 0xF) << 4) | (dOffset & 0xF));
267
- payload.push((mb >> 4) & 0xF);
268
- payload.push(d & 0xFF);
269
- payload.push(gr & 0xFF);
270
- const Messages = this.protocol.getAnt().Messages;
271
- let msg = Messages.acknowledgedData(payload);
272
- this.send(msg, logStr);
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
- var payload = [];
276
- payload.push(this.channel);
277
- const logStr = `sendBasicResistance(${resistance})`;
278
- var res = resistance === undefined ? 0 : resistance;
279
- res = res / 0.5;
280
- payload.push(0x30);
281
- payload.push(0xFF);
282
- payload.push(0xFF);
283
- payload.push(0xFF);
284
- payload.push(0xFF);
285
- payload.push(0xFF);
286
- payload.push(0xFF);
287
- payload.push(res & 0xFF);
288
- const Messages = this.protocol.getAnt().Messages;
289
- let msg = Messages.acknowledgedData(payload);
290
- this.send(msg, logStr);
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
- var payload = [];
294
- payload.push(this.channel);
295
- const logStr = `sendTargetPower(${power})`;
296
- var p = power === undefined ? 0x00 : power;
297
- p = p * 4;
298
- payload.push(0x31);
299
- payload.push(0xFF);
300
- payload.push(0xFF);
301
- payload.push(0xFF);
302
- payload.push(0xFF);
303
- payload.push(0xFF);
304
- payload.push(p & 0xFF);
305
- payload.push((p >> 8) & 0xFF);
306
- const Messages = this.protocol.getAnt().Messages;
307
- let msg = Messages.acknowledgedData(payload);
308
- this.send(msg, logStr);
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
- var payload = [];
312
- payload.push(this.channel);
313
- const logStr = `sendWindResistance(${windCoeff},${windSpeed},${draftFactor})`;
314
- var wc = windCoeff === undefined ? 0xFF : windCoeff;
315
- var ws = windSpeed === undefined ? 0xFF : windSpeed;
316
- var df = draftFactor === undefined ? 0xFF : draftFactor;
317
- if (wc !== 0xFF) {
318
- wc = Math.trunc(wc / 0.01);
319
- }
320
- if (ws !== 0xFF) {
321
- ws = Math.trunc(ws + 127);
322
- }
323
- if (df !== 0xFF) {
324
- df = Math.trunc(df / 0.01);
325
- }
326
- payload.push(0x32);
327
- payload.push(0xFF);
328
- payload.push(0xFF);
329
- payload.push(0xFF);
330
- payload.push(0xFF);
331
- payload.push(wc & 0xFF);
332
- payload.push(ws & 0xFF);
333
- payload.push(df & 0xFF);
334
- const Messages = this.protocol.getAnt().Messages;
335
- let msg = Messages.acknowledgedData(payload);
336
- this.send(msg, logStr);
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
- var payload = [];
340
- payload.push(this.channel);
341
- const logStr = `sendTrackResistance(${slope},${rrCoeff})`;
342
- var s = slope === undefined ? 0xFFFF : slope;
343
- var rr = rrCoeff === undefined ? 0xFF : rrCoeff;
344
- if (s !== 0xFFFF) {
345
- s = Math.trunc((s + 200) / 0.01);
346
- }
347
- if (rr !== 0xFF) {
348
- rr = Math.trunc(rr / 0.00005);
349
- }
350
- payload.push(0x33);
351
- payload.push(0xFF);
352
- payload.push(0xFF);
353
- payload.push(0xFF);
354
- payload.push(0xFF);
355
- payload.push(s & 0xFF);
356
- payload.push((s >> 8) & 0xFF);
357
- payload.push(rr & 0xFF);
358
- const Messages = this.protocol.getAnt().Messages;
359
- let msg = Messages.acknowledgedData(payload);
360
- this.send(msg, logStr);
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;