incyclist-services 1.0.3 → 1.0.5
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.
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IncyclistCapability } from "incyclist-devices";
|
|
1
2
|
import { DeviceProperties } from "incyclist-devices/lib/types/device";
|
|
2
3
|
import { AdapterInfo } from "../configuration";
|
|
3
4
|
export interface AdapterRideInfo extends AdapterInfo {
|
|
@@ -10,6 +11,12 @@ export interface RideServiceDeviceProperties extends DeviceProperties {
|
|
|
10
11
|
rideMode?: string;
|
|
11
12
|
route?: any;
|
|
12
13
|
}
|
|
14
|
+
export interface RideServiceCheckFilter {
|
|
15
|
+
interface?: string;
|
|
16
|
+
interfaces?: string[];
|
|
17
|
+
udid?: string;
|
|
18
|
+
capability?: IncyclistCapability;
|
|
19
|
+
}
|
|
13
20
|
export interface Point {
|
|
14
21
|
elevation: number;
|
|
15
22
|
distance: number;
|
|
@@ -4,7 +4,7 @@ import { DeviceData, DeviceSettings } from "incyclist-devices";
|
|
|
4
4
|
import { DeviceAccessService } from "../access/service";
|
|
5
5
|
import { AdapterInfo, DeviceConfigurationService } from "../configuration";
|
|
6
6
|
import CyclingMode, { UpdateRequest } from "incyclist-devices/lib/modes/cycling-mode";
|
|
7
|
-
import { AdapterRideInfo, PreparedRoute, RideServiceDeviceProperties } from "./model";
|
|
7
|
+
import { AdapterRideInfo, PreparedRoute, RideServiceCheckFilter, RideServiceDeviceProperties } from "./model";
|
|
8
8
|
import { UserSettingsService } from "../../settings";
|
|
9
9
|
import { EventLogger } from 'gd-eventlog';
|
|
10
10
|
export declare class DeviceRideService extends EventEmitter {
|
|
@@ -34,6 +34,10 @@ export declare class DeviceRideService extends EventEmitter {
|
|
|
34
34
|
};
|
|
35
35
|
protected getAdapterList(): AdapterRideInfo[];
|
|
36
36
|
prepareEppRoute(props: RideServiceDeviceProperties): PreparedRoute;
|
|
37
|
+
protected waitForPreviousStartToFinish(): Promise<boolean>;
|
|
38
|
+
startCheck(filter: RideServiceCheckFilter): Promise<void>;
|
|
39
|
+
protected getAdapters(filter: RideServiceCheckFilter): AdapterRideInfo[];
|
|
40
|
+
protected startAdapters(adapters: AdapterRideInfo[], startType: 'start' | 'check', props?: RideServiceDeviceProperties): Promise<boolean>;
|
|
37
41
|
start(props: RideServiceDeviceProperties): Promise<boolean>;
|
|
38
42
|
cancelStart(): Promise<boolean>;
|
|
39
43
|
startRide(_props: any): void;
|
|
@@ -267,70 +267,115 @@ class DeviceRideService extends events_1.default {
|
|
|
267
267
|
}
|
|
268
268
|
return res;
|
|
269
269
|
}
|
|
270
|
-
|
|
270
|
+
waitForPreviousStartToFinish() {
|
|
271
271
|
return __awaiter(this, void 0, void 0, function* () {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
272
|
+
const TIMEOUT = 3000;
|
|
273
|
+
if (!this.startPromises)
|
|
274
|
+
return true;
|
|
275
|
+
const prevStartState = yield Promise.race([
|
|
276
|
+
(0, sleep_1.sleep)(TIMEOUT).then(() => 'timeout'),
|
|
277
|
+
Promise.allSettled(this.startPromises)
|
|
278
|
+
]).then(() => 'finished');
|
|
279
|
+
return (prevStartState === 'finished');
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
startCheck(filter) {
|
|
283
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
284
|
+
yield this.lazyInit();
|
|
285
|
+
const adapters = this.getAdapters(filter);
|
|
286
|
+
const goodToGo = yield this.waitForPreviousStartToFinish();
|
|
287
|
+
if (!goodToGo)
|
|
288
|
+
return;
|
|
289
|
+
this.emit('check-request', adapters.map(this.getAdapterStateInfo));
|
|
290
|
+
yield this.startAdapters(adapters, 'check');
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
getAdapters(filter) {
|
|
294
|
+
const { udid, interface: ifName, interfaces, capability } = filter;
|
|
295
|
+
let adapters = this.getAdapterList();
|
|
296
|
+
const getIf = (adapter) => {
|
|
297
|
+
var _a;
|
|
298
|
+
const i = (_a = adapter === null || adapter === void 0 ? void 0 : adapter.getSettings()) === null || _a === void 0 ? void 0 : _a.interface;
|
|
299
|
+
if (!i)
|
|
300
|
+
return;
|
|
301
|
+
if (typeof (i) === 'string')
|
|
302
|
+
return i;
|
|
303
|
+
return i.getName();
|
|
304
|
+
};
|
|
305
|
+
if (udid) {
|
|
306
|
+
adapters = adapters === null || adapters === void 0 ? void 0 : adapters.filter(ai => ai.udid === udid);
|
|
307
|
+
}
|
|
308
|
+
if (ifName) {
|
|
309
|
+
adapters = adapters === null || adapters === void 0 ? void 0 : adapters.filter(ai => getIf(ai.adapter) === ifName);
|
|
310
|
+
}
|
|
311
|
+
if (interfaces) {
|
|
312
|
+
adapters = adapters === null || adapters === void 0 ? void 0 : adapters.filter(ai => interfaces.includes(getIf(ai.adapter)));
|
|
313
|
+
}
|
|
314
|
+
return adapters || [];
|
|
315
|
+
}
|
|
316
|
+
startAdapters(adapters, startType, props) {
|
|
317
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
318
|
+
const { forceErgMode, startPos, realityFactor, rideMode, route } = props || {};
|
|
279
319
|
this.startPromises = adapters.map(ai => {
|
|
280
|
-
const startProps = (0, clone_1.default)(props);
|
|
281
|
-
if (
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
320
|
+
const startProps = (0, clone_1.default)(props || {});
|
|
321
|
+
if (startType === 'check') {
|
|
322
|
+
startProps.timeout = 5000;
|
|
323
|
+
}
|
|
324
|
+
if (startType === 'start') {
|
|
325
|
+
if (ai.adapter.isControllable()) {
|
|
326
|
+
const d = ai.adapter;
|
|
327
|
+
let mode, settings;
|
|
328
|
+
if (!this.simulatorEnforced) {
|
|
329
|
+
if (forceErgMode) {
|
|
330
|
+
const modes = d.getSupportedCyclingModes().filter(C => C.isERG);
|
|
331
|
+
if (modes.length > 0) {
|
|
332
|
+
mode = new modes[0](d);
|
|
333
|
+
const modeInfo = this.configurationService.getModeSettings(ai.udid, mode);
|
|
334
|
+
settings = modeInfo.settings;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (!mode) {
|
|
338
|
+
const modeInfo = this.configurationService.getModeSettings(ai.udid);
|
|
339
|
+
mode = modeInfo.mode;
|
|
290
340
|
settings = modeInfo.settings;
|
|
291
341
|
}
|
|
292
342
|
}
|
|
293
|
-
if (!mode)
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
343
|
+
if (!mode)
|
|
344
|
+
mode = d.getDefaultCyclingMode();
|
|
345
|
+
d.setCyclingMode(mode, settings);
|
|
346
|
+
if (d.getCyclingMode().getModeProperty('eppSupport')) {
|
|
347
|
+
startProps.route = this.prepareEppRoute({ route, startPos, realityFactor, rideMode });
|
|
348
|
+
startProps.onStatusUpdate = (completed, total) => {
|
|
349
|
+
this.emit('start-update', this.getAdapterStateInfo(ai), completed, total);
|
|
350
|
+
};
|
|
297
351
|
}
|
|
298
352
|
}
|
|
299
|
-
if (!mode)
|
|
300
|
-
mode = d.getDefaultCyclingMode();
|
|
301
|
-
d.setCyclingMode(mode, settings);
|
|
302
|
-
if (d.getCyclingMode().getModeProperty('eppSupport')) {
|
|
303
|
-
startProps.route = this.prepareEppRoute({ route, startPos, realityFactor, rideMode });
|
|
304
|
-
startProps.onStatusUpdate = (completed, total) => {
|
|
305
|
-
this.emit('start-update', this.getAdapterStateInfo(ai), completed, total);
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
353
|
}
|
|
309
354
|
const sType = ai.adapter.hasCapability(incyclist_devices_1.IncyclistCapability.Control) ? 'bike' : 'sensor';
|
|
310
355
|
const logProps = {};
|
|
311
356
|
logProps[sType] = ai.adapter.getUniqueName();
|
|
312
357
|
logProps.cability = ai.adapter.getCapabilities().join('/');
|
|
313
358
|
logProps.interface = (0, logging_1.getLegacyInterface)(ai.adapter);
|
|
314
|
-
this.logEvent(Object.assign({ message:
|
|
359
|
+
this.logEvent(Object.assign({ message: `${startType} ${sType} request` }, logProps));
|
|
315
360
|
return ai.adapter.start(startProps)
|
|
316
361
|
.then(success => {
|
|
317
362
|
if (success) {
|
|
318
|
-
this.emit(
|
|
363
|
+
this.emit(`${startType}-success`, this.getAdapterStateInfo(ai));
|
|
319
364
|
}
|
|
320
365
|
ai.isStarted = true;
|
|
321
|
-
this.logEvent(Object.assign({ message:
|
|
366
|
+
this.logEvent(Object.assign({ message: `${startType} ${sType} request finished` }, logProps));
|
|
322
367
|
return success;
|
|
323
368
|
})
|
|
324
369
|
.catch(err => {
|
|
325
370
|
ai.isStarted = false;
|
|
326
|
-
this.logEvent(Object.assign(Object.assign({ message:
|
|
327
|
-
this.emit(
|
|
371
|
+
this.logEvent(Object.assign(Object.assign({ message: `${startType} ${sType} request failed` }, logProps), { reason: err.message }));
|
|
372
|
+
this.emit(`${startType}-error`, this.getAdapterStateInfo(ai), err);
|
|
328
373
|
return false;
|
|
329
374
|
});
|
|
330
375
|
});
|
|
331
376
|
const status = yield Promise.all(this.startPromises);
|
|
332
377
|
const allOK = status.find(s => s === false) === undefined;
|
|
333
|
-
this.emit(
|
|
378
|
+
this.emit(`${startType}-result`, allOK);
|
|
334
379
|
if (allOK) {
|
|
335
380
|
this.startRide(props);
|
|
336
381
|
}
|
|
@@ -338,6 +383,17 @@ class DeviceRideService extends events_1.default {
|
|
|
338
383
|
return allOK;
|
|
339
384
|
});
|
|
340
385
|
}
|
|
386
|
+
start(props) {
|
|
387
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
388
|
+
yield this.lazyInit();
|
|
389
|
+
const adapters = this.getAdapterList();
|
|
390
|
+
this.emit('start-request', adapters.map(this.getAdapterStateInfo));
|
|
391
|
+
const goodToGo = yield this.waitForPreviousStartToFinish();
|
|
392
|
+
if (!goodToGo)
|
|
393
|
+
return;
|
|
394
|
+
return this.startAdapters(adapters, 'start', props);
|
|
395
|
+
});
|
|
396
|
+
}
|
|
341
397
|
cancelStart() {
|
|
342
398
|
return __awaiter(this, void 0, void 0, function* () {
|
|
343
399
|
const adapters = this.getAdapterList();
|
|
@@ -386,6 +442,8 @@ class DeviceRideService extends events_1.default {
|
|
|
386
442
|
const hasControl = adapters.find(ai => ai.capabilities.includes(incyclist_devices_1.IncyclistCapability.Control)) !== undefined;
|
|
387
443
|
const hasPower = adapters.find(ai => ai.capabilities.includes(incyclist_devices_1.IncyclistCapability.Power)) !== undefined;
|
|
388
444
|
const adapterInfo = adapters.find(ai => ai.adapter.isEqual(deviceSettings));
|
|
445
|
+
if (!adapterInfo)
|
|
446
|
+
return;
|
|
389
447
|
adapterInfo.capabilities.forEach(capability => {
|
|
390
448
|
switch (capability) {
|
|
391
449
|
case incyclist_devices_1.IncyclistCapability.HeartRate:
|
package/lib/utils/clone.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "incyclist-services",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"gd-eventlog": "^0.1.22"
|
|
6
6
|
},
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"lib": "./src"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"incyclist-devices": "^2.0.
|
|
39
|
+
"incyclist-devices": "^2.0.4",
|
|
40
40
|
"uuid": "^9.0.0"
|
|
41
41
|
}
|
|
42
42
|
}
|