incyclist-devices 1.4.51 → 1.4.54
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/ant/antfe/AntFEAdapter.d.ts +43 -2
- package/lib/ant/antfe/AntFEAdapter.js +66 -35
- package/lib/ant/antfe/ant-fe-erg-mode.d.ts +5 -0
- package/lib/ant/antfe/ant-fe-erg-mode.js +13 -0
- package/lib/ant/antfe/ant-fe-st-mode.d.ts +7 -0
- package/lib/ant/antfe/ant-fe-st-mode.js +52 -0
- package/lib/ble/ble-erg-mode.d.ts +2 -2
- package/lib/ble/ble-interface.js +1 -0
- package/lib/ble/ble-st-mode.d.ts +2 -2
- package/lib/ble/fm.js +9 -0
- package/lib/ble/incyclist-protocol.js +1 -0
- package/package.json +46 -46
|
@@ -1,5 +1,41 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import AntAdapter from '../AntAdapter';
|
|
2
3
|
import { Queue } from '../../utils';
|
|
4
|
+
import CyclingMode, { IncyclistBikeData } from '../../CyclingMode';
|
|
5
|
+
export declare type AntFEDeviceData = {
|
|
6
|
+
DeviceID: number;
|
|
7
|
+
Temperature?: number;
|
|
8
|
+
ZeroOffset?: number;
|
|
9
|
+
SpinDownTime?: number;
|
|
10
|
+
EquipmentType?: 'Treadmill' | 'Elliptical' | 'StationaryBike' | 'Rower' | 'Climber' | 'NordicSkier' | 'Trainer' | 'General';
|
|
11
|
+
ElapsedTime?: number;
|
|
12
|
+
Distance?: number;
|
|
13
|
+
RealSpeed?: number;
|
|
14
|
+
VirtualSpeed?: number;
|
|
15
|
+
HeartRate?: number;
|
|
16
|
+
HeartRateSource?: 'HandContact' | 'EM' | 'ANT+';
|
|
17
|
+
State?: 'OFF' | 'READY' | 'IN_USE' | 'FINISHED';
|
|
18
|
+
CycleLength?: number;
|
|
19
|
+
Incline?: number;
|
|
20
|
+
Resistance?: number;
|
|
21
|
+
METs?: number;
|
|
22
|
+
CaloricBurnRate?: number;
|
|
23
|
+
Calories?: number;
|
|
24
|
+
_EventCount0x19?: number;
|
|
25
|
+
Cadence?: number;
|
|
26
|
+
AccumulatedPower?: number;
|
|
27
|
+
InstantaneousPower?: number;
|
|
28
|
+
AveragePower?: number;
|
|
29
|
+
TrainerStatus?: number;
|
|
30
|
+
TargetStatus?: 'OnTarget' | 'LowSpeed' | 'HighSpeed';
|
|
31
|
+
HwVersion?: number;
|
|
32
|
+
ManId?: number;
|
|
33
|
+
ModelNum?: number;
|
|
34
|
+
SwVersion?: number;
|
|
35
|
+
SerialNumber?: number;
|
|
36
|
+
PairedDevices?: any[];
|
|
37
|
+
RawData: Buffer;
|
|
38
|
+
};
|
|
3
39
|
export default class AntFEAdapter extends AntAdapter {
|
|
4
40
|
started: boolean;
|
|
5
41
|
starting: boolean;
|
|
@@ -8,6 +44,7 @@ export default class AntFEAdapter extends AntAdapter {
|
|
|
8
44
|
queue?: Queue<any>;
|
|
9
45
|
workerId?: any;
|
|
10
46
|
currentCmd?: any;
|
|
47
|
+
cyclingMode: CyclingMode;
|
|
11
48
|
constructor(DeviceID: any, port: any, stick: any, protocol: any);
|
|
12
49
|
isBike(): boolean;
|
|
13
50
|
isHrm(): boolean;
|
|
@@ -15,11 +52,15 @@ export default class AntFEAdapter extends AntAdapter {
|
|
|
15
52
|
getProfile(): string;
|
|
16
53
|
getName(): string;
|
|
17
54
|
getDisplayName(): string;
|
|
55
|
+
getSupportedCyclingModes(): Array<any>;
|
|
56
|
+
setCyclingMode(mode: string | CyclingMode, settings?: any): void;
|
|
57
|
+
getCyclingMode(): CyclingMode;
|
|
58
|
+
getDefaultCyclingMode(): CyclingMode;
|
|
18
59
|
onAttached(): void;
|
|
19
60
|
getLogData(data: any, excludeList: any): any;
|
|
20
|
-
onDeviceData(deviceData:
|
|
61
|
+
onDeviceData(deviceData: AntFEDeviceData): void;
|
|
62
|
+
mapData(deviceData: AntFEDeviceData): IncyclistBikeData;
|
|
21
63
|
onDeviceEvent(data: any): void;
|
|
22
|
-
updateData(data: any, deviceData: any): any;
|
|
23
64
|
transformData(bikeData: any): any;
|
|
24
65
|
start(props?: any): Promise<any>;
|
|
25
66
|
stop(): Promise<boolean>;
|
|
@@ -16,6 +16,8 @@ const gd_eventlog_1 = require("gd-eventlog");
|
|
|
16
16
|
const AntAdapter_1 = __importDefault(require("../AntAdapter"));
|
|
17
17
|
const utils_1 = require("../utils");
|
|
18
18
|
const utils_2 = require("../../utils");
|
|
19
|
+
const ant_fe_st_mode_1 = __importDefault(require("./ant-fe-st-mode"));
|
|
20
|
+
const ant_fe_erg_mode_1 = __importDefault(require("./ant-fe-erg-mode"));
|
|
19
21
|
const floatVal = (d) => d ? parseFloat(d) : d;
|
|
20
22
|
const intVal = (d) => d ? parseInt(d) : d;
|
|
21
23
|
const hex = (v) => Math.abs(v).toString(16).toUpperCase();
|
|
@@ -54,6 +56,34 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
54
56
|
const hrmStr = ComputedHeartRate ? ` (${ComputedHeartRate})` : '';
|
|
55
57
|
return `${(0, utils_1.getBrand)(ManId)} FE ${DeviceID}${hrmStr}`;
|
|
56
58
|
}
|
|
59
|
+
getSupportedCyclingModes() {
|
|
60
|
+
return [ant_fe_st_mode_1.default, ant_fe_erg_mode_1.default];
|
|
61
|
+
}
|
|
62
|
+
setCyclingMode(mode, settings) {
|
|
63
|
+
let selectedMode;
|
|
64
|
+
if (typeof mode === 'string') {
|
|
65
|
+
const supported = this.getSupportedCyclingModes();
|
|
66
|
+
const CyclingModeClass = supported.find(M => { const m = new M(this); return m.getName() === mode; });
|
|
67
|
+
if (CyclingModeClass) {
|
|
68
|
+
this.cyclingMode = new CyclingModeClass(this, settings);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
selectedMode = this.getDefaultCyclingMode();
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
selectedMode = mode;
|
|
75
|
+
}
|
|
76
|
+
this.cyclingMode = selectedMode;
|
|
77
|
+
this.cyclingMode.setSettings(settings);
|
|
78
|
+
}
|
|
79
|
+
getCyclingMode() {
|
|
80
|
+
if (!this.cyclingMode)
|
|
81
|
+
this.cyclingMode = this.getDefaultCyclingMode();
|
|
82
|
+
return this.cyclingMode;
|
|
83
|
+
}
|
|
84
|
+
getDefaultCyclingMode() {
|
|
85
|
+
return new ant_fe_st_mode_1.default(this);
|
|
86
|
+
}
|
|
57
87
|
onAttached() {
|
|
58
88
|
this.logger.logEvent({ message: 'Device connected' });
|
|
59
89
|
this.connected = true;
|
|
@@ -74,8 +104,9 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
74
104
|
if (!this.lastUpdate || (Date.now() - this.lastUpdate) > this.updateFrequency) {
|
|
75
105
|
const logData = this.getLogData(deviceData, ['PairedDevices', 'RawData']);
|
|
76
106
|
this.logger.logEvent({ message: 'onDeviceData', data: logData });
|
|
77
|
-
|
|
78
|
-
|
|
107
|
+
let incyclistData = this.mapData(deviceData);
|
|
108
|
+
incyclistData = this.getCyclingMode().updateData(incyclistData);
|
|
109
|
+
const data = this.transformData(incyclistData);
|
|
79
110
|
this.onDataFn(data);
|
|
80
111
|
this.lastUpdate = Date.now();
|
|
81
112
|
}
|
|
@@ -84,6 +115,25 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
84
115
|
catch (err) {
|
|
85
116
|
}
|
|
86
117
|
}
|
|
118
|
+
mapData(deviceData) {
|
|
119
|
+
const data = {
|
|
120
|
+
isPedalling: false,
|
|
121
|
+
power: 0,
|
|
122
|
+
pedalRpm: undefined,
|
|
123
|
+
speed: 0,
|
|
124
|
+
heartrate: 0,
|
|
125
|
+
distanceInternal: 0,
|
|
126
|
+
slope: undefined,
|
|
127
|
+
time: undefined
|
|
128
|
+
};
|
|
129
|
+
data.speed = (deviceData.VirtualSpeed !== undefined ? deviceData.VirtualSpeed : (deviceData.RealSpeed || 0)) * 3.6;
|
|
130
|
+
data.slope = (deviceData.Incline !== undefined ? deviceData.Incline : data.slope);
|
|
131
|
+
data.power = (deviceData.InstantaneousPower !== undefined ? deviceData.InstantaneousPower : data.power);
|
|
132
|
+
data.time = (deviceData.ElapsedTime !== undefined ? deviceData.ElapsedTime : data.time);
|
|
133
|
+
data.pedalRpm = (deviceData.Cadence !== undefined ? deviceData.Cadence : data.pedalRpm);
|
|
134
|
+
data.isPedalling = data.pedalRpm > 0 || (data.pedalRpm === undefined && data.power > 0);
|
|
135
|
+
return data;
|
|
136
|
+
}
|
|
87
137
|
onDeviceEvent(data) {
|
|
88
138
|
try {
|
|
89
139
|
const cmdInfo = this.currentCmd;
|
|
@@ -127,43 +177,21 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
127
177
|
this.logger.logEvent({ message: 'Error', fn: 'parseEvent', event: { message: hex(data.message), code: hex(data.code) }, error: err.message || err });
|
|
128
178
|
}
|
|
129
179
|
}
|
|
130
|
-
updateData(data, deviceData) {
|
|
131
|
-
if (data.distanceOffs === undefined)
|
|
132
|
-
data.distanceOffs = 0;
|
|
133
|
-
data.speed = (deviceData.VirtualSpeed !== undefined ? deviceData.VirtualSpeed : deviceData.RealSpeed) * 3.6;
|
|
134
|
-
data.slope = (deviceData.Incline !== undefined ? deviceData.Incline : data.slope);
|
|
135
|
-
data.power = (deviceData.InstantaneousPower !== undefined ? deviceData.InstantaneousPower : data.power);
|
|
136
|
-
data.pedalRpm = (deviceData.Cadence !== undefined ? deviceData.Cadence : data.pedalRpm);
|
|
137
|
-
data.heartrate = (deviceData.HeartRate !== undefined ? deviceData.HeartRate : data.heartrate);
|
|
138
|
-
if (deviceData.Distance !== undefined && deviceData.Distance !== 0) {
|
|
139
|
-
data.distanceInternal = deviceData.Distance - data.distanceOffs;
|
|
140
|
-
data.distance = data.distanceInternal / 1000;
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
if (this.lastUpdate && deviceData.Cadence !== undefined && deviceData.Cadence > 0 && data.speed) {
|
|
144
|
-
const t = (Date.now() - this.lastUpdate) / 1000;
|
|
145
|
-
const prevDistance = data.distanceInternal || 0;
|
|
146
|
-
data.distanceInternal = Math.round(data.speed / 3.6 * t) + prevDistance;
|
|
147
|
-
data.distance = data.distanceInternal / 1000;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return data;
|
|
151
|
-
}
|
|
152
180
|
transformData(bikeData) {
|
|
153
181
|
if (bikeData === undefined)
|
|
154
182
|
return;
|
|
155
183
|
let distance = 0;
|
|
156
184
|
if (this.distanceInternal !== undefined && bikeData.distanceInternal !== undefined) {
|
|
157
|
-
distance =
|
|
185
|
+
distance = Math.round(bikeData.distanceInternal - this.distanceInternal);
|
|
158
186
|
}
|
|
159
187
|
if (bikeData.distanceInternal !== undefined)
|
|
160
188
|
this.distanceInternal = bikeData.distanceInternal;
|
|
161
189
|
let data = {
|
|
162
|
-
speed:
|
|
163
|
-
slope:
|
|
164
|
-
power:
|
|
165
|
-
cadence:
|
|
166
|
-
heartrate:
|
|
190
|
+
speed: bikeData.speed,
|
|
191
|
+
slope: bikeData.slope,
|
|
192
|
+
power: bikeData.power !== undefined ? Math.round(bikeData.power) : undefined,
|
|
193
|
+
cadence: bikeData.pedalRpm !== undefined ? Math.round(bikeData.pedalRpm) : undefined,
|
|
194
|
+
heartrate: bikeData.heartrate !== undefined ? Math.round(bikeData.heartrate) : undefined,
|
|
167
195
|
distance,
|
|
168
196
|
timestamp: Date.now()
|
|
169
197
|
};
|
|
@@ -295,14 +323,17 @@ class AntFEAdapter extends AntAdapter_1.default {
|
|
|
295
323
|
}
|
|
296
324
|
sendUpdate(request) {
|
|
297
325
|
return __awaiter(this, void 0, void 0, function* () {
|
|
298
|
-
this.
|
|
326
|
+
if (this.paused)
|
|
327
|
+
return;
|
|
328
|
+
const update = this.getCyclingMode().sendBikeUpdate(request);
|
|
329
|
+
this.logger.logEvent({ message: 'send bike update requested', update, request });
|
|
299
330
|
try {
|
|
300
331
|
const isReset = (!request || request.reset || Object.keys(request).length === 0);
|
|
301
|
-
if (
|
|
302
|
-
yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTrackResistance(
|
|
332
|
+
if (update.slope !== undefined) {
|
|
333
|
+
yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTrackResistance(update.slope); }), 2, 100);
|
|
303
334
|
}
|
|
304
|
-
if (
|
|
305
|
-
yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(
|
|
335
|
+
if (update.targetPower !== undefined) {
|
|
336
|
+
yield (0, utils_2.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () { return yield this.sendTargetPower(update.targetPower); }), 2, 100);
|
|
306
337
|
}
|
|
307
338
|
else if (request.maxPower !== undefined) {
|
|
308
339
|
if (this.data.power && this.data.power > request.maxPower)
|
|
@@ -0,0 +1,13 @@
|
|
|
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 ble_erg_mode_1 = __importDefault(require("../../ble/ble-erg-mode"));
|
|
7
|
+
class AntFeERGCyclingMode extends ble_erg_mode_1.default {
|
|
8
|
+
constructor(adapter, props) {
|
|
9
|
+
super(adapter, props);
|
|
10
|
+
this.initLogger('AntERGMode');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.default = AntFeERGCyclingMode;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import FtmsCyclingMode from "../../ble/ble-st-mode";
|
|
2
|
+
import { UpdateRequest } from "../../CyclingMode";
|
|
3
|
+
import { DeviceAdapter } from "../../Device";
|
|
4
|
+
export default class AntStCyclingMode extends FtmsCyclingMode {
|
|
5
|
+
constructor(adapter: DeviceAdapter, props?: any);
|
|
6
|
+
sendBikeUpdate(request: UpdateRequest): UpdateRequest;
|
|
7
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
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 ble_st_mode_1 = __importDefault(require("../../ble/ble-st-mode"));
|
|
7
|
+
class AntStCyclingMode extends ble_st_mode_1.default {
|
|
8
|
+
constructor(adapter, props) {
|
|
9
|
+
super(adapter, props);
|
|
10
|
+
this.initLogger('AntSTMode');
|
|
11
|
+
}
|
|
12
|
+
sendBikeUpdate(request) {
|
|
13
|
+
const getData = () => {
|
|
14
|
+
if (!this.data)
|
|
15
|
+
return {};
|
|
16
|
+
const { gear, pedalRpm, slope, power, speed } = this.data;
|
|
17
|
+
return { gear, pedalRpm, slope, power, speed };
|
|
18
|
+
};
|
|
19
|
+
const event = {};
|
|
20
|
+
if (this.data === undefined)
|
|
21
|
+
event.noData = true;
|
|
22
|
+
if (request.slope !== undefined && (event.noData || Math.abs(request.slope - this.data.slope) >= 0.1))
|
|
23
|
+
event.slopeUpdate = true;
|
|
24
|
+
if (this.prevRequest === undefined)
|
|
25
|
+
event.initialCall = true;
|
|
26
|
+
this.logger.logEvent({ message: "processing update request", request, prev: this.prevRequest, data: getData(), event });
|
|
27
|
+
let newRequest = {};
|
|
28
|
+
if (request.slope === undefined && request.targetPower === undefined && request.refresh && this.prevRequest) {
|
|
29
|
+
return this.prevRequest;
|
|
30
|
+
}
|
|
31
|
+
if (request.slope !== undefined) {
|
|
32
|
+
newRequest.slope = parseFloat(request.slope.toFixed(1));
|
|
33
|
+
this.data.slope = newRequest.slope;
|
|
34
|
+
}
|
|
35
|
+
if (request.targetPower !== undefined) {
|
|
36
|
+
newRequest.targetPower = request.targetPower;
|
|
37
|
+
}
|
|
38
|
+
if (request.minPower && request.maxPower && request.minPower === request.maxPower) {
|
|
39
|
+
newRequest.targetPower = request.minPower;
|
|
40
|
+
}
|
|
41
|
+
const prevData = this.data;
|
|
42
|
+
if (newRequest.targetPower === undefined && prevData && prevData.power) {
|
|
43
|
+
if (request.minPower !== undefined && prevData.power < request.minPower)
|
|
44
|
+
newRequest.targetPower = request.minPower;
|
|
45
|
+
if (request.maxPower !== undefined && prevData.power > request.maxPower)
|
|
46
|
+
newRequest.targetPower = request.maxPower;
|
|
47
|
+
}
|
|
48
|
+
this.prevRequest = JSON.parse(JSON.stringify(newRequest));
|
|
49
|
+
return newRequest;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.default = AntStCyclingMode;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import CyclingMode, { CyclingModeProperty, IncyclistBikeData, UpdateRequest } from "../CyclingMode";
|
|
2
|
+
import { DeviceAdapter } from "../Device";
|
|
2
3
|
import PowerBasedCyclingModeBase from "../modes/power-base";
|
|
3
|
-
import { FmAdapter } from "./fm";
|
|
4
4
|
export default class BleERGCyclingMode extends PowerBasedCyclingModeBase implements CyclingMode {
|
|
5
5
|
prevRequest: UpdateRequest;
|
|
6
6
|
hasBikeUpdate: boolean;
|
|
7
7
|
chain: number[];
|
|
8
8
|
cassette: number[];
|
|
9
|
-
constructor(adapter:
|
|
9
|
+
constructor(adapter: DeviceAdapter, props?: any);
|
|
10
10
|
getName(): string;
|
|
11
11
|
getDescription(): string;
|
|
12
12
|
getProperties(): CyclingModeProperty[];
|
package/lib/ble/ble-interface.js
CHANGED
|
@@ -346,6 +346,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
|
|
|
346
346
|
return DeviceClasses;
|
|
347
347
|
}
|
|
348
348
|
createDevice(DeviceClass, peripheral, characteristics) {
|
|
349
|
+
this.logEvent({ message: 'trying to create device', peripheral: peripheral.address, characteristics });
|
|
349
350
|
const C = DeviceClass;
|
|
350
351
|
const device = new C({ peripheral });
|
|
351
352
|
const existingDevice = this.devices.find(i => i.device.id === device.id && i.device.getProfile() === device.getProfile());
|
package/lib/ble/ble-st-mode.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import CyclingMode, { CyclingModeProperty, IncyclistBikeData, UpdateRequest } from "../CyclingMode";
|
|
2
|
+
import { DeviceAdapter } from "../Device";
|
|
2
3
|
import PowerBasedCyclingModeBase from "../modes/power-base";
|
|
3
|
-
import { FmAdapter } from "./fm";
|
|
4
4
|
export default class FtmsCyclingMode extends PowerBasedCyclingModeBase implements CyclingMode {
|
|
5
5
|
prevRequest: UpdateRequest;
|
|
6
6
|
hasBikeUpdate: boolean;
|
|
7
|
-
constructor(adapter:
|
|
7
|
+
constructor(adapter: DeviceAdapter, props?: any);
|
|
8
8
|
getName(): string;
|
|
9
9
|
getDescription(): string;
|
|
10
10
|
getProperties(): CyclingModeProperty[];
|
package/lib/ble/fm.js
CHANGED
|
@@ -332,6 +332,8 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
332
332
|
this.logEvent({ message: 'setTargetPower', power, skip: (this.data.targetPower !== undefined && this.data.targetPower === power) });
|
|
333
333
|
if (this.data.targetPower !== undefined && this.data.targetPower === power)
|
|
334
334
|
return true;
|
|
335
|
+
if (!this.hasControl)
|
|
336
|
+
return;
|
|
335
337
|
const hasControl = yield this.requestControl();
|
|
336
338
|
const data = Buffer.alloc(3);
|
|
337
339
|
data.writeUInt8(5, 0);
|
|
@@ -343,6 +345,8 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
343
345
|
setSlope(slope) {
|
|
344
346
|
return __awaiter(this, void 0, void 0, function* () {
|
|
345
347
|
this.logEvent({ message: 'setSlope', slope });
|
|
348
|
+
if (!this.hasControl)
|
|
349
|
+
return;
|
|
346
350
|
const { windSpeed, crr, cw } = this;
|
|
347
351
|
return yield this.setIndoorBikeSimulation(windSpeed, slope, crr, cw);
|
|
348
352
|
});
|
|
@@ -351,6 +355,8 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
351
355
|
return __awaiter(this, void 0, void 0, function* () {
|
|
352
356
|
if (this.data.targetInclination !== undefined && this.data.targetInclination === inclination)
|
|
353
357
|
return true;
|
|
358
|
+
if (!this.hasControl)
|
|
359
|
+
return;
|
|
354
360
|
const hasControl = yield this.requestControl();
|
|
355
361
|
if (!hasControl) {
|
|
356
362
|
this.logEvent({ message: 'setTargetInclination failed', reason: 'control is disabled' });
|
|
@@ -365,6 +371,8 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
|
|
|
365
371
|
}
|
|
366
372
|
setIndoorBikeSimulation(windSpeed, gradient, crr, cw) {
|
|
367
373
|
return __awaiter(this, void 0, void 0, function* () {
|
|
374
|
+
if (!this.hasControl)
|
|
375
|
+
return;
|
|
368
376
|
const hasControl = yield this.requestControl();
|
|
369
377
|
const data = Buffer.alloc(7);
|
|
370
378
|
data.writeUInt8(17, 0);
|
|
@@ -569,6 +577,7 @@ class FmAdapter extends Device_1.default {
|
|
|
569
577
|
break;
|
|
570
578
|
}
|
|
571
579
|
}
|
|
580
|
+
this.device.requestControl();
|
|
572
581
|
const startRequest = this.getCyclingMode().getBikeInitRequest();
|
|
573
582
|
yield this.sendUpdate(startRequest);
|
|
574
583
|
bleDevice.on('data', (data) => {
|
|
@@ -77,6 +77,7 @@ class BleProtocol extends DeviceProtocol_1.default {
|
|
|
77
77
|
return new hrm_1.HrmAdapter(fromDevice ? bleDevice : new hrm_1.default(props()), this);
|
|
78
78
|
case 'fm':
|
|
79
79
|
case 'smart trainer':
|
|
80
|
+
case 'wahoo smart trainer':
|
|
80
81
|
case 'fitness machine':
|
|
81
82
|
let device;
|
|
82
83
|
if (fromDevice)
|
package/package.json
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "incyclist-devices",
|
|
3
|
-
"version": "1.4.
|
|
4
|
-
"dependencies": {
|
|
5
|
-
"@serialport/parser-byte-length": "^9.0.1",
|
|
6
|
-
"@serialport/parser-delimiter": "^9.0.1",
|
|
7
|
-
"@types/serialport": "^8.0.1",
|
|
8
|
-
"gd-ant-plus": "^0.0.33",
|
|
9
|
-
"win32filetime": "^1.0.2"
|
|
10
|
-
},
|
|
11
|
-
"peerDependencies": {
|
|
12
|
-
"gd-eventlog": "^0.1.22"
|
|
13
|
-
},
|
|
14
|
-
"devDependencies": {
|
|
15
|
-
"@types/jest": "^27.0.3",
|
|
16
|
-
"@types/node": "^10.17.58",
|
|
17
|
-
"eslint": "^7.32.0",
|
|
18
|
-
"eslint-config-react-app": "^6.0.0",
|
|
19
|
-
"eslint-loader": "^4.0.2",
|
|
20
|
-
"jest": "^27.4.3",
|
|
21
|
-
"ts-jest": "^27.1.0",
|
|
22
|
-
"typescript": "^4.5.2"
|
|
23
|
-
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"lint": "eslint . --ext .ts",
|
|
26
|
-
"build": "tsc",
|
|
27
|
-
"test": "jest --coverage",
|
|
28
|
-
"dev": "nodemon --watch src -e ts,js --exec npm run build"
|
|
29
|
-
},
|
|
30
|
-
"files": [
|
|
31
|
-
"lib/"
|
|
32
|
-
],
|
|
33
|
-
"main": "lib/DeviceSupport.js",
|
|
34
|
-
"directories": {
|
|
35
|
-
"example": "./sample",
|
|
36
|
-
"lib": "./src"
|
|
37
|
-
},
|
|
38
|
-
"eslintConfig": {
|
|
39
|
-
"extends": "react-app",
|
|
40
|
-
"rules": {
|
|
41
|
-
"jsx-a11y/anchor-is-valid": [
|
|
42
|
-
"off"
|
|
43
|
-
]
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "incyclist-devices",
|
|
3
|
+
"version": "1.4.54",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"@serialport/parser-byte-length": "^9.0.1",
|
|
6
|
+
"@serialport/parser-delimiter": "^9.0.1",
|
|
7
|
+
"@types/serialport": "^8.0.1",
|
|
8
|
+
"gd-ant-plus": "^0.0.33",
|
|
9
|
+
"win32filetime": "^1.0.2"
|
|
10
|
+
},
|
|
11
|
+
"peerDependencies": {
|
|
12
|
+
"gd-eventlog": "^0.1.22"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/jest": "^27.0.3",
|
|
16
|
+
"@types/node": "^10.17.58",
|
|
17
|
+
"eslint": "^7.32.0",
|
|
18
|
+
"eslint-config-react-app": "^6.0.0",
|
|
19
|
+
"eslint-loader": "^4.0.2",
|
|
20
|
+
"jest": "^27.4.3",
|
|
21
|
+
"ts-jest": "^27.1.0",
|
|
22
|
+
"typescript": "^4.5.2"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"lint": "eslint . --ext .ts",
|
|
26
|
+
"build": "tsc",
|
|
27
|
+
"test": "jest --coverage",
|
|
28
|
+
"dev": "nodemon --watch src -e ts,js --exec npm run build"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"lib/"
|
|
32
|
+
],
|
|
33
|
+
"main": "lib/DeviceSupport.js",
|
|
34
|
+
"directories": {
|
|
35
|
+
"example": "./sample",
|
|
36
|
+
"lib": "./src"
|
|
37
|
+
},
|
|
38
|
+
"eslintConfig": {
|
|
39
|
+
"extends": "react-app",
|
|
40
|
+
"rules": {
|
|
41
|
+
"jsx-a11y/anchor-is-valid": [
|
|
42
|
+
"off"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|