incyclist-devices 1.4.92 → 1.4.93

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
@@ -55,7 +55,8 @@ export default class IncyclistDevice implements DeviceAdapter {
55
55
  detected: boolean;
56
56
  selected: boolean;
57
57
  onDataFn: OnDeviceDataCallback;
58
- constructor(proto: DeviceProtocol);
58
+ settings: any;
59
+ constructor(proto: DeviceProtocol, settings?: any);
59
60
  isBike(): boolean;
60
61
  isPower(): boolean;
61
62
  isHrm(): boolean;
@@ -66,7 +67,10 @@ export default class IncyclistDevice implements DeviceAdapter {
66
67
  getPort(): string;
67
68
  getProtocol(): DeviceProtocol;
68
69
  getProtocolName(): string | undefined;
70
+ getSupportedCyclingModes(): any[];
71
+ getDefaultCyclingMode(): CyclingMode;
69
72
  setCyclingMode(mode: CyclingMode | string, settings?: any): void;
73
+ getCyclingMode(): CyclingMode;
70
74
  setIgnoreHrm(ignore: any): void;
71
75
  setIgnorePower(ignore: any): void;
72
76
  setIgnoreBike(ignore: any): void;
package/lib/Device.js CHANGED
@@ -4,11 +4,12 @@ exports.DEFAULT_USER_WEIGHT = exports.DEFAULT_BIKE_WEIGHT = void 0;
4
4
  exports.DEFAULT_BIKE_WEIGHT = 10;
5
5
  exports.DEFAULT_USER_WEIGHT = 75;
6
6
  class IncyclistDevice {
7
- constructor(proto) {
7
+ constructor(proto, settings) {
8
8
  this.protocol = proto;
9
9
  this.detected = false;
10
10
  this.selected = false;
11
11
  this.onDataFn = undefined;
12
+ this.settings = settings;
12
13
  }
13
14
  isBike() { throw new Error('not implemented'); }
14
15
  isPower() { throw new Error('not implemented'); }
@@ -22,7 +23,30 @@ class IncyclistDevice {
22
23
  getProtocolName() {
23
24
  return this.protocol ? this.protocol.getName() : undefined;
24
25
  }
25
- setCyclingMode(mode, settings) { }
26
+ getSupportedCyclingModes() { throw new Error('not implemented'); }
27
+ getDefaultCyclingMode() { throw new Error('not implemented'); }
28
+ setCyclingMode(mode, settings) {
29
+ let selectedMode;
30
+ if (typeof mode === 'string') {
31
+ const supported = this.getSupportedCyclingModes();
32
+ const CyclingModeClass = supported.find(M => { const m = new M(this); return m.getName() === mode; });
33
+ if (CyclingModeClass) {
34
+ this.settings.cyclingMode = new CyclingModeClass(this, settings);
35
+ return;
36
+ }
37
+ selectedMode = this.getDefaultCyclingMode();
38
+ }
39
+ else {
40
+ selectedMode = mode;
41
+ }
42
+ this.settings.cyclingMode = selectedMode;
43
+ this.settings.cyclingMode.setSettings(settings);
44
+ }
45
+ getCyclingMode() {
46
+ if (!this.settings.cyclingMode)
47
+ this.setCyclingMode(this.getDefaultCyclingMode());
48
+ return this.settings.cyclingMode;
49
+ }
26
50
  setIgnoreHrm(ignore) { }
27
51
  setIgnorePower(ignore) { }
28
52
  setIgnoreBike(ignore) { }
@@ -0,0 +1,24 @@
1
+ import CyclingMode, { CyclingModeProperty, IncyclistBikeData, UpdateRequest } from '../../CyclingMode';
2
+ import KettlerAdapter from "./adapter";
3
+ import PowerBasedCyclingModeBase from '../../modes/power-base';
4
+ export declare type ERGEvent = {
5
+ rpmUpdated?: boolean;
6
+ gearUpdated?: boolean;
7
+ starting?: boolean;
8
+ tsStart?: number;
9
+ };
10
+ export default class ERGCyclingMode extends PowerBasedCyclingModeBase implements CyclingMode {
11
+ prevRequest: UpdateRequest;
12
+ hasBikeUpdate: boolean;
13
+ chain: number[];
14
+ cassette: number[];
15
+ event: ERGEvent;
16
+ constructor(adapter: KettlerAdapter, props?: any);
17
+ getName(): string;
18
+ getDescription(): string;
19
+ getProperties(): CyclingModeProperty[];
20
+ getProperty(name: string): CyclingModeProperty;
21
+ getBikeInitRequest(): UpdateRequest;
22
+ sendBikeUpdate(request: UpdateRequest): UpdateRequest;
23
+ updateData(bikeData: IncyclistBikeData): any;
24
+ }
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const CyclingMode_1 = require("../../CyclingMode");
7
+ const power_base_1 = __importDefault(require("../../modes/power-base"));
8
+ const MIN_SPEED = 10;
9
+ const config = {
10
+ name: "ERG",
11
+ description: "Calculates speed based on power and slope. Power is either set by a workout",
12
+ properties: [
13
+ { key: 'bikeType', name: 'Bike Type', description: '', type: CyclingMode_1.CyclingModeProperyType.SingleSelect, options: ['Race', 'Mountain', 'Triathlon'], default: 'Race' },
14
+ { key: 'startPower', name: 'Starting Power', description: 'Initial power in Watts at start of training', type: CyclingMode_1.CyclingModeProperyType.Integer, default: 50, min: 25, max: 800 },
15
+ ]
16
+ };
17
+ class ERGCyclingMode extends power_base_1.default {
18
+ constructor(adapter, props) {
19
+ super(adapter, props);
20
+ this.hasBikeUpdate = false;
21
+ this.event = {};
22
+ this.initLogger('ERGMode');
23
+ }
24
+ getName() {
25
+ return config.name;
26
+ }
27
+ getDescription() {
28
+ return config.description;
29
+ }
30
+ getProperties() {
31
+ return config.properties;
32
+ }
33
+ getProperty(name) {
34
+ return config.properties.find(p => p.name === name);
35
+ }
36
+ getBikeInitRequest() {
37
+ const startPower = this.getSetting('startPower');
38
+ return { targetPower: startPower };
39
+ }
40
+ sendBikeUpdate(request) {
41
+ const getData = () => {
42
+ if (!this.data)
43
+ return {};
44
+ const { pedalRpm, slope, power, speed } = this.data;
45
+ return { pedalRpm, slope, power, speed };
46
+ };
47
+ this.logger.logEvent({ message: "processing update request", request, prev: this.prevRequest, data: getData() });
48
+ let newRequest = {};
49
+ try {
50
+ if (!request || request.reset || Object.keys(request).length === 0) {
51
+ this.prevRequest = {};
52
+ return request.reset ? { reset: true } : {};
53
+ }
54
+ const prevData = this.data || {};
55
+ if (request.targetPower !== undefined) {
56
+ delete request.slope;
57
+ delete request.refresh;
58
+ }
59
+ if (request.refresh) {
60
+ delete request.refresh;
61
+ if (this.prevRequest)
62
+ newRequest.targetPower = this.prevRequest.targetPower;
63
+ else {
64
+ this.prevRequest = this.getBikeInitRequest();
65
+ newRequest.targetPower = this.prevRequest.targetPower;
66
+ }
67
+ }
68
+ if (request.slope !== undefined) {
69
+ if (!this.data)
70
+ this.data = {};
71
+ this.data.slope = request.slope;
72
+ delete request.slope;
73
+ }
74
+ if (request.maxPower !== undefined && request.minPower !== undefined && request.maxPower === request.minPower) {
75
+ request.targetPower = request.maxPower;
76
+ newRequest.targetPower = request.targetPower;
77
+ }
78
+ if (request.maxPower !== undefined) {
79
+ if (newRequest.targetPower !== undefined && newRequest.targetPower > request.maxPower) {
80
+ newRequest.targetPower = request.maxPower;
81
+ }
82
+ newRequest.maxPower = request.maxPower;
83
+ }
84
+ if (request.minPower !== undefined) {
85
+ if (newRequest.targetPower !== undefined && newRequest.targetPower < request.minPower) {
86
+ newRequest.targetPower = request.minPower;
87
+ }
88
+ newRequest.minPower = request.minPower;
89
+ if (prevData.power && prevData.power < request.minPower)
90
+ newRequest.targetPower = request.minPower;
91
+ }
92
+ if (!newRequest.targetPower && newRequest.maxPower && prevData.power > newRequest.maxPower) {
93
+ newRequest.targetPower = newRequest.maxPower;
94
+ }
95
+ if (!newRequest.targetPower && newRequest.minPower && prevData.power < newRequest.minPower) {
96
+ newRequest.targetPower = newRequest.minPower;
97
+ }
98
+ this.prevRequest = JSON.parse(JSON.stringify(request));
99
+ }
100
+ catch (err) {
101
+ this.logger.logEvent({ message: "error", fn: 'sendBikeUpdate()', error: err.message || err, stack: err.stack });
102
+ }
103
+ return newRequest;
104
+ }
105
+ updateData(bikeData) {
106
+ const prevData = JSON.parse(JSON.stringify(this.data || {}));
107
+ const prevSpeed = prevData.speed;
108
+ const prevRequest = this.prevRequest || {};
109
+ const data = this.data || {};
110
+ const bikeType = this.getSetting('bikeType').toLowerCase();
111
+ try {
112
+ let power = bikeData.power || 0;
113
+ const slope = (prevData.slope !== undefined ? prevData.slope : prevRequest.slope || 0);
114
+ const distanceInternal = prevData.distanceInternal || 0;
115
+ const m = this.getWeight();
116
+ const t = this.getTimeSinceLastUpdate();
117
+ const { speed, distance } = this.calculateSpeedAndDistance(power, slope, m, t, { bikeType });
118
+ if (power === 0 && speed < MIN_SPEED) {
119
+ data.speed = Math.round(prevData.speed - 1) < 0 ? 0 : Math.round(prevData.speed - 1);
120
+ data.distanceInternal = distanceInternal + data.speed / 3.6 * t;
121
+ }
122
+ else {
123
+ data.speed = (power === 0 && speed < MIN_SPEED) ? 0 : speed;
124
+ data.distanceInternal = (power === 0 && speed < MIN_SPEED) ? distanceInternal : distanceInternal + distance;
125
+ }
126
+ data.power = Math.round(power);
127
+ data.slope = slope;
128
+ data.pedalRpm = bikeData.pedalRpm || 0;
129
+ if (data.time !== undefined && data.speed > 0)
130
+ data.time += t;
131
+ else
132
+ data.time = 0;
133
+ data.heartrate = bikeData.heartrate;
134
+ data.isPedalling = bikeData.isPedalling;
135
+ }
136
+ catch (err) {
137
+ this.logger.logEvent({ message: 'error', fn: 'updateData()', error: err.message || err });
138
+ }
139
+ this.logger.logEvent({ message: "updateData result", data, bikeData, prevRequest, prevSpeed });
140
+ this.data = data;
141
+ return data;
142
+ }
143
+ }
144
+ exports.default = ERGCyclingMode;
@@ -28,7 +28,6 @@ export interface KettlerDeviceSettings extends DeviceSettings {
28
28
  }
29
29
  export default class KettlerRacerAdapter extends DeviceAdapterBase implements DeviceAdapter, Bike {
30
30
  private id;
31
- private settings;
32
31
  private ignoreHrm;
33
32
  private ignoreBike;
34
33
  private ignorePower;
@@ -43,7 +42,7 @@ export default class KettlerRacerAdapter extends DeviceAdapterBase implements De
43
42
  private requestBusy;
44
43
  private comms;
45
44
  private prevDistance;
46
- constructor(protocol: DeviceProtocol, settings: DeviceSettings);
45
+ constructor(protocol: DeviceProtocol, settings: KettlerDeviceSettings);
47
46
  isBike(): boolean;
48
47
  isPower(): boolean;
49
48
  isHrm(): boolean;
@@ -96,8 +95,6 @@ export default class KettlerRacerAdapter extends DeviceAdapterBase implements De
96
95
  waitForOpened(retries?: boolean): Promise<boolean>;
97
96
  waitForClosed(): Promise<boolean>;
98
97
  getSupportedCyclingModes(): any[];
99
- setCyclingMode(mode: CyclingMode | string, settings?: any): void;
100
- getCyclingMode(): CyclingMode;
101
98
  getDefaultCyclingMode(): CyclingMode;
102
99
  setUserSettings(userSettings: any): void;
103
100
  setBikeSettings(bikeSettings: any): void;
@@ -36,12 +36,12 @@ const gd_eventlog_1 = require("gd-eventlog");
36
36
  const comms_1 = __importDefault(require("../comms"));
37
37
  const utils_1 = require("../../utils");
38
38
  const power_meter_1 = __importDefault(require("../../modes/power-meter"));
39
+ const ERGCyclingMode_1 = __importDefault(require("./ERGCyclingMode"));
39
40
  class KettlerRacerAdapter extends Device_1.default {
40
41
  constructor(protocol, settings) {
41
- super(protocol);
42
+ super(protocol, settings);
42
43
  this.requests = [];
43
44
  this.logger = new gd_eventlog_1.EventLogger('KettlerRacer');
44
- this.settings = settings;
45
45
  this.ignoreHrm = false;
46
46
  this.ignorePower = false;
47
47
  this.ignoreBike = false;
@@ -624,32 +624,10 @@ class KettlerRacerAdapter extends Device_1.default {
624
624
  });
625
625
  }
626
626
  getSupportedCyclingModes() {
627
- return [power_meter_1.default];
628
- }
629
- setCyclingMode(mode, settings) {
630
- let selectedMode;
631
- if (typeof mode === 'string') {
632
- const supported = this.getSupportedCyclingModes();
633
- const CyclingModeClass = supported.find(M => { const m = new M(this); return m.getName() === mode; });
634
- if (CyclingModeClass) {
635
- this.settings.cyclingMode = new CyclingModeClass(this, settings);
636
- return;
637
- }
638
- selectedMode = this.getDefaultCyclingMode();
639
- }
640
- else {
641
- selectedMode = mode;
642
- }
643
- this.settings.cyclingMode = selectedMode;
644
- this.settings.cyclingMode.setSettings(settings);
645
- }
646
- getCyclingMode() {
647
- if (!this.settings.cyclingMode)
648
- this.setCyclingMode(this.getDefaultCyclingMode());
649
- return this.settings.cyclingMode;
627
+ return [power_meter_1.default, ERGCyclingMode_1.default];
650
628
  }
651
629
  getDefaultCyclingMode() {
652
- return new power_meter_1.default(this);
630
+ return new ERGCyclingMode_1.default(this);
653
631
  }
654
632
  setUserSettings(userSettings) {
655
633
  this.settings.userSettings = userSettings;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.4.92",
3
+ "version": "1.4.93",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",