incyclist-devices 1.5.30 → 1.5.32

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.
@@ -217,6 +217,8 @@ class DaumAdapterBase extends device_1.default {
217
217
  clearInterval(this.iv.update);
218
218
  this.iv = undefined;
219
219
  }
220
+ if (this.bike.stopWorker && typeof (this.bike.stopWorker) === 'function')
221
+ this.bike.stopWorker();
220
222
  this.logEvent({ message: 'stop request completed' });
221
223
  this.paused = undefined;
222
224
  resolve(true);
@@ -150,6 +150,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
150
150
  let startState = {};
151
151
  return (0, utils_1.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () {
152
152
  try {
153
+ this.logger.logEvent({ message: 'start attempt', udid: this.udid, isRelaunch, isConnected: this.bike.isConnected() });
153
154
  if (!isRelaunch && !this.bike.isConnected())
154
155
  yield this.bike.saveConnect();
155
156
  yield this.getBike().resetDevice();
@@ -187,6 +188,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
187
188
  return data;
188
189
  }
189
190
  catch (err) {
191
+ this.logger.logEvent({ message: 'start attempt failed', udid: this.udid, error: err.message });
190
192
  if (startState.checkRunData) {
191
193
  startState = {};
192
194
  }
@@ -48,6 +48,7 @@ export default class Daum8008 {
48
48
  onPortClose(): void;
49
49
  onPortError(err: any): void;
50
50
  startWorker(): void;
51
+ stopWorker(): void;
51
52
  sendDaum8008CommandfromQueue(): any;
52
53
  sendDaum8008Command(logStr: any, payload: any, expected: any, callback?: any, callbackErr?: any, options?: any): void;
53
54
  send(cmdInfo: any): void;
@@ -139,12 +139,7 @@ class Daum8008 {
139
139
  }
140
140
  var serialPort = this.sp;
141
141
  this.closing = true;
142
- if (this.bikeCmdWorker !== undefined) {
143
- clearInterval(this.bikeCmdWorker);
144
- this.bikeCmdWorker = undefined;
145
- }
146
- if (this.queue !== undefined)
147
- this.queue.clear();
142
+ this.stopWorker();
148
143
  let connected = this.connected;
149
144
  if (connected) {
150
145
  if (serialPort) {
@@ -224,6 +219,16 @@ class Daum8008 {
224
219
  this.sendDaum8008CommandfromQueue();
225
220
  }, 50);
226
221
  }
222
+ stopWorker() {
223
+ if (this.queue !== undefined)
224
+ this.queue.clear();
225
+ if (this.bikeCmdWorker !== undefined) {
226
+ clearInterval(this.bikeCmdWorker);
227
+ this.bikeCmdWorker = undefined;
228
+ }
229
+ if (this.queue !== undefined)
230
+ this.queue.clear();
231
+ }
227
232
  sendDaum8008CommandfromQueue() {
228
233
  if (!this.connected || this.closing)
229
234
  return;
@@ -60,16 +60,18 @@ declare class Daum8i {
60
60
  waitingForAck: any;
61
61
  retry: any;
62
62
  };
63
- onPortError(error: any): void;
63
+ onPortError(error: any): Promise<void>;
64
64
  errorHandler(): void;
65
- saveClose(force?: any): Promise<unknown>;
66
- forceClose(updateState?: boolean): void;
67
- close(): void;
65
+ saveClose(force?: any): Promise<void>;
66
+ forceClose(updateState?: boolean): Promise<void>;
67
+ closePort(timeout: any): Promise<boolean>;
68
+ close(): Promise<void>;
68
69
  sendTimeout(message: any): void;
69
70
  checkForResponse(): boolean;
70
71
  getTimeoutValue(cmd?: any): number;
71
- onData(data: any): any;
72
+ onData(data: any, depth?: number): any;
72
73
  sendDaum8iCommand(command: any, queryType: any, payload: any): Promise<unknown>;
74
+ writeDone(): void;
73
75
  sendACK(): void;
74
76
  sendNAK(): void;
75
77
  sendReservedDaum8iCommand(command: ReservedCommands, cmdType: any, data?: Buffer): Promise<any[]>;
@@ -127,12 +127,7 @@ class Daum8i {
127
127
  this.state.commandsInQueue = {};
128
128
  try {
129
129
  if (this.sp !== undefined) {
130
- try {
131
- this.sp.removeAllListeners();
132
- yield this.sp.close();
133
- }
134
- catch (err) {
135
- }
130
+ yield this.forceClose();
136
131
  this.sp = undefined;
137
132
  }
138
133
  if (this.sp === undefined) {
@@ -148,8 +143,8 @@ class Daum8i {
148
143
  this.logEvent({ message: "creating SerialPort", port: this.port, settings });
149
144
  this.sp = new __SerialPort(this.port, settings);
150
145
  }
151
- this.sp.on('open', this.onPortOpen.bind(this));
152
- this.sp.on('close', this.onPortClose.bind(this));
146
+ this.sp.once('open', this.onPortOpen.bind(this));
147
+ this.sp.once('close', this.onPortClose.bind(this));
153
148
  this.sp.on('error', (error) => { this.onPortError(error); });
154
149
  this.sp.on('data', (data) => { this.onData(data); });
155
150
  }
@@ -185,13 +180,12 @@ class Daum8i {
185
180
  }
186
181
  catch (_a) { }
187
182
  const tTimeout = Date.now() + TIMEOUT_START;
188
- const iv = setInterval(() => {
183
+ const iv = setInterval(() => __awaiter(this, void 0, void 0, function* () {
189
184
  try {
190
185
  if (this.state.error !== undefined) {
191
186
  clearInterval(iv);
192
- this.forceClose();
187
+ yield this.forceClose();
193
188
  reject(this.state.error);
194
- this.state = { opened: false, closed: true, busy: false };
195
189
  }
196
190
  else if (this.isConnected()) {
197
191
  this.state.connecting = false;
@@ -201,14 +195,14 @@ class Daum8i {
201
195
  else {
202
196
  if (Date.now() > tTimeout) {
203
197
  this.state.connecting = false;
204
- this.forceClose();
198
+ yield this.forceClose();
205
199
  clearInterval(iv);
206
200
  reject(new Error('timeout'));
207
201
  }
208
202
  }
209
203
  }
210
- catch (_a) { }
211
- }, 100);
204
+ catch (_b) { }
205
+ }), 100);
212
206
  }));
213
207
  }
214
208
  onPortOpen() {
@@ -246,116 +240,128 @@ class Daum8i {
246
240
  return { sending: s, busy, writeBusy, opening, connecting, waitingForStart, waitingForEnd, waitingForAck, retry };
247
241
  }
248
242
  onPortError(error) {
249
- this.logEvent({ message: "port error:", port: this.portName, error: error.message, connected: this.connected, state: this.getLogState() });
250
- this.error = error;
251
- if (this.blocked) {
252
- if (!this.state.closed) {
253
- try {
254
- if (this.sp) {
255
- this.sp.removeAllListeners();
256
- this.sp.close();
257
- this.sp = undefined;
258
- }
243
+ return __awaiter(this, void 0, void 0, function* () {
244
+ this.logEvent({ message: "port error:", port: this.portName, error: error.message, connected: this.connected, state: this.getLogState() });
245
+ this.error = error;
246
+ if (this.blocked) {
247
+ if (!this.state.closed) {
248
+ yield this.forceClose();
259
249
  }
260
- catch (_a) { }
261
- this.state = { opened: false, closed: true, busy: false };
262
- }
263
- return;
264
- }
265
- if (this.state.closing) {
266
- if (error.message === 'Port is not open') {
267
- this.state = { opened: false, closed: true, busy: false };
268
250
  return;
269
251
  }
270
- else {
271
- this.forceClose();
252
+ if (this.state.closing) {
253
+ if (error.message === 'Port is not open') {
254
+ this.state = { opened: false, closed: true, busy: false };
255
+ return;
256
+ }
257
+ else {
258
+ yield this.forceClose();
259
+ }
272
260
  }
273
- }
274
- else if (this.state.opening) {
275
- if (this.state.connecting) {
276
- this.state.error = error;
261
+ else if (this.state.opening) {
262
+ if (this.state.connecting) {
263
+ this.state.error = error;
264
+ }
265
+ else {
266
+ this.onPortOpen();
267
+ }
277
268
  }
278
- else {
279
- this.onPortOpen();
269
+ else if (this.state.sending) {
270
+ if (this.state.sending.reject)
271
+ this.state.sending.reject(error);
272
+ this.writeDone();
273
+ yield this.forceClose(false);
274
+ return;
280
275
  }
281
- }
282
- else if (this.state.sending) {
283
- this.state.error = error;
284
- this.forceClose(false);
285
- return;
286
- }
287
- this.state.busy = false;
276
+ this.state.busy = false;
277
+ });
288
278
  }
289
279
  errorHandler() {
290
280
  throw new Error("Error");
291
281
  }
292
282
  saveClose(force) {
293
- return new Promise((resolve, reject) => {
294
- if (force)
295
- this.blocked = true;
296
- this.close();
297
- const start = Date.now();
298
- const iv = setInterval(() => {
299
- if (this.state.closed || (Date.now() - start > DEFAULT_TIMEOUT)) {
300
- clearInterval(iv);
301
- resolve(true);
302
- return;
303
- }
304
- }, 50);
283
+ return __awaiter(this, void 0, void 0, function* () {
284
+ return yield this.close();
305
285
  });
306
286
  }
307
287
  forceClose(updateState = false) {
308
- const sp = this.sp;
309
- if (!this.sp)
310
- return;
311
- this.sp.removeAllListeners();
312
- try {
313
- sp.unpipe();
314
- sp.flush();
315
- }
316
- catch (_a) { }
317
- try {
318
- sp.close();
319
- }
320
- catch (_b) { }
321
- this.connected = false;
322
- if (updateState)
323
- this.state = { opened: false, closed: true, busy: false };
288
+ return __awaiter(this, void 0, void 0, function* () {
289
+ const sp = this.sp;
290
+ if (!this.sp)
291
+ return;
292
+ this.state.closing = true;
293
+ sp.removeAllListeners();
294
+ sp.on('error', () => { });
295
+ try {
296
+ sp.unpipe();
297
+ sp.flush();
298
+ }
299
+ catch (_a) { }
300
+ try {
301
+ yield this.closePort(1000);
302
+ this.writeDone();
303
+ if (this.queue !== undefined)
304
+ this.queue.clear();
305
+ }
306
+ catch (_b) { }
307
+ this.connected = false;
308
+ if (updateState)
309
+ this.state = { opened: false, closed: true, busy: false };
310
+ });
311
+ }
312
+ closePort(timeout) {
313
+ return __awaiter(this, void 0, void 0, function* () {
314
+ return new Promise((resolve, reject) => {
315
+ let isClosed = false;
316
+ const to = setTimeout(() => {
317
+ if (!isClosed)
318
+ resolve(false);
319
+ }, timeout);
320
+ this.sp.removeAllListeners('close');
321
+ this.sp.removeAllListeners('error');
322
+ this.sp.on('error', () => { });
323
+ this.sp.once('close', () => {
324
+ clearTimeout(to);
325
+ isClosed = true;
326
+ resolve(true);
327
+ });
328
+ this.sp.close();
329
+ });
330
+ });
324
331
  }
325
332
  close() {
326
- this.logEvent({ message: 'close request', port: this.portName });
327
- var sp = this.sp;
328
- let connected = this.connected;
329
- try {
330
- if (connected) {
331
- if (sp) {
332
- sp.unpipe();
333
- sp.flush();
334
- sp.close();
333
+ return __awaiter(this, void 0, void 0, function* () {
334
+ this.logEvent({ message: 'close request', port: this.portName });
335
+ var sp = this.sp;
336
+ if (!sp) {
337
+ this.state = { opened: false, closed: true, busy: false };
338
+ this.connected = false;
339
+ return;
340
+ }
341
+ let connected = this.connected;
342
+ try {
343
+ if (connected) {
344
+ try {
345
+ sp.removeAllListeners();
346
+ sp.on('error', () => { });
347
+ sp.unpipe();
348
+ sp.flush();
349
+ }
350
+ catch (_a) { }
335
351
  }
352
+ yield this.closePort(this.getTimeoutValue());
353
+ this.writeDone();
336
354
  if (this.queue !== undefined) {
337
355
  this.queue.clear();
338
356
  this.queue = undefined;
339
357
  }
340
358
  }
341
- else {
342
- if (sp)
343
- sp.close();
359
+ catch (err) {
360
+ this.logEvent({ message: 'close: Exception', port: this.portName, error: err.message });
344
361
  }
345
- }
346
- catch (err) {
347
- this.logEvent({ message: 'close: Exception', port: this.portName, error: err.message });
348
- }
349
- this.connected = false;
350
- const start = Date.now();
351
- if (this.state.closing === undefined)
352
- this.state.closing = { start, timeout: start + this.getTimeoutValue(), retry: 0, maxRetries: MAX_RETRIES };
353
- else {
354
- this.state.closing.start = start;
355
- this.state.closing.timeout = start + this.getTimeoutValue();
356
- this.state.retry = this.state.retry + 1;
357
- }
358
- this.state.busy = false;
362
+ this.state = { opened: false, closed: true, busy: false };
363
+ this.connected = false;
364
+ });
359
365
  }
360
366
  sendTimeout(message) {
361
367
  this.logEvent({ message: `sendCommand:${message || 'timeout'}`, port: this.portName, cmd: this.cmdCurrent });
@@ -413,29 +419,21 @@ class Daum8i {
413
419
  }
414
420
  return timeout;
415
421
  }
416
- onData(data) {
422
+ onData(data, depth = 0) {
417
423
  let cmd = '';
424
+ const MAX_DEPTH = 5;
418
425
  if (this.state.waitingForEnd) {
419
426
  cmd = this.state.partialCmd;
420
427
  }
421
428
  const bufferData = Buffer.isBuffer(data) ? data : Buffer.from(data, 'latin1');
422
429
  const s = this.state.sending;
423
430
  if (s === undefined) {
424
- if (this.state.input === undefined)
425
- this.state.input = bufferData;
431
+ this.logEvent({ message: 'onData:IGNORED', data: bufferData.toString('hex') });
426
432
  return;
427
433
  }
428
434
  const { portName, resolve } = this.state.sending;
429
- let incoming;
430
- if (this.state.input !== undefined) {
431
- const arr = [this.state.input, bufferData];
432
- incoming = Buffer.concat(arr);
433
- }
434
- else {
435
- incoming = bufferData;
436
- }
437
- const response = [...incoming];
438
- this.logEvent({ message: 'sendCommand:RECV', data: (0, utils_1.hexstr)(response) });
435
+ let incoming = bufferData;
436
+ this.logEvent({ message: 'sendCommand:RECV', data: (0, utils_1.hexstr)(incoming) });
439
437
  for (let i = 0; i < incoming.length; i++) {
440
438
  const getRemaining = () => {
441
439
  let remaining = '';
@@ -448,53 +446,59 @@ class Daum8i {
448
446
  };
449
447
  const c = incoming.readUInt8(i);
450
448
  if (c === 0x06) {
451
- this.logEvent({ message: "sendCommand:ACK received:", port: portName });
452
449
  this.state.waitingForStart = true;
453
450
  this.state.waitingForACK = false;
454
451
  const remaining = getRemaining();
455
- if (remaining && remaining !== '')
456
- return this.onData(remaining);
452
+ this.logEvent({ message: "sendCommand:ACK received:", port: portName, remaining: (0, utils_1.hexstr)(remaining) });
453
+ if (remaining && remaining !== '' && depth < MAX_DEPTH)
454
+ return this.onData(remaining, depth + 1);
457
455
  }
458
456
  else if (c === 0x15) {
459
457
  this.state.waitingForStart = true;
460
458
  this.state.waitingForACK = false;
461
- this.logEvent({ message: "sendCommand:NAK received:", port: portName });
462
459
  const remaining = getRemaining();
463
- if (remaining && remaining !== '')
464
- return this.onData(remaining);
460
+ this.logEvent({ message: "sendCommand:NAK received:", port: portName, remaining: (0, utils_1.hexstr)(remaining) });
461
+ if (remaining && remaining !== '' && depth < MAX_DEPTH)
462
+ return this.onData(remaining, depth + 1);
465
463
  }
466
464
  else if (c === 0x01) {
467
465
  this.state.waitingForEnd = true;
468
466
  }
469
467
  else if (c === 0x17) {
470
468
  const remaining = getRemaining();
471
- this.logEvent({ message: "sendCommand:received:", duration: Date.now() - this.state.sending.tsRequest, port: portName, cmd: `${cmd} [${(0, utils_1.hexstr)(cmd)}]`, remaining: (0, utils_1.hexstr)(remaining) });
472
- this.state.waitingForEnd = false;
473
- const cmdStr = cmd.substring(0, cmd.length - 2);
474
- const checksumExtracted = cmd.slice(-2);
475
- const checksumCalculated = (0, utils_1.checkSum)((0, utils_1.getAsciiArrayFromStr)(cmdStr), []);
476
- if (checksumExtracted === checksumCalculated) {
477
- this.sendACK();
478
- if (this.state.sending && this.state.sending.responseCheckIv) {
479
- clearInterval(this.state.sending.responseCheckIv);
480
- }
481
- this.state = {
482
- sending: undefined,
483
- busy: false,
484
- writeBusy: false,
485
- waitingForStart: false,
486
- waitingForEnd: false,
487
- waitingForACK: false,
488
- };
489
- const payload = cmd.substring(3, cmd.length - 2);
490
- resolve(payload);
469
+ if (this.state.waitingForACK) {
470
+ this.logEvent({ message: "sendCommand:ignored:", duration: Date.now() - this.state.sending.tsRequest, port: portName, cmd: `${cmd} [${(0, utils_1.hexstr)(cmd)}]`, remaining: (0, utils_1.hexstr)(remaining) });
471
+ this.state.waitingForEnd = false;
491
472
  }
492
473
  else {
493
- this.sendNAK();
474
+ this.logEvent({ message: "sendCommand:received:", duration: Date.now() - this.state.sending.tsRequest, port: portName, cmd: `${cmd} [${(0, utils_1.hexstr)(cmd)}]`, remaining: (0, utils_1.hexstr)(remaining) });
475
+ this.state.waitingForEnd = false;
476
+ const cmdStr = cmd.substring(0, cmd.length - 2);
477
+ const checksumExtracted = cmd.slice(-2);
478
+ const checksumCalculated = (0, utils_1.checkSum)((0, utils_1.getAsciiArrayFromStr)(cmdStr), []);
479
+ if (checksumExtracted === checksumCalculated) {
480
+ this.sendACK();
481
+ if (this.state.sending && this.state.sending.responseCheckIv) {
482
+ clearInterval(this.state.sending.responseCheckIv);
483
+ }
484
+ this.state = {
485
+ sending: undefined,
486
+ busy: false,
487
+ writeBusy: false,
488
+ waitingForStart: false,
489
+ waitingForEnd: false,
490
+ waitingForACK: false,
491
+ };
492
+ const payload = cmd.substring(3, cmd.length - 2);
493
+ resolve(payload);
494
+ }
495
+ else {
496
+ this.sendNAK();
497
+ }
494
498
  }
495
499
  cmd = '';
496
- if (remaining)
497
- return this.onData(remaining);
500
+ if (remaining && depth < 5)
501
+ return this.onData(remaining, depth + 1);
498
502
  }
499
503
  else {
500
504
  if (this.state.waitingForEnd)
@@ -541,15 +545,6 @@ class Daum8i {
541
545
  }
542
546
  this.state.busy = true;
543
547
  }
544
- const writeDone = () => {
545
- this.state.sending = undefined;
546
- this.state.writeBusy = false;
547
- this.state.busy = false;
548
- this.state.sending = undefined;
549
- this.state.waitingForStart = false;
550
- this.state.waitingForEnd = false;
551
- this.state.waitingForACK = false;
552
- };
553
548
  const port = this.sp;
554
549
  const portName = this.portName;
555
550
  this.state.received = [];
@@ -561,7 +556,7 @@ class Daum8i {
561
556
  this.state.writeBusy = true;
562
557
  if (!this.connected || port === undefined) {
563
558
  this.logEvent({ message: "sendCommand:error: not connected", port: this.portName });
564
- writeDone();
559
+ this.writeDone();
565
560
  return reject(new Error('not connected'));
566
561
  }
567
562
  port.write(message);
@@ -570,21 +565,33 @@ class Daum8i {
570
565
  this.state.retry = 0;
571
566
  this.state.ack = { start, timeout };
572
567
  this.state.sending = { command, payload, start, timeout, port, portName, tsRequest, resolve, reject };
573
- const iv = this.state.sending.responseCheckIv = setInterval(() => {
568
+ const iv = setInterval(() => {
574
569
  const stillWaiting = this.checkForResponse();
575
570
  if (!stillWaiting) {
576
571
  clearInterval(iv);
577
- writeDone();
572
+ this.writeDone();
578
573
  }
579
574
  }, 10);
575
+ this.state.sending.responseCheckIv = iv;
580
576
  }
581
577
  catch (err) {
582
578
  this.logEvent({ message: "sendCommand:error:", port: portName, error: err.message, stack: err.stack });
583
- writeDone();
579
+ this.writeDone();
584
580
  reject(err);
585
581
  }
586
582
  }));
587
583
  }
584
+ writeDone() {
585
+ this.state.writeBusy = false;
586
+ this.state.busy = false;
587
+ if (this.state.sending && this.state.sending.responseCheckIv) {
588
+ clearInterval(this.state.sending.responseCheckIv);
589
+ }
590
+ this.state.sending = undefined;
591
+ this.state.waitingForStart = false;
592
+ this.state.waitingForEnd = false;
593
+ this.state.waitingForACK = false;
594
+ }
588
595
  sendACK() {
589
596
  const port = this.portName;
590
597
  this.state.writeBusy = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.5.30",
3
+ "version": "1.5.32",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",