incyclist-services 1.6.2 → 1.6.4

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.
@@ -56,6 +56,7 @@ export declare class ActivityRideService extends IncyclistService {
56
56
  prevRidesLogs?: PastActivityInfo;
57
57
  lap?: number;
58
58
  pointsErrorLogged?: boolean;
59
+ info?: string;
59
60
  };
60
61
  constructor();
61
62
  init(id?: string): Observer;
@@ -225,7 +225,15 @@ let ActivityRideService = (() => {
225
225
  const display = Math.floor(time / 3) % 2;
226
226
  const avgMaxStats = (display === 0) ? this.getAverageValues() : this.getMaximumValues();
227
227
  const info = this.buildDashboardInfo(currentValues, avgMaxStats, display);
228
- this.logEvent({ message: 'Dashboard update', items: info.map(i => { var _a, _b, _c, _d, _e, _f; return `${i.title}:${(_b = (_a = i.data[0]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ''}:${(_d = (_c = i.data[1]) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : ''}${((_e = i.data[1]) === null || _e === void 0 ? void 0 : _e.label) ? '(' + ((_f = i.data[1]) === null || _f === void 0 ? void 0 : _f.label) + ')' : ''}`; }).join('|') });
228
+ let showLog = true;
229
+ try {
230
+ const infoStr = JSON.stringify(info);
231
+ showLog = infoStr !== this.current.info;
232
+ this.current.info = infoStr;
233
+ }
234
+ catch (_a) { }
235
+ if (showLog)
236
+ this.logEvent({ message: 'Dashboard update', items: info.map(i => { var _a, _b, _c, _d, _e, _f; return `${i.title}:${(_b = (_a = i.data[0]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ''}:${(_d = (_c = i.data[1]) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : ''}${((_e = i.data[1]) === null || _e === void 0 ? void 0 : _e.label) ? '(' + ((_f = i.data[1]) === null || _f === void 0 ? void 0 : _f.label) + ')' : ''}`; }).join('|') });
229
237
  return info;
230
238
  }
231
239
  catch (err) {
@@ -654,6 +662,7 @@ let ActivityRideService = (() => {
654
662
  }
655
663
  this.current.deviceData = Object.assign(Object.assign({}, this.current.deviceData), update);
656
664
  if (this.state !== 'active') {
665
+ this.emit('data');
657
666
  if (this.state === 'paused' && (data.power > 0 || data.cadence > 0) && this.current.isAutoResume) {
658
667
  this.resume('system');
659
668
  return;
@@ -831,7 +831,7 @@ class DevicePairingService extends service_2.IncyclistService {
831
831
  }
832
832
  checkPairingSuccess() {
833
833
  const configReadyToRide = this.configuration.canStartRide();
834
- if (!configReadyToRide)
834
+ if (!configReadyToRide || this.isScanning())
835
835
  return false;
836
836
  const control = this.getCapability(incyclist_devices_1.IncyclistCapability.Control);
837
837
  const power = this.getCapability(incyclist_devices_1.IncyclistCapability.Power);
@@ -164,7 +164,7 @@ let RideDisplayService = (() => {
164
164
  try {
165
165
  const props = this.getStartOverlayProps();
166
166
  this.logEvent({ message: 'button clicked', overlay: 'start overlay', button: 'Cancel', reason: 'user cancel', state: props, eventSource: 'user' });
167
- yield this.stopRide();
167
+ yield this.stopRide({ noStateUpdates: true });
168
168
  }
169
169
  catch (err) {
170
170
  this.logError(err, 'cancelStart');
@@ -3,7 +3,7 @@ import { Observer } from "../../base/types";
3
3
  import { LocalizationService } from "../../i18n";
4
4
  import { RouteListService } from "../../routes";
5
5
  import { Route } from "../../routes/base/model/route";
6
- import { RouteInfoText } from "../../routes/base/types";
6
+ import { RouteInfoText, RoutePoint } from "../../routes/base/types";
7
7
  import { VideoConversion, VideoSyncHelper } from "../../video";
8
8
  import { CurrentPosition, CurrentRideDisplayProps, InfotextDisplayProps, OverlayDisplayProps, RLVDisplayProps } from "../base";
9
9
  import { RouteDisplayService } from "./RouteDisplayService";
@@ -45,6 +45,7 @@ export declare class RLVDisplayService extends RouteDisplayService {
45
45
  getDisplayProperties(props: CurrentRideDisplayProps): RLVDisplayProps;
46
46
  protected getInfotextDisplayProps(): InfotextDisplayProps;
47
47
  protected checkFinishOptions(position: CurrentPosition): boolean;
48
+ protected preparePointsForMerge(currentPoints: RoutePoint[], nextPoints: RoutePoint[]): void;
48
49
  protected onNextVideo(): void;
49
50
  protected checkInfotextDisplayProps(time: number): void;
50
51
  protected getUIText(input: string): string;
@@ -76,13 +77,14 @@ export declare class RLVDisplayService extends RouteDisplayService {
76
77
  start: number;
77
78
  end: number;
78
79
  }>, video?: VideoState): void;
80
+ protected getCode(error: MediaError): any;
79
81
  protected onVideoPlaybackError(error: MediaError, video?: VideoState): void;
80
82
  protected onVideoPlayBackUpdate(time: number, rate: number, e: any, video?: VideoState): void;
81
83
  protected onVideoEnded(video?: VideoState): void;
82
84
  onActivityUpdate(activityPos: ActivityUpdate, data: any): void;
83
85
  protected initVideoSource(video: VideoState): VideoConversion;
84
86
  protected initMp4VideoSource(video: VideoState): void;
85
- protected buildVideoError(error: MediaError): string;
87
+ protected buildVideoError(error: MediaError, video?: VideoState): string;
86
88
  protected getVideoUrl(video: VideoState): string;
87
89
  protected getVideoTime(routeDistance: number, video?: VideoState): number;
88
90
  protected initAviVideoSource(video: VideoState): VideoConversion;
@@ -49,6 +49,7 @@ const types_1 = require("../../base/types");
49
49
  const i18n_1 = require("../../i18n");
50
50
  const utils_1 = require("../../maps/MapArea/utils");
51
51
  const routes_1 = require("../../routes");
52
+ const geo_1 = require("../../utils/geo");
52
53
  const video_1 = require("../../video");
53
54
  const RouteDisplayService_1 = require("./RouteDisplayService");
54
55
  let RLVDisplayService = (() => {
@@ -209,6 +210,22 @@ let RLVDisplayService = (() => {
209
210
  return false;
210
211
  }
211
212
  }
213
+ preparePointsForMerge(currentPoints, nextPoints) {
214
+ (0, routes_1.correctDistanceValues)(currentPoints);
215
+ (0, routes_1.correctDistanceValues)(nextPoints);
216
+ nextPoints.forEach(p => {
217
+ delete p.routeDistance;
218
+ delete p.cnt;
219
+ delete p.elevationGain;
220
+ delete p.slope;
221
+ });
222
+ const pLastCurrent = currentPoints[currentPoints.length - 1];
223
+ const pFirstNext = nextPoints[0];
224
+ const distance = (0, geo_1.distanceBetween)(pLastCurrent, pFirstNext);
225
+ const elevationGain = distance < 5 ? 0 : pLastCurrent.slope * distance / 100;
226
+ const elevationDelta = (pLastCurrent.elevation + elevationGain) - pFirstNext.elevation;
227
+ nextPoints.forEach(p => { p.elevation += elevationDelta; });
228
+ }
212
229
  onNextVideo() {
213
230
  const old = this.currentVideo;
214
231
  const next = this.currentVideo.next;
@@ -225,8 +242,11 @@ let RLVDisplayService = (() => {
225
242
  setTimeout(() => {
226
243
  old.syncHelper.reset();
227
244
  }, 2000);
228
- (0, utils_1.concatPaths)(this.getCurrentRoute().details.points, next.route.details.points, 'after');
229
- (0, routes_1.validateRoute)(this.getCurrentRoute(), true);
245
+ const currentPoints = this.getCurrentRoute().details.points;
246
+ const nextPoints = next.route.details.points;
247
+ this.preparePointsForMerge(currentPoints, nextPoints);
248
+ (0, utils_1.concatPaths)(currentPoints, nextPoints, 'after');
249
+ (0, routes_1.validateRoute)(this.getCurrentRoute(), false);
230
250
  this.emit('route-updated', this.getCurrentRoute());
231
251
  this.logEvent({ message: 'switching to next video', route: this.getCurrentRoute().details.title,
232
252
  segment: this.currentVideo.route.description.title, offset: this.offset, segmentDistance: this.currentVideo.route.description.distance,
@@ -352,9 +372,12 @@ let RLVDisplayService = (() => {
352
372
  }
353
373
  onVideoLoadError(error, video = this.currentVideo) {
354
374
  video.loaded = false;
355
- video.error = this.buildVideoError(error);
356
- if (!video.isInitial) {
357
- this.logEvent({ message: 'could not load next video', video: this.getVideoUrl(video), error: error.message, errorCode: error.code });
375
+ video.error = this.buildVideoError(error, video);
376
+ if (video.isInitial) {
377
+ this.logEvent({ message: 'could not load video', video: this.getVideoUrl(video), error: error.message, errorCode: this.getCode(error) });
378
+ }
379
+ else {
380
+ this.logEvent({ message: 'could not load next video', video: this.getVideoUrl(video), error: error.message, errorCode: this.getCode(error) });
358
381
  const errIdx = this.videos.indexOf(video);
359
382
  if (errIdx !== -1) {
360
383
  this.videos.splice(errIdx);
@@ -370,7 +393,27 @@ let RLVDisplayService = (() => {
370
393
  onVideoWaiting(time, rate, bufferedTime, buffers, video = this.currentVideo) {
371
394
  video.syncHelper.onVideoWaiting(time, rate, bufferedTime, buffers);
372
395
  }
396
+ getCode(error) {
397
+ const codes = ['MEDIA_ERR_ABORTED', 'MEDIA_ERR_NETWORK', 'MEDIA_ERR_DECODE', 'MEDIA_ERR_SRC_NOT_SUPPORTED'];
398
+ try {
399
+ let codeStr;
400
+ if (error.code !== undefined) {
401
+ codeStr = codes === null || codes === void 0 ? void 0 : codes[error.code - 1];
402
+ if (codeStr) {
403
+ codeStr = `${codeStr} (${error.code})`;
404
+ }
405
+ else {
406
+ codeStr = error.code.toString();
407
+ }
408
+ }
409
+ return codeStr;
410
+ }
411
+ catch (err) {
412
+ this.logError(err, 'getCode');
413
+ }
414
+ }
373
415
  onVideoPlaybackError(error, video = this.currentVideo) {
416
+ this.logEvent({ message: 'video playback error', video: this.getVideoUrl(video), error: error.message, errorCode: this.getCode(error) });
374
417
  }
375
418
  onVideoPlayBackUpdate(time, rate, e, video = this.currentVideo) {
376
419
  video.syncHelper.onVideoPlaybackUpdate(time, rate, e);
@@ -413,7 +456,21 @@ let RLVDisplayService = (() => {
413
456
  video.playback = 'native';
414
457
  }
415
458
  }
416
- buildVideoError(error) {
459
+ buildVideoError(error, video = this.currentVideo) {
460
+ const src = this.getVideoUrl(video);
461
+ const remote = src === null || src === void 0 ? void 0 : src.startsWith('http');
462
+ switch (error.code) {
463
+ case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:
464
+ if (error.message.includes('Format error'))
465
+ return remote ? 'Could not load video' : 'Could not open video file';
466
+ return 'Could not decode video';
467
+ case MediaError.MEDIA_ERR_NETWORK:
468
+ return remote ? 'Could not load video' : 'Could not open video file';
469
+ case MediaError.MEDIA_ERR_ABORTED:
470
+ return 'The playback was canceled';
471
+ case MediaError.MEDIA_ERR_DECODE:
472
+ return 'Could not decode video';
473
+ }
417
474
  return error.message;
418
475
  }
419
476
  getVideoUrl(video) {
@@ -89,12 +89,12 @@ let RouteDisplayService = (() => {
89
89
  return;
90
90
  }
91
91
  try {
92
+ const prevPosition = Object.assign({}, this.position);
92
93
  const newPosition = this.updatePosition(activityPos);
93
94
  if (!newPosition)
94
95
  return;
95
96
  const isCompleted = this.checkFinishOptions(newPosition);
96
97
  if (!isCompleted) {
97
- const prevPosition = this.position;
98
98
  this.position = Object.assign({}, newPosition);
99
99
  const { lat, lng, routeDistance, lap } = newPosition;
100
100
  this.onPositionUpdate({ route: this.getOriginalRoute(), position: this.position });
@@ -275,7 +275,7 @@ let RouteDisplayService = (() => {
275
275
  const current = this.toLapPoint(this.position);
276
276
  props = { routeDistance: activityPos === null || activityPos === void 0 ? void 0 : activityPos.routeDistance, prev: current };
277
277
  const next = (0, routes_1.getNextPosition)(this.getCurrentRoute(), props);
278
- return this.fromLapPoint(next);
278
+ this.position = this.fromLapPoint(next);
279
279
  }
280
280
  return this.position;
281
281
  }
@@ -7,6 +7,7 @@ export declare const validateSlopes: (points: Array<RoutePoint>) => void;
7
7
  export declare const updateSlopes: (points: Array<RoutePoint>, validateOnly?: boolean) => void;
8
8
  export declare const getSegments: (route: Route) => Array<RouteSegment>;
9
9
  export declare const addDetails: (route: Route, details: RouteApiDetail) => void;
10
+ export declare const correctDistanceValues: (points: RoutePoint[]) => void;
10
11
  export declare const validateRoute: (route: Route | RouteApiDetail, reset?: boolean) => void;
11
12
  export declare const validateDistance: (points: Array<RoutePoint>) => void;
12
13
  export declare const getTotalElevation: (route: RouteApiDetail) => number;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getNextVideoId = exports.hasNextVideo = exports.createFromJson = exports.getPointAtDistance = exports.getHeading = exports.getPosition = exports.getNextPosition = exports.getRouteHash = exports.getTotalDistance = exports.updateCnt = exports.updateElevationGain = exports.getElevationGainAt = exports.getTotalElevation = exports.validateDistance = exports.validateRoute = exports.addDetails = exports.getSegments = exports.updateSlopes = exports.validateSlopes = exports.checkIsLoop = void 0;
6
+ exports.getNextVideoId = exports.hasNextVideo = exports.createFromJson = exports.getPointAtDistance = exports.getHeading = exports.getPosition = exports.getNextPosition = exports.getRouteHash = exports.getTotalDistance = exports.updateCnt = exports.updateElevationGain = exports.getElevationGainAt = exports.getTotalElevation = exports.validateDistance = exports.validateRoute = exports.correctDistanceValues = exports.addDetails = exports.getSegments = exports.updateSlopes = exports.validateSlopes = exports.checkIsLoop = void 0;
7
7
  const utils_1 = require("../../../utils");
8
8
  const clone_1 = __importDefault(require("../../../utils/clone"));
9
9
  const geo_1 = require("../../../utils/geo");
@@ -179,6 +179,15 @@ const addVideoDetails = (route, details) => {
179
179
  route.description.hasGpx = details.points.find(p => p.lat && p.lng) !== undefined;
180
180
  route.description.next = (_c = details.video) === null || _c === void 0 ? void 0 : _c.next;
181
181
  };
182
+ const correctDistanceValues = (points) => {
183
+ points.forEach((p, idx) => {
184
+ if (idx == 0) {
185
+ return;
186
+ }
187
+ p.distance = p.routeDistance - points[idx - 1].routeDistance;
188
+ });
189
+ };
190
+ exports.correctDistanceValues = correctDistanceValues;
182
191
  const validateRoute = (route, reset = false) => {
183
192
  var _a;
184
193
  if (!((_a = route === null || route === void 0 ? void 0 : route.points) === null || _a === void 0 ? void 0 : _a.length))
@@ -207,7 +207,7 @@ class VideoSyncHelper extends service_1.IncyclistService {
207
207
  this.onUpdate(updates);
208
208
  }
209
209
  onUpdate(updates = []) {
210
- var _a, _b, _c;
210
+ var _a, _b, _c, _d;
211
211
  if (this.isStopped || this.rlvStatus.timeRequested)
212
212
  return;
213
213
  try {
@@ -244,13 +244,16 @@ class VideoSyncHelper extends service_1.IncyclistService {
244
244
  this.logEvent({ message: 'video debug', videoState: this.rlvStatus, activityState: this.activityStatus });
245
245
  }
246
246
  };
247
- if (this.loopMode && this.rlvStatus.lap > this.activityStatus.lap) {
248
- rlvDistance = rlvDistance + totalDistance;
247
+ if (this.loopMode && actDistance > totalDistance) {
248
+ actDistance = actDistance % totalDistance;
249
+ rlvDistance = rlvDistance % totalDistance;
249
250
  }
250
- else if (this.loopMode && this.rlvStatus.lap < this.activityStatus.lap) {
251
- actDistance = actDistance + totalDistance;
251
+ let delta = rlvDistance - actDistance;
252
+ if (this.loopMode) {
253
+ const deltaActAhead = rlvDistance - (actDistance + totalDistance);
254
+ const deltaRlvAhead = (rlvDistance + totalDistance) - actDistance;
255
+ delta = [delta, deltaActAhead, deltaRlvAhead].reduce((best, cur) => Math.abs(cur) < Math.abs(best) ? cur : best, delta);
252
256
  }
253
- const delta = rlvDistance - actDistance;
254
257
  if (Math.abs(delta) > Math.abs(this.maxDelta)) {
255
258
  this.maxDelta = delta;
256
259
  }
@@ -278,13 +281,13 @@ class VideoSyncHelper extends service_1.IncyclistService {
278
281
  return;
279
282
  }
280
283
  const tTarget = 5;
281
- const maxCorrection = Math.max(20, this.rlvStatus.time < 100 ? 15 : this.bufferedTime / 2.5 * 15);
284
+ const maxCorrection = Math.max(20, this.rlvStatus.time < 100 ? 15 : ((_c = this.bufferedTime) !== null && _c !== void 0 ? _c : 0) / 2.5 * 15);
282
285
  const correction = Math.sign(delta) * Math.min(Math.abs(delta), maxCorrection);
283
286
  const rate = (this.activityStatus.speed - correction / tTarget * 3.6) / this.rlvStatus.speed;
284
287
  this.updateRate(rate);
285
288
  }
286
289
  }
287
- this.cpuTime = ((_c = this.cpuTime) !== null && _c !== void 0 ? _c : 0) + (Date.now() - tsStart);
290
+ this.cpuTime = ((_d = this.cpuTime) !== null && _d !== void 0 ? _d : 0) + (Date.now() - tsStart);
288
291
  }
289
292
  catch (err) {
290
293
  this.logError(err, 'onUpdate');
@@ -93,7 +93,10 @@ let WorkoutListService = (() => {
93
93
  this.getWorkoutCalendar().off('updated', this.onUpdate);
94
94
  this.getWorkoutCalendar().reset();
95
95
  }
96
- getSelected() { return this.selectedWorkout; }
96
+ getSelected() {
97
+ const workoutShown = this.getAppState().getState('workoutShown');
98
+ return workoutShown ? this.selectedWorkout : undefined;
99
+ }
97
100
  setScreenProps(props) { this.screenProps = props; }
98
101
  getScreenProps() { return this.screenProps; }
99
102
  open() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-services",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "peerDependencies": {
5
5
  "gd-eventlog": "^0.1.26"
6
6
  },
@@ -42,7 +42,7 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "axios": "^1.8.2",
45
- "incyclist-devices": "^2.4.7",
45
+ "incyclist-devices": "^2.4.9",
46
46
  "promise.any": "^2.0.6",
47
47
  "semver": "^7.6.3",
48
48
  "tcx-builder": "^1.1.1",