incyclist-devices 1.4.98 → 1.4.100

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 (128) hide show
  1. package/LICENSE +0 -0
  2. package/lib/CyclingMode.d.ts +76 -76
  3. package/lib/CyclingMode.js +79 -79
  4. package/lib/Device.d.ts +92 -92
  5. package/lib/Device.js +71 -71
  6. package/lib/DeviceProtocol.d.ts +74 -74
  7. package/lib/DeviceProtocol.js +41 -41
  8. package/lib/DeviceRegistry.d.ts +8 -8
  9. package/lib/DeviceRegistry.js +33 -33
  10. package/lib/DeviceSupport.d.ts +34 -34
  11. package/lib/DeviceSupport.js +78 -78
  12. package/lib/ant/AntAdapter.d.ts +50 -50
  13. package/lib/ant/AntAdapter.js +109 -109
  14. package/lib/ant/AntScanner.d.ts +60 -60
  15. package/lib/ant/AntScanner.js +651 -651
  16. package/lib/ant/antfe/AntFEAdapter.d.ts +83 -83
  17. package/lib/ant/antfe/AntFEAdapter.js +652 -652
  18. package/lib/ant/antfe/ant-fe-adv-st-mode.d.ts +9 -9
  19. package/lib/ant/antfe/ant-fe-adv-st-mode.js +51 -51
  20. package/lib/ant/antfe/ant-fe-erg-mode.d.ts +6 -6
  21. package/lib/ant/antfe/ant-fe-erg-mode.js +14 -14
  22. package/lib/ant/antfe/ant-fe-st-mode.d.ts +5 -5
  23. package/lib/ant/antfe/ant-fe-st-mode.js +13 -13
  24. package/lib/ant/anthrm/AntHrmAdapter.d.ts +16 -16
  25. package/lib/ant/anthrm/AntHrmAdapter.js +130 -130
  26. package/lib/ant/antpwr/pwr-adapter.d.ts +49 -49
  27. package/lib/ant/antpwr/pwr-adapter.js +251 -251
  28. package/lib/ant/utils.d.ts +1 -1
  29. package/lib/ant/utils.js +23 -23
  30. package/lib/ble/ble-device.d.ts +63 -63
  31. package/lib/ble/ble-device.js +442 -442
  32. package/lib/ble/ble-erg-mode.d.ts +18 -18
  33. package/lib/ble/ble-erg-mode.js +132 -127
  34. package/lib/ble/ble-interface.d.ts +100 -99
  35. package/lib/ble/ble-interface.js +717 -712
  36. package/lib/ble/ble-peripheral.d.ts +36 -36
  37. package/lib/ble/ble-peripheral.js +200 -200
  38. package/lib/ble/ble-st-mode.d.ts +15 -15
  39. package/lib/ble/ble-st-mode.js +102 -102
  40. package/lib/ble/ble.d.ts +129 -129
  41. package/lib/ble/ble.js +86 -86
  42. package/lib/ble/consts.d.ts +14 -14
  43. package/lib/ble/consts.js +17 -17
  44. package/lib/ble/fm.d.ts +125 -125
  45. package/lib/ble/fm.js +739 -739
  46. package/lib/ble/hrm.d.ts +48 -48
  47. package/lib/ble/hrm.js +134 -134
  48. package/lib/ble/incyclist-protocol.d.ts +31 -31
  49. package/lib/ble/incyclist-protocol.js +147 -147
  50. package/lib/ble/pwr.d.ts +89 -89
  51. package/lib/ble/pwr.js +321 -321
  52. package/lib/ble/tacx.d.ts +90 -90
  53. package/lib/ble/tacx.js +731 -730
  54. package/lib/ble/wahoo-kickr.d.ts +98 -98
  55. package/lib/ble/wahoo-kickr.js +496 -496
  56. package/lib/calculations.d.ts +13 -13
  57. package/lib/calculations.js +150 -150
  58. package/lib/daum/DaumAdapter.d.ts +66 -66
  59. package/lib/daum/DaumAdapter.js +396 -396
  60. package/lib/daum/DaumPowerMeterCyclingMode.d.ts +8 -8
  61. package/lib/daum/DaumPowerMeterCyclingMode.js +21 -21
  62. package/lib/daum/ERGCyclingMode.d.ts +26 -26
  63. package/lib/daum/ERGCyclingMode.js +201 -201
  64. package/lib/daum/SmartTrainerCyclingMode.d.ts +41 -41
  65. package/lib/daum/SmartTrainerCyclingMode.js +344 -344
  66. package/lib/daum/classic/DaumClassicAdapter.d.ts +18 -18
  67. package/lib/daum/classic/DaumClassicAdapter.js +146 -146
  68. package/lib/daum/classic/DaumClassicCyclingMode.d.ts +13 -13
  69. package/lib/daum/classic/DaumClassicCyclingMode.js +97 -97
  70. package/lib/daum/classic/DaumClassicProtocol.d.ts +27 -27
  71. package/lib/daum/classic/DaumClassicProtocol.js +185 -185
  72. package/lib/daum/classic/bike.d.ts +64 -64
  73. package/lib/daum/classic/bike.js +456 -456
  74. package/lib/daum/classic/utils.d.ts +13 -13
  75. package/lib/daum/classic/utils.js +143 -143
  76. package/lib/daum/constants.d.ts +19 -19
  77. package/lib/daum/constants.js +22 -22
  78. package/lib/daum/premium/DaumClassicCyclingMode.d.ts +14 -14
  79. package/lib/daum/premium/DaumClassicCyclingMode.js +86 -86
  80. package/lib/daum/premium/DaumPremiumAdapter.d.ts +12 -12
  81. package/lib/daum/premium/DaumPremiumAdapter.js +131 -131
  82. package/lib/daum/premium/DaumPremiumProtocol.d.ts +32 -32
  83. package/lib/daum/premium/DaumPremiumProtocol.js +207 -207
  84. package/lib/daum/premium/bike.d.ts +123 -123
  85. package/lib/daum/premium/bike.js +894 -894
  86. package/lib/daum/premium/tcpserial.d.ts +33 -33
  87. package/lib/daum/premium/tcpserial.js +123 -123
  88. package/lib/daum/premium/utils.d.ts +62 -62
  89. package/lib/daum/premium/utils.js +376 -376
  90. package/lib/kettler/comms.d.ts +59 -59
  91. package/lib/kettler/comms.js +242 -242
  92. package/lib/kettler/ergo-racer/ERGCyclingMode.d.ts +25 -25
  93. package/lib/kettler/ergo-racer/ERGCyclingMode.js +144 -145
  94. package/lib/kettler/ergo-racer/adapter.d.ts +101 -101
  95. package/lib/kettler/ergo-racer/adapter.js +639 -639
  96. package/lib/kettler/ergo-racer/protocol.d.ts +41 -41
  97. package/lib/kettler/ergo-racer/protocol.js +203 -203
  98. package/lib/modes/power-base.d.ts +20 -20
  99. package/lib/modes/power-base.js +70 -70
  100. package/lib/modes/power-meter.d.ts +20 -20
  101. package/lib/modes/power-meter.js +78 -78
  102. package/lib/modes/simulator.d.ts +29 -29
  103. package/lib/modes/simulator.js +140 -140
  104. package/lib/simulator/Simulator.d.ts +69 -69
  105. package/lib/simulator/Simulator.js +288 -288
  106. package/lib/types/command.d.ts +8 -8
  107. package/lib/types/command.js +2 -2
  108. package/lib/types/route.d.ts +24 -24
  109. package/lib/types/route.js +9 -9
  110. package/lib/types/user.d.ts +11 -11
  111. package/lib/types/user.js +9 -9
  112. package/lib/utils.d.ts +14 -14
  113. package/lib/utils.js +114 -114
  114. package/package.json +46 -46
  115. package/lib/ant/antfe/ant-fe-st-mode copy.d.ts +0 -7
  116. package/lib/ant/antfe/ant-fe-st-mode copy.js +0 -54
  117. package/lib/ant/antpwr/AntPWRAdapter.d.ts +0 -24
  118. package/lib/ant/antpwr/AntPWRAdapter.js +0 -252
  119. package/lib/daum/PowerMeterCyclingMode.d.ts +0 -18
  120. package/lib/daum/PowerMeterCyclingMode.js +0 -78
  121. package/lib/daum/classic/ERGCyclingMode.d.ts +0 -23
  122. package/lib/daum/classic/ERGCyclingMode.js +0 -171
  123. package/lib/daum/indoorbike.d.ts +0 -24
  124. package/lib/daum/indoorbike.js +0 -178
  125. package/lib/kettler/ergo-racer/modes/power-meter.d.ts +0 -18
  126. package/lib/kettler/ergo-racer/modes/power-meter.js +0 -86
  127. package/lib/simulator/simulator-mode.d.ts +0 -28
  128. package/lib/simulator/simulator-mode.js +0 -120
@@ -1,456 +1,456 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const gd_eventlog_1 = require("gd-eventlog");
4
- const utils_1 = require("./utils");
5
- const utils_2 = require("../../utils");
6
- const ByteLength = require('@serialport/parser-byte-length');
7
- const nop = () => { };
8
- const TIMEOUT_START = 15000;
9
- const TIMEOUT_CLOSE = 5000;
10
- const TIMEOUT_SEND = 2000;
11
- var __SerialPort = undefined;
12
- class Daum8008 {
13
- constructor(opts = {}) {
14
- this.logger = opts.logger || new gd_eventlog_1.EventLogger('DaumClassic');
15
- this.portName = opts.port || process.env.COM_PORT;
16
- this.settings = opts.settings || {};
17
- this.bikeData = {
18
- userWeight: utils_1.DEFAULT_USER_WEIGHT,
19
- bikeWeight: utils_1.DEFAULT_BIKE_WEIGHT,
20
- maxPower: 800
21
- };
22
- this.sp = undefined;
23
- this.error = undefined;
24
- this.opening = false;
25
- this.connected = false;
26
- this.closing = false;
27
- this.closed = undefined;
28
- this.cmdBusy = false;
29
- this.queue = new utils_2.Queue();
30
- }
31
- static setSerialPort(spClass) {
32
- __SerialPort = spClass;
33
- }
34
- static getClassName() {
35
- return "Daum8008";
36
- }
37
- getType() {
38
- return "DaumClassic";
39
- }
40
- getPort() {
41
- return this.portName;
42
- }
43
- isConnected() {
44
- return this.connected;
45
- }
46
- setUser(user, callback) {
47
- this.logger.logEvent({ message: "setUser()", user });
48
- if (user)
49
- this.settings.user = user;
50
- var cb = callback || nop;
51
- cb(200, user);
52
- }
53
- getUserWeight() {
54
- if (this.settings && this.settings.user && this.settings.user.weight)
55
- return (0, utils_1.getWeight)(this.settings.user.weight);
56
- else
57
- return (0, utils_1.getWeight)();
58
- }
59
- getBikeWeight() {
60
- if (this.settings && this.settings.weight) {
61
- let m = this.settings.weight;
62
- if (m > 0 && m < 20)
63
- return m;
64
- }
65
- return 10;
66
- }
67
- connect() {
68
- this.logger.logEvent({ message: "connect()", port: this.getPort(), sp: (this.sp !== undefined), });
69
- if (this.closing || this.opening) {
70
- return;
71
- }
72
- try {
73
- if (this.sp === undefined) {
74
- const settings = this.settings.port || {};
75
- settings.autoOpen = false;
76
- this.sp = new __SerialPort(this.portName, settings);
77
- this.sp.on('open', () => { this.onPortOpen(); });
78
- this.sp.on('close', () => { this.onPortClose(); });
79
- this.sp.on('error', (error) => { this.onPortError(error); });
80
- }
81
- this.cmdBusy = true;
82
- this.opening = true;
83
- this.closed = undefined;
84
- this.sp.open();
85
- }
86
- catch (err) {
87
- this.logger.logEvent({ message: "startTraining:error:", error: err.message });
88
- }
89
- }
90
- saveConnect() {
91
- return new Promise((resolve, reject) => {
92
- if (this.isConnected()) {
93
- this.opening = false;
94
- return resolve(true);
95
- }
96
- this.connect();
97
- const timeoutStart = this.settings.timeoutStart || TIMEOUT_START;
98
- const tTimeout = Date.now() + timeoutStart;
99
- const iv = setInterval(() => {
100
- if (this.isConnected()) {
101
- clearInterval(iv);
102
- this.opening = false;
103
- resolve(true);
104
- }
105
- else {
106
- if (this.error) {
107
- clearInterval(iv);
108
- this.cmdBusy = false;
109
- reject(this.error);
110
- return;
111
- }
112
- if (Date.now() > tTimeout) {
113
- clearInterval(iv);
114
- this.opening = false;
115
- this.cmdBusy = false;
116
- reject(new Error('timeout'));
117
- }
118
- }
119
- }, 100);
120
- });
121
- }
122
- close() {
123
- this.logger.logEvent({ message: 'close()', port: this.getPort() });
124
- if (this.closing) {
125
- return;
126
- }
127
- var serialPort = this.sp;
128
- this.closing = true;
129
- if (this.bikeCmdWorker !== undefined) {
130
- clearInterval(this.bikeCmdWorker);
131
- this.bikeCmdWorker = undefined;
132
- }
133
- if (this.queue !== undefined)
134
- this.queue.clear();
135
- let connected = this.connected;
136
- if (connected) {
137
- if (serialPort) {
138
- serialPort.unpipe();
139
- serialPort.flush();
140
- if (this.cmdBusy) {
141
- serialPort.drain(() => {
142
- serialPort.close();
143
- });
144
- }
145
- else {
146
- serialPort.close();
147
- }
148
- }
149
- }
150
- else {
151
- if (serialPort) {
152
- serialPort.close();
153
- }
154
- }
155
- this.cmdBusy = false;
156
- }
157
- saveClose() {
158
- return new Promise((resolve, reject) => {
159
- this.close();
160
- const tTimeout = Date.now() + TIMEOUT_CLOSE;
161
- const iv = setInterval(() => {
162
- if (!this.closing || this.closed) {
163
- clearInterval(iv);
164
- resolve(true);
165
- }
166
- else {
167
- if (Date.now() > tTimeout) {
168
- clearInterval(iv);
169
- this.closing = false;
170
- reject(new Error('timeout'));
171
- }
172
- }
173
- }, 100);
174
- });
175
- }
176
- onPortOpen() {
177
- this.logger.logEvent({ message: "port opened", port: this.getPort() });
178
- this.error = undefined;
179
- this.connected = true;
180
- this.opening = false;
181
- this.closed = false;
182
- if (this.cmdStart !== undefined) {
183
- this.cmdStart = Date.now();
184
- }
185
- this.cmdBusy = false;
186
- }
187
- onPortClose() {
188
- this.logger.logEvent({ message: "port closed", port: this.getPort() });
189
- this.error = undefined;
190
- this.connected = false;
191
- this.closing = false;
192
- this.closed = true;
193
- this.cmdBusy = false;
194
- if (this.queue !== undefined)
195
- this.queue.clear();
196
- }
197
- onPortError(err) {
198
- if (this.closed && !this.opening)
199
- return;
200
- if ((this.closing || this.closed) && (err.message === 'Port is not open' || err.message === 'Writing to COM port (GetOverlappedResult): Operation aborted'))
201
- return;
202
- if (this.opening && (err.message === 'Port is already open' || err.message === 'Port is opening'))
203
- return;
204
- const state = { opening: this.opening, connected: this.connected, closing: this.closing, closed: this.closed, busy: this.cmdBusy };
205
- this.logger.logEvent({ message: "port error:", port: this.getPort(), error: err.message, stack: err.stack, state });
206
- this.error = err;
207
- this.cmdBusy = false;
208
- }
209
- startWorker() {
210
- this.bikeCmdWorker = setInterval(() => {
211
- this.sendDaum8008CommandfromQueue();
212
- }, 50);
213
- }
214
- sendDaum8008CommandfromQueue() {
215
- if (!this.connected || this.closing)
216
- return;
217
- if (this.cmdStart !== undefined && this.error !== undefined) {
218
- if (this.cmdStart !== undefined) {
219
- const cmdInfo = this.cmdCurrent;
220
- var retry = 0;
221
- if (cmdInfo.options !== undefined && cmdInfo.options.retries !== undefined) {
222
- retry = this.cmdCurrent.options.retries;
223
- }
224
- if (cmdInfo.callbackErr !== undefined && retry === 0) {
225
- let cb = cmdInfo.callbackErr;
226
- let error = this.error;
227
- this.cmdBusy = false;
228
- this.cmdCurrent = undefined;
229
- this.cmdStart = undefined;
230
- this.error = undefined;
231
- return cb(500, { message: error });
232
- }
233
- }
234
- }
235
- if (this.connected && this.cmdBusy) {
236
- if (this.cmdCurrent !== undefined && this.cmdCurrent.start !== undefined) {
237
- const cmdInfo = this.cmdCurrent;
238
- const timeout = (cmdInfo.options && cmdInfo.options.timeout) ? cmdInfo.options.timeout : (this.settings.timeoutMessage || TIMEOUT_SEND);
239
- let d = Date.now() - cmdInfo.start;
240
- if (d > timeout) {
241
- this.logger.logEvent({ message: 'sendCommmand:timeout', port: this.getPort() });
242
- const port = this.sp;
243
- port.unpipe();
244
- port.flush();
245
- if (this.cmdCurrent.callbackErr !== undefined) {
246
- let cb = this.cmdCurrent.callbackErr;
247
- this.cmdBusy = false;
248
- this.cmdCurrent = undefined;
249
- this.cmdStart = undefined;
250
- return cb(408, { message: "timeout" });
251
- }
252
- }
253
- }
254
- return;
255
- }
256
- else {
257
- }
258
- if (this.cmdBusy)
259
- return;
260
- if (this.queue === undefined || this.queue.isEmpty()) {
261
- return;
262
- }
263
- const cmd = this.queue.dequeue();
264
- this.send(cmd);
265
- }
266
- sendDaum8008Command(logStr, payload, expected, callback, callbackErr, options) {
267
- let cmdInfo = {
268
- logStr,
269
- payload,
270
- expected,
271
- callback: callback || nop,
272
- callbackErr: callbackErr || nop,
273
- options: options
274
- };
275
- this.queue.enqueue(cmdInfo);
276
- if (this.queue.size() > 1)
277
- this.logger.logEvent({ message: "sendCommand:adding:", cmd: logStr, hex: (0, utils_1.hexstr)(payload), queueSize: this.queue.size() });
278
- if (this.bikeCmdWorker === undefined) {
279
- this.startWorker();
280
- }
281
- }
282
- send(cmdInfo) {
283
- this.cmdBusy = true;
284
- this.cmdCurrent = cmdInfo;
285
- const { logStr, payload, expected, callback, callbackErr } = cmdInfo;
286
- const done = () => {
287
- this.cmdBusy = false;
288
- this.cmdCurrent = undefined;
289
- this.cmdStart = undefined;
290
- };
291
- try {
292
- const serialPort = this.sp;
293
- const parser = serialPort.pipe(new ByteLength({ length: expected }));
294
- parser.on('data', (data) => {
295
- let duration = Date.now() - this.cmdStart;
296
- this.logger.logEvent({ message: "sendCommand:received:", duration, hex: (0, utils_1.hexstr)(data), port: this.getPort() });
297
- serialPort.unpipe();
298
- if (callbackErr !== undefined) {
299
- if (data[0] !== payload[0]) {
300
- serialPort.flush();
301
- this.logger.logEvent({ message: "sendCommand:illegal response", port: this.getPort() });
302
- done();
303
- return callbackErr(512, { message: "illegal response" });
304
- }
305
- }
306
- callback(data);
307
- done();
308
- });
309
- this.logger.logEvent({ message: "sendCommand:sending:", cmd: logStr, hex: (0, utils_1.hexstr)(payload), port: this.getPort() });
310
- this.cmdCurrent.start = this.cmdStart = Date.now();
311
- serialPort.write(payload);
312
- }
313
- catch (err) {
314
- this.logger.logEvent({ message: "sendCommand:error:", error: err.message, port: this.getPort() });
315
- done();
316
- callbackErr(500, { message: `Exception: ${err.message}` });
317
- }
318
- }
319
- checkCockpit(bikeNo = 0) {
320
- return new Promise((resolve, reject) => {
321
- this.sendDaum8008Command(`checkCockpit(${bikeNo})`, [0x10, bikeNo], 3, (data) => resolve({ bike: data[1], version: data[2] }), (status, err) => {
322
- if (status === 408)
323
- return resolve({ bike: bikeNo, version: undefined });
324
- reject((0, utils_1.buildError)(status, err));
325
- });
326
- });
327
- }
328
- getAddress() {
329
- return new Promise((resolve, reject) => {
330
- this.sendDaum8008Command(`getAddress()`, [0x11], 2, (data) => resolve({ bike: data[1] }), (status, err) => reject((0, utils_1.buildError)(status, err)));
331
- });
332
- }
333
- getVersion(bikeNo = 0) {
334
- return new Promise((resolve, reject) => {
335
- 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)));
336
- });
337
- }
338
- resetDevice(bikeNo = 0) {
339
- return new Promise((resolve, reject) => {
340
- this.sendDaum8008Command(`resetDevice(${bikeNo})`, [0x12, bikeNo], 2, (data) => resolve({}), (status, err) => reject((0, utils_1.buildError)(status, err)));
341
- });
342
- }
343
- startProg(bikeNo = 0) {
344
- return new Promise((resolve, reject) => {
345
- 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)));
346
- });
347
- }
348
- stopProg(bikeNo = 0) {
349
- return new Promise((resolve, reject) => {
350
- 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)));
351
- });
352
- }
353
- setProg(progNo = 0, bikeNo = 0) {
354
- return new Promise((resolve, reject) => {
355
- 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)));
356
- });
357
- }
358
- setBikeType(bikeType, bikeNo = 0) {
359
- const bikeVal = (0, utils_1.getBikeType)(bikeType);
360
- return new Promise((resolve, reject) => {
361
- this.sendDaum8008Command(`setBikeType(${bikeNo},${bikeType})`, [0x69, bikeNo, 0, 0, bikeVal], 3, (data) => resolve({}), (status, err) => reject((0, utils_1.buildError)(status, err)));
362
- });
363
- }
364
- setPerson(user = {}, bikeNo = 0) {
365
- const age = user.age !== undefined ? user.age : utils_1.DEFAULT_AGE;
366
- const gender = (0, utils_1.getGender)(user.sex);
367
- const length = (0, utils_1.getLength)(user.length);
368
- const maxPower = this.settings.maxPower === undefined ? 800 : this.settings.maxPower;
369
- const mUser = user.weight || this.getUserWeight();
370
- const weight = (0, utils_1.getWeight)(mUser) + this.getBikeWeight();
371
- var cmd = [0x24, bikeNo, 0];
372
- cmd.push(age);
373
- cmd.push(gender);
374
- cmd.push(length);
375
- cmd.push(weight);
376
- cmd.push(0);
377
- cmd.push(0);
378
- cmd.push(3);
379
- cmd.push(Math.round(maxPower / 5));
380
- cmd.push(0);
381
- cmd.push(0);
382
- cmd.push(0);
383
- cmd.push(0);
384
- return new Promise((resolve, reject) => {
385
- this.sendDaum8008Command(`setPerson(${bikeNo},${age},${gender},${length},${weight})`, cmd, 16, (data) => {
386
- let ok = true;
387
- cmd.forEach((v, i) => {
388
- if (data[i] !== v) {
389
- if (i === 10 && v >= 160) {
390
- if (data[i] === 0 || data[i] === 80)
391
- return;
392
- }
393
- reject((0, utils_1.buildError)(512, 'illegal response'));
394
- ok = false;
395
- }
396
- });
397
- if (ok)
398
- resolve({ bike: data[1], age, gender, length, weight });
399
- }, (status, err) => reject((0, utils_1.buildError)(status, err)));
400
- });
401
- }
402
- runData(bikeNo = 0) {
403
- return new Promise((resolve, reject) => {
404
- this.sendDaum8008Command(`runData(${bikeNo})`, [0x40, bikeNo], 19, (data) => {
405
- try {
406
- const parsed = (0, utils_1.parseRunData)(data);
407
- resolve(parsed);
408
- }
409
- catch (e) {
410
- reject((0, utils_1.buildError)(500, e));
411
- }
412
- }, (status, err) => reject((0, utils_1.buildError)(status, err)));
413
- });
414
- }
415
- setGear(gear, bikeNo = 0) {
416
- let gearVal = gear;
417
- if (gear === undefined || gear < 1)
418
- gearVal = 1;
419
- if (gear > 28)
420
- gearVal = 28;
421
- return new Promise((resolve, reject) => {
422
- 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)));
423
- });
424
- }
425
- setPower(power, bikeNo = 0) {
426
- return new Promise((resolve, reject) => {
427
- if (power === undefined) {
428
- resolve({});
429
- return;
430
- }
431
- let powerRequest = power;
432
- if (power < 25)
433
- powerRequest = 25;
434
- if (power > 800)
435
- powerRequest = 800;
436
- const powerVal = Math.round(powerRequest / 5);
437
- 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)));
438
- });
439
- }
440
- setSlope(slope, bikeNo = 0) {
441
- return new Promise((resolve, reject) => {
442
- if (slope === undefined) {
443
- resolve({});
444
- return;
445
- }
446
- const cmd = [0x55, bikeNo];
447
- const arr = (0, utils_1.Float32ToIntArray)(slope);
448
- cmd.push(arr[3]);
449
- cmd.push(arr[2]);
450
- cmd.push(arr[1]);
451
- cmd.push(arr[0]);
452
- this.sendDaum8008Command(`setSlope(${bikeNo},${slope})`, cmd, 6, (data) => resolve({ bike: data[1], slope: slope }), (status, err) => reject((0, utils_1.buildError)(status, err)));
453
- });
454
- }
455
- }
456
- exports.default = Daum8008;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const gd_eventlog_1 = require("gd-eventlog");
4
+ const utils_1 = require("./utils");
5
+ const utils_2 = require("../../utils");
6
+ const ByteLength = require('@serialport/parser-byte-length');
7
+ const nop = () => { };
8
+ const TIMEOUT_START = 15000;
9
+ const TIMEOUT_CLOSE = 5000;
10
+ const TIMEOUT_SEND = 2000;
11
+ var __SerialPort = undefined;
12
+ class Daum8008 {
13
+ constructor(opts = {}) {
14
+ this.logger = opts.logger || new gd_eventlog_1.EventLogger('DaumClassic');
15
+ this.portName = opts.port || process.env.COM_PORT;
16
+ this.settings = opts.settings || {};
17
+ this.bikeData = {
18
+ userWeight: utils_1.DEFAULT_USER_WEIGHT,
19
+ bikeWeight: utils_1.DEFAULT_BIKE_WEIGHT,
20
+ maxPower: 800
21
+ };
22
+ this.sp = undefined;
23
+ this.error = undefined;
24
+ this.opening = false;
25
+ this.connected = false;
26
+ this.closing = false;
27
+ this.closed = undefined;
28
+ this.cmdBusy = false;
29
+ this.queue = new utils_2.Queue();
30
+ }
31
+ static setSerialPort(spClass) {
32
+ __SerialPort = spClass;
33
+ }
34
+ static getClassName() {
35
+ return "Daum8008";
36
+ }
37
+ getType() {
38
+ return "DaumClassic";
39
+ }
40
+ getPort() {
41
+ return this.portName;
42
+ }
43
+ isConnected() {
44
+ return this.connected;
45
+ }
46
+ setUser(user, callback) {
47
+ this.logger.logEvent({ message: "setUser()", user });
48
+ if (user)
49
+ this.settings.user = user;
50
+ var cb = callback || nop;
51
+ cb(200, user);
52
+ }
53
+ getUserWeight() {
54
+ if (this.settings && this.settings.user && this.settings.user.weight)
55
+ return (0, utils_1.getWeight)(this.settings.user.weight);
56
+ else
57
+ return (0, utils_1.getWeight)();
58
+ }
59
+ getBikeWeight() {
60
+ if (this.settings && this.settings.weight) {
61
+ let m = this.settings.weight;
62
+ if (m > 0 && m < 20)
63
+ return m;
64
+ }
65
+ return 10;
66
+ }
67
+ connect() {
68
+ this.logger.logEvent({ message: "connect()", port: this.getPort(), sp: (this.sp !== undefined), });
69
+ if (this.closing || this.opening) {
70
+ return;
71
+ }
72
+ try {
73
+ if (this.sp === undefined) {
74
+ const settings = this.settings.port || {};
75
+ settings.autoOpen = false;
76
+ this.sp = new __SerialPort(this.portName, settings);
77
+ this.sp.on('open', () => { this.onPortOpen(); });
78
+ this.sp.on('close', () => { this.onPortClose(); });
79
+ this.sp.on('error', (error) => { this.onPortError(error); });
80
+ }
81
+ this.cmdBusy = true;
82
+ this.opening = true;
83
+ this.closed = undefined;
84
+ this.sp.open();
85
+ }
86
+ catch (err) {
87
+ this.logger.logEvent({ message: "startTraining:error:", error: err.message });
88
+ }
89
+ }
90
+ saveConnect() {
91
+ return new Promise((resolve, reject) => {
92
+ if (this.isConnected()) {
93
+ this.opening = false;
94
+ return resolve(true);
95
+ }
96
+ this.connect();
97
+ const timeoutStart = this.settings.timeoutStart || TIMEOUT_START;
98
+ const tTimeout = Date.now() + timeoutStart;
99
+ const iv = setInterval(() => {
100
+ if (this.isConnected()) {
101
+ clearInterval(iv);
102
+ this.opening = false;
103
+ resolve(true);
104
+ }
105
+ else {
106
+ if (this.error) {
107
+ clearInterval(iv);
108
+ this.cmdBusy = false;
109
+ reject(this.error);
110
+ return;
111
+ }
112
+ if (Date.now() > tTimeout) {
113
+ clearInterval(iv);
114
+ this.opening = false;
115
+ this.cmdBusy = false;
116
+ reject(new Error('timeout'));
117
+ }
118
+ }
119
+ }, 100);
120
+ });
121
+ }
122
+ close() {
123
+ this.logger.logEvent({ message: 'close()', port: this.getPort() });
124
+ if (this.closing) {
125
+ return;
126
+ }
127
+ var serialPort = this.sp;
128
+ this.closing = true;
129
+ if (this.bikeCmdWorker !== undefined) {
130
+ clearInterval(this.bikeCmdWorker);
131
+ this.bikeCmdWorker = undefined;
132
+ }
133
+ if (this.queue !== undefined)
134
+ this.queue.clear();
135
+ let connected = this.connected;
136
+ if (connected) {
137
+ if (serialPort) {
138
+ serialPort.unpipe();
139
+ serialPort.flush();
140
+ if (this.cmdBusy) {
141
+ serialPort.drain(() => {
142
+ serialPort.close();
143
+ });
144
+ }
145
+ else {
146
+ serialPort.close();
147
+ }
148
+ }
149
+ }
150
+ else {
151
+ if (serialPort) {
152
+ serialPort.close();
153
+ }
154
+ }
155
+ this.cmdBusy = false;
156
+ }
157
+ saveClose() {
158
+ return new Promise((resolve, reject) => {
159
+ this.close();
160
+ const tTimeout = Date.now() + TIMEOUT_CLOSE;
161
+ const iv = setInterval(() => {
162
+ if (!this.closing || this.closed) {
163
+ clearInterval(iv);
164
+ resolve(true);
165
+ }
166
+ else {
167
+ if (Date.now() > tTimeout) {
168
+ clearInterval(iv);
169
+ this.closing = false;
170
+ reject(new Error('timeout'));
171
+ }
172
+ }
173
+ }, 100);
174
+ });
175
+ }
176
+ onPortOpen() {
177
+ this.logger.logEvent({ message: "port opened", port: this.getPort() });
178
+ this.error = undefined;
179
+ this.connected = true;
180
+ this.opening = false;
181
+ this.closed = false;
182
+ if (this.cmdStart !== undefined) {
183
+ this.cmdStart = Date.now();
184
+ }
185
+ this.cmdBusy = false;
186
+ }
187
+ onPortClose() {
188
+ this.logger.logEvent({ message: "port closed", port: this.getPort() });
189
+ this.error = undefined;
190
+ this.connected = false;
191
+ this.closing = false;
192
+ this.closed = true;
193
+ this.cmdBusy = false;
194
+ if (this.queue !== undefined)
195
+ this.queue.clear();
196
+ }
197
+ onPortError(err) {
198
+ if (this.closed && !this.opening)
199
+ return;
200
+ if ((this.closing || this.closed) && (err.message === 'Port is not open' || err.message === 'Writing to COM port (GetOverlappedResult): Operation aborted'))
201
+ return;
202
+ if (this.opening && (err.message === 'Port is already open' || err.message === 'Port is opening'))
203
+ return;
204
+ const state = { opening: this.opening, connected: this.connected, closing: this.closing, closed: this.closed, busy: this.cmdBusy };
205
+ this.logger.logEvent({ message: "port error:", port: this.getPort(), error: err.message, stack: err.stack, state });
206
+ this.error = err;
207
+ this.cmdBusy = false;
208
+ }
209
+ startWorker() {
210
+ this.bikeCmdWorker = setInterval(() => {
211
+ this.sendDaum8008CommandfromQueue();
212
+ }, 50);
213
+ }
214
+ sendDaum8008CommandfromQueue() {
215
+ if (!this.connected || this.closing)
216
+ return;
217
+ if (this.cmdStart !== undefined && this.error !== undefined) {
218
+ if (this.cmdStart !== undefined) {
219
+ const cmdInfo = this.cmdCurrent;
220
+ var retry = 0;
221
+ if (cmdInfo.options !== undefined && cmdInfo.options.retries !== undefined) {
222
+ retry = this.cmdCurrent.options.retries;
223
+ }
224
+ if (cmdInfo.callbackErr !== undefined && retry === 0) {
225
+ let cb = cmdInfo.callbackErr;
226
+ let error = this.error;
227
+ this.cmdBusy = false;
228
+ this.cmdCurrent = undefined;
229
+ this.cmdStart = undefined;
230
+ this.error = undefined;
231
+ return cb(500, { message: error });
232
+ }
233
+ }
234
+ }
235
+ if (this.connected && this.cmdBusy) {
236
+ if (this.cmdCurrent !== undefined && this.cmdCurrent.start !== undefined) {
237
+ const cmdInfo = this.cmdCurrent;
238
+ const timeout = (cmdInfo.options && cmdInfo.options.timeout) ? cmdInfo.options.timeout : (this.settings.timeoutMessage || TIMEOUT_SEND);
239
+ let d = Date.now() - cmdInfo.start;
240
+ if (d > timeout) {
241
+ this.logger.logEvent({ message: 'sendCommmand:timeout', port: this.getPort() });
242
+ const port = this.sp;
243
+ port.unpipe();
244
+ port.flush();
245
+ if (this.cmdCurrent.callbackErr !== undefined) {
246
+ let cb = this.cmdCurrent.callbackErr;
247
+ this.cmdBusy = false;
248
+ this.cmdCurrent = undefined;
249
+ this.cmdStart = undefined;
250
+ return cb(408, { message: "timeout" });
251
+ }
252
+ }
253
+ }
254
+ return;
255
+ }
256
+ else {
257
+ }
258
+ if (this.cmdBusy)
259
+ return;
260
+ if (this.queue === undefined || this.queue.isEmpty()) {
261
+ return;
262
+ }
263
+ const cmd = this.queue.dequeue();
264
+ this.send(cmd);
265
+ }
266
+ sendDaum8008Command(logStr, payload, expected, callback, callbackErr, options) {
267
+ let cmdInfo = {
268
+ logStr,
269
+ payload,
270
+ expected,
271
+ callback: callback || nop,
272
+ callbackErr: callbackErr || nop,
273
+ options: options
274
+ };
275
+ this.queue.enqueue(cmdInfo);
276
+ if (this.queue.size() > 1)
277
+ this.logger.logEvent({ message: "sendCommand:adding:", cmd: logStr, hex: (0, utils_1.hexstr)(payload), queueSize: this.queue.size() });
278
+ if (this.bikeCmdWorker === undefined) {
279
+ this.startWorker();
280
+ }
281
+ }
282
+ send(cmdInfo) {
283
+ this.cmdBusy = true;
284
+ this.cmdCurrent = cmdInfo;
285
+ const { logStr, payload, expected, callback, callbackErr } = cmdInfo;
286
+ const done = () => {
287
+ this.cmdBusy = false;
288
+ this.cmdCurrent = undefined;
289
+ this.cmdStart = undefined;
290
+ };
291
+ try {
292
+ const serialPort = this.sp;
293
+ const parser = serialPort.pipe(new ByteLength({ length: expected }));
294
+ parser.on('data', (data) => {
295
+ let duration = Date.now() - this.cmdStart;
296
+ this.logger.logEvent({ message: "sendCommand:received:", duration, hex: (0, utils_1.hexstr)(data), port: this.getPort() });
297
+ serialPort.unpipe();
298
+ if (callbackErr !== undefined) {
299
+ if (data[0] !== payload[0]) {
300
+ serialPort.flush();
301
+ this.logger.logEvent({ message: "sendCommand:illegal response", port: this.getPort() });
302
+ done();
303
+ return callbackErr(512, { message: "illegal response" });
304
+ }
305
+ }
306
+ callback(data);
307
+ done();
308
+ });
309
+ this.logger.logEvent({ message: "sendCommand:sending:", cmd: logStr, hex: (0, utils_1.hexstr)(payload), port: this.getPort() });
310
+ this.cmdCurrent.start = this.cmdStart = Date.now();
311
+ serialPort.write(payload);
312
+ }
313
+ catch (err) {
314
+ this.logger.logEvent({ message: "sendCommand:error:", error: err.message, port: this.getPort() });
315
+ done();
316
+ callbackErr(500, { message: `Exception: ${err.message}` });
317
+ }
318
+ }
319
+ checkCockpit(bikeNo = 0) {
320
+ return new Promise((resolve, reject) => {
321
+ this.sendDaum8008Command(`checkCockpit(${bikeNo})`, [0x10, bikeNo], 3, (data) => resolve({ bike: data[1], version: data[2] }), (status, err) => {
322
+ if (status === 408)
323
+ return resolve({ bike: bikeNo, version: undefined });
324
+ reject((0, utils_1.buildError)(status, err));
325
+ });
326
+ });
327
+ }
328
+ getAddress() {
329
+ return new Promise((resolve, reject) => {
330
+ this.sendDaum8008Command(`getAddress()`, [0x11], 2, (data) => resolve({ bike: data[1] }), (status, err) => reject((0, utils_1.buildError)(status, err)));
331
+ });
332
+ }
333
+ getVersion(bikeNo = 0) {
334
+ return new Promise((resolve, reject) => {
335
+ 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)));
336
+ });
337
+ }
338
+ resetDevice(bikeNo = 0) {
339
+ return new Promise((resolve, reject) => {
340
+ this.sendDaum8008Command(`resetDevice(${bikeNo})`, [0x12, bikeNo], 2, (data) => resolve({}), (status, err) => reject((0, utils_1.buildError)(status, err)));
341
+ });
342
+ }
343
+ startProg(bikeNo = 0) {
344
+ return new Promise((resolve, reject) => {
345
+ 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)));
346
+ });
347
+ }
348
+ stopProg(bikeNo = 0) {
349
+ return new Promise((resolve, reject) => {
350
+ 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)));
351
+ });
352
+ }
353
+ setProg(progNo = 0, bikeNo = 0) {
354
+ return new Promise((resolve, reject) => {
355
+ 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)));
356
+ });
357
+ }
358
+ setBikeType(bikeType, bikeNo = 0) {
359
+ const bikeVal = (0, utils_1.getBikeType)(bikeType);
360
+ return new Promise((resolve, reject) => {
361
+ this.sendDaum8008Command(`setBikeType(${bikeNo},${bikeType})`, [0x69, bikeNo, 0, 0, bikeVal], 3, (data) => resolve({}), (status, err) => reject((0, utils_1.buildError)(status, err)));
362
+ });
363
+ }
364
+ setPerson(user = {}, bikeNo = 0) {
365
+ const age = user.age !== undefined ? user.age : utils_1.DEFAULT_AGE;
366
+ const gender = (0, utils_1.getGender)(user.sex);
367
+ const length = (0, utils_1.getLength)(user.length);
368
+ const maxPower = this.settings.maxPower === undefined ? 800 : this.settings.maxPower;
369
+ const mUser = user.weight || this.getUserWeight();
370
+ const weight = (0, utils_1.getWeight)(mUser) + this.getBikeWeight();
371
+ var cmd = [0x24, bikeNo, 0];
372
+ cmd.push(age);
373
+ cmd.push(gender);
374
+ cmd.push(length);
375
+ cmd.push(weight);
376
+ cmd.push(0);
377
+ cmd.push(0);
378
+ cmd.push(3);
379
+ cmd.push(Math.round(maxPower / 5));
380
+ cmd.push(0);
381
+ cmd.push(0);
382
+ cmd.push(0);
383
+ cmd.push(0);
384
+ return new Promise((resolve, reject) => {
385
+ this.sendDaum8008Command(`setPerson(${bikeNo},${age},${gender},${length},${weight})`, cmd, 16, (data) => {
386
+ let ok = true;
387
+ cmd.forEach((v, i) => {
388
+ if (data[i] !== v) {
389
+ if (i === 10 && v >= 160) {
390
+ if (data[i] === 0 || data[i] === 80)
391
+ return;
392
+ }
393
+ reject((0, utils_1.buildError)(512, 'illegal response'));
394
+ ok = false;
395
+ }
396
+ });
397
+ if (ok)
398
+ resolve({ bike: data[1], age, gender, length, weight });
399
+ }, (status, err) => reject((0, utils_1.buildError)(status, err)));
400
+ });
401
+ }
402
+ runData(bikeNo = 0) {
403
+ return new Promise((resolve, reject) => {
404
+ this.sendDaum8008Command(`runData(${bikeNo})`, [0x40, bikeNo], 19, (data) => {
405
+ try {
406
+ const parsed = (0, utils_1.parseRunData)(data);
407
+ resolve(parsed);
408
+ }
409
+ catch (e) {
410
+ reject((0, utils_1.buildError)(500, e));
411
+ }
412
+ }, (status, err) => reject((0, utils_1.buildError)(status, err)));
413
+ });
414
+ }
415
+ setGear(gear, bikeNo = 0) {
416
+ let gearVal = gear;
417
+ if (gear === undefined || gear < 1)
418
+ gearVal = 1;
419
+ if (gear > 28)
420
+ gearVal = 28;
421
+ return new Promise((resolve, reject) => {
422
+ 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)));
423
+ });
424
+ }
425
+ setPower(power, bikeNo = 0) {
426
+ return new Promise((resolve, reject) => {
427
+ if (power === undefined) {
428
+ resolve({});
429
+ return;
430
+ }
431
+ let powerRequest = power;
432
+ if (power < 25)
433
+ powerRequest = 25;
434
+ if (power > 800)
435
+ powerRequest = 800;
436
+ const powerVal = Math.round(powerRequest / 5);
437
+ 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)));
438
+ });
439
+ }
440
+ setSlope(slope, bikeNo = 0) {
441
+ return new Promise((resolve, reject) => {
442
+ if (slope === undefined) {
443
+ resolve({});
444
+ return;
445
+ }
446
+ const cmd = [0x55, bikeNo];
447
+ const arr = (0, utils_1.Float32ToIntArray)(slope);
448
+ cmd.push(arr[3]);
449
+ cmd.push(arr[2]);
450
+ cmd.push(arr[1]);
451
+ cmd.push(arr[0]);
452
+ this.sendDaum8008Command(`setSlope(${bikeNo},${slope})`, cmd, 6, (data) => resolve({ bike: data[1], slope: slope }), (status, err) => reject((0, utils_1.buildError)(status, err)));
453
+ });
454
+ }
455
+ }
456
+ exports.default = Daum8008;