incyclist-devices 1.4.56 → 1.4.59

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/Device.d.ts CHANGED
@@ -34,7 +34,7 @@ export interface DeviceAdapter extends Device {
34
34
  getName(): string;
35
35
  getPort(): string;
36
36
  getProtocol(): DeviceProtocol;
37
- getProtocolName(): string;
37
+ getProtocolName(): string | undefined;
38
38
  setIgnoreHrm(ignore: boolean): void;
39
39
  setIgnorePower(ignore: boolean): void;
40
40
  setIgnoreBike(ignore: boolean): void;
@@ -17,6 +17,12 @@ export default class AntAdapter extends DeviceAdapter {
17
17
  logger: EventLogger;
18
18
  lastUpdate?: number;
19
19
  updateFrequency: number;
20
+ userSettings: {
21
+ weight?: number;
22
+ };
23
+ bikeSettings: {
24
+ weight?: number;
25
+ };
20
26
  constructor(protocol: any);
21
27
  isSame(device: DeviceAdapter): boolean;
22
28
  setSensor(sensor: any): void;
@@ -26,6 +32,7 @@ export default class AntAdapter extends DeviceAdapter {
26
32
  setIgnorePower(ignore: any): void;
27
33
  getProfile(): string;
28
34
  getPort(): string;
35
+ getWeight(): number;
29
36
  setChannel(channel: any): void;
30
37
  setStick(stick: any): void;
31
38
  isStopped(): boolean;
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DEFAULT_UPDATE_FREQUENCY = void 0;
7
7
  const Device_1 = __importDefault(require("../Device"));
8
+ const Device_2 = require("../Device");
8
9
  exports.DEFAULT_UPDATE_FREQUENCY = 1000;
9
10
  class AntAdapter extends Device_1.default {
10
11
  constructor(protocol) {
@@ -49,6 +50,17 @@ class AntAdapter extends Device_1.default {
49
50
  getPort() {
50
51
  return this.port;
51
52
  }
53
+ getWeight() {
54
+ let userWeight = Device_2.DEFAULT_USER_WEIGHT;
55
+ let bikeWeight = Device_2.DEFAULT_BIKE_WEIGHT;
56
+ if (this.userSettings && this.userSettings.weight) {
57
+ userWeight = Number(this.userSettings.weight);
58
+ }
59
+ if (this.bikeSettings && this.bikeSettings.weight) {
60
+ bikeWeight = Number(this.bikeSettings.weight);
61
+ }
62
+ return bikeWeight + userWeight;
63
+ }
52
64
  setChannel(channel) {
53
65
  this.channel = channel;
54
66
  }
@@ -78,6 +90,10 @@ class AntAdapter extends Device_1.default {
78
90
  });
79
91
  }
80
92
  start(props) {
93
+ if (props && props.user)
94
+ this.userSettings = props.user;
95
+ if (props && props.bikeSettings)
96
+ this.bikeSettings = props.bikeSettings;
81
97
  return new Promise(resolve => {
82
98
  this.stopped = false;
83
99
  resolve(true);
@@ -61,6 +61,8 @@ export default class BleInterface extends BleInterfaceClass {
61
61
  disconnect(): Promise<boolean>;
62
62
  isConnected(): boolean;
63
63
  getDevicesFromServices(deviceTypes: (typeof BleDeviceClass)[], services: string | string[]): (typeof BleDeviceClass)[];
64
+ getAllSupportedServices(): any[];
65
+ getAllSupportedDeviceTypes(): (typeof BleDeviceClass)[];
64
66
  getServicesFromDeviceTypes(deviceTypes: (typeof BleDeviceClass)[]): string[];
65
67
  getServicesFromDevice(device: BleDeviceClass): string[];
66
68
  waitForConnectFinished(timeout: any): Promise<unknown>;
@@ -18,8 +18,6 @@ const ble_1 = require("./ble");
18
18
  const ble_peripheral_1 = __importDefault(require("./ble-peripheral"));
19
19
  const CONNECT_TIMEOUT = 5000;
20
20
  const DEFAULT_SCAN_TIMEOUT = 20000;
21
- const BACKGROUND_SCAN_TIMEOUT = 30000;
22
- const DEFAULT_SERVICES = ['1818', '180d', '1826'];
23
21
  class BleInterface extends ble_1.BleInterfaceClass {
24
22
  constructor(props = {}) {
25
23
  super(props);
@@ -76,14 +74,6 @@ class BleInterface extends ble_1.BleInterfaceClass {
76
74
  const timeout = props.timeout || 2000;
77
75
  const runBackgroundScan = () => {
78
76
  return;
79
- this.scanState.isBackgroundScan = true;
80
- this.scan({ timeout: BACKGROUND_SCAN_TIMEOUT, isBackgroundScan: true })
81
- .then(() => {
82
- this.scanState.isBackgroundScan = false;
83
- })
84
- .catch(() => {
85
- this.scanState.isBackgroundScan = false;
86
- });
87
77
  };
88
78
  return new Promise((resolve, reject) => {
89
79
  if (this.connectState.isConnected) {
@@ -223,6 +213,25 @@ class BleInterface extends ble_1.BleInterfaceClass {
223
213
  }
224
214
  return [];
225
215
  }
216
+ getAllSupportedServices() {
217
+ const supported = BleInterface.deviceClasses;
218
+ const res = [];
219
+ if (supported && supported.length > 0) {
220
+ supported.forEach(dc => {
221
+ if (dc && dc.services) {
222
+ dc.services.forEach(s => {
223
+ if (!res.includes(s))
224
+ res.push(s);
225
+ });
226
+ }
227
+ });
228
+ }
229
+ return res;
230
+ }
231
+ getAllSupportedDeviceTypes() {
232
+ const supported = BleInterface.deviceClasses;
233
+ return supported.map(dc => dc.Class);
234
+ }
226
235
  getServicesFromDeviceTypes(deviceTypes) {
227
236
  let services = [];
228
237
  try {
@@ -369,7 +378,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
369
378
  this.scanState.isConnecting = true;
370
379
  const existing = this.devices.find(i => (!profile || i.device.getProfile() === profile) && (i.device.address === requested.address || i.device.id === requested.id || i.device.name === requested.name));
371
380
  if (existing) {
372
- const connected = yield existing.device.connect();
381
+ yield existing.device.connect();
373
382
  this.scanState.isConnecting = false;
374
383
  return existing.device;
375
384
  }
@@ -461,7 +470,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
461
470
  requested.profile;
462
471
  const { id, address, name } = requested || {};
463
472
  const scanForDevice = (requested !== null && requested !== undefined);
464
- const services = (props.isBackgroundScan || !deviceTypes || deviceTypes.length === 0) ? DEFAULT_SERVICES : this.getServicesFromDeviceTypes(deviceTypes);
473
+ const services = (props.isBackgroundScan || !deviceTypes || deviceTypes.length === 0) ? this.getAllSupportedServices() : this.getServicesFromDeviceTypes(deviceTypes);
465
474
  const bleBinding = this.getBinding();
466
475
  if (!bleBinding)
467
476
  return Promise.reject(new Error('no binding defined'));
@@ -485,7 +494,8 @@ class BleInterface extends ble_1.BleInterfaceClass {
485
494
  }
486
495
  else {
487
496
  opStr = 'scan';
488
- this.logEvent({ message: 'scan start', services });
497
+ const supported = BleInterface.deviceClasses.map(dc => ({ id: dc.id, type: dc.type, services: dc.services }));
498
+ this.logEvent({ message: 'scan start', services, supported });
489
499
  }
490
500
  if (this.scanState.isScanning) {
491
501
  try {
@@ -506,6 +516,8 @@ class BleInterface extends ble_1.BleInterfaceClass {
506
516
  const knownDevices = this.devices.map(i => ({ name: i.device.name, address: i.device.address, isConnected: i.isConnected, connectState: i.device.getConnectState() }));
507
517
  this.logEvent({ message: `${opStr}: check if already registered`, device: { name, address }, knownDevices });
508
518
  const existing = this.devices.find(i => (i.device.address === address || i.device.name === name || i.device.id === id));
519
+ if (existing)
520
+ this.logEvent({ message: `${opStr}: device already registered`, device: { name, address } });
509
521
  }
510
522
  }
511
523
  const onTimeout = () => {
@@ -527,14 +539,18 @@ class BleInterface extends ble_1.BleInterfaceClass {
527
539
  const onPeripheralFound = (peripheral, fromCache = false) => __awaiter(this, void 0, void 0, function* () {
528
540
  if (fromCache)
529
541
  this.logEvent({ message: 'adding from Cache', peripheral: peripheral.address });
542
+ else {
543
+ const { id, name, address } = peripheral;
544
+ this.logEvent({ message: 'BLE scan: found device', peripheral: { id, name, address } });
545
+ }
530
546
  if (!peripheral || !peripheral.advertisement || !peripheral.advertisement.serviceUuids || peripheral.advertisement.serviceUuids.length === 0)
531
547
  return;
548
+ if (peripheral.address === undefined || peripheral.address === '')
549
+ peripheral.address = peripheral.id;
532
550
  const isPeripheralProcessed = peripheralsProcessed.find(p => p === peripheral.address) !== undefined;
533
551
  if (isPeripheralProcessed)
534
552
  return;
535
553
  peripheralsProcessed.push(peripheral.address);
536
- let chachedPeripheralInfo = this.peripheralCache.find(i => i.address === peripheral.address);
537
- const str = fromCache ? 'added' : 'detected';
538
554
  const characteristics = yield this.getCharacteristics(peripheral);
539
555
  const DeviceClasses = this.getDeviceClasses(peripheral, { profile });
540
556
  let cntFound = 0;
@@ -39,7 +39,7 @@ const ble_interface_1 = __importDefault(require("./ble-interface"));
39
39
  const fm_1 = __importStar(require("./fm"));
40
40
  const hrm_1 = __importStar(require("./hrm"));
41
41
  const pwr_1 = __importStar(require("./pwr"));
42
- const supportedDeviceTypes = [hrm_1.default, pwr_1.default, fm_1.default];
42
+ const wahoo_kickr_1 = __importDefault(require("./wahoo-kickr"));
43
43
  class BleProtocol extends DeviceProtocol_1.default {
44
44
  constructor(binding) {
45
45
  super();
@@ -79,9 +79,13 @@ class BleProtocol extends DeviceProtocol_1.default {
79
79
  if (fromDevice)
80
80
  device = bleDevice;
81
81
  else {
82
- device = this.ble.findDeviceInCache(Object.assign(Object.assign({}, props()), { profile: 'Smart Trainer' }));
83
- if (!device)
84
- device = new fm_1.default(props());
82
+ device = this.ble.findDeviceInCache(Object.assign(Object.assign({}, props()), { profile }));
83
+ if (!device) {
84
+ if (profile.toLocaleLowerCase() === 'wahoo smart trainer')
85
+ device = new wahoo_kickr_1.default(props());
86
+ else
87
+ device = new fm_1.default(props());
88
+ }
85
89
  }
86
90
  return new fm_1.FmAdapter(device, this);
87
91
  case 'cp':
@@ -109,6 +113,7 @@ class BleProtocol extends DeviceProtocol_1.default {
109
113
  }
110
114
  });
111
115
  this.logger.logEvent({ message: 'scan started' });
116
+ const supportedDeviceTypes = this.ble.getAllSupportedDeviceTypes();
112
117
  yield this.ble.scan({ deviceTypes: supportedDeviceTypes, timeout: 20000 });
113
118
  if (props && props.onScanFinished) {
114
119
  props.onScanFinished(props.id);
package/lib/ble/pwr.d.ts CHANGED
@@ -54,6 +54,12 @@ export declare class PwrAdapter extends DeviceAdapter {
54
54
  mode: CyclingMode;
55
55
  distanceInternal: number;
56
56
  prevDataTS: number;
57
+ userSettings: {
58
+ weight?: number;
59
+ };
60
+ bikeSettings: {
61
+ weight?: number;
62
+ };
57
63
  constructor(device: BleDeviceClass, protocol: BleProtocol);
58
64
  isBike(): boolean;
59
65
  isHrm(): boolean;
@@ -65,6 +71,7 @@ export declare class PwrAdapter extends DeviceAdapter {
65
71
  getCyclingMode(): CyclingMode;
66
72
  getDefaultCyclingMode(): CyclingMode;
67
73
  getPort(): string;
74
+ getWeight(): number;
68
75
  setIgnoreBike(ignore: any): void;
69
76
  setIgnorePower(ignore: any): void;
70
77
  onDeviceData(deviceData: PowerData): void;
package/lib/ble/pwr.js CHANGED
@@ -1,4 +1,23 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
2
21
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
22
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
23
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -15,7 +34,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
34
  exports.PwrAdapter = void 0;
16
35
  const ble_device_1 = require("./ble-device");
17
36
  const ble_interface_1 = __importDefault(require("./ble-interface"));
18
- const Device_1 = __importDefault(require("../Device"));
37
+ const Device_1 = __importStar(require("../Device"));
19
38
  const gd_eventlog_1 = require("gd-eventlog");
20
39
  const power_meter_1 = __importDefault(require("../modes/power-meter"));
21
40
  class BleCyclingPowerDevice extends ble_device_1.BleDevice {
@@ -172,6 +191,17 @@ class PwrAdapter extends Device_1.default {
172
191
  getPort() {
173
192
  return 'ble';
174
193
  }
194
+ getWeight() {
195
+ let userWeight = Device_1.DEFAULT_USER_WEIGHT;
196
+ let bikeWeight = Device_1.DEFAULT_BIKE_WEIGHT;
197
+ if (this.userSettings && this.userSettings.weight) {
198
+ userWeight = Number(this.userSettings.weight);
199
+ }
200
+ if (this.bikeSettings && this.bikeSettings.weight) {
201
+ bikeWeight = Number(this.bikeSettings.weight);
202
+ }
203
+ return bikeWeight + userWeight;
204
+ }
175
205
  setIgnoreBike(ignore) {
176
206
  this.ignore = ignore;
177
207
  }
@@ -230,6 +260,10 @@ class PwrAdapter extends Device_1.default {
230
260
  }
231
261
  start(props) {
232
262
  return __awaiter(this, void 0, void 0, function* () {
263
+ if (props && props.user)
264
+ this.userSettings = props.user;
265
+ if (props && props.bikeSettings)
266
+ this.bikeSettings = props.bikeSettings;
233
267
  this.logger.logEvent({ message: 'start requested', profile: this.getProfile(), props });
234
268
  try {
235
269
  const bleDevice = yield this.ble.connectDevice(this.device);
@@ -108,8 +108,8 @@ class DaumAdapterBase extends Device_1.default {
108
108
  }
109
109
  }
110
110
  getWeight() {
111
- const userWeight = this.userSettings.weight || Device_1.DEFAULT_USER_WEIGHT;
112
- const bikeWeight = this.bikeSettings.weight || Device_1.DEFAULT_BIKE_WEIGHT;
111
+ const userWeight = Number(this.userSettings.weight || Device_1.DEFAULT_USER_WEIGHT);
112
+ const bikeWeight = Number(this.bikeSettings.weight || Device_1.DEFAULT_BIKE_WEIGHT);
113
113
  return bikeWeight + userWeight;
114
114
  }
115
115
  getCurrentBikeData() {
@@ -318,13 +318,13 @@ class DaumAdapterBase extends Device_1.default {
318
318
  return;
319
319
  let distance = 0;
320
320
  if (this.distanceInternal !== undefined && this.cyclingData.distanceInternal !== undefined) {
321
- distance = (0, utils_1.intVal)(this.cyclingData.distanceInternal - this.distanceInternal);
321
+ distance = this.cyclingData.distanceInternal - this.distanceInternal;
322
322
  }
323
323
  if (this.cyclingData.distanceInternal !== undefined)
324
324
  this.distanceInternal = this.cyclingData.distanceInternal;
325
325
  let data = {
326
- speed: (0, utils_1.floatVal)(this.cyclingData.speed),
327
- slope: (0, utils_1.floatVal)(this.cyclingData.slope),
326
+ speed: this.cyclingData.speed,
327
+ slope: this.cyclingData.slope,
328
328
  power: (0, utils_1.intVal)(this.cyclingData.power),
329
329
  cadence: (0, utils_1.intVal)(this.cyclingData.pedalRpm),
330
330
  heartrate: (0, utils_1.intVal)(this.cyclingData.heartrate),
@@ -366,7 +366,7 @@ class DaumAdapterBase extends Device_1.default {
366
366
  }
367
367
  catch (err) {
368
368
  this.requestBusy = false;
369
- this.logEvent({ message: 'error', fn: 'sendRequest()', error: err.message || err });
369
+ this.logEvent({ message: 'sendRequest error', error: err.message || err });
370
370
  return;
371
371
  }
372
372
  });
@@ -147,7 +147,7 @@ class ERGCyclingMode extends power_base_1.default {
147
147
  const m = this.getWeight();
148
148
  const t = this.getTimeSinceLastUpdate();
149
149
  const { speed, distance } = this.calculateSpeedAndDistance(power, slope, m, t, { bikeType });
150
- data.speed = parseFloat(speed.toFixed(1));
150
+ data.speed = speed;
151
151
  data.power = Math.round(power);
152
152
  data.distanceInternal = distanceInternal + distance;
153
153
  data.slope = slope;
@@ -83,7 +83,11 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
83
83
  return __awaiter(this, void 0, void 0, function* () {
84
84
  this.logger.logEvent({ message: 'start()', props });
85
85
  const opts = props || {};
86
- const { user } = props;
86
+ const { user, bikeSettings } = opts;
87
+ if (user && user.weight)
88
+ this.userSettings.weight = user.weight;
89
+ if (bikeSettings && bikeSettings.weight)
90
+ this.bikeSettings.weight = bikeSettings.weight;
87
91
  this.initData();
88
92
  let startState = {};
89
93
  return (0, utils_1.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () {
@@ -68,6 +68,10 @@ class DaumPremiumDevice extends DaumAdapter_1.default {
68
68
  console.log('~~~setPersonSupport:', this.getCyclingMode().getModeProperty('setPersonSupport'));
69
69
  console.log('~~~eppSupport:', this.getCyclingMode().getModeProperty('eppSupport'));
70
70
  const opts = props || {};
71
+ if (opts.user && opts.user.weight)
72
+ this.userSettings.weight = opts.user.weight;
73
+ if (opts.bikeSettings && opts.bikeSettings.weight)
74
+ this.bikeSettings.weight = opts.bikeSettings.weight;
71
75
  const user = opts.user || this.userSettings;
72
76
  const route = opts.route;
73
77
  var info = {};
@@ -1,13 +1,14 @@
1
1
  import { EventLogger } from "gd-eventlog";
2
- import CyclingMode, { CyclingModeBase, CyclingModeProperty, IncyclistBikeData, UpdateRequest } from "../CyclingMode";
2
+ import { CyclingModeProperty, IncyclistBikeData, UpdateRequest } from "../CyclingMode";
3
3
  import { Simulator } from "../simulator/Simulator";
4
+ import PowerBasedCyclingModeBase from "./power-base";
4
5
  export declare type ERGEvent = {
5
6
  rpmUpdated?: boolean;
6
7
  gearUpdated?: boolean;
7
8
  starting?: boolean;
8
9
  tsStart?: number;
9
10
  };
10
- export default class SimulatorCyclingMode extends CyclingModeBase implements CyclingMode {
11
+ export default class SimulatorCyclingMode extends PowerBasedCyclingModeBase {
11
12
  logger: EventLogger;
12
13
  data: IncyclistBikeData;
13
14
  prevRequest: UpdateRequest;
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const gd_eventlog_1 = require("gd-eventlog");
7
7
  const CyclingMode_1 = require("../CyclingMode");
8
- const calculations_1 = __importDefault(require("../calculations"));
8
+ const power_base_1 = __importDefault(require("./power-base"));
9
9
  const config = {
10
10
  name: "Simulator",
11
11
  description: "Simulates a ride with constant speed or power output",
@@ -14,9 +14,10 @@ const config = {
14
14
  { key: 'delay', name: 'Start Delay', description: 'Delay (in s) at start of training', type: CyclingMode_1.CyclingModeProperyType.Integer, default: 2, min: 0, max: 30 },
15
15
  { key: 'power', name: 'Power', description: 'Power (in W) at start of training', condition: (s) => !s.mode || s.mode === 'Power', type: CyclingMode_1.CyclingModeProperyType.Integer, default: 150, min: 25, max: 800 },
16
16
  { key: 'speed', name: 'Speed', description: 'Speed (in km/h) at start of training', condition: (s) => s.mode === 'Speed', type: CyclingMode_1.CyclingModeProperyType.Integer, default: 30, min: 5, max: 50 },
17
+ { key: 'bikeType', name: 'Bike Type', description: '', type: CyclingMode_1.CyclingModeProperyType.SingleSelect, options: ['Race', 'Mountain', 'Triathlon'], default: 'Race' }
17
18
  ]
18
19
  };
19
- class SimulatorCyclingMode extends CyclingMode_1.CyclingModeBase {
20
+ class SimulatorCyclingMode extends power_base_1.default {
20
21
  constructor(adapter, props) {
21
22
  super(adapter, props);
22
23
  this.prevUpdateTS = 0;
@@ -62,41 +63,52 @@ class SimulatorCyclingMode extends CyclingMode_1.CyclingModeBase {
62
63
  const prevSpeed = prevData.speed;
63
64
  const prevRequest = this.prevRequest || {};
64
65
  const data = this.data || {};
66
+ const bikeType = (this.getSetting('bikeType') || 'Race').toLowerCase();
65
67
  const mode = this.getSetting('mode');
66
68
  delete this.event.gearUpdated;
67
69
  delete this.event.rpmUpdated;
68
70
  try {
69
71
  let rpm = 90;
70
- let power = (mode === 'Power' || !mode) ? Number(this.getSetting('power')) : bikeData.power || 0;
72
+ let power = (!mode || mode.toLowerCase() === 'power') ? Number(this.getSetting('power')) : bikeData.power || 0;
71
73
  let slope = (prevData.slope !== undefined ? prevData.slope : prevRequest.slope || 0);
72
- let speed = mode === 'Speed' ? Number(this.getSetting('speed')) : bikeData.speed || 0;
73
- let m = 75;
74
+ let speed = mode.toLowerCase() === 'speed' ? Number(this.getSetting('speed')) : bikeData.speed || 0;
75
+ let m = this.getWeight();
74
76
  let distanceInternal = prevData.distanceInternal || 0;
75
77
  let ts = Date.now();
76
78
  let duration = this.prevUpdateTS === 0 ? 0 : ((ts - this.prevUpdateTS) / 1000);
77
- if (mode === 'Power' || !mode) {
78
- speed = calculations_1.default.calculateSpeed(m, power, slope, { bikeType: 'race' });
79
+ const t = this.getTimeSinceLastUpdate();
80
+ let distance = 0;
81
+ if (!mode || mode.toLowerCase() === 'power') {
82
+ const res = this.calculateSpeedAndDistance(power, slope, m, t, { bikeType });
83
+ speed = res.speed;
84
+ distance = res.distance;
79
85
  }
80
- else if (mode === 'Speed') {
81
- power = calculations_1.default.calculatePower(m, speed / 3.6, slope, { bikeType: 'race' });
86
+ else if (mode.toLowerCase() === 'speed') {
87
+ const res = this.calculatePowerAndDistance(speed, slope, m, t, { bikeType });
88
+ power = res.power;
89
+ distance = res.distance;
82
90
  }
83
91
  if (prevRequest.targetPower) {
84
92
  power = prevRequest.targetPower;
85
- speed = calculations_1.default.calculateSpeed(m, power, slope, { bikeType: 'race' });
93
+ const res = this.calculateSpeedAndDistance(power, slope, m, t, { bikeType });
94
+ speed = res.speed;
95
+ distance = res.distance;
86
96
  }
87
97
  if (prevRequest.maxPower && power > prevRequest.maxPower) {
88
98
  power = prevRequest.maxPower;
89
- speed = calculations_1.default.calculateSpeed(m, power, slope, { bikeType: 'race' });
99
+ const res = this.calculateSpeedAndDistance(power, slope, m, t, { bikeType });
100
+ speed = res.speed;
101
+ distance = res.distance;
90
102
  }
91
103
  else if (prevRequest.minPower && power < prevRequest.minPower) {
92
104
  power = prevRequest.minPower;
93
- speed = calculations_1.default.calculateSpeed(m, power, slope, { bikeType: 'race' });
105
+ const res = this.calculateSpeedAndDistance(power, slope, m, t, { bikeType });
106
+ speed = res.speed;
107
+ distance = res.distance;
94
108
  }
95
- let v = speed / 3.6;
96
- distanceInternal += (v * duration);
97
- data.speed = parseFloat(speed.toFixed(1));
109
+ data.speed = speed;
98
110
  data.power = Math.round(power);
99
- data.distanceInternal = distanceInternal;
111
+ data.distanceInternal = distanceInternal + distance;
100
112
  data.slope = slope;
101
113
  data.pedalRpm = rpm;
102
114
  if (data.time !== undefined)
@@ -24,6 +24,12 @@ export declare class Simulator extends DeviceAdapter {
24
24
  data: IncyclistBikeData;
25
25
  isBot: boolean;
26
26
  ignoreHrm: boolean;
27
+ userSettings: {
28
+ weight?: number;
29
+ };
30
+ bikeSettings: {
31
+ weight?: number;
32
+ };
27
33
  constructor(protocol?: DeviceProtocol, props?: SimulatorSettings);
28
34
  isBike(): boolean;
29
35
  isHrm(): boolean;
@@ -32,6 +38,7 @@ export declare class Simulator extends DeviceAdapter {
32
38
  getID(): string;
33
39
  getName(): string;
34
40
  getPort(): string;
41
+ getWeight(): number;
35
42
  setIgnoreHrm(ignore: any): void;
36
43
  getSupportedCyclingModes(): Array<any>;
37
44
  getDefaultCyclingMode(): CyclingMode;
@@ -37,6 +37,7 @@ const DeviceRegistry_1 = __importDefault(require("../DeviceRegistry"));
37
37
  const Device_1 = __importDefault(require("../Device"));
38
38
  const gd_eventlog_1 = require("gd-eventlog");
39
39
  const simulator_1 = __importDefault(require("../modes/simulator"));
40
+ const Device_2 = require("../Device");
40
41
  const DEFAULT_SETTINGS = { name: 'Simulator', port: '', isBot: false };
41
42
  class Simulator extends Device_1.default {
42
43
  constructor(protocol, props = DEFAULT_SETTINGS) {
@@ -72,6 +73,17 @@ class Simulator extends Device_1.default {
72
73
  getID() { return Simulator.NAME; }
73
74
  getName() { return Simulator.NAME; }
74
75
  getPort() { return 'local'; }
76
+ getWeight() {
77
+ let userWeight = Device_2.DEFAULT_USER_WEIGHT;
78
+ let bikeWeight = Device_2.DEFAULT_BIKE_WEIGHT;
79
+ if (this.userSettings && this.userSettings.weight) {
80
+ userWeight = Number(this.userSettings.weight);
81
+ }
82
+ if (this.bikeSettings && this.bikeSettings.weight) {
83
+ bikeWeight = Number(this.bikeSettings.weight);
84
+ }
85
+ return bikeWeight + userWeight;
86
+ }
75
87
  setIgnoreHrm(ignore) {
76
88
  this.ignoreHrm = ignore;
77
89
  }
@@ -108,6 +120,10 @@ class Simulator extends Device_1.default {
108
120
  start(props) {
109
121
  return __awaiter(this, void 0, void 0, function* () {
110
122
  this.startProps = props;
123
+ if (props && props.user)
124
+ this.userSettings = props.user;
125
+ if (props && props.bikeSettings)
126
+ this.bikeSettings = props.bikeSettings;
111
127
  return new Promise((resolve) => {
112
128
  if (!this.isBot)
113
129
  this.logger.logEvent({ message: 'start', iv: this.iv });
@@ -117,6 +133,12 @@ class Simulator extends Device_1.default {
117
133
  this.started = true;
118
134
  this.time = Date.now();
119
135
  this.startTS = this.time;
136
+ if (this.isBot) {
137
+ this.startTS = props.activity ? Date.parse(props.activity.startTime) : this.startTS - 1500;
138
+ const sm = this.getCyclingMode();
139
+ sm.prevUpdateTS = this.startTS;
140
+ this.update();
141
+ }
120
142
  if (this.iv !== undefined) {
121
143
  clearInterval(this.iv);
122
144
  this.iv = undefined;
@@ -192,8 +214,9 @@ class Simulator extends Device_1.default {
192
214
  update() {
193
215
  const startDelay = this.getCyclingMode().getSetting('delay');
194
216
  const timeSinceStart = Date.now() - this.startTS;
195
- if (startDelay && timeSinceStart < startDelay * 1000)
217
+ if (!this.isBot && startDelay && timeSinceStart < startDelay * 1000) {
196
218
  return;
219
+ }
197
220
  const prevDist = this.data.distanceInternal;
198
221
  this.data = this.getCyclingMode().updateData(this.data);
199
222
  let data = {
@@ -204,7 +227,7 @@ class Simulator extends Device_1.default {
204
227
  distance: this.data.distanceInternal - prevDist,
205
228
  heartrate: Math.round(this.data.power - 10 + Math.random() * 20),
206
229
  timestamp: Date.now(),
207
- deviceTime: Math.round((Date.now() - this.startTS) / 1000),
230
+ deviceTime: (Date.now() - this.startTS) / 1000,
208
231
  deviceDistanceCounter: this.data.distanceInternal
209
232
  };
210
233
  this.paused = (this.data.speed === 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.4.56",
3
+ "version": "1.4.59",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",