incyclist-services 1.0.71 → 1.0.73

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.
@@ -0,0 +1,18 @@
1
+ export interface IObserver {
2
+ on(event: string, callback: any): any;
3
+ off(event: string, callback: any): any;
4
+ once(event: string, callback: any): any;
5
+ stop(): any;
6
+ }
7
+ export type ScreenshotProps = {
8
+ outDir: string;
9
+ position: number | string;
10
+ size: string;
11
+ };
12
+ export type ConvertProps = {
13
+ outDir: string;
14
+ };
15
+ export interface IVideoProcessor {
16
+ screenshot(url: string, props?: any): Promise<string>;
17
+ convert(url: string, props?: any): Promise<IObserver>;
18
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -823,7 +823,7 @@ class DevicePairingService extends service_2.IncyclistService {
823
823
  this.state.tsPrevStart = Date.now();
824
824
  this.processConnectedDevices(adapters);
825
825
  const selected = this.state.capabilities.map(c => c.selected);
826
- const target = adapters.filter(ai => !ai.adapter.isStarted() && selected.includes(ai.udid));
826
+ const target = adapters.filter(ai => selected.includes(ai.udid));
827
827
  if (this.isPairing() && this.state.check.preparing !== preparing) {
828
828
  return;
829
829
  }
@@ -340,67 +340,71 @@ class DeviceRideService extends events_1.default {
340
340
  }
341
341
  }
342
342
  checkAntSameDeviceID(adapters) {
343
- const antDevices = adapters.map((ai, idx) => (Object.assign(Object.assign({}, ai), { idx })))
344
- .filter(ai => ai.adapter.getInterface() === 'ant')
345
- .map(ai => ({ idx: ai.idx, deviceID: ai.adapter.getID(), capabilities: ai.capabilities, udid: ai.udid }));
346
- const antDeviceIds = antDevices.map(di => di.deviceID);
347
- const duplicateIds = antDeviceIds.filter((item, index) => antDeviceIds.indexOf(item) !== index);
348
- const score = (capabilities) => {
349
- let value = 0;
350
- if (capabilities.includes(incyclist_devices_1.IncyclistCapability.Control))
351
- value += 100;
352
- if (capabilities.includes(incyclist_devices_1.IncyclistCapability.Power))
353
- value += 50;
354
- value += capabilities.length;
355
- return value;
356
- };
357
- const duplicateDevices = antDevices.filter(di => duplicateIds.includes(di.deviceID)).sort((a, b) => score(b.capabilities) - score(a.capabilities));
358
- const leading = duplicateDevices[0];
359
- const duplicateAdapters = [];
360
- duplicateDevices.forEach((di, i) => {
361
- if (i == 0)
362
- return;
363
- duplicateAdapters.push({ udid: leading.udid, info: adapters[di.idx] });
364
- });
365
- return duplicateAdapters;
343
+ try {
344
+ const antDevices = adapters.map((ai, idx) => (Object.assign(Object.assign({}, ai), { idx })))
345
+ .filter(ai => ai.adapter.getInterface() === 'ant')
346
+ .map(ai => ({ idx: ai.idx, deviceID: ai.adapter.getID(), capabilities: ai.capabilities, udid: ai.udid }));
347
+ const antDeviceIds = antDevices.map(di => di.deviceID);
348
+ const duplicateIds = antDeviceIds.filter((item, index) => antDeviceIds.indexOf(item) !== index);
349
+ const score = (capabilities) => {
350
+ let value = 0;
351
+ if (capabilities.includes(incyclist_devices_1.IncyclistCapability.Control))
352
+ value += 100;
353
+ if (capabilities.includes(incyclist_devices_1.IncyclistCapability.Power))
354
+ value += 50;
355
+ value += capabilities.length;
356
+ return value;
357
+ };
358
+ const duplicateDevices = antDevices.filter(di => duplicateIds.includes(di.deviceID)).sort((a, b) => score(b.capabilities) - score(a.capabilities));
359
+ const leading = duplicateDevices[0];
360
+ const duplicateAdapters = [];
361
+ duplicateDevices.forEach((di, i) => {
362
+ if (i == 0)
363
+ return;
364
+ duplicateAdapters.push({ udid: leading.udid, info: adapters[di.idx] });
365
+ });
366
+ return duplicateAdapters;
367
+ }
368
+ catch (err) {
369
+ return [];
370
+ }
366
371
  }
367
372
  startAdapters(adapters, startType, props) {
368
373
  return __awaiter(this, void 0, void 0, function* () {
369
374
  const { forceErgMode, startPos, realityFactor, rideMode, route } = props || {};
370
375
  const duplicates = this.checkAntSameDeviceID(adapters);
371
376
  this.startPromises = adapters === null || adapters === void 0 ? void 0 : adapters.map((ai) => __awaiter(this, void 0, void 0, function* () {
372
- var _a;
377
+ var _a, _b, _c;
373
378
  if (duplicates.find(dai => dai.info.udid === ai.udid))
374
379
  return;
375
380
  const startProps = (0, clone_1.default)(props || {});
381
+ let mode, settings, bike;
382
+ if ((_a = ai.adapter) === null || _a === void 0 ? void 0 : _a.isControllable()) {
383
+ bike = ai.adapter;
384
+ const modeInfo = this.configurationService.getModeSettings(ai.udid);
385
+ mode = modeInfo.mode;
386
+ settings = modeInfo.settings;
387
+ if (!this.simulatorEnforced && forceErgMode) {
388
+ const modes = bike.getSupportedCyclingModes().filter(C => C.supportsERGMode());
389
+ if (modes.length > 0) {
390
+ mode = new modes[0](bike);
391
+ const modeInfo = this.configurationService.getModeSettings(ai.udid, mode);
392
+ settings = modeInfo.settings;
393
+ }
394
+ }
395
+ if (!mode)
396
+ mode = bike.getDefaultCyclingMode();
397
+ bike.setCyclingMode(mode, settings);
398
+ console.log('~~~ mode', mode, 'settings', settings);
399
+ }
376
400
  if (startType === 'check' || startType === 'pair') {
377
401
  startProps.timeout = 10000;
378
402
  if (ai.adapter.getSettings().interface === 'ble')
379
403
  startProps.timeout = 30000;
380
404
  }
381
405
  if (startType === 'start') {
382
- if (ai.adapter && ai.adapter.isControllable()) {
383
- const d = ai.adapter;
384
- let mode, settings;
385
- if (!this.simulatorEnforced) {
386
- if (forceErgMode) {
387
- const modes = d.getSupportedCyclingModes().filter(C => C.supportsERGMode());
388
- if (modes.length > 0) {
389
- mode = new modes[0](d);
390
- const modeInfo = this.configurationService.getModeSettings(ai.udid, mode);
391
- settings = modeInfo.settings;
392
- }
393
- }
394
- if (!mode) {
395
- const modeInfo = this.configurationService.getModeSettings(ai.udid);
396
- mode = modeInfo.mode;
397
- settings = modeInfo.settings;
398
- }
399
- }
400
- if (!mode)
401
- mode = d.getDefaultCyclingMode();
402
- d.setCyclingMode(mode, settings);
403
- if (d.getCyclingMode().getModeProperty('eppSupport')) {
406
+ if ((_b = ai.adapter) === null || _b === void 0 ? void 0 : _b.isControllable()) {
407
+ if (bike.getCyclingMode().getModeProperty('eppSupport')) {
404
408
  startProps.route = this.prepareEppRoute({ route, startPos, realityFactor, rideMode });
405
409
  startProps.onStatusUpdate = (completed, total) => {
406
410
  this.emit('start-update', this.getAdapterStateInfo(ai), completed, total);
@@ -413,8 +417,11 @@ class DeviceRideService extends events_1.default {
413
417
  logProps[sType] = ai.adapter.getUniqueName();
414
418
  logProps.cability = ai.adapter.getCapabilities().join('/');
415
419
  logProps.interface = (0, logging_1.getLegacyInterface)(ai.adapter);
416
- if (sType === 'bike')
417
- logProps.cyclingMode = (_a = ai.adapter.getCyclingMode()) === null || _a === void 0 ? void 0 : _a.getName();
420
+ if (sType === 'bike') {
421
+ const bike = ai.adapter;
422
+ logProps.cyclingMode = (_c = bike.getCyclingMode()) === null || _c === void 0 ? void 0 : _c.getName();
423
+ logProps.bikeType = bike.getCyclingMode().getSetting('bikeType');
424
+ }
418
425
  this.logEvent(Object.assign({ message: `${startType} ${sType} request` }, logProps));
419
426
  return ai.adapter.start(startProps)
420
427
  .then((success) => __awaiter(this, void 0, void 0, function* () {
@@ -474,6 +481,8 @@ class DeviceRideService extends events_1.default {
474
481
  }
475
482
  startHealthCheck(ai) {
476
483
  const check = () => {
484
+ if (!ai.ivToCheck)
485
+ return;
477
486
  const tsNow = Date.now();
478
487
  const isPaused = ai.adapter.isPaused();
479
488
  const prevStatus = ai.dataStatus;
@@ -491,8 +500,7 @@ class DeviceRideService extends events_1.default {
491
500
  ai.dataStatus = 'red';
492
501
  if (ai.isHealthy && (isAmber || isRed)) {
493
502
  ai.isHealthy = false;
494
- this.logEvent({ message: 'device unhealthy', device: ai.adapter.getUniqueName(), udid: ai.udid });
495
- console.log('~~~~ health check: prepare reconnect');
503
+ this.logEvent({ message: 'device unhealthy', device: ai.adapter.getUniqueName(), udid: ai.udid, noDataSince: (tsNow - ai.tsLastData), tsLastData: ai.tsLastData });
496
504
  this.prepareReconnect(ai);
497
505
  }
498
506
  else if (!ai.isHealthy && !isAmber && !isRed) {
@@ -504,7 +512,10 @@ class DeviceRideService extends events_1.default {
504
512
  this.emit('health', ai.udid, ai.dataStatus, enabledCapabilities);
505
513
  }
506
514
  };
507
- ai.ivToCheck = (0, timers_1.setInterval)(check, 1000);
515
+ if (ai.ivToCheck) {
516
+ this.stopHealthCheck(ai);
517
+ }
518
+ ai.ivToCheck = (0, timers_1.setInterval)(() => { check(); }, 1000);
508
519
  ai.isHealthy = true;
509
520
  }
510
521
  stopHealthCheck(ai) {
@@ -518,11 +529,9 @@ class DeviceRideService extends events_1.default {
518
529
  return __awaiter(this, void 0, void 0, function* () {
519
530
  if (unhealthy.isRestarting)
520
531
  return;
521
- console.log('~~~~ health check: wait 45s', unhealthy.udid);
522
532
  yield (0, sleep_1.sleep)(UNHEALTHY_THRESHOLD - NO_DATA_THRESHOLD - 5000);
523
533
  if (unhealthy.isHealthy || unhealthy.isRestarting)
524
534
  return;
525
- console.log('~~~~ health check: still unhealthy', unhealthy.udid, unhealthy.isHealthy, unhealthy.isRestarting);
526
535
  const ifName = unhealthy.adapter.getInterface();
527
536
  const adapters = this.getAdapterList().filter(ai => ai.adapter.getInterface() === ifName);
528
537
  if (!adapters.find(ai => ai.isHealthy)) {
@@ -536,46 +545,52 @@ class DeviceRideService extends events_1.default {
536
545
  }
537
546
  reconnectInterface(ifName, adapters) {
538
547
  return __awaiter(this, void 0, void 0, function* () {
539
- console.log('~~~~ health check: restart interface', ifName);
548
+ if (ifName === 'simulator')
549
+ return;
540
550
  this.logger.logEvent({ message: 'restart interface', interface: ifName });
541
551
  let stopRequested = false;
542
552
  this.once('stop-ride', () => { stopRequested = true; });
543
- const i = incyclist_devices_1.InterfaceFactory.create(ifName);
544
553
  try {
545
- console.log('~~~~ health check: prepare stop Adapters', ifName);
554
+ const i = incyclist_devices_1.InterfaceFactory.create(ifName);
546
555
  const promisesStop = [];
547
556
  adapters.map(ai => {
548
557
  promisesStop.push(this.stopAfterRestart(ai));
549
558
  });
550
- console.log('~~~~ health check: stop Adapters', ifName, promisesStop.length);
551
559
  if (promisesStop.length > 0) {
552
- yield Promise.allSettled(promisesStop);
560
+ yield Promise.race([(0, sleep_1.sleep)(66000), Promise.allSettled(promisesStop)]);
553
561
  }
554
- console.log('~~~~ health check: reconnect interface', ifName);
555
562
  if (!stopRequested) {
556
563
  yield i.disconnect();
557
564
  yield (0, sleep_1.sleep)(1000);
558
565
  yield i.connect();
559
566
  }
560
- console.log('~~~~ health check: start adapters', ifName);
561
567
  if (!stopRequested) {
562
568
  const promisesStart = [];
563
569
  adapters.map(ai => { promisesStart.push(ai.adapter.start()); });
564
570
  if (promisesStart.length > 0) {
565
- yield Promise.allSettled(promisesStart);
571
+ if (ifName === 'ant') {
572
+ for (let i = 0; i < promisesStart.length; i++) {
573
+ try {
574
+ yield promisesStart[i];
575
+ }
576
+ catch (_a) {
577
+ }
578
+ }
579
+ }
580
+ else {
581
+ yield Promise.allSettled(promisesStart);
582
+ }
566
583
  }
567
584
  }
568
585
  }
569
586
  catch (err) {
570
587
  this.logger.logEvent({ message: 'restart interface failed', interface: ifName, reason: err.message });
571
- console.log('~~~~ health check: restart interface error', ifName, err);
572
588
  }
573
589
  adapters.map(ai => {
574
590
  if (ai.adapter.isStarted()) {
575
591
  ai.tsLastData = Date.now();
576
592
  }
577
593
  else {
578
- console.log('~~~~ health check: adapter still not healthy', ifName, ai.udid);
579
594
  ai.isRestarting = false;
580
595
  this.prepareReconnect(ai);
581
596
  }
@@ -586,13 +601,12 @@ class DeviceRideService extends events_1.default {
586
601
  }
587
602
  stopAfterRestart(unhealthy) {
588
603
  return __awaiter(this, void 0, void 0, function* () {
604
+ this.emit('stop-adapter', unhealthy.udid);
589
605
  if (unhealthy.isRestarting) {
590
- console.log('~~~ health adapter lready stopping', unhealthy.udid);
591
606
  yield new Promise(done => {
592
607
  const to = setTimeout(done, 65000);
593
608
  this.once('stop-adapter-confirmed', (udid) => {
594
609
  if (udid === unhealthy.udid) {
595
- console.log('~~~ health adapter now can be stopped', unhealthy.udid);
596
610
  clearTimeout(to);
597
611
  done();
598
612
  }
@@ -601,7 +615,6 @@ class DeviceRideService extends events_1.default {
601
615
  }
602
616
  unhealthy.isRestarting = true;
603
617
  unhealthy.adapter.off('data', this.deviceDataHandler);
604
- console.log('~~~ health stop adapter', unhealthy.udid);
605
618
  yield unhealthy.adapter.stop();
606
619
  });
607
620
  }
@@ -616,7 +629,6 @@ class DeviceRideService extends events_1.default {
616
629
  });
617
630
  let success = false;
618
631
  do {
619
- console.log('~~~~ health check: restart adapter', unhealthy.udid);
620
632
  this.logger.logEvent({ message: 'restart adapter', device: unhealthy.udid });
621
633
  unhealthy.adapter.off('data', this.deviceDataHandler);
622
634
  const adapter = unhealthy.adapter;
@@ -665,13 +677,23 @@ class DeviceRideService extends events_1.default {
665
677
  }
666
678
  cancelStart() {
667
679
  return __awaiter(this, void 0, void 0, function* () {
680
+ if (!this.startPromises)
681
+ return;
682
+ this.logEvent({ message: 'cancel start' });
668
683
  const adapters = this.getAdapterList();
684
+ const promises = [];
669
685
  adapters === null || adapters === void 0 ? void 0 : adapters.forEach(ai => {
670
686
  const d = ai.adapter;
671
687
  d.off('data', this.deviceDataHandler);
672
- if (!ai.isStarted)
673
- d.stop();
688
+ if (!d.isStarted()) {
689
+ this.logEvent({ message: 'cancel start of device', udid: ai.udid });
690
+ promises.push(d.stop());
691
+ }
692
+ else {
693
+ d.pause();
694
+ }
674
695
  });
696
+ yield Promise.allSettled(promises);
675
697
  this.startPromises = null;
676
698
  return true;
677
699
  });
@@ -679,7 +701,7 @@ class DeviceRideService extends events_1.default {
679
701
  startRide(_props) {
680
702
  const adapters = this.getAdapterList();
681
703
  adapters === null || adapters === void 0 ? void 0 : adapters.forEach(ai => {
682
- ai.adapter.removeAllListeners('data');
704
+ ai.adapter.off('data', this.deviceDataHandler);
683
705
  ai.adapter.on('data', this.deviceDataHandler);
684
706
  });
685
707
  }
@@ -707,6 +729,7 @@ class DeviceRideService extends events_1.default {
707
729
  ai.tsLastData = Date.now();
708
730
  ai.adapter.pause();
709
731
  ai.adapter.off('data', this.deviceDataHandler);
732
+ this.stopHealthCheck(ai);
710
733
  });
711
734
  }
712
735
  resume() {
@@ -715,6 +738,7 @@ class DeviceRideService extends events_1.default {
715
738
  ai.tsLastData = Date.now();
716
739
  ai.adapter.resume();
717
740
  ai.adapter.on('data', this.deviceDataHandler);
741
+ this.startHealthCheck(ai);
718
742
  });
719
743
  }
720
744
  verifySelected(selectedDevices, capability) {
@@ -5,6 +5,7 @@ import { IncyclistService } from "../../base/service";
5
5
  import { FileInfo, IFileLoader, IJsonRepositoryBinding, JsonRepository } from "../../api";
6
6
  import { LatLng } from "../../utils/geo";
7
7
  import { IPathBinding } from "../../api/path";
8
+ import { IVideoProcessor } from "../../api/video";
8
9
  type filterFn = (route: Route, idx: number, obj: Route[]) => boolean;
9
10
  export declare class RouteListService extends IncyclistService {
10
11
  protected static _instance: any;
@@ -17,11 +18,13 @@ export declare class RouteListService extends IncyclistService {
17
18
  protected api: IncyclistRoutesApi;
18
19
  protected routeDescriptions: RoutesDB;
19
20
  protected loader: IFileLoader;
21
+ protected videoProcessor: IVideoProcessor;
20
22
  constructor();
21
23
  initBindings(bindings: {
22
24
  path?: IPathBinding;
23
25
  db: IJsonRepositoryBinding;
24
26
  loader?: IFileLoader;
27
+ video?: IVideoProcessor;
25
28
  }): void;
26
29
  protected getVideosRepo(): JsonRepository;
27
30
  protected getRoutesRepo(): JsonRepository;
@@ -19,7 +19,6 @@ const service_1 = require("../../base/service");
19
19
  const route_1 = require("../base/utils/route");
20
20
  const settings_1 = require("../../settings");
21
21
  const api_2 = require("../../api");
22
- const clone_1 = __importDefault(require("../../utils/clone"));
23
22
  const FreeRideCard_1 = require("./FreeRideCard");
24
23
  const ImportCard_1 = require("./ImportCard");
25
24
  const utils_1 = require("../../utils");
@@ -43,13 +42,14 @@ class RouteListService extends service_1.IncyclistService {
43
42
  this.routeDescriptions = {};
44
43
  }
45
44
  initBindings(bindings) {
46
- console.log('~~~ initBindings', bindings);
47
45
  if (bindings.db)
48
46
  api_2.JsonRepository.setBinding(bindings.db);
49
47
  if (bindings.path)
50
48
  path_1.default.initBinding(bindings.path);
51
49
  if (bindings.loader)
52
50
  this.loader = bindings.loader;
51
+ if (bindings.video)
52
+ this.videoProcessor = bindings.video;
53
53
  this.state.initialized = true;
54
54
  }
55
55
  getVideosRepo() {
@@ -222,7 +222,7 @@ class RouteListService extends service_1.IncyclistService {
222
222
  }
223
223
  console.log('~~~ DATA', content);
224
224
  const parser = parsers.findMatching(file.ext, content);
225
- const res = yield parser.import(file, content);
225
+ const res = yield parser.import(file, content, this.loader);
226
226
  const data = res.data;
227
227
  data.state = 'loaded';
228
228
  const details = res.data;
@@ -365,9 +365,7 @@ class RouteListService extends service_1.IncyclistService {
365
365
  }
366
366
  });
367
367
  }
368
- console.log('~~~ DEBUG: during preload', promises.length);
369
- Promise.allSettled(promises).then((res) => {
370
- console.log('~~~ DEBUG: after preload', (0, clone_1.default)(this.state), (0, clone_1.default)(this.routeDescriptions), res);
368
+ Promise.allSettled(promises).then(() => {
371
369
  this.saveRouteDescriptions();
372
370
  });
373
371
  });
@@ -585,18 +583,19 @@ class RouteListService extends service_1.IncyclistService {
585
583
  return data;
586
584
  }
587
585
  getListFromApiDesciption(description) {
588
- var _a;
586
+ var _a, _b;
589
587
  let list;
588
+ const category = (_a = description.category) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase();
590
589
  if (description.type === 'gpx') {
591
- if (description.category === 'personal')
590
+ if (category === 'personal')
592
591
  return 'myRoutes';
593
592
  list = description.category ? 'alternatives' : 'selected';
594
593
  return list;
595
594
  }
596
595
  if (description.type === 'video') {
597
- if (description.category === undefined || description.category === 'personal')
596
+ if (category === undefined || category === 'personal' || category === 'imported')
598
597
  return 'myRoutes';
599
- if ((_a = description.video) === null || _a === void 0 ? void 0 : _a.url) {
598
+ if ((_b = description.video) === null || _b === void 0 ? void 0 : _b.url) {
600
599
  return 'selected';
601
600
  }
602
601
  }
@@ -782,7 +781,6 @@ class RouteListService extends service_1.IncyclistService {
782
781
  if (!Array.isArray(r.points))
783
782
  delete r.points;
784
783
  });
785
- console.log('~~~ DEBUG:', all);
786
784
  this.addDescriptionsFromDB(all);
787
785
  }
788
786
  this.saveRouteDescriptions();
@@ -834,6 +832,7 @@ class RouteListService extends service_1.IncyclistService {
834
832
  }
835
833
  loadRouteDetais(route) {
836
834
  return __awaiter(this, void 0, void 0, function* () {
835
+ console.log('~~~ loadRouteDetails', route);
837
836
  if (route.data.state === 'loaded' || route.data.state === 'loading')
838
837
  return;
839
838
  try {
@@ -844,7 +843,8 @@ class RouteListService extends service_1.IncyclistService {
844
843
  yield this.getVideosRepo().read(route.id)
845
844
  :
846
845
  yield this.getRoutesRepo().read(route.id);
847
- api_1.default.verify(route.details);
846
+ if (route.details)
847
+ api_1.default.verify(route.details);
848
848
  }
849
849
  catch (err) {
850
850
  console.log('~~~ DEBUG:error', route.data.title, route.data.isLocal, err);
@@ -853,8 +853,14 @@ class RouteListService extends service_1.IncyclistService {
853
853
  }
854
854
  if (!route.details) {
855
855
  route.details = yield this.api.getRouteDetails(route.id);
856
- api_1.default.verify(route.details);
857
- this.saveRouteDetails(route);
856
+ if (route.details) {
857
+ api_1.default.verify(route.details);
858
+ this.saveRouteDetails(route);
859
+ route.data.state = 'loaded';
860
+ }
861
+ else {
862
+ route.data.state = 'prepared';
863
+ }
858
864
  }
859
865
  if (route.details.id !== route.data.id) {
860
866
  route.data.state = 'error';
@@ -864,7 +870,7 @@ class RouteListService extends service_1.IncyclistService {
864
870
  this.mergeWithDetails(route);
865
871
  route.data.state = 'loaded';
866
872
  this.emitRouteUpdated(route);
867
- const { list } = this.routeDescriptions[route.id];
873
+ const { list } = this.routeDescriptions[route.data.id];
868
874
  this.routeDescriptions[route.id] = Object.assign(Object.assign({}, route.data), { list });
869
875
  return route.data;
870
876
  }
@@ -2,15 +2,19 @@ import { EventLogger } from 'gd-eventlog';
2
2
  import { IUserSettingsBinding } from './bindings';
3
3
  export declare class UserSettingsService {
4
4
  static _instance: UserSettingsService;
5
+ static _defaultBinding: IUserSettingsBinding;
5
6
  settings: any;
6
7
  binding: IUserSettingsBinding;
7
8
  logger: EventLogger;
8
9
  isInitialized: boolean;
9
10
  isDirty: boolean;
10
11
  savePromise: Promise<boolean> | null;
12
+ instanceId: number;
13
+ initPromise: Promise<boolean>;
11
14
  static getInstance(): UserSettingsService;
12
15
  constructor(binding?: IUserSettingsBinding);
13
16
  setBinding(binding: IUserSettingsBinding): void;
17
+ static setDefaultBinding(binding: IUserSettingsBinding): void;
14
18
  init(): Promise<boolean>;
15
19
  getAll(): any;
16
20
  get(key: string, defValue: any): any;
@@ -30,19 +30,29 @@ class UserSettingsService {
30
30
  this.isInitialized = false;
31
31
  this.isDirty = false;
32
32
  this.savePromise = null;
33
+ this.instanceId = Date.now();
34
+ this.initPromise = undefined;
33
35
  this.setBinding(binding);
34
36
  }
35
37
  setBinding(binding) {
36
38
  this.binding = binding;
39
+ UserSettingsService.setDefaultBinding(binding);
40
+ }
41
+ static setDefaultBinding(binding) {
42
+ UserSettingsService._defaultBinding = binding;
37
43
  }
38
44
  init() {
39
45
  return __awaiter(this, void 0, void 0, function* () {
40
46
  if (this.isInitialized)
41
47
  return true;
42
- if (!this.binding)
48
+ if (this.initPromise)
49
+ return yield this.initPromise;
50
+ const binding = this.binding || UserSettingsService._defaultBinding;
51
+ if (!binding)
43
52
  return false;
44
53
  try {
45
- this.settings = yield this.binding.getAll();
54
+ this.initPromise = binding.getAll();
55
+ this.settings = yield this.initPromise;
46
56
  this.logger.logEvent({ message: 'settings loaded' });
47
57
  this.isInitialized = true;
48
58
  return true;
@@ -175,6 +185,7 @@ exports.useUserSettings = useUserSettings;
175
185
  const initUserSettings = (binding) => {
176
186
  const us = UserSettingsService.getInstance();
177
187
  us.setBinding(binding);
188
+ us.init();
178
189
  return us;
179
190
  };
180
191
  exports.initUserSettings = initUserSettings;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-services",
3
- "version": "1.0.71",
3
+ "version": "1.0.73",
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.30",
42
+ "incyclist-devices": "^2.1.35",
43
43
  "uuid": "^9.0.0",
44
44
  "xml2js": "^0.6.2"
45
45
  }