incyclist-devices 2.3.34 → 2.3.36
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/ble/base/adapter.d.ts +1 -0
- package/lib/ble/base/adapter.js +5 -1
- package/lib/ble/base/peripheral.d.ts +3 -0
- package/lib/ble/base/peripheral.js +20 -0
- package/lib/ble/base/sensor.d.ts +2 -0
- package/lib/ble/base/sensor.js +7 -0
- package/lib/ble/fm/adapter.d.ts +5 -0
- package/lib/ble/fm/adapter.js +42 -1
- package/lib/ble/fm/sensor.js +68 -62
- package/lib/ble/types.d.ts +2 -0
- package/lib/ble/zwift/play/helperfactory.d.ts +7 -0
- package/lib/ble/zwift/play/helperfactory.js +17 -0
- package/lib/ble/zwift/play/protohelper.d.ts +4 -0
- package/lib/ble/zwift/play/protohelper.js +11 -0
- package/lib/ble/zwift/play/sensor.d.ts +22 -6
- package/lib/ble/zwift/play/sensor.js +251 -61
- package/lib/ble/zwift/play/types.d.ts +6 -0
- package/lib/ble/zwift/play/types.js +2 -0
- package/lib/direct-connect/base/peripheral.d.ts +3 -0
- package/lib/direct-connect/base/peripheral.js +9 -0
- package/lib/modes/antble-smarttrainer.d.ts +0 -1
- package/lib/modes/antble-smarttrainer.js +84 -27
- package/lib/modes/types.d.ts +2 -0
- package/lib/proto/org/cagnulen/qdomyoszwift/zwift_hub_pb.d.ts +156 -0
- package/lib/proto/org/cagnulen/qdomyoszwift/zwift_hub_pb.js +59 -0
- package/lib/proto/zwift_hub.d.ts +282 -0
- package/lib/proto/zwift_hub.js +1146 -0
- package/package.json +7 -2
|
@@ -13,6 +13,7 @@ export default class BleAdapter<TDeviceData extends BleDeviceData, TDevice exten
|
|
|
13
13
|
protected lastDataTS: number;
|
|
14
14
|
protected device: TDevice;
|
|
15
15
|
protected onDeviceDataHandler: any;
|
|
16
|
+
protected onDeviceDisconnectHandler: any;
|
|
16
17
|
protected startTask: InteruptableTask<TaskState, boolean>;
|
|
17
18
|
constructor(settings: BleDeviceSettings, props?: DeviceProperties);
|
|
18
19
|
getUniqueName(): string;
|
package/lib/ble/base/adapter.js
CHANGED
|
@@ -21,6 +21,7 @@ class BleAdapter extends adpater_1.default {
|
|
|
21
21
|
constructor(settings, props) {
|
|
22
22
|
super(settings, props);
|
|
23
23
|
this.onDeviceDataHandler = this.onDeviceData.bind(this);
|
|
24
|
+
this.onDeviceDisconnectHandler = this.emit.bind(this);
|
|
24
25
|
this.deviceData = {};
|
|
25
26
|
this.data = {};
|
|
26
27
|
this.dataMsgCount = 0;
|
|
@@ -346,7 +347,7 @@ class BleAdapter extends adpater_1.default {
|
|
|
346
347
|
yield sensor.subscribe();
|
|
347
348
|
if (connected) {
|
|
348
349
|
sensor.on('data', this.onDeviceDataHandler);
|
|
349
|
-
sensor.on('disconnected', this.
|
|
350
|
+
sensor.on('disconnected', this.onDeviceDisconnectHandler);
|
|
350
351
|
sensor.on('error', console.log);
|
|
351
352
|
connected = yield sensor.pair();
|
|
352
353
|
}
|
|
@@ -386,6 +387,9 @@ class BleAdapter extends adpater_1.default {
|
|
|
386
387
|
return true;
|
|
387
388
|
}
|
|
388
389
|
const sensor = this.getSensor();
|
|
390
|
+
sensor.off('data', this.onDeviceDataHandler);
|
|
391
|
+
sensor.off('disconnected', this.onDeviceDisconnectHandler);
|
|
392
|
+
sensor.off('error', console.log);
|
|
389
393
|
sensor.reset();
|
|
390
394
|
this.resetData();
|
|
391
395
|
this.stopped = true;
|
|
@@ -13,10 +13,13 @@ export declare class BlePeripheral implements IBlePeripheral {
|
|
|
13
13
|
}>;
|
|
14
14
|
protected disconnecting: boolean;
|
|
15
15
|
protected disconnectedSignalled: boolean;
|
|
16
|
+
protected discoveredServiceUUIds: Array<string>;
|
|
16
17
|
protected onErrorHandler: any;
|
|
17
18
|
constructor(announcement: BlePeripheralAnnouncement);
|
|
18
19
|
get services(): BleService[];
|
|
19
20
|
getPeripheral(): BleRawPeripheral;
|
|
21
|
+
getAnnouncedServices(): string[];
|
|
22
|
+
getDiscoveredServices(): string[];
|
|
20
23
|
getInfo(): BleDeviceIdentifier;
|
|
21
24
|
connect(): Promise<boolean>;
|
|
22
25
|
disconnect(connectionLost?: boolean): Promise<boolean>;
|
|
@@ -29,6 +29,12 @@ class BlePeripheral {
|
|
|
29
29
|
getPeripheral() {
|
|
30
30
|
return this.announcement.peripheral;
|
|
31
31
|
}
|
|
32
|
+
getAnnouncedServices() {
|
|
33
|
+
return this.announcement.serviceUUIDs.map(s => (0, utils_1.beautifyUUID)(s));
|
|
34
|
+
}
|
|
35
|
+
getDiscoveredServices() {
|
|
36
|
+
return this.discoveredServiceUUIds;
|
|
37
|
+
}
|
|
32
38
|
getInfo() {
|
|
33
39
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
34
40
|
return {
|
|
@@ -132,11 +138,13 @@ class BlePeripheral {
|
|
|
132
138
|
if (this.getPeripheral().discoverServicesAsync) {
|
|
133
139
|
this.logEvent({ message: 'discover services', address: this.getPeripheral().address });
|
|
134
140
|
const services = yield this.getPeripheral().discoverServicesAsync([]);
|
|
141
|
+
this.discoveredServiceUUIds = services.map(s => (0, utils_1.beautifyUUID)(s.uuid));
|
|
135
142
|
return services.map(s => s.uuid);
|
|
136
143
|
}
|
|
137
144
|
else {
|
|
138
145
|
this.logEvent({ message: 'discover services and characteristics', address: this.getPeripheral().address });
|
|
139
146
|
const res = yield this.getPeripheral().discoverSomeServicesAndCharacteristicsAsync([], []);
|
|
147
|
+
this.discoveredServiceUUIds = res.services.map(s => (0, utils_1.beautifyUUID)(s.uuid));
|
|
140
148
|
return res.services.map(s => s.uuid);
|
|
141
149
|
}
|
|
142
150
|
});
|
|
@@ -246,6 +254,12 @@ class BlePeripheral {
|
|
|
246
254
|
}
|
|
247
255
|
subscribeSelected(characteristics, callback) {
|
|
248
256
|
return __awaiter(this, void 0, void 0, function* () {
|
|
257
|
+
if (!this.discoveredServiceUUIds) {
|
|
258
|
+
try {
|
|
259
|
+
yield this.discoverServices();
|
|
260
|
+
}
|
|
261
|
+
catch (_a) { }
|
|
262
|
+
}
|
|
249
263
|
try {
|
|
250
264
|
if (Object.keys(this.characteristics).length === 0) {
|
|
251
265
|
yield this.discoverAllCharacteristics();
|
|
@@ -308,6 +322,12 @@ class BlePeripheral {
|
|
|
308
322
|
}
|
|
309
323
|
subscribeAll(callback) {
|
|
310
324
|
return __awaiter(this, void 0, void 0, function* () {
|
|
325
|
+
if (!this.discoveredServiceUUIds) {
|
|
326
|
+
try {
|
|
327
|
+
yield this.discoverServices();
|
|
328
|
+
}
|
|
329
|
+
catch (_a) { }
|
|
330
|
+
}
|
|
311
331
|
const characteristics = yield this.discoverAllCharacteristics();
|
|
312
332
|
const success = yield this.subscribeSelected(characteristics, callback);
|
|
313
333
|
return success;
|
package/lib/ble/base/sensor.d.ts
CHANGED
|
@@ -12,10 +12,12 @@ export declare class TBleSensor extends EventEmitter implements IBleSensor {
|
|
|
12
12
|
constructor(peripheral: IBlePeripheral, props?: {
|
|
13
13
|
logger?: EventLogger;
|
|
14
14
|
});
|
|
15
|
+
getPeripheral(): IBlePeripheral;
|
|
15
16
|
getDetectionPriority(): number;
|
|
16
17
|
getProfile(): LegacyProfile;
|
|
17
18
|
getProtocol(): BleProtocol;
|
|
18
19
|
getServiceUUids(): string[];
|
|
20
|
+
getSupportedServiceUUids(): string[];
|
|
19
21
|
isMatching(serviceUUIDs: string[]): boolean;
|
|
20
22
|
hasPeripheral(): boolean;
|
|
21
23
|
pair(): Promise<boolean>;
|
package/lib/ble/base/sensor.js
CHANGED
|
@@ -28,6 +28,9 @@ class TBleSensor extends events_1.default {
|
|
|
28
28
|
this.reset();
|
|
29
29
|
this.onDataHandler = this.onData.bind(this);
|
|
30
30
|
}
|
|
31
|
+
getPeripheral() {
|
|
32
|
+
return this.peripheral;
|
|
33
|
+
}
|
|
31
34
|
getDetectionPriority() {
|
|
32
35
|
var _a;
|
|
33
36
|
const C = this.constructor;
|
|
@@ -45,6 +48,10 @@ class TBleSensor extends events_1.default {
|
|
|
45
48
|
const C = this.constructor;
|
|
46
49
|
return C['services'];
|
|
47
50
|
}
|
|
51
|
+
getSupportedServiceUUids() {
|
|
52
|
+
var _a;
|
|
53
|
+
return (_a = this.peripheral) === null || _a === void 0 ? void 0 : _a.getDiscoveredServices();
|
|
54
|
+
}
|
|
48
55
|
isMatching(serviceUUIDs) {
|
|
49
56
|
const uuids = serviceUUIDs.map(uuid => (0, utils_2.beautifyUUID)(uuid));
|
|
50
57
|
const required = this.getServiceUUids();
|
package/lib/ble/fm/adapter.d.ts
CHANGED
|
@@ -5,21 +5,26 @@ import { IndoorBikeData, IndoorBikeFeatures } from './types';
|
|
|
5
5
|
import { BleDeviceProperties, BleDeviceSettings, BleStartProperties, IBlePeripheral } from '../types';
|
|
6
6
|
import { IAdapter, IncyclistAdapterData, IncyclistBikeData } from '../../types';
|
|
7
7
|
import { LegacyProfile } from '../../antv2/types';
|
|
8
|
+
import { BleZwiftPlaySensor } from '../zwift/play';
|
|
8
9
|
export default class BleFmAdapter extends BleAdapter<IndoorBikeData, BleFitnessMachineDevice> {
|
|
9
10
|
protected static INCYCLIST_PROFILE_NAME: LegacyProfile;
|
|
10
11
|
protected distanceInternal: number;
|
|
11
12
|
protected connectPromise: Promise<boolean>;
|
|
12
13
|
protected requestControlRetryDelay: number;
|
|
13
14
|
protected promiseSendUpdate: Promise<UpdateRequest | void>;
|
|
15
|
+
protected zwiftPlay: BleZwiftPlaySensor;
|
|
16
|
+
protected virtualShiftingSupported: undefined;
|
|
14
17
|
constructor(settings: BleDeviceSettings, props?: BleDeviceProperties);
|
|
15
18
|
updateSensor(peripheral: IBlePeripheral): void;
|
|
16
19
|
isSame(device: IAdapter): boolean;
|
|
17
20
|
isControllable(): boolean;
|
|
21
|
+
supportsVirtualShifting(): boolean;
|
|
18
22
|
getSupportedCyclingModes(): Array<typeof CyclingMode>;
|
|
19
23
|
getDefaultCyclingMode(): ICyclingMode;
|
|
20
24
|
mapData(deviceData: IndoorBikeData): IncyclistBikeData;
|
|
21
25
|
transformData(bikeData: IncyclistBikeData): IncyclistAdapterData;
|
|
22
26
|
protected checkResume(): boolean[];
|
|
27
|
+
protected initVirtualShifting(): Promise<void>;
|
|
23
28
|
protected initControl(_startProps?: BleStartProperties): Promise<void>;
|
|
24
29
|
protected setConstants(): void;
|
|
25
30
|
protected establishControl(): Promise<boolean>;
|
package/lib/ble/fm/adapter.js
CHANGED
|
@@ -21,6 +21,9 @@ const adapter_1 = __importDefault(require("../base/adapter"));
|
|
|
21
21
|
const consts_1 = require("./consts");
|
|
22
22
|
const types_1 = require("../../types");
|
|
23
23
|
const utils_1 = require("../../utils/utils");
|
|
24
|
+
const utils_2 = require("../utils");
|
|
25
|
+
const play_1 = require("../zwift/play");
|
|
26
|
+
const ZWIFT_PLAY_UUID = '0000000119ca465186e5fa29dcdd09d1';
|
|
24
27
|
class BleFmAdapter extends adapter_1.default {
|
|
25
28
|
constructor(settings, props) {
|
|
26
29
|
super(settings, props);
|
|
@@ -44,6 +47,10 @@ class BleFmAdapter extends adapter_1.default {
|
|
|
44
47
|
isControllable() {
|
|
45
48
|
return true;
|
|
46
49
|
}
|
|
50
|
+
supportsVirtualShifting() {
|
|
51
|
+
var _a, _b;
|
|
52
|
+
return (_b = (_a = this.device) === null || _a === void 0 ? void 0 : _a.getSupportedServiceUUids()) === null || _b === void 0 ? void 0 : _b.some(s => (0, utils_2.matches)(s, ZWIFT_PLAY_UUID));
|
|
53
|
+
}
|
|
47
54
|
getSupportedCyclingModes() {
|
|
48
55
|
var _a, _b;
|
|
49
56
|
const modes = [power_meter_1.default];
|
|
@@ -121,6 +128,18 @@ class BleFmAdapter extends adapter_1.default {
|
|
|
121
128
|
return [wasPaused, true];
|
|
122
129
|
return [wasPaused, false];
|
|
123
130
|
}
|
|
131
|
+
initVirtualShifting() {
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
var _a;
|
|
134
|
+
try {
|
|
135
|
+
this.zwiftPlay = (_a = this.zwiftPlay) !== null && _a !== void 0 ? _a : new play_1.BleZwiftPlaySensor(this.device);
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
this.logEvent({ message: 'could not init virtual shifting', reason: err.message });
|
|
139
|
+
delete this.zwiftPlay;
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
124
143
|
initControl(_startProps) {
|
|
125
144
|
return __awaiter(this, void 0, void 0, function* () {
|
|
126
145
|
if (!this.isStarting())
|
|
@@ -163,6 +182,9 @@ class BleFmAdapter extends adapter_1.default {
|
|
|
163
182
|
resolve(false);
|
|
164
183
|
});
|
|
165
184
|
const waitUntilControl = () => __awaiter(this, void 0, void 0, function* () {
|
|
185
|
+
if (this.supportsVirtualShifting()) {
|
|
186
|
+
yield this.initVirtualShifting();
|
|
187
|
+
}
|
|
166
188
|
while (!hasControl && this.isStarting()) {
|
|
167
189
|
if (tryCnt++ === 0) {
|
|
168
190
|
this.logEvent({ message: 'requesting control', device: this.getName(), interface: this.getInterface() });
|
|
@@ -247,6 +269,7 @@ class BleFmAdapter extends adapter_1.default {
|
|
|
247
269
|
const device = this.getSensor();
|
|
248
270
|
if (this.hasCapability(types_1.IncyclistCapability.Control)) {
|
|
249
271
|
const send = () => __awaiter(this, void 0, void 0, function* () {
|
|
272
|
+
var _a;
|
|
250
273
|
const res = {};
|
|
251
274
|
if (update.slope !== undefined) {
|
|
252
275
|
yield device.setSlope(update.slope);
|
|
@@ -257,6 +280,19 @@ class BleFmAdapter extends adapter_1.default {
|
|
|
257
280
|
yield device.setTargetPower(tp);
|
|
258
281
|
res.targetPower = tp;
|
|
259
282
|
}
|
|
283
|
+
if (update.gearRatio !== undefined) {
|
|
284
|
+
if (!this.zwiftPlay) {
|
|
285
|
+
this.initVirtualShifting();
|
|
286
|
+
}
|
|
287
|
+
if (this.zwiftPlay && !isNaN(update.gearRatio)) {
|
|
288
|
+
let slope = (_a = update.slope) !== null && _a !== void 0 ? _a : 0;
|
|
289
|
+
if (slope === 0)
|
|
290
|
+
slope = 0.01;
|
|
291
|
+
yield this.zwiftPlay.setSimulationData({ inclineX100: slope * 100 });
|
|
292
|
+
const gearRatio = yield this.zwiftPlay.setGearRatio(update.gearRatio);
|
|
293
|
+
res.gearRatio = gearRatio;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
260
296
|
return res;
|
|
261
297
|
});
|
|
262
298
|
this.promiseSendUpdate = send();
|
|
@@ -278,12 +314,17 @@ class BleFmAdapter extends adapter_1.default {
|
|
|
278
314
|
return __awaiter(this, void 0, void 0, function* () {
|
|
279
315
|
if (this.started && !this.stopped) {
|
|
280
316
|
try {
|
|
281
|
-
|
|
317
|
+
const mode = this.getCyclingMode();
|
|
318
|
+
if (mode.isERG()) {
|
|
282
319
|
const power = this.data.power;
|
|
283
320
|
const request = power ? { targetPower: power } : this.getCyclingMode().getBikeInitRequest();
|
|
284
321
|
yield this.sendUpdate(request, true);
|
|
285
322
|
return true;
|
|
286
323
|
}
|
|
324
|
+
else if (mode.isSIM() && this.supportsVirtualShifting()) {
|
|
325
|
+
yield this.sendInitialRequest();
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
287
328
|
}
|
|
288
329
|
catch (_a) {
|
|
289
330
|
return false;
|
package/lib/ble/fm/sensor.js
CHANGED
|
@@ -147,70 +147,72 @@ class BleFitnessMachineDevice extends sensor_1.TBleSensor {
|
|
|
147
147
|
parseIndoorBikeData(_data) {
|
|
148
148
|
const data = Buffer.from(_data);
|
|
149
149
|
let offset = 2;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
150
|
+
if (data.length > 2) {
|
|
151
|
+
try {
|
|
152
|
+
const flags = data.readUInt16LE(0);
|
|
153
|
+
if ((flags & consts_2.IndoorBikeDataFlag.MoreData) === 0) {
|
|
154
|
+
this.data.speed = data.readUInt16LE(offset) / 100;
|
|
155
|
+
offset += 2;
|
|
156
|
+
}
|
|
157
|
+
if (flags & consts_2.IndoorBikeDataFlag.AverageSpeedPresent) {
|
|
158
|
+
this.data.averageSpeed = data.readUInt16LE(offset) / 100;
|
|
159
|
+
offset += 2;
|
|
160
|
+
}
|
|
161
|
+
if (flags & consts_2.IndoorBikeDataFlag.InstantaneousCadence) {
|
|
162
|
+
this.data.cadence = data.readUInt16LE(offset) / 2;
|
|
163
|
+
offset += 2;
|
|
164
|
+
}
|
|
165
|
+
if (flags & consts_2.IndoorBikeDataFlag.AverageCadencePresent) {
|
|
166
|
+
this.data.averageCadence = data.readUInt16LE(offset) / 2;
|
|
167
|
+
offset += 2;
|
|
168
|
+
}
|
|
169
|
+
if (flags & consts_2.IndoorBikeDataFlag.TotalDistancePresent) {
|
|
170
|
+
const dvLow = data.readUInt8(offset);
|
|
171
|
+
offset += 1;
|
|
172
|
+
const dvHigh = data.readUInt16LE(offset);
|
|
173
|
+
offset += 2;
|
|
174
|
+
this.data.totalDistance = (dvHigh << 8) + dvLow;
|
|
175
|
+
}
|
|
176
|
+
if (flags & consts_2.IndoorBikeDataFlag.ResistanceLevelPresent) {
|
|
177
|
+
this.data.resistanceLevel = data.readInt16LE(offset);
|
|
178
|
+
offset += 2;
|
|
179
|
+
}
|
|
180
|
+
if (flags & consts_2.IndoorBikeDataFlag.InstantaneousPowerPresent) {
|
|
181
|
+
this.data.instantaneousPower = data.readInt16LE(offset);
|
|
182
|
+
offset += 2;
|
|
183
|
+
}
|
|
184
|
+
if (flags & consts_2.IndoorBikeDataFlag.AveragePowerPresent) {
|
|
185
|
+
this.data.averagePower = data.readInt16LE(offset);
|
|
186
|
+
offset += 2;
|
|
187
|
+
}
|
|
188
|
+
if (flags & consts_2.IndoorBikeDataFlag.ExpendedEnergyPresent) {
|
|
189
|
+
this.data.totalEnergy = data.readUInt16LE(offset);
|
|
190
|
+
offset += 2;
|
|
191
|
+
this.data.energyPerHour = data.readUInt16LE(offset);
|
|
192
|
+
offset += 2;
|
|
193
|
+
this.data.energyPerMinute = data.readUInt8(offset);
|
|
194
|
+
offset += 1;
|
|
195
|
+
}
|
|
196
|
+
if (flags & consts_2.IndoorBikeDataFlag.HeartRatePresent) {
|
|
197
|
+
this.data.heartrate = data.readUInt8(offset);
|
|
198
|
+
offset += 1;
|
|
199
|
+
}
|
|
200
|
+
if (flags & consts_2.IndoorBikeDataFlag.MetabolicEquivalentPresent) {
|
|
201
|
+
this.data.metabolicEquivalent = data.readUInt8(offset) / 10;
|
|
202
|
+
offset += 1;
|
|
203
|
+
}
|
|
204
|
+
if (flags & consts_2.IndoorBikeDataFlag.ElapsedTimePresent) {
|
|
205
|
+
this.data.time = data.readUInt16LE(offset);
|
|
206
|
+
offset += 2;
|
|
207
|
+
}
|
|
208
|
+
if (flags & consts_2.IndoorBikeDataFlag.RemainingTimePresent) {
|
|
209
|
+
this.data.remainingTime = data.readUInt16LE(offset);
|
|
210
|
+
}
|
|
206
211
|
}
|
|
207
|
-
|
|
208
|
-
this.
|
|
212
|
+
catch (err) {
|
|
213
|
+
this.logEvent({ message: 'error', fn: 'parseIndoorBikeData()', data: data.toString('hex'), offset, error: err.message, stack: err.stack });
|
|
209
214
|
}
|
|
210
215
|
}
|
|
211
|
-
catch (err) {
|
|
212
|
-
this.logEvent({ message: 'error', fn: 'parseIndoorBikeData()', data: data.toString('hex'), offset, error: err.message, stack: err.stack });
|
|
213
|
-
}
|
|
214
216
|
return Object.assign(Object.assign({}, this.data), { raw: `2ad2:${data.toString('hex')}` });
|
|
215
217
|
}
|
|
216
218
|
parseFitnessMachineStatus(_data) {
|
|
@@ -278,7 +280,7 @@ class BleFitnessMachineDevice extends sensor_1.TBleSensor {
|
|
|
278
280
|
const services = ((_a = this.peripheral) === null || _a === void 0 ? void 0 : _a.services) || [];
|
|
279
281
|
let power = services.some(s => (0, utils_1.matches)(s.uuid, '1818'));
|
|
280
282
|
let heartrate = services.some(s => (0, utils_1.matches)(s.uuid, '180d'));
|
|
281
|
-
if (buffer) {
|
|
283
|
+
if ((buffer === null || buffer === void 0 ? void 0 : buffer.length) >= 8) {
|
|
282
284
|
const fitnessMachine = buffer.readUInt32LE(0);
|
|
283
285
|
const targetSettings = buffer.readUInt32LE(4);
|
|
284
286
|
power = power || (fitnessMachine & consts_2.FitnessMachineFeatureFlag.PowerMeasurementSupported) !== 0;
|
|
@@ -289,6 +291,10 @@ class BleFitnessMachineDevice extends sensor_1.TBleSensor {
|
|
|
289
291
|
const setPower = (targetSettings & consts_2.TargetSettingFeatureFlag.PowerTargetSettingSupported) !== 0;
|
|
290
292
|
this._features = { fitnessMachine, targetSettings, power, heartrate, cadence, setPower, setSlope };
|
|
291
293
|
this.logEvent({ message: 'supported Features: ', fatures: this._features, power, heartrate, cadence });
|
|
294
|
+
return this._features;
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
return { fitnessMachine: undefined, targetSettings: undefined, power, heartrate };
|
|
292
298
|
}
|
|
293
299
|
}
|
|
294
300
|
catch (err) {
|
package/lib/ble/types.d.ts
CHANGED
|
@@ -160,6 +160,8 @@ export interface IBlePeripheral {
|
|
|
160
160
|
write(characteristicUUID: string, data: Buffer, options?: BleWriteProps): Promise<Buffer>;
|
|
161
161
|
getManufacturerData?(): Buffer;
|
|
162
162
|
getInfo(): BleDeviceIdentifier;
|
|
163
|
+
getAnnouncedServices(): string[];
|
|
164
|
+
getDiscoveredServices(): string[];
|
|
163
165
|
}
|
|
164
166
|
export interface IBleSensor extends EventEmitter {
|
|
165
167
|
startSensor(): Promise<boolean>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HubHelperFactory = void 0;
|
|
4
|
+
const protohelper_1 = require("./protohelper");
|
|
5
|
+
class HubHelperFactory {
|
|
6
|
+
constructor() { }
|
|
7
|
+
static getInstance() {
|
|
8
|
+
if (!HubHelperFactory.instance) {
|
|
9
|
+
HubHelperFactory.instance = new HubHelperFactory();
|
|
10
|
+
}
|
|
11
|
+
return HubHelperFactory.instance;
|
|
12
|
+
}
|
|
13
|
+
create() {
|
|
14
|
+
return new protohelper_1.HubProtoHelper();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.HubHelperFactory = HubHelperFactory;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HubProtoHelper = void 0;
|
|
4
|
+
const zwift_hub_pb_js_1 = require("../../../proto/org/cagnulen/qdomyoszwift/zwift_hub_pb.js");
|
|
5
|
+
const protobuf_1 = require("@bufbuild/protobuf");
|
|
6
|
+
class HubProtoHelper {
|
|
7
|
+
createHubRequest(request) {
|
|
8
|
+
return Buffer.from((0, protobuf_1.toBinary)(zwift_hub_pb_js_1.HubRequestSchema, (0, protobuf_1.fromJson)(zwift_hub_pb_js_1.HubRequestSchema, request)));
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.HubProtoHelper = HubProtoHelper;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LegacyProfile } from "../../../antv2/types";
|
|
2
|
+
import { HubCommand, HubRequest, SimulationParam } from "../../../proto/zwift_hub";
|
|
2
3
|
import { TBleSensor } from "../../base/sensor";
|
|
3
|
-
import { BleProtocol } from "../../types";
|
|
4
|
+
import { BleProtocol, IBlePeripheral } from "../../types";
|
|
4
5
|
import { EventEmitter } from "events";
|
|
5
6
|
type ButtonState = {
|
|
6
7
|
pressed: boolean;
|
|
@@ -23,15 +24,30 @@ export declare class BleZwiftPlaySensor extends TBleSensor {
|
|
|
23
24
|
protected deviceType: DeviceType;
|
|
24
25
|
protected publicKey: Buffer;
|
|
25
26
|
protected privateKey: Buffer;
|
|
26
|
-
|
|
27
|
+
protected isFM: boolean;
|
|
28
|
+
protected tsLastRidingData: number;
|
|
29
|
+
protected isHubServiceActive: boolean;
|
|
30
|
+
protected isHubServicePaired: boolean;
|
|
31
|
+
protected isHubServiceSubscribed: boolean;
|
|
32
|
+
protected initHubServicePromise: Promise<boolean>;
|
|
33
|
+
constructor(peripheral: IBlePeripheral | TBleSensor, props?: any);
|
|
27
34
|
reconnectSensor(): Promise<void>;
|
|
28
35
|
stopSensor(): Promise<boolean>;
|
|
29
36
|
protected getRequiredCharacteristics(): Array<string>;
|
|
30
37
|
onData(characteristic: string, data: Buffer, isNotify?: boolean): boolean;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
requestDataUpdate(dataId: number): Promise<void>;
|
|
39
|
+
setSimulationData(data?: SimulationParam): Promise<void>;
|
|
40
|
+
setGearRatio(gearRatio: number): Promise<number>;
|
|
41
|
+
protected sendPlayCommand(id: number, command: Buffer): Promise<Buffer<ArrayBufferLike>>;
|
|
42
|
+
protected onMeasurement(d: Buffer): boolean;
|
|
43
|
+
initHubService(setSimulation?: boolean): Promise<boolean>;
|
|
44
|
+
sendHubRequest(request: HubRequest): Promise<Buffer<ArrayBufferLike>>;
|
|
45
|
+
sendHubCommand(command: HubCommand): Promise<Buffer<ArrayBufferLike>>;
|
|
46
|
+
protected onRidingData(m: Buffer): void;
|
|
47
|
+
protected onDeviceInformation(m: Buffer): void;
|
|
48
|
+
onClickButtonMessage(d: Buffer): void;
|
|
49
|
+
onPingMessage(message: Buffer): void;
|
|
50
|
+
onResponse(d: Buffer): boolean;
|
|
35
51
|
read(characteristic: string, ignoreErrors?: boolean): Promise<Buffer | null>;
|
|
36
52
|
pair(): Promise<boolean>;
|
|
37
53
|
reset(): void;
|