incyclist-devices 3.0.25 → 3.0.26
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/cjs/ble/base/adapter.js +9 -2
- package/lib/cjs/ble/fm/adapter.js +43 -1
- package/lib/cjs/ble/fm/sensor.js +0 -3
- package/lib/esm/ble/base/adapter.js +9 -2
- package/lib/esm/ble/fm/adapter.js +43 -1
- package/lib/esm/ble/fm/sensor.js +0 -3
- package/lib/types/ble/base/adapter.d.ts +1 -0
- package/lib/types/ble/fm/adapter.d.ts +3 -0
- package/package.json +1 -1
|
@@ -253,6 +253,8 @@ class BleAdapter extends adpater_js_1.default {
|
|
|
253
253
|
}
|
|
254
254
|
async initControl(_props) {
|
|
255
255
|
}
|
|
256
|
+
async initControlBestEffort(_props) {
|
|
257
|
+
}
|
|
256
258
|
getStartLogProps(props) {
|
|
257
259
|
const capabilities = this.props?.capabilities;
|
|
258
260
|
const { user, userWeight, bikeWeight, timeout, wheelDiameter, restart, scanOnly } = props ?? {};
|
|
@@ -288,11 +290,16 @@ class BleAdapter extends adpater_js_1.default {
|
|
|
288
290
|
this.stopped = true;
|
|
289
291
|
return false;
|
|
290
292
|
}
|
|
291
|
-
await this.waitForInitialData(timeout);
|
|
292
293
|
await this.checkCapabilities();
|
|
293
294
|
const skipControl = this.props.capabilities && !this.props.capabilities.includes(index_js_1.IncyclistCapability.Control);
|
|
294
|
-
|
|
295
|
+
const isControllable = this.hasCapability(index_js_1.IncyclistCapability.Control) && !skipControl;
|
|
296
|
+
if (isControllable) {
|
|
295
297
|
await this.initControl(startProps);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
await this.initControlBestEffort(startProps);
|
|
301
|
+
}
|
|
302
|
+
await this.waitForInitialData(timeout);
|
|
296
303
|
this.stopped = false;
|
|
297
304
|
this.started = true;
|
|
298
305
|
if (wasPaused)
|
|
@@ -12,6 +12,7 @@ const adapter_js_1 = __importDefault(require("../base/adapter.js"));
|
|
|
12
12
|
const consts_js_1 = require("./consts.js");
|
|
13
13
|
const index_js_1 = require("../../types/index.js");
|
|
14
14
|
const utils_js_1 = require("../../utils/utils.js");
|
|
15
|
+
const task_js_1 = require("../../utils/task.js");
|
|
15
16
|
const index_js_2 = require("../zwift/play/index.js");
|
|
16
17
|
const index_js_3 = require("../../features/index.js");
|
|
17
18
|
const fm_resistance_js_1 = __importDefault(require("../../modes/fm-resistance.js"));
|
|
@@ -21,6 +22,7 @@ class BleFmAdapter extends adapter_js_1.default {
|
|
|
21
22
|
distanceInternal = 0;
|
|
22
23
|
connectPromise;
|
|
23
24
|
requestControlRetryDelay = 1000;
|
|
25
|
+
requestControlTimeout = 10000;
|
|
24
26
|
promiseSendUpdate;
|
|
25
27
|
zwiftPlay;
|
|
26
28
|
isHubInitialized = false;
|
|
@@ -168,8 +170,36 @@ class BleFmAdapter extends adapter_js_1.default {
|
|
|
168
170
|
if (!this.hasCapability(index_js_1.IncyclistCapability.Control))
|
|
169
171
|
return;
|
|
170
172
|
await this.establishControl();
|
|
173
|
+
await this.attemptStartRequest();
|
|
171
174
|
await this.sendInitialRequest();
|
|
172
175
|
}
|
|
176
|
+
async initControlBestEffort(_startProps) {
|
|
177
|
+
if (!this.isStarting())
|
|
178
|
+
return;
|
|
179
|
+
this.setConstants();
|
|
180
|
+
try {
|
|
181
|
+
const hasControl = await this.getSensor().requestControl();
|
|
182
|
+
if (hasControl) {
|
|
183
|
+
this.logEvent({ message: 'control granted (downgraded device)', device: this.getName(), interface: this.getInterface() });
|
|
184
|
+
await this.attemptStartRequest();
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
this.logEvent({ message: 'could not establish control (downgraded device, non-fatal)', device: this.getName(), interface: this.getInterface() });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
this.logEvent({ message: 'could not establish control (downgraded device, non-fatal)', device: this.getName(), interface: this.getInterface(), error: err.message });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async attemptStartRequest() {
|
|
195
|
+
try {
|
|
196
|
+
const started = await this.getSensor().startRequest();
|
|
197
|
+
this.logEvent({ message: started ? 'start request acknowledged' : 'start request not acknowledged (non-fatal)', device: this.getName(), interface: this.getInterface() });
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
this.logEvent({ message: 'start request failed (non-fatal)', device: this.getName(), interface: this.getInterface(), error: err.message });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
173
203
|
setConstants() {
|
|
174
204
|
const mode = this.getCyclingMode();
|
|
175
205
|
const sensor = this.getSensor();
|
|
@@ -195,7 +225,7 @@ class BleFmAdapter extends adapter_js_1.default {
|
|
|
195
225
|
let hasControl = false;
|
|
196
226
|
let tryCnt = 0;
|
|
197
227
|
const sensor = this.getSensor();
|
|
198
|
-
|
|
228
|
+
const controlPromise = new Promise((resolve) => {
|
|
199
229
|
this.startTask.notifyOnStop(() => {
|
|
200
230
|
resolve(false);
|
|
201
231
|
});
|
|
@@ -219,6 +249,18 @@ class BleFmAdapter extends adapter_js_1.default {
|
|
|
219
249
|
};
|
|
220
250
|
waitUntilControl();
|
|
221
251
|
});
|
|
252
|
+
const waitTask = new task_js_1.InteruptableTask(controlPromise, {
|
|
253
|
+
timeout: this.requestControlTimeout,
|
|
254
|
+
name: 'establishControl',
|
|
255
|
+
errorOnTimeout: false,
|
|
256
|
+
log: this.logEvent.bind(this)
|
|
257
|
+
});
|
|
258
|
+
const granted = await waitTask.run();
|
|
259
|
+
if (!granted && this.isStarting()) {
|
|
260
|
+
this.logEvent({ message: 'could not establish control', device: this.getName(), interface: this.getInterface() });
|
|
261
|
+
throw new Error('could not establish control');
|
|
262
|
+
}
|
|
263
|
+
return granted;
|
|
222
264
|
}
|
|
223
265
|
async sendInitialRequest() {
|
|
224
266
|
const startRequest = this.getCyclingMode().getBikeInitRequest();
|
package/lib/cjs/ble/fm/sensor.js
CHANGED
|
@@ -111,9 +111,6 @@ class BleFitnessMachineDevice extends sensor_js_1.TBleSensor {
|
|
|
111
111
|
}
|
|
112
112
|
if (!this.isSubscribed())
|
|
113
113
|
return false;
|
|
114
|
-
if (this.features?.setPower === false && this.features?.setSlope === false && this.features?.setResistance === false) {
|
|
115
|
-
return true;
|
|
116
|
-
}
|
|
117
114
|
this.logEvent({ message: 'requestControl' });
|
|
118
115
|
this.isCheckingControl = true;
|
|
119
116
|
const data = Buffer.alloc(1);
|
|
@@ -248,6 +248,8 @@ export default class BleAdapter extends IncyclistDevice {
|
|
|
248
248
|
}
|
|
249
249
|
async initControl(_props) {
|
|
250
250
|
}
|
|
251
|
+
async initControlBestEffort(_props) {
|
|
252
|
+
}
|
|
251
253
|
getStartLogProps(props) {
|
|
252
254
|
const capabilities = this.props?.capabilities;
|
|
253
255
|
const { user, userWeight, bikeWeight, timeout, wheelDiameter, restart, scanOnly } = props ?? {};
|
|
@@ -283,11 +285,16 @@ export default class BleAdapter extends IncyclistDevice {
|
|
|
283
285
|
this.stopped = true;
|
|
284
286
|
return false;
|
|
285
287
|
}
|
|
286
|
-
await this.waitForInitialData(timeout);
|
|
287
288
|
await this.checkCapabilities();
|
|
288
289
|
const skipControl = this.props.capabilities && !this.props.capabilities.includes(IncyclistCapability.Control);
|
|
289
|
-
|
|
290
|
+
const isControllable = this.hasCapability(IncyclistCapability.Control) && !skipControl;
|
|
291
|
+
if (isControllable) {
|
|
290
292
|
await this.initControl(startProps);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
await this.initControlBestEffort(startProps);
|
|
296
|
+
}
|
|
297
|
+
await this.waitForInitialData(timeout);
|
|
291
298
|
this.stopped = false;
|
|
292
299
|
this.started = true;
|
|
293
300
|
if (wasPaused)
|
|
@@ -7,6 +7,7 @@ import BleAdapter from '../base/adapter.js';
|
|
|
7
7
|
import { cRR, cwABike } from './consts.js';
|
|
8
8
|
import { IncyclistCapability } from '../../types/index.js';
|
|
9
9
|
import { sleep } from '../../utils/utils.js';
|
|
10
|
+
import { InteruptableTask } from '../../utils/task.js';
|
|
10
11
|
import { BleZwiftPlaySensor } from '../zwift/play/index.js';
|
|
11
12
|
import { useFeatureToggle } from '../../features/index.js';
|
|
12
13
|
import FMResistanceMode from '../../modes/fm-resistance.js';
|
|
@@ -16,6 +17,7 @@ export default class BleFmAdapter extends BleAdapter {
|
|
|
16
17
|
distanceInternal = 0;
|
|
17
18
|
connectPromise;
|
|
18
19
|
requestControlRetryDelay = 1000;
|
|
20
|
+
requestControlTimeout = 10000;
|
|
19
21
|
promiseSendUpdate;
|
|
20
22
|
zwiftPlay;
|
|
21
23
|
isHubInitialized = false;
|
|
@@ -163,8 +165,36 @@ export default class BleFmAdapter extends BleAdapter {
|
|
|
163
165
|
if (!this.hasCapability(IncyclistCapability.Control))
|
|
164
166
|
return;
|
|
165
167
|
await this.establishControl();
|
|
168
|
+
await this.attemptStartRequest();
|
|
166
169
|
await this.sendInitialRequest();
|
|
167
170
|
}
|
|
171
|
+
async initControlBestEffort(_startProps) {
|
|
172
|
+
if (!this.isStarting())
|
|
173
|
+
return;
|
|
174
|
+
this.setConstants();
|
|
175
|
+
try {
|
|
176
|
+
const hasControl = await this.getSensor().requestControl();
|
|
177
|
+
if (hasControl) {
|
|
178
|
+
this.logEvent({ message: 'control granted (downgraded device)', device: this.getName(), interface: this.getInterface() });
|
|
179
|
+
await this.attemptStartRequest();
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
this.logEvent({ message: 'could not establish control (downgraded device, non-fatal)', device: this.getName(), interface: this.getInterface() });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
this.logEvent({ message: 'could not establish control (downgraded device, non-fatal)', device: this.getName(), interface: this.getInterface(), error: err.message });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async attemptStartRequest() {
|
|
190
|
+
try {
|
|
191
|
+
const started = await this.getSensor().startRequest();
|
|
192
|
+
this.logEvent({ message: started ? 'start request acknowledged' : 'start request not acknowledged (non-fatal)', device: this.getName(), interface: this.getInterface() });
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
this.logEvent({ message: 'start request failed (non-fatal)', device: this.getName(), interface: this.getInterface(), error: err.message });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
168
198
|
setConstants() {
|
|
169
199
|
const mode = this.getCyclingMode();
|
|
170
200
|
const sensor = this.getSensor();
|
|
@@ -190,7 +220,7 @@ export default class BleFmAdapter extends BleAdapter {
|
|
|
190
220
|
let hasControl = false;
|
|
191
221
|
let tryCnt = 0;
|
|
192
222
|
const sensor = this.getSensor();
|
|
193
|
-
|
|
223
|
+
const controlPromise = new Promise((resolve) => {
|
|
194
224
|
this.startTask.notifyOnStop(() => {
|
|
195
225
|
resolve(false);
|
|
196
226
|
});
|
|
@@ -214,6 +244,18 @@ export default class BleFmAdapter extends BleAdapter {
|
|
|
214
244
|
};
|
|
215
245
|
waitUntilControl();
|
|
216
246
|
});
|
|
247
|
+
const waitTask = new InteruptableTask(controlPromise, {
|
|
248
|
+
timeout: this.requestControlTimeout,
|
|
249
|
+
name: 'establishControl',
|
|
250
|
+
errorOnTimeout: false,
|
|
251
|
+
log: this.logEvent.bind(this)
|
|
252
|
+
});
|
|
253
|
+
const granted = await waitTask.run();
|
|
254
|
+
if (!granted && this.isStarting()) {
|
|
255
|
+
this.logEvent({ message: 'could not establish control', device: this.getName(), interface: this.getInterface() });
|
|
256
|
+
throw new Error('could not establish control');
|
|
257
|
+
}
|
|
258
|
+
return granted;
|
|
217
259
|
}
|
|
218
260
|
async sendInitialRequest() {
|
|
219
261
|
const startRequest = this.getCyclingMode().getBikeInitRequest();
|
package/lib/esm/ble/fm/sensor.js
CHANGED
|
@@ -109,9 +109,6 @@ export default class BleFitnessMachineDevice extends TBleSensor {
|
|
|
109
109
|
}
|
|
110
110
|
if (!this.isSubscribed())
|
|
111
111
|
return false;
|
|
112
|
-
if (this.features?.setPower === false && this.features?.setSlope === false && this.features?.setResistance === false) {
|
|
113
|
-
return true;
|
|
114
|
-
}
|
|
115
112
|
this.logEvent({ message: 'requestControl' });
|
|
116
113
|
this.isCheckingControl = true;
|
|
117
114
|
const data = Buffer.alloc(1);
|
|
@@ -48,6 +48,7 @@ export default class BleAdapter<TDeviceData extends BleDeviceData, TDevice exten
|
|
|
48
48
|
protected waitForInitialData(startupTimeout: any): Promise<void>;
|
|
49
49
|
protected checkCapabilities(): Promise<void>;
|
|
50
50
|
protected initControl(_props?: BleStartProperties): Promise<void>;
|
|
51
|
+
protected initControlBestEffort(_props?: BleStartProperties): Promise<void>;
|
|
51
52
|
protected getStartLogProps(props: BleStartProperties): BleStartProperties;
|
|
52
53
|
protected startAdapter(startProps?: BleStartProperties): Promise<boolean>;
|
|
53
54
|
startSensor(): Promise<boolean>;
|
|
@@ -12,6 +12,7 @@ export default class BleFmAdapter extends BleAdapter<IndoorBikeData, BleFitnessM
|
|
|
12
12
|
protected distanceInternal: number;
|
|
13
13
|
protected connectPromise: Promise<boolean> | undefined;
|
|
14
14
|
protected requestControlRetryDelay: number;
|
|
15
|
+
protected requestControlTimeout: number;
|
|
15
16
|
protected promiseSendUpdate: Promise<UpdateRequest | void> | undefined;
|
|
16
17
|
protected zwiftPlay: BleZwiftPlaySensor | undefined;
|
|
17
18
|
protected isHubInitialized: boolean;
|
|
@@ -28,6 +29,8 @@ export default class BleFmAdapter extends BleAdapter<IndoorBikeData, BleFitnessM
|
|
|
28
29
|
protected checkResume(): boolean[];
|
|
29
30
|
protected initVirtualShifting(initHub?: boolean): Promise<void>;
|
|
30
31
|
protected initControl(_startProps?: BleStartProperties): Promise<void>;
|
|
32
|
+
protected initControlBestEffort(_startProps?: BleStartProperties): Promise<void>;
|
|
33
|
+
protected attemptStartRequest(): Promise<void>;
|
|
31
34
|
protected setConstants(): void;
|
|
32
35
|
protected establishControl(): Promise<boolean>;
|
|
33
36
|
protected sendInitialRequest(): Promise<void>;
|