incyclist-services 1.0.68 → 1.0.70

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.
@@ -39,7 +39,10 @@ export declare class DeviceRideService extends EventEmitter {
39
39
  startAdapters(adapters: AdapterRideInfo[], startType: 'start' | 'check' | 'pair', props?: RideServiceDeviceProperties): Promise<boolean>;
40
40
  startHealthCheck(ai: AdapterRideInfo): void;
41
41
  stopHealthCheck(ai: AdapterRideInfo): void;
42
- prepareReconnect(down: AdapterRideInfo): Promise<void>;
42
+ prepareReconnect(unhealthy: AdapterRideInfo): Promise<void>;
43
+ private reconnectInterface;
44
+ protected stopAfterRestart(unhealthy: AdapterRideInfo): Promise<void>;
45
+ private reconnectSingle;
43
46
  start(props: RideServiceDeviceProperties): Promise<boolean>;
44
47
  startRetry(props: RideServiceDeviceProperties): Promise<boolean>;
45
48
  cancelStart(): Promise<boolean>;
@@ -476,12 +476,12 @@ class DeviceRideService extends events_1.default {
476
476
  const check = () => {
477
477
  const tsNow = Date.now();
478
478
  const isPaused = ai.adapter.isPaused();
479
+ const prevStatus = ai.dataStatus;
479
480
  if (isPaused || !ai.tsLastData) {
480
481
  ai.tsLastData = tsNow;
481
482
  ai.dataStatus = 'green';
482
483
  return;
483
484
  }
484
- const prevStatus = ai.dataStatus;
485
485
  const isAmber = (tsNow - ai.tsLastData) > NO_DATA_THRESHOLD;
486
486
  const isRed = (tsNow - ai.tsLastData) > UNHEALTHY_THRESHOLD;
487
487
  ai.dataStatus = 'green';
@@ -489,19 +489,19 @@ class DeviceRideService extends events_1.default {
489
489
  ai.dataStatus = 'amber';
490
490
  if (isRed)
491
491
  ai.dataStatus = 'red';
492
- if (ai.isHealthy && isAmber) {
492
+ if (ai.isHealthy && (isAmber || isRed)) {
493
493
  ai.isHealthy = false;
494
494
  this.logEvent({ message: 'device unhealthy', device: ai.adapter.getUniqueName(), udid: ai.udid });
495
- const { enabledCapabilities } = this.getEnabledCapabilities(ai);
496
- this.emit('unhealthy', ai.udid, ai.dataStatus, enabledCapabilities);
497
495
  console.log('~~~~ health check: prepare reconnect');
498
496
  this.prepareReconnect(ai);
499
497
  }
500
- else if (!ai.isHealthy && !isAmber) {
501
- const { enabledCapabilities } = this.getEnabledCapabilities(ai);
498
+ else if (!ai.isHealthy && !isAmber && !isRed) {
502
499
  ai.isHealthy = true;
503
500
  this.logEvent({ message: 'device healthy', device: ai.adapter.getUniqueName(), udid: ai.udid });
504
- this.emit('healthy', ai.udid, ai.dataStatus, enabledCapabilities);
501
+ }
502
+ if (ai.dataStatus !== prevStatus) {
503
+ const { enabledCapabilities } = this.getEnabledCapabilities(ai);
504
+ this.emit('health', ai.udid, ai.dataStatus, enabledCapabilities);
505
505
  }
506
506
  };
507
507
  ai.ivToCheck = (0, timers_1.setInterval)(check, 1000);
@@ -514,75 +514,128 @@ class DeviceRideService extends events_1.default {
514
514
  delete ai.isHealthy;
515
515
  }
516
516
  }
517
- prepareReconnect(down) {
517
+ prepareReconnect(unhealthy) {
518
518
  return __awaiter(this, void 0, void 0, function* () {
519
- if (down.isRestarting)
519
+ if (unhealthy.isRestarting)
520
520
  return;
521
- console.log('~~~~ health check: wait 45s', down.udid);
521
+ console.log('~~~~ health check: wait 45s', unhealthy.udid);
522
522
  yield (0, sleep_1.sleep)(UNHEALTHY_THRESHOLD - NO_DATA_THRESHOLD - 5000);
523
- console.log('~~~~ health check: check if still unhealthy', down.udid, down.isHealthy, down.isRestarting);
524
- if (down.isHealthy || down.isRestarting)
523
+ if (unhealthy.isHealthy || unhealthy.isRestarting)
525
524
  return;
526
- const ifName = down.adapter.getInterface();
525
+ console.log('~~~~ health check: still unhealthy', unhealthy.udid, unhealthy.isHealthy, unhealthy.isRestarting);
526
+ unhealthy.isRestarting = true;
527
+ const ifName = unhealthy.adapter.getInterface();
527
528
  const adapters = this.getAdapterList().filter(ai => ai.adapter.getInterface() === ifName);
528
- down.isRestarting = true;
529
529
  if (!adapters.find(ai => ai.isHealthy)) {
530
- console.log('~~~~ health check: restart interface', ifName);
531
- this.logger.logEvent({ message: 'restart interface', interface: ifName });
532
- const i = incyclist_devices_1.InterfaceFactory.create(ifName);
533
- try {
534
- const promisesStop = [];
535
- adapters.map(ai => {
536
- ai.isRestarting = true;
537
- ai.adapter.off('data', this.deviceDataHandler);
530
+ yield this.reconnectInterface(ifName, adapters);
531
+ }
532
+ else {
533
+ yield this.reconnectSingle(unhealthy);
534
+ }
535
+ unhealthy.isRestarting = false;
536
+ });
537
+ }
538
+ reconnectInterface(ifName, adapters) {
539
+ return __awaiter(this, void 0, void 0, function* () {
540
+ console.log('~~~~ health check: restart interface', ifName);
541
+ this.logger.logEvent({ message: 'restart interface', interface: ifName });
542
+ let stopRequested = false;
543
+ this.once('stop-ride', () => { stopRequested = true; });
544
+ const i = incyclist_devices_1.InterfaceFactory.create(ifName);
545
+ try {
546
+ console.log('~~~~ health check: stop Adapters', ifName);
547
+ const promisesStop = [];
548
+ adapters.map(ai => {
549
+ if (ai.isRestarting) {
550
+ promisesStop.push(this.stopAfterRestart(ai));
551
+ }
552
+ else {
538
553
  promisesStop.push(ai.adapter.stop());
539
- });
540
- if (promisesStop.length > 0) {
541
- yield Promise.allSettled(promisesStop);
542
554
  }
555
+ ai.isRestarting = true;
556
+ ai.adapter.off('data', this.deviceDataHandler);
557
+ });
558
+ if (promisesStop.length > 0) {
559
+ yield Promise.allSettled(promisesStop);
560
+ }
561
+ console.log('~~~~ health check: reconnect interface', ifName);
562
+ if (!stopRequested) {
543
563
  yield i.disconnect();
544
564
  yield (0, sleep_1.sleep)(1000);
545
- yield i.connect;
565
+ yield i.connect();
566
+ }
567
+ console.log('~~~~ health check: start adapters', ifName);
568
+ if (!stopRequested) {
546
569
  const promisesStart = [];
547
570
  adapters.map(ai => { promisesStart.push(ai.adapter.start()); });
548
571
  if (promisesStart.length > 0) {
549
572
  yield Promise.allSettled(promisesStart);
550
573
  }
551
574
  }
552
- catch (err) {
553
- this.logger.logEvent({ message: 'restart interface failed', interface: ifName, reason: err.message });
575
+ }
576
+ catch (err) {
577
+ this.logger.logEvent({ message: 'restart interface failed', interface: ifName, reason: err.message });
578
+ console.log('~~~~ health check: restart interface error', ifName, err);
579
+ }
580
+ adapters.map(ai => {
581
+ if (ai.adapter.isStarted()) {
582
+ ai.tsLastData = Date.now();
554
583
  }
555
- adapters.map(ai => {
556
- if (ai.adapter.isStarted()) {
557
- ai.isHealthy = true;
558
- ai.dataStatus = 'green';
559
- }
560
- else {
561
- ai.isHealthy = false;
562
- ai.dataStatus = 'red';
563
- this.prepareReconnect(ai);
564
- }
565
- ai.adapter.on('data', this.deviceDataHandler);
584
+ else {
585
+ console.log('~~~~ health check: adapter still not healthy', ifName, ai.udid);
566
586
  ai.isRestarting = false;
587
+ this.prepareReconnect(ai);
588
+ }
589
+ ai.adapter.on('data', this.deviceDataHandler);
590
+ ai.isRestarting = false;
591
+ });
592
+ });
593
+ }
594
+ stopAfterRestart(unhealthy) {
595
+ return __awaiter(this, void 0, void 0, function* () {
596
+ if (unhealthy.isRestarting) {
597
+ yield new Promise(done => {
598
+ this.once('stop-adapter-confirmed', (udid) => {
599
+ if (udid === unhealthy.udid)
600
+ done();
601
+ });
567
602
  });
568
603
  }
569
- else {
570
- console.log('~~~~ health check: restart adapter', down.udid);
571
- this.logger.logEvent({ message: 'restart adapter', device: down.udid });
572
- down.adapter.off('data', this.deviceDataHandler);
573
- const adapter = down.adapter;
604
+ yield unhealthy.adapter.stop();
605
+ });
606
+ }
607
+ reconnectSingle(unhealthy) {
608
+ return __awaiter(this, void 0, void 0, function* () {
609
+ let stopRequested = false;
610
+ this.once('stop-ride', () => { stopRequested = true; });
611
+ this.once('stop-adapter', (udid) => {
612
+ if (udid === unhealthy.udid)
613
+ stopRequested = true;
614
+ });
615
+ let success = false;
616
+ do {
617
+ console.log('~~~~ health check: restart adapter', unhealthy.udid);
618
+ this.logger.logEvent({ message: 'restart adapter', device: unhealthy.udid });
619
+ unhealthy.adapter.off('data', this.deviceDataHandler);
620
+ const adapter = unhealthy.adapter;
574
621
  try {
575
- yield adapter.restart();
576
- down.isHealthy = true;
577
- down.dataStatus = 'green';
622
+ const started = yield adapter.restart();
623
+ if (started) {
624
+ unhealthy.tsLastData = Date.now();
625
+ success = true;
626
+ }
578
627
  }
579
628
  catch (err) {
580
- this.logger.logEvent({ message: 'restart adapter failed', device: down.udid, reason: err.message });
581
- this.prepareReconnect(down);
629
+ this.logger.logEvent({ message: 'restart adapter failed', device: unhealthy.udid, reason: err.message });
630
+ this.prepareReconnect(unhealthy);
582
631
  }
583
- down.adapter.on('data', this.deviceDataHandler);
584
- }
585
- down.isRestarting = false;
632
+ unhealthy.adapter.on('data', this.deviceDataHandler);
633
+ if (!success) {
634
+ for (let i = 0; i < 60 && !stopRequested; i++)
635
+ yield (0, sleep_1.sleep)(1000);
636
+ }
637
+ } while (!stopRequested && !success);
638
+ this.emit('stop-adapter-confirmed', unhealthy.udid);
586
639
  });
587
640
  }
588
641
  start(props) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-services",
3
- "version": "1.0.68",
3
+ "version": "1.0.70",
4
4
  "peerDependencies": {
5
5
  "gd-eventlog": "^0.1.26"
6
6
  },
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "axios": "^1.6.1",
42
- "incyclist-devices": "^2.1.28",
42
+ "incyclist-devices": "^2.1.29",
43
43
  "uuid": "^9.0.0",
44
44
  "xml2js": "^0.6.2"
45
45
  }