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.
- package/lib/devices/ride/service.d.ts +4 -1
- package/lib/devices/ride/service.js +105 -52
- package/package.json +2 -2
|
@@ -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(
|
|
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
|
-
|
|
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(
|
|
517
|
+
prepareReconnect(unhealthy) {
|
|
518
518
|
return __awaiter(this, void 0, void 0, function* () {
|
|
519
|
-
if (
|
|
519
|
+
if (unhealthy.isRestarting)
|
|
520
520
|
return;
|
|
521
|
-
console.log('~~~~ health check: wait 45s',
|
|
521
|
+
console.log('~~~~ health check: wait 45s', unhealthy.udid);
|
|
522
522
|
yield (0, sleep_1.sleep)(UNHEALTHY_THRESHOLD - NO_DATA_THRESHOLD - 5000);
|
|
523
|
-
|
|
524
|
-
if (down.isHealthy || down.isRestarting)
|
|
523
|
+
if (unhealthy.isHealthy || unhealthy.isRestarting)
|
|
525
524
|
return;
|
|
526
|
-
|
|
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
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
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
|
-
|
|
553
|
-
|
|
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
|
-
|
|
556
|
-
|
|
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
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
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
|
-
|
|
577
|
-
|
|
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:
|
|
581
|
-
this.prepareReconnect(
|
|
629
|
+
this.logger.logEvent({ message: 'restart adapter failed', device: unhealthy.udid, reason: err.message });
|
|
630
|
+
this.prepareReconnect(unhealthy);
|
|
582
631
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
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.
|
|
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.
|
|
42
|
+
"incyclist-devices": "^2.1.29",
|
|
43
43
|
"uuid": "^9.0.0",
|
|
44
44
|
"xml2js": "^0.6.2"
|
|
45
45
|
}
|