incyclist-devices 1.2.0 → 1.4.0
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 +9 -2
- package/lib/ant/AntAdapter.js +26 -2
- package/lib/ant/AntScanner.d.ts +16 -6
- package/lib/ant/AntScanner.js +379 -138
- package/lib/ant/antfe/AntFEAdapter.d.ts +4 -2
- package/lib/ant/antfe/AntFEAdapter.js +209 -72
- package/lib/ant/anthrm/AntHrmAdapter.d.ts +4 -1
- package/lib/ant/anthrm/AntHrmAdapter.js +73 -19
- 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
package/lib/daum/classic/bike.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const indoorbike_js_1 = require("../indoorbike.js");
|
|
4
3
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
5
4
|
const utils_1 = require("./utils");
|
|
6
5
|
const utils_2 = require("../../utils");
|
|
@@ -9,10 +8,10 @@ const nop = () => { };
|
|
|
9
8
|
const TIMEOUT_START = 15000;
|
|
10
9
|
const TIMEOUT_CLOSE = 5000;
|
|
11
10
|
const TIMEOUT_SEND = 2000;
|
|
12
|
-
var
|
|
11
|
+
var __SerialPort = undefined;
|
|
13
12
|
class Daum8008 {
|
|
14
13
|
constructor(opts = {}) {
|
|
15
|
-
this.logger = new gd_eventlog_1.EventLogger('DaumClassic');
|
|
14
|
+
this.logger = opts.logger || new gd_eventlog_1.EventLogger('DaumClassic');
|
|
16
15
|
this.portName = opts.port || process.env.COM_PORT;
|
|
17
16
|
this.settings = opts.settings || {};
|
|
18
17
|
this.bikeData = {
|
|
@@ -20,7 +19,6 @@ class Daum8008 {
|
|
|
20
19
|
bikeWeight: 10,
|
|
21
20
|
maxPower: 800
|
|
22
21
|
};
|
|
23
|
-
this.processor = new indoorbike_js_1.default(this, {});
|
|
24
22
|
this.sp = undefined;
|
|
25
23
|
this.error = undefined;
|
|
26
24
|
this.opening = false;
|
|
@@ -31,7 +29,7 @@ class Daum8008 {
|
|
|
31
29
|
this.queue = new utils_2.Queue();
|
|
32
30
|
}
|
|
33
31
|
static setSerialPort(spClass) {
|
|
34
|
-
|
|
32
|
+
__SerialPort = spClass;
|
|
35
33
|
}
|
|
36
34
|
static getClassName() {
|
|
37
35
|
return "Daum8008";
|
|
@@ -52,13 +50,13 @@ class Daum8008 {
|
|
|
52
50
|
cb(200, user);
|
|
53
51
|
}
|
|
54
52
|
getUserWeight() {
|
|
55
|
-
if (this.settings
|
|
56
|
-
return utils_1.getWeight(
|
|
53
|
+
if (this.settings && this.settings.user && this.settings.user.weight)
|
|
54
|
+
return (0, utils_1.getWeight)(this.settings.user.weight);
|
|
57
55
|
else
|
|
58
|
-
return utils_1.getWeight(
|
|
56
|
+
return (0, utils_1.getWeight)();
|
|
59
57
|
}
|
|
60
58
|
getBikeWeight() {
|
|
61
|
-
if (this.settings.weight) {
|
|
59
|
+
if (this.settings && this.settings.weight) {
|
|
62
60
|
let m = this.settings.weight;
|
|
63
61
|
if (m > 0 && m < 20)
|
|
64
62
|
return m;
|
|
@@ -74,19 +72,15 @@ class Daum8008 {
|
|
|
74
72
|
if (this.sp === undefined) {
|
|
75
73
|
const settings = this.settings.port || {};
|
|
76
74
|
settings.autoOpen = false;
|
|
77
|
-
this.sp = new
|
|
75
|
+
this.sp = new __SerialPort(this.portName, settings);
|
|
78
76
|
this.sp.on('open', () => { this.onPortOpen(); });
|
|
79
77
|
this.sp.on('close', () => { this.onPortClose(); });
|
|
80
78
|
this.sp.on('error', (error) => { this.onPortError(error); });
|
|
81
|
-
this.firstOpen = true;
|
|
82
79
|
}
|
|
83
|
-
else {
|
|
84
|
-
this.sp.open();
|
|
85
|
-
}
|
|
86
|
-
this.sp.open();
|
|
87
80
|
this.cmdBusy = true;
|
|
88
81
|
this.opening = true;
|
|
89
82
|
this.closed = undefined;
|
|
83
|
+
this.sp.open();
|
|
90
84
|
}
|
|
91
85
|
catch (err) {
|
|
92
86
|
this.logger.logEvent({ message: "startTraining:error:", error: err.message });
|
|
@@ -99,18 +93,26 @@ class Daum8008 {
|
|
|
99
93
|
return resolve(true);
|
|
100
94
|
}
|
|
101
95
|
this.connect();
|
|
102
|
-
const
|
|
96
|
+
const timeoutStart = this.settings.timeoutStart || TIMEOUT_START;
|
|
97
|
+
const tTimeout = Date.now() + timeoutStart;
|
|
103
98
|
const iv = setInterval(() => {
|
|
104
99
|
if (this.isConnected()) {
|
|
100
|
+
clearInterval(iv);
|
|
105
101
|
this.opening = false;
|
|
106
102
|
resolve(true);
|
|
107
|
-
clearInterval(iv);
|
|
108
103
|
}
|
|
109
104
|
else {
|
|
105
|
+
if (this.error) {
|
|
106
|
+
clearInterval(iv);
|
|
107
|
+
this.cmdBusy = false;
|
|
108
|
+
reject(this.error);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
110
111
|
if (Date.now() > tTimeout) {
|
|
112
|
+
clearInterval(iv);
|
|
111
113
|
this.opening = false;
|
|
114
|
+
this.cmdBusy = false;
|
|
112
115
|
reject(new Error('timeout'));
|
|
113
|
-
clearInterval(iv);
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
}, 100);
|
|
@@ -123,25 +125,31 @@ class Daum8008 {
|
|
|
123
125
|
}
|
|
124
126
|
var serialPort = this.sp;
|
|
125
127
|
this.closing = true;
|
|
126
|
-
if (this.queue !== undefined)
|
|
127
|
-
this.queue.clear();
|
|
128
128
|
if (this.bikeCmdWorker !== undefined) {
|
|
129
129
|
clearInterval(this.bikeCmdWorker);
|
|
130
130
|
this.bikeCmdWorker = undefined;
|
|
131
131
|
}
|
|
132
|
+
if (this.queue !== undefined)
|
|
133
|
+
this.queue.clear();
|
|
132
134
|
let connected = this.connected;
|
|
133
135
|
if (connected) {
|
|
134
136
|
if (serialPort) {
|
|
135
137
|
serialPort.unpipe();
|
|
136
138
|
serialPort.flush();
|
|
137
|
-
|
|
139
|
+
if (this.cmdBusy) {
|
|
140
|
+
serialPort.drain(() => {
|
|
141
|
+
serialPort.close();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
138
145
|
serialPort.close();
|
|
139
|
-
}
|
|
146
|
+
}
|
|
140
147
|
}
|
|
141
148
|
}
|
|
142
149
|
else {
|
|
143
|
-
if (serialPort)
|
|
150
|
+
if (serialPort) {
|
|
144
151
|
serialPort.close();
|
|
152
|
+
}
|
|
145
153
|
}
|
|
146
154
|
this.cmdBusy = false;
|
|
147
155
|
}
|
|
@@ -151,16 +159,14 @@ class Daum8008 {
|
|
|
151
159
|
const tTimeout = Date.now() + TIMEOUT_CLOSE;
|
|
152
160
|
const iv = setInterval(() => {
|
|
153
161
|
if (!this.closing || this.closed) {
|
|
154
|
-
resolve(true);
|
|
155
162
|
clearInterval(iv);
|
|
163
|
+
resolve(true);
|
|
156
164
|
}
|
|
157
165
|
else {
|
|
158
|
-
if (this.sp)
|
|
159
|
-
this.sp.close();
|
|
160
166
|
if (Date.now() > tTimeout) {
|
|
167
|
+
clearInterval(iv);
|
|
161
168
|
this.closing = false;
|
|
162
169
|
reject(new Error('timeout'));
|
|
163
|
-
clearInterval(iv);
|
|
164
170
|
}
|
|
165
171
|
}
|
|
166
172
|
}, 100);
|
|
@@ -175,9 +181,6 @@ class Daum8008 {
|
|
|
175
181
|
if (this.cmdStart !== undefined) {
|
|
176
182
|
this.cmdStart = Date.now();
|
|
177
183
|
}
|
|
178
|
-
if (this.firstOpen !== undefined) {
|
|
179
|
-
this.firstOpen = undefined;
|
|
180
|
-
}
|
|
181
184
|
this.cmdBusy = false;
|
|
182
185
|
}
|
|
183
186
|
onPortClose() {
|
|
@@ -231,7 +234,7 @@ class Daum8008 {
|
|
|
231
234
|
if (this.connected && this.cmdBusy) {
|
|
232
235
|
if (this.cmdCurrent !== undefined && this.cmdCurrent.start !== undefined) {
|
|
233
236
|
const cmdInfo = this.cmdCurrent;
|
|
234
|
-
const timeout = (cmdInfo.options && cmdInfo.options.timeout) ? cmdInfo.options.timeout : TIMEOUT_SEND;
|
|
237
|
+
const timeout = (cmdInfo.options && cmdInfo.options.timeout) ? cmdInfo.options.timeout : (this.settings.timeoutMessage || TIMEOUT_SEND);
|
|
235
238
|
let d = Date.now() - cmdInfo.start;
|
|
236
239
|
if (d > timeout) {
|
|
237
240
|
this.logger.logEvent({ message: 'sendCommmand:timeout', port: this.getPort() });
|
|
@@ -269,6 +272,8 @@ class Daum8008 {
|
|
|
269
272
|
options: options
|
|
270
273
|
};
|
|
271
274
|
this.queue.enqueue(cmdInfo);
|
|
275
|
+
if (this.queue.size() > 1)
|
|
276
|
+
this.logger.logEvent({ message: "sendCommand:adding:", cmd: logStr, hex: (0, utils_1.hexstr)(payload), queueSize: this.queue.size() });
|
|
272
277
|
if (this.bikeCmdWorker === undefined) {
|
|
273
278
|
this.startWorker();
|
|
274
279
|
}
|
|
@@ -287,7 +292,7 @@ class Daum8008 {
|
|
|
287
292
|
const parser = serialPort.pipe(new ByteLength({ length: expected }));
|
|
288
293
|
parser.on('data', (data) => {
|
|
289
294
|
let duration = Date.now() - this.cmdStart;
|
|
290
|
-
this.logger.logEvent({ message: "sendCommand:received:", duration, hex: utils_1.hexstr(data), port: this.getPort() });
|
|
295
|
+
this.logger.logEvent({ message: "sendCommand:received:", duration, hex: (0, utils_1.hexstr)(data), port: this.getPort() });
|
|
291
296
|
serialPort.unpipe();
|
|
292
297
|
if (callbackErr !== undefined) {
|
|
293
298
|
if (data[0] !== payload[0]) {
|
|
@@ -300,7 +305,7 @@ class Daum8008 {
|
|
|
300
305
|
callback(data);
|
|
301
306
|
done();
|
|
302
307
|
});
|
|
303
|
-
this.logger.logEvent({ message: "sendCommand:sending:", cmd: logStr, hex: utils_1.hexstr(payload), port: this.getPort() });
|
|
308
|
+
this.logger.logEvent({ message: "sendCommand:sending:", cmd: logStr, hex: (0, utils_1.hexstr)(payload), port: this.getPort() });
|
|
304
309
|
this.cmdCurrent.start = this.cmdStart = Date.now();
|
|
305
310
|
serialPort.write(payload);
|
|
306
311
|
}
|
|
@@ -312,50 +317,56 @@ class Daum8008 {
|
|
|
312
317
|
}
|
|
313
318
|
checkCockpit(bikeNo = 0) {
|
|
314
319
|
return new Promise((resolve, reject) => {
|
|
315
|
-
this.sendDaum8008Command(`checkCockpit(${bikeNo})`, [0x10, bikeNo], 3, (data) => resolve({ bike: data[1], version: data[2] }), (status, err) =>
|
|
320
|
+
this.sendDaum8008Command(`checkCockpit(${bikeNo})`, [0x10, bikeNo], 3, (data) => resolve({ bike: data[1], version: data[2] }), (status, err) => {
|
|
321
|
+
if (status === 408)
|
|
322
|
+
return resolve({ bike: bikeNo, version: undefined });
|
|
323
|
+
reject((0, utils_1.buildError)(status, err));
|
|
324
|
+
});
|
|
316
325
|
});
|
|
317
326
|
}
|
|
318
327
|
getAddress() {
|
|
319
328
|
return new Promise((resolve, reject) => {
|
|
320
|
-
this.sendDaum8008Command(`getAddress()`, [0x11], 2, (data) => resolve({ bike: data[1] }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
329
|
+
this.sendDaum8008Command(`getAddress()`, [0x11], 2, (data) => resolve({ bike: data[1] }), (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
321
330
|
});
|
|
322
331
|
}
|
|
323
332
|
getVersion(bikeNo = 0) {
|
|
324
333
|
return new Promise((resolve, reject) => {
|
|
325
|
-
this.sendDaum8008Command(`getVersion(${bikeNo})`, [0x73, bikeNo], 11, (data) => resolve({ bike: data[1], serialNo: utils_1.hexstr(data, 2, 8), cockpit: utils_1.getCockpit(data[10]) }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
334
|
+
this.sendDaum8008Command(`getVersion(${bikeNo})`, [0x73, bikeNo], 11, (data) => resolve({ bike: data[1], serialNo: (0, utils_1.hexstr)(data, 2, 8), cockpit: (0, utils_1.getCockpit)(data[10]) }), (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
326
335
|
});
|
|
327
336
|
}
|
|
328
337
|
resetDevice(bikeNo = 0) {
|
|
329
338
|
return new Promise((resolve, reject) => {
|
|
330
|
-
this.sendDaum8008Command(`resetDevice(${bikeNo})`, [0x12, bikeNo], 2, (data) => resolve({}), (status, err) => reject(utils_1.buildError(status, err)));
|
|
339
|
+
this.sendDaum8008Command(`resetDevice(${bikeNo})`, [0x12, bikeNo], 2, (data) => resolve({}), (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
331
340
|
});
|
|
332
341
|
}
|
|
333
342
|
startProg(bikeNo = 0) {
|
|
334
343
|
return new Promise((resolve, reject) => {
|
|
335
|
-
this.sendDaum8008Command(`startProg(${bikeNo})`, [0x21, bikeNo], 3, (data) => resolve({ bike: data[1], pedalling: data[2] > 0 }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
344
|
+
this.sendDaum8008Command(`startProg(${bikeNo})`, [0x21, bikeNo], 3, (data) => resolve({ bike: data[1], pedalling: data[2] > 0 }), (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
336
345
|
});
|
|
337
346
|
}
|
|
338
347
|
stopProg(bikeNo = 0) {
|
|
339
348
|
return new Promise((resolve, reject) => {
|
|
340
|
-
this.sendDaum8008Command(`stopProg(${bikeNo})`, [0x22, bikeNo], 3, (data) => resolve({ bike: data[1], pedalling: data[2] !== 0 }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
349
|
+
this.sendDaum8008Command(`stopProg(${bikeNo})`, [0x22, bikeNo], 3, (data) => resolve({ bike: data[1], pedalling: data[2] !== 0 }), (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
341
350
|
});
|
|
342
351
|
}
|
|
343
352
|
setProg(progNo = 0, bikeNo = 0) {
|
|
344
353
|
return new Promise((resolve, reject) => {
|
|
345
|
-
this.sendDaum8008Command(`setProg(${bikeNo},${progNo})`, [0x23, bikeNo, progNo], 4, (data) => resolve({ bike: data[1], progNo: data[2], pedalling: data[3] !== 0 }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
354
|
+
this.sendDaum8008Command(`setProg(${bikeNo},${progNo})`, [0x23, bikeNo, progNo], 4, (data) => resolve({ bike: data[1], progNo: data[2], pedalling: data[3] !== 0 }), (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
346
355
|
});
|
|
347
356
|
}
|
|
348
357
|
setBikeType(bikeType, bikeNo = 0) {
|
|
349
|
-
const bikeVal = utils_1.getBikeType(bikeType);
|
|
358
|
+
const bikeVal = (0, utils_1.getBikeType)(bikeType);
|
|
350
359
|
return new Promise((resolve, reject) => {
|
|
351
|
-
this.sendDaum8008Command(`setBikeType(${bikeNo},${bikeType})`, [0x69, bikeNo, 0, 0, bikeVal], 3, (data) => resolve({}), (status, err) => reject(utils_1.buildError(status, err)));
|
|
360
|
+
this.sendDaum8008Command(`setBikeType(${bikeNo},${bikeType})`, [0x69, bikeNo, 0, 0, bikeVal], 3, (data) => resolve({}), (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
352
361
|
});
|
|
353
362
|
}
|
|
354
363
|
setPerson(user = {}, bikeNo = 0) {
|
|
355
|
-
const age = user.age !== undefined ? user.age : utils_1.getAge(user.birthday);
|
|
356
|
-
const gender = utils_1.getGender(user.sex);
|
|
357
|
-
const length = utils_1.getLength(user.length);
|
|
358
|
-
const
|
|
364
|
+
const age = user.age !== undefined ? user.age : (0, utils_1.getAge)(user.birthday);
|
|
365
|
+
const gender = (0, utils_1.getGender)(user.sex);
|
|
366
|
+
const length = (0, utils_1.getLength)(user.length);
|
|
367
|
+
const maxPower = this.settings.maxPower === undefined ? 800 : this.settings.maxPower;
|
|
368
|
+
const mUser = user.weight || this.getUserWeight();
|
|
369
|
+
const weight = (0, utils_1.getWeight)(mUser) + this.getBikeWeight();
|
|
359
370
|
var cmd = [0x24, bikeNo, 0];
|
|
360
371
|
cmd.push(age);
|
|
361
372
|
cmd.push(gender);
|
|
@@ -364,18 +375,40 @@ class Daum8008 {
|
|
|
364
375
|
cmd.push(0);
|
|
365
376
|
cmd.push(0);
|
|
366
377
|
cmd.push(3);
|
|
367
|
-
cmd.push(
|
|
378
|
+
cmd.push(Math.round(maxPower / 5));
|
|
368
379
|
cmd.push(0);
|
|
369
380
|
cmd.push(0);
|
|
370
381
|
cmd.push(0);
|
|
371
382
|
cmd.push(0);
|
|
372
383
|
return new Promise((resolve, reject) => {
|
|
373
|
-
this.sendDaum8008Command(`setPerson(${bikeNo},${age},${gender},${length},${weight})`, cmd, 16, (data) =>
|
|
384
|
+
this.sendDaum8008Command(`setPerson(${bikeNo},${age},${gender},${length},${weight})`, cmd, 16, (data) => {
|
|
385
|
+
let ok = true;
|
|
386
|
+
cmd.forEach((v, i) => {
|
|
387
|
+
if (data[i] !== v) {
|
|
388
|
+
if (i === 10 && v >= 160) {
|
|
389
|
+
if (data[i] === 0 || data[i] === 80)
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
reject((0, utils_1.buildError)(512, 'illegal response'));
|
|
393
|
+
ok = false;
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
if (ok)
|
|
397
|
+
resolve({ bike: data[1], age, gender, length, weight });
|
|
398
|
+
}, (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
374
399
|
});
|
|
375
400
|
}
|
|
376
401
|
runData(bikeNo = 0) {
|
|
377
402
|
return new Promise((resolve, reject) => {
|
|
378
|
-
this.sendDaum8008Command(`runData(${bikeNo})`, [0x40, bikeNo], 19, (data) =>
|
|
403
|
+
this.sendDaum8008Command(`runData(${bikeNo})`, [0x40, bikeNo], 19, (data) => {
|
|
404
|
+
try {
|
|
405
|
+
const parsed = (0, utils_1.parseRunData)(data);
|
|
406
|
+
resolve(parsed);
|
|
407
|
+
}
|
|
408
|
+
catch (e) {
|
|
409
|
+
reject((0, utils_1.buildError)(500, e));
|
|
410
|
+
}
|
|
411
|
+
}, (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
379
412
|
});
|
|
380
413
|
}
|
|
381
414
|
setGear(gear, bikeNo = 0) {
|
|
@@ -385,7 +418,7 @@ class Daum8008 {
|
|
|
385
418
|
if (gear > 28)
|
|
386
419
|
gearVal = 28;
|
|
387
420
|
return new Promise((resolve, reject) => {
|
|
388
|
-
this.sendDaum8008Command(`setGear(${bikeNo},${gearVal})`, [0x53, bikeNo, gearVal], 3, (data) => resolve({ bike: data[1], gear: data[2] }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
421
|
+
this.sendDaum8008Command(`setGear(${bikeNo},${gearVal})`, [0x53, bikeNo, gearVal], 3, (data) => resolve({ bike: data[1], gear: data[2] }), (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
389
422
|
});
|
|
390
423
|
}
|
|
391
424
|
setPower(power, bikeNo = 0) {
|
|
@@ -400,7 +433,7 @@ class Daum8008 {
|
|
|
400
433
|
if (power > 800)
|
|
401
434
|
powerRequest = 800;
|
|
402
435
|
const powerVal = Math.round(powerRequest / 5);
|
|
403
|
-
this.sendDaum8008Command(`setPower(${bikeNo},${power})`, [0x51, bikeNo, powerVal], 3, (data) => resolve({ bike: data[1], power: (data[2] * 5) }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
436
|
+
this.sendDaum8008Command(`setPower(${bikeNo},${power})`, [0x51, bikeNo, powerVal], 3, (data) => resolve({ bike: data[1], power: (data[2] * 5) }), (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
404
437
|
});
|
|
405
438
|
}
|
|
406
439
|
setSlope(slope, bikeNo = 0) {
|
|
@@ -410,12 +443,12 @@ class Daum8008 {
|
|
|
410
443
|
return;
|
|
411
444
|
}
|
|
412
445
|
const cmd = [0x55, bikeNo];
|
|
413
|
-
const arr = utils_1.Float32ToIntArray(slope);
|
|
446
|
+
const arr = (0, utils_1.Float32ToIntArray)(slope);
|
|
414
447
|
cmd.push(arr[3]);
|
|
415
448
|
cmd.push(arr[2]);
|
|
416
449
|
cmd.push(arr[1]);
|
|
417
450
|
cmd.push(arr[0]);
|
|
418
|
-
this.sendDaum8008Command(`setSlope(${bikeNo},${slope})`, cmd, 6, (data) => resolve({ bike: data[1], slope: slope }), (status, err) => reject(utils_1.buildError(status, err)));
|
|
451
|
+
this.sendDaum8008Command(`setSlope(${bikeNo},${slope})`, cmd, 6, (data) => resolve({ bike: data[1], slope: slope }), (status, err) => reject((0, utils_1.buildError)(status, err)));
|
|
419
452
|
});
|
|
420
453
|
}
|
|
421
454
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export declare function getCockpit(c: any): "Cardio" | "Fitness" | "Vita De Luxe" | "8008" | "8080" | "Therapie" | "Unknown";
|
|
1
|
+
export declare function getCockpit(c: any): "Cardio" | "Fitness" | "Vita De Luxe" | "8008" | "8080" | "Therapie" | "8008 TRS Pro" | "8008 TRS3" | "Unknown";
|
|
2
2
|
export declare function getBikeType(type: any): 1 | 0;
|
|
3
3
|
export declare function getAge(birthday: any): number;
|
|
4
4
|
export declare function getGender(sex: any): 1 | 2;
|
|
5
|
-
export declare function getLength(length: any):
|
|
6
|
-
export declare function getWeight(weight
|
|
5
|
+
export declare function getLength(length: any): number;
|
|
6
|
+
export declare function getWeight(weight?: any): number;
|
|
7
7
|
export declare function parseRunData(data: any): any;
|
|
8
8
|
export declare function buildError(status: any, err: any): any;
|
|
9
9
|
export declare function hexstr(arr: any, start?: any, len?: any): string;
|
|
@@ -15,6 +15,10 @@ function getCockpit(c) {
|
|
|
15
15
|
return "8080";
|
|
16
16
|
case 60:
|
|
17
17
|
return "Therapie";
|
|
18
|
+
case 100:
|
|
19
|
+
return "8008 TRS Pro";
|
|
20
|
+
case 160:
|
|
21
|
+
return "8008 TRS3";
|
|
18
22
|
default:
|
|
19
23
|
return "Unknown";
|
|
20
24
|
}
|
|
@@ -64,25 +68,27 @@ function getGender(sex) {
|
|
|
64
68
|
}
|
|
65
69
|
exports.getGender = getGender;
|
|
66
70
|
function getLength(length) {
|
|
67
|
-
if (length === undefined)
|
|
71
|
+
if (length === undefined || length === null)
|
|
68
72
|
return 180;
|
|
69
|
-
|
|
70
|
-
if (
|
|
73
|
+
let l = Math.round(length);
|
|
74
|
+
if (l < 100)
|
|
71
75
|
return 100;
|
|
72
|
-
if (
|
|
76
|
+
if (l > 220)
|
|
73
77
|
return 220;
|
|
74
|
-
return
|
|
78
|
+
return l;
|
|
75
79
|
}
|
|
76
80
|
exports.getLength = getLength;
|
|
77
81
|
function getWeight(weight) {
|
|
78
|
-
if (weight === undefined)
|
|
82
|
+
if (weight === undefined || weight === null)
|
|
79
83
|
return 80;
|
|
80
|
-
|
|
81
|
-
if (
|
|
84
|
+
let m = Math.round(weight);
|
|
85
|
+
if (isNaN(m))
|
|
86
|
+
return 80;
|
|
87
|
+
if (m < 10)
|
|
82
88
|
return 10;
|
|
83
|
-
if (
|
|
89
|
+
if (m > 250)
|
|
84
90
|
return 250;
|
|
85
|
-
return
|
|
91
|
+
return m;
|
|
86
92
|
}
|
|
87
93
|
exports.getWeight = getWeight;
|
|
88
94
|
function parseRunData(data) {
|
package/lib/daum/indoorbike.d.ts
CHANGED
|
@@ -12,7 +12,8 @@ export default class IndoorBikeProcessor {
|
|
|
12
12
|
lastUpdate: any;
|
|
13
13
|
hasBikeUpdate: boolean;
|
|
14
14
|
logger: EventLogger;
|
|
15
|
-
constructor(bike: any, opts
|
|
15
|
+
constructor(bike: any, opts?: any);
|
|
16
|
+
reset(): void;
|
|
16
17
|
setValues(data: any): any;
|
|
17
18
|
isAccelMode(): any;
|
|
18
19
|
getSlope(data: any): any;
|
package/lib/daum/indoorbike.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const calculations_1 = require("../calculations");
|
|
6
|
+
const calculations_1 = __importDefault(require("../calculations"));
|
|
4
7
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
5
8
|
const constants_1 = require("./constants");
|
|
6
9
|
const DEFAULT_BIKE_WEIGHT = 10;
|
|
@@ -9,6 +12,10 @@ class IndoorBikeProcessor {
|
|
|
9
12
|
constructor(bike, opts) {
|
|
10
13
|
const props = opts || {};
|
|
11
14
|
this.bike = bike;
|
|
15
|
+
this.logger = props.logger || new gd_eventlog_1.EventLogger('IndoorBike');
|
|
16
|
+
this.reset();
|
|
17
|
+
}
|
|
18
|
+
reset() {
|
|
12
19
|
this.prevTS = 0;
|
|
13
20
|
this.prevDistance = 0;
|
|
14
21
|
this.prevRpm = 0;
|
|
@@ -19,28 +26,28 @@ class IndoorBikeProcessor {
|
|
|
19
26
|
this.prevSettings = undefined;
|
|
20
27
|
this.hasBikeUpdate = false;
|
|
21
28
|
this.lastUpdate = {};
|
|
22
|
-
this.logger = props.logger || new gd_eventlog_1.EventLogger('IndoorBike');
|
|
23
29
|
}
|
|
24
30
|
setValues(data) {
|
|
25
31
|
this.logger.logEvent({ message: "setValues request", data, prev: this.prevSettings });
|
|
26
32
|
try {
|
|
27
|
-
if (
|
|
28
|
-
this.
|
|
33
|
+
if (!data || data.reset || Object.keys(data).length === 0) {
|
|
34
|
+
this.prevSettings = undefined;
|
|
29
35
|
return data;
|
|
30
36
|
}
|
|
31
37
|
if (data.refresh) {
|
|
32
|
-
if (this.prevSettings !== undefined)
|
|
33
|
-
|
|
38
|
+
if (this.prevSettings !== undefined) {
|
|
39
|
+
data.slope = this.prevSettings.slope;
|
|
40
|
+
data.targetPower = this.prevSettings.targetPower;
|
|
41
|
+
data.minPower = this.prevSettings.minPower;
|
|
42
|
+
data.maxPower = this.prevSettings.maxPower;
|
|
43
|
+
return data;
|
|
44
|
+
}
|
|
34
45
|
else {
|
|
35
46
|
return this.caclulateTargetPower(data);
|
|
36
47
|
}
|
|
37
48
|
}
|
|
38
49
|
let updateMode = false;
|
|
39
50
|
const isSlopeUpdate = data.slope !== undefined && Object.keys(data).length === 1;
|
|
40
|
-
if (data.slope === undefined && data.targetPower === undefined && data.minPower === undefined && data.maxPower === undefined) {
|
|
41
|
-
data.slope = this.prevSlope;
|
|
42
|
-
updateMode = true;
|
|
43
|
-
}
|
|
44
51
|
if (data.targetPower !== undefined) {
|
|
45
52
|
data.slope = undefined;
|
|
46
53
|
this.bike.settings.targetPower = data.targetPower;
|
|
@@ -67,9 +74,6 @@ class IndoorBikeProcessor {
|
|
|
67
74
|
data.targetPower = data.minPower;
|
|
68
75
|
}
|
|
69
76
|
}
|
|
70
|
-
if (data.targetPower !== undefined) {
|
|
71
|
-
this.bike.settings.targetPower = data.targetPower;
|
|
72
|
-
}
|
|
73
77
|
}
|
|
74
78
|
if (!isSlopeUpdate)
|
|
75
79
|
this.prevSettings = JSON.parse(JSON.stringify(data));
|
|
@@ -111,13 +115,13 @@ class IndoorBikeProcessor {
|
|
|
111
115
|
getValues(data, props = {}) {
|
|
112
116
|
this.logger.logEvent({ message: "getValues request", data });
|
|
113
117
|
try {
|
|
114
|
-
let rpm = data.pedalRpm;
|
|
115
|
-
let gear = data.gear;
|
|
116
|
-
let power = data.power;
|
|
118
|
+
let rpm = data.pedalRpm || 0;
|
|
119
|
+
let gear = data.gear || 0;
|
|
120
|
+
let power = data.power || 0;
|
|
117
121
|
let slope = this.getSlope(data);
|
|
118
|
-
let speed = data.speed;
|
|
122
|
+
let speed = data.speed || 0;
|
|
119
123
|
let m = this.getWeight(props);
|
|
120
|
-
let distanceInternal = this.prevDistance;
|
|
124
|
+
let distanceInternal = this.prevDistance || 0;
|
|
121
125
|
let distance = Math.round(distanceInternal / 100);
|
|
122
126
|
let ts = Date.now();
|
|
123
127
|
let duration = this.prevTS === 0 ? 0 : ((ts - this.prevTS) / 1000);
|
|
@@ -126,9 +130,7 @@ class IndoorBikeProcessor {
|
|
|
126
130
|
power = 0;
|
|
127
131
|
}
|
|
128
132
|
else {
|
|
129
|
-
|
|
130
|
-
speed = calculations_1.default.calculateSpeed(m, power, slope);
|
|
131
|
-
}
|
|
133
|
+
speed = calculations_1.default.calculateSpeed(m, power, slope);
|
|
132
134
|
let v = speed / 3.6;
|
|
133
135
|
distanceInternal += Math.round(v * duration);
|
|
134
136
|
distance = Math.round(distanceInternal / 100);
|
|
@@ -4,8 +4,8 @@ export default class DaumPremiumDevice extends DaumAdapter {
|
|
|
4
4
|
constructor(protocol: any, bike: any);
|
|
5
5
|
getName(): string;
|
|
6
6
|
getPort(): any;
|
|
7
|
+
getInterface(): any;
|
|
7
8
|
check(): Promise<unknown>;
|
|
8
9
|
start(props: any): Promise<unknown>;
|
|
9
|
-
getCurrentBikeData(): any
|
|
10
|
-
updateData(data: any, bikeData: any): any;
|
|
10
|
+
getCurrentBikeData(): Promise<any>;
|
|
11
11
|
}
|
|
@@ -8,10 +8,13 @@ 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
16
|
const utils_1 = require("../../utils");
|
|
14
|
-
const DaumAdapter_1 = require("../DaumAdapter");
|
|
17
|
+
const DaumAdapter_1 = __importDefault(require("../DaumAdapter"));
|
|
15
18
|
const PROTOCOL_NAME = "Daum Premium";
|
|
16
19
|
class DaumPremiumDevice extends DaumAdapter_1.default {
|
|
17
20
|
constructor(protocol, bike) {
|
|
@@ -32,10 +35,15 @@ class DaumPremiumDevice extends DaumAdapter_1.default {
|
|
|
32
35
|
getPort() {
|
|
33
36
|
return this.bike.getPort();
|
|
34
37
|
}
|
|
38
|
+
getInterface() {
|
|
39
|
+
return this.bike.getInterface();
|
|
40
|
+
}
|
|
35
41
|
check() {
|
|
36
42
|
var info = {};
|
|
37
43
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
38
44
|
this.logger.logEvent({ message: "check()", port: this.getPort() });
|
|
45
|
+
if (this.isStopped())
|
|
46
|
+
reject(new Error("device is stopped"));
|
|
39
47
|
try {
|
|
40
48
|
if (!this.bike.isConnected())
|
|
41
49
|
yield this.bike.saveConnect();
|
|
@@ -52,16 +60,28 @@ class DaumPremiumDevice extends DaumAdapter_1.default {
|
|
|
52
60
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53
61
|
this.logger.logEvent({ message: 'start()', props });
|
|
54
62
|
const opts = props || {};
|
|
63
|
+
var info = {};
|
|
55
64
|
this.initData();
|
|
56
|
-
return utils_1.runWithRetries(() => __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
return (0, utils_1.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
if (this.isStopped())
|
|
67
|
+
return;
|
|
57
68
|
try {
|
|
69
|
+
if (!this.bike.isConnected()) {
|
|
70
|
+
yield this.bike.saveConnect();
|
|
71
|
+
}
|
|
72
|
+
if (!info.deviceType) {
|
|
73
|
+
info.deviceType = yield this.bike.getDeviceType();
|
|
74
|
+
}
|
|
75
|
+
if (!info.version) {
|
|
76
|
+
info.version = yield this.bike.getProtocolVersion();
|
|
77
|
+
}
|
|
58
78
|
const gear = yield this.bike.setGear(this.data.gear || (opts.gear || 10));
|
|
59
79
|
return gear;
|
|
60
80
|
}
|
|
61
81
|
catch (err) {
|
|
62
|
-
throw err;
|
|
82
|
+
throw (new Error(`could not start device, reason:${err.message}`));
|
|
63
83
|
}
|
|
64
|
-
}),
|
|
84
|
+
}), 5, 1000)
|
|
65
85
|
.then(data => {
|
|
66
86
|
this.startUpdatePull();
|
|
67
87
|
return data;
|
|
@@ -69,22 +89,12 @@ class DaumPremiumDevice extends DaumAdapter_1.default {
|
|
|
69
89
|
});
|
|
70
90
|
}
|
|
71
91
|
getCurrentBikeData() {
|
|
72
|
-
return this
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
data.speed = bikeData.speed;
|
|
79
|
-
data.heartrate = bikeData.heartrate;
|
|
80
|
-
data.distance = bikeData.distance / 1000;
|
|
81
|
-
data.distanceInternal = bikeData.distance;
|
|
82
|
-
data.time = bikeData.time;
|
|
83
|
-
data.gear = bikeData.gear;
|
|
84
|
-
if (this.bike.processor !== undefined) {
|
|
85
|
-
data = this.bike.processor.getValues(data);
|
|
86
|
-
}
|
|
87
|
-
return data;
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
if (!this.bike.isConnected()) {
|
|
94
|
+
yield this.bike.saveConnect();
|
|
95
|
+
}
|
|
96
|
+
return this.getBike().getTrainingData();
|
|
97
|
+
});
|
|
88
98
|
}
|
|
89
99
|
}
|
|
90
100
|
exports.default = DaumPremiumDevice;
|
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
import DeviceProtocol from '../../DeviceProtocol';
|
|
1
|
+
import DeviceProtocolBase, { DeviceProtocol, DeviceSettings } from '../../DeviceProtocol';
|
|
2
2
|
import { EventLogger } from 'gd-eventlog';
|
|
3
3
|
export interface DaumPremiumProtocolState {
|
|
4
4
|
activeScans: Array<any>;
|
|
5
5
|
scanning: boolean;
|
|
6
6
|
stopScanning?: boolean;
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
interface DaumPremiumSettings extends DeviceSettings {
|
|
9
|
+
interface: string;
|
|
10
|
+
}
|
|
11
|
+
interface DaumPremiumTCPSettings extends DaumPremiumSettings {
|
|
12
|
+
host: string;
|
|
13
|
+
}
|
|
14
|
+
export default class DaumPremiumProtocol extends DeviceProtocolBase implements DeviceProtocol {
|
|
9
15
|
state: DaumPremiumProtocolState;
|
|
10
16
|
logger: EventLogger;
|
|
11
17
|
constructor();
|
|
18
|
+
add(settings: DaumPremiumSettings | DaumPremiumTCPSettings): any;
|
|
12
19
|
getName(): string;
|
|
13
20
|
getInterfaces(): string[];
|
|
14
21
|
isBike(): boolean;
|
|
@@ -18,6 +25,8 @@ export default class DaumPremiumProtocol extends DeviceProtocol {
|
|
|
18
25
|
addDevice(DeviceClass: any, opts: any, portName: any): any;
|
|
19
26
|
scanTcpip(opts: any): void;
|
|
20
27
|
scanSerial(opts: any): void;
|
|
28
|
+
isScanning(): boolean;
|
|
21
29
|
stopScan(): Promise<boolean>;
|
|
22
30
|
scanCommand(device: any, opts: any): void;
|
|
23
31
|
}
|
|
32
|
+
export {};
|