incyclist-services 1.0.72 → 1.0.74

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 });
@@ -53,11 +53,13 @@ export declare class DevicePairingService extends IncyclistService {
53
53
  protected waitForInit(): Promise<void>;
54
54
  protected getExternaState(toEmit: PairingState): PairingState;
55
55
  protected emitStateChange(newState?: PairingState): void;
56
+ protected emitStartStatus(): void;
56
57
  protected onInterfaceConfigChanged(ifName: string, settings: InterfaceSetting): void;
57
58
  protected mergeState(current: any, newState: any): void;
58
59
  protected onConfigurationUpdate(newCapabilities: DeviceConfigurationInfo): void;
59
60
  protected onInterfaceStateChanged(ifName: any, ifDetails: any, interfacesNew?: any): Promise<any>;
60
61
  protected isInterfaceEnabled(target: string | InterfaceSetting): boolean;
62
+ protected isInterfaceInUse(target: string | InterfaceSetting): CapabilityData;
61
63
  protected logCapabilities(capabilities?: Array<CapabilityData>): CapabilityData[];
62
64
  protected initPairingCallbacks(): void;
63
65
  protected removePairingCallbacks(): void;
@@ -74,6 +76,7 @@ export declare class DevicePairingService extends IncyclistService {
74
76
  private markConnected;
75
77
  protected disconnectInterface(name: string): void;
76
78
  protected connectInterface(name: string): void;
79
+ protected updateCapabilityConfig(): void;
77
80
  protected checkCanStart(): boolean;
78
81
  protected checkPairingSuccess(): boolean;
79
82
  private stopScanning;
@@ -64,19 +64,22 @@ class DevicePairingService extends service_2.IncyclistService {
64
64
  this.state.deleted = [];
65
65
  }
66
66
  try {
67
- if (this.settings.onStateChanged) {
68
- this.settings.onStateChanged = onStateChanged;
67
+ yield this.loadConfiguration();
68
+ this.updateCapabilityConfig();
69
+ const alreadyInitialized = this.settings.onStateChanged !== undefined && this.settings.onStateChanged !== null;
70
+ this.settings.onStateChanged = onStateChanged;
71
+ if (alreadyInitialized) {
69
72
  this.emitStateChange(this.state);
73
+ this.emitStartStatus();
70
74
  return;
71
75
  }
72
- yield this.loadConfiguration();
76
+ this.initConfigHandlers();
73
77
  this.state.interfaces.forEach(i => {
74
78
  if (!this.isInterfaceEnabled(i.name))
75
79
  this.unselectOnInterface(i.name);
76
80
  });
77
- this.settings.onStateChanged = onStateChanged;
78
81
  this.emitStateChange(this.state);
79
- this.initConfigHandlers();
82
+ this.emitStartStatus();
80
83
  this.run();
81
84
  }
82
85
  catch (err) {
@@ -88,8 +91,6 @@ class DevicePairingService extends service_2.IncyclistService {
88
91
  return __awaiter(this, void 0, void 0, function* () {
89
92
  yield this.waitForInit();
90
93
  const { capabilities, interfaces } = this.configuration.load();
91
- const state = Object.assign({}, this.state);
92
- delete state.adapters;
93
94
  this.state.capabilities = this.mappedCapabilities(capabilities);
94
95
  this.state.interfaces = this.access.enrichWithAccessState(interfaces);
95
96
  this.state.canStartRide = this.configuration.canStartRide();
@@ -378,6 +379,13 @@ class DevicePairingService extends service_2.IncyclistService {
378
379
  if (onDeviceSelectStateChanged && typeof onDeviceSelectStateChanged === 'function')
379
380
  onDeviceSelectStateChanged(this.getDeviceSelectionState());
380
381
  }
382
+ emitStartStatus() {
383
+ const { onStateChanged } = this.settings || {};
384
+ const { canStartRide } = this.state;
385
+ if (onStateChanged && typeof onStateChanged === 'function') {
386
+ onStateChanged({ canStartRide });
387
+ }
388
+ }
381
389
  onInterfaceConfigChanged(ifName, settings) {
382
390
  this.logEvent({ message: 'Interface Config changed', interface: ifName, settings });
383
391
  const prev = this.state.interfaces;
@@ -488,7 +496,7 @@ class DevicePairingService extends service_2.IncyclistService {
488
496
  else if (ifDetails.state !== 'unavailable' && current.state === 'unavailable') {
489
497
  this.enableAdaptersOnInterface(ifName);
490
498
  }
491
- else if (ifDetails.state === 'connected' && current.state !== 'connected' && !this.isPairing()) {
499
+ else if (ifDetails.state === 'connected' && current.state !== 'connected' && !this.isPairing() && !this.state.canStartRide) {
492
500
  restartScan = true;
493
501
  }
494
502
  else if (ifDetails.state === 'connected' && current.state !== 'connected' && this.isPairingWaiting()) {
@@ -498,9 +506,10 @@ class DevicePairingService extends service_2.IncyclistService {
498
506
  prev[changedIdx].isScanning = ifDetails.isScanning;
499
507
  prev[changedIdx].state = ifDetails.state;
500
508
  }
501
- if (restartScan)
509
+ if (restartScan) {
502
510
  this.restart();
503
- if (restartPair) {
511
+ }
512
+ if (restartPair && this.isInterfaceInUse(ifName)) {
504
513
  this.restartPair();
505
514
  }
506
515
  this.emitStateChange({ interfaces: this.state.interfaces });
@@ -518,6 +527,12 @@ class DevicePairingService extends service_2.IncyclistService {
518
527
  const { interfaces } = this.state;
519
528
  return interfaces.find(i => i.name === name && i.enabled && i.state !== 'unavailable') !== undefined;
520
529
  }
530
+ isInterfaceInUse(target) {
531
+ const name = (typeof target === 'string') ? target : target.name;
532
+ const { capabilities } = this.state;
533
+ const res = capabilities.find(c => c.interface === name);
534
+ return res;
535
+ }
521
536
  logCapabilities(capabilities) {
522
537
  const ci = capabilities || this.state.capabilities;
523
538
  ci.forEach(c => {
@@ -713,6 +728,19 @@ class DevicePairingService extends service_2.IncyclistService {
713
728
  this.logError(err, 'enableInterface');
714
729
  }
715
730
  }
731
+ updateCapabilityConfig() {
732
+ try {
733
+ const { capabilities } = this.state;
734
+ capabilities.forEach(c => {
735
+ var _a;
736
+ if (c.connectState !== 'connected' && c.selected && ((_a = this.getDeviceAdapter(c.selected)) === null || _a === void 0 ? void 0 : _a.isStarted()))
737
+ c.connectState = 'connected';
738
+ });
739
+ }
740
+ catch (err) {
741
+ console.log(err);
742
+ }
743
+ }
716
744
  checkCanStart() {
717
745
  try {
718
746
  const prev = this.state.canStartRide;
@@ -725,8 +753,8 @@ class DevicePairingService extends service_2.IncyclistService {
725
753
  const power = this.getCapability(incyclist_devices_1.IncyclistCapability.Power);
726
754
  const canStartRide = ((control === null || control === void 0 ? void 0 : control.connectState) === 'connected' || (power === null || power === void 0 ? void 0 : power.connectState) === 'connected');
727
755
  this.state.canStartRide = canStartRide;
728
- if (this.state.canStartRide !== prev) {
729
- this.emitStateChange({ canStartRide });
756
+ if (canStartRide !== prev) {
757
+ this.emitStartStatus();
730
758
  }
731
759
  }
732
760
  catch (err) {
@@ -793,7 +821,10 @@ class DevicePairingService extends service_2.IncyclistService {
793
821
  return;
794
822
  }
795
823
  if (configOKToStart && !this.deviceSelectState && !props.enforcedScan) {
796
- yield this.startPairing(adapters, props);
824
+ if (!(this.checkPairingSuccess() === true))
825
+ yield this.startPairing(adapters, props);
826
+ else
827
+ this.emitStateChange();
797
828
  }
798
829
  else {
799
830
  yield this.startScanning(adapters, props);
@@ -802,7 +833,7 @@ class DevicePairingService extends service_2.IncyclistService {
802
833
  }
803
834
  startPairing(adapters, props) {
804
835
  return __awaiter(this, void 0, void 0, function* () {
805
- if (this.isPairing())
836
+ if (this.isPairing() || this.checkPairingSuccess())
806
837
  return;
807
838
  const preparing = DevicePairingService.checkCounter++;
808
839
  this.state.check = { preparing };
@@ -824,7 +855,7 @@ class DevicePairingService extends service_2.IncyclistService {
824
855
  this.processConnectedDevices(adapters);
825
856
  const selected = this.state.capabilities.map(c => c.selected);
826
857
  const target = adapters.filter(ai => selected.includes(ai.udid));
827
- if (this.isPairing() && this.state.check.preparing !== preparing) {
858
+ if ((this.isPairing() && this.state.check.preparing !== preparing) || (this.checkPairingSuccess() === true)) {
828
859
  return;
829
860
  }
830
861
  this.initPairingCallbacks();
@@ -834,6 +865,7 @@ class DevicePairingService extends service_2.IncyclistService {
834
865
  this.onPairingStarted();
835
866
  this.logEvent({ message: 'Start Pairing', adapters, props });
836
867
  yield this.state.check.promise;
868
+ this.checkCanStart();
837
869
  if (this.state.check)
838
870
  delete this.state.check;
839
871
  this.emit('pairing-done');
@@ -366,7 +366,6 @@ class DeviceRideService extends events_1.default {
366
366
  return duplicateAdapters;
367
367
  }
368
368
  catch (err) {
369
- console.log('~~~~ ERROR', err);
370
369
  return [];
371
370
  }
372
371
  }
@@ -375,38 +374,37 @@ class DeviceRideService extends events_1.default {
375
374
  const { forceErgMode, startPos, realityFactor, rideMode, route } = props || {};
376
375
  const duplicates = this.checkAntSameDeviceID(adapters);
377
376
  this.startPromises = adapters === null || adapters === void 0 ? void 0 : adapters.map((ai) => __awaiter(this, void 0, void 0, function* () {
378
- var _a;
377
+ var _a, _b, _c;
379
378
  if (duplicates.find(dai => dai.info.udid === ai.udid))
380
379
  return;
381
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
+ }
382
400
  if (startType === 'check' || startType === 'pair') {
383
401
  startProps.timeout = 10000;
384
402
  if (ai.adapter.getSettings().interface === 'ble')
385
403
  startProps.timeout = 30000;
386
404
  }
387
405
  if (startType === 'start') {
388
- if (ai.adapter && ai.adapter.isControllable()) {
389
- const d = ai.adapter;
390
- let mode, settings;
391
- if (!this.simulatorEnforced) {
392
- if (forceErgMode) {
393
- const modes = d.getSupportedCyclingModes().filter(C => C.supportsERGMode());
394
- if (modes.length > 0) {
395
- mode = new modes[0](d);
396
- const modeInfo = this.configurationService.getModeSettings(ai.udid, mode);
397
- settings = modeInfo.settings;
398
- }
399
- }
400
- if (!mode) {
401
- const modeInfo = this.configurationService.getModeSettings(ai.udid);
402
- mode = modeInfo.mode;
403
- settings = modeInfo.settings;
404
- }
405
- }
406
- if (!mode)
407
- mode = d.getDefaultCyclingMode();
408
- d.setCyclingMode(mode, settings);
409
- if (d.getCyclingMode().getModeProperty('eppSupport')) {
406
+ if ((_b = ai.adapter) === null || _b === void 0 ? void 0 : _b.isControllable()) {
407
+ if (bike.getCyclingMode().getModeProperty('eppSupport')) {
410
408
  startProps.route = this.prepareEppRoute({ route, startPos, realityFactor, rideMode });
411
409
  startProps.onStatusUpdate = (completed, total) => {
412
410
  this.emit('start-update', this.getAdapterStateInfo(ai), completed, total);
@@ -419,8 +417,11 @@ class DeviceRideService extends events_1.default {
419
417
  logProps[sType] = ai.adapter.getUniqueName();
420
418
  logProps.cability = ai.adapter.getCapabilities().join('/');
421
419
  logProps.interface = (0, logging_1.getLegacyInterface)(ai.adapter);
422
- if (sType === 'bike')
423
- 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
+ }
424
425
  this.logEvent(Object.assign({ message: `${startType} ${sType} request` }, logProps));
425
426
  return ai.adapter.start(startProps)
426
427
  .then((success) => __awaiter(this, void 0, void 0, function* () {
@@ -499,7 +500,7 @@ class DeviceRideService extends events_1.default {
499
500
  ai.dataStatus = 'red';
500
501
  if (ai.isHealthy && (isAmber || isRed)) {
501
502
  ai.isHealthy = false;
502
- this.logEvent({ message: 'device unhealthy', device: ai.adapter.getUniqueName(), udid: ai.udid });
503
+ this.logEvent({ message: 'device unhealthy', device: ai.adapter.getUniqueName(), udid: ai.udid, noDataSince: (tsNow - ai.tsLastData), tsLastData: ai.tsLastData });
503
504
  this.prepareReconnect(ai);
504
505
  }
505
506
  else if (!ai.isHealthy && !isAmber && !isRed) {
@@ -544,6 +545,8 @@ class DeviceRideService extends events_1.default {
544
545
  }
545
546
  reconnectInterface(ifName, adapters) {
546
547
  return __awaiter(this, void 0, void 0, function* () {
548
+ if (ifName === 'simulator')
549
+ return;
547
550
  this.logger.logEvent({ message: 'restart interface', interface: ifName });
548
551
  let stopRequested = false;
549
552
  this.once('stop-ride', () => { stopRequested = true; });
@@ -674,13 +677,23 @@ class DeviceRideService extends events_1.default {
674
677
  }
675
678
  cancelStart() {
676
679
  return __awaiter(this, void 0, void 0, function* () {
680
+ if (!this.startPromises)
681
+ return;
682
+ this.logEvent({ message: 'cancel start' });
677
683
  const adapters = this.getAdapterList();
684
+ const promises = [];
678
685
  adapters === null || adapters === void 0 ? void 0 : adapters.forEach(ai => {
679
686
  const d = ai.adapter;
680
687
  d.off('data', this.deviceDataHandler);
681
- if (!ai.isStarted)
682
- 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
+ }
683
695
  });
696
+ yield Promise.allSettled(promises);
684
697
  this.startPromises = null;
685
698
  return true;
686
699
  });
@@ -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() {
@@ -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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-services",
3
- "version": "1.0.72",
3
+ "version": "1.0.74",
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.31",
42
+ "incyclist-devices": "^2.1.35",
43
43
  "uuid": "^9.0.0",
44
44
  "xml2js": "^0.6.2"
45
45
  }