incyclist-devices 1.5.10 → 1.5.12

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