incyclist-devices 2.3.35 → 2.3.37

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.
@@ -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;
@@ -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.emit.bind(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;
@@ -269,6 +269,7 @@ class BleFmAdapter extends adapter_1.default {
269
269
  const device = this.getSensor();
270
270
  if (this.hasCapability(types_1.IncyclistCapability.Control)) {
271
271
  const send = () => __awaiter(this, void 0, void 0, function* () {
272
+ var _a;
272
273
  const res = {};
273
274
  if (update.slope !== undefined) {
274
275
  yield device.setSlope(update.slope);
@@ -283,9 +284,12 @@ class BleFmAdapter extends adapter_1.default {
283
284
  if (!this.zwiftPlay) {
284
285
  this.initVirtualShifting();
285
286
  }
286
- if (this.zwiftPlay) {
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 });
287
292
  const gearRatio = yield this.zwiftPlay.setGearRatio(update.gearRatio);
288
- yield this.zwiftPlay.setSimulationData({ inclineX100: update.slope * 100 });
289
293
  res.gearRatio = gearRatio;
290
294
  }
291
295
  }
@@ -27,8 +27,9 @@ export declare class BleZwiftPlaySensor extends TBleSensor {
27
27
  protected isFM: boolean;
28
28
  protected tsLastRidingData: number;
29
29
  protected isHubServiceActive: boolean;
30
- protected isPaired: boolean;
31
- protected isSubscribed: boolean;
30
+ protected isHubServicePaired: boolean;
31
+ protected isHubServiceSubscribed: boolean;
32
+ protected initHubServicePromise: Promise<boolean>;
32
33
  constructor(peripheral: IBlePeripheral | TBleSensor, props?: any);
33
34
  reconnectSensor(): Promise<void>;
34
35
  stopSensor(): Promise<boolean>;
@@ -74,11 +74,14 @@ class BleZwiftPlaySensor extends sensor_1.TBleSensor {
74
74
  if (!this.isHubServiceActive) {
75
75
  yield this.initHubService(false);
76
76
  }
77
- const crrx100000 = Math.round((_a = data === null || data === void 0 ? void 0 : data.crrx100000) !== null && _a !== void 0 ? _a : 5100);
78
- const cWax10000 = Math.round((_b = data === null || data === void 0 ? void 0 : data.cWax10000) !== null && _b !== void 0 ? _b : 400);
77
+ const crrx100000 = Math.round((_a = data === null || data === void 0 ? void 0 : data.crrx100000) !== null && _a !== void 0 ? _a : 400);
78
+ const cWax10000 = Math.round((_b = data === null || data === void 0 ? void 0 : data.cWax10000) !== null && _b !== void 0 ? _b : 5100);
79
79
  const windx100 = Math.round((_c = data === null || data === void 0 ? void 0 : data.windx100) !== null && _c !== void 0 ? _c : 0);
80
- const inclineX100 = Math.round((_d = data === null || data === void 0 ? void 0 : data.inclineX100) !== null && _d !== void 0 ? _d : 0);
80
+ let inclineX100 = Math.round((_d = data === null || data === void 0 ? void 0 : data.inclineX100) !== null && _d !== void 0 ? _d : 1);
81
+ if (inclineX100 === 0 || Number.isNaN(inclineX100))
82
+ inclineX100 = 1;
81
83
  const simulation = { inclineX100, crrx100000, cWax10000, windx100 };
84
+ console.log('# set simulation data', simulation);
82
85
  yield this.sendHubCommand({ simulation });
83
86
  yield this.requestDataUpdate(512);
84
87
  });
@@ -142,17 +145,21 @@ class BleZwiftPlaySensor extends sensor_1.TBleSensor {
142
145
  }
143
146
  initHubService() {
144
147
  return __awaiter(this, arguments, void 0, function* (setSimulation = true) {
145
- console.log('# init Hub Service');
148
+ if (!this.isHubServiceActive && this.initHubServicePromise !== undefined) {
149
+ yield this.initHubServicePromise;
150
+ }
146
151
  if (this.isHubServiceActive)
147
152
  return true;
148
- if (!this.isPaired) {
153
+ this.logEvent({ message: 'init hub service', paired: this.paired, subscribed: this.isHubServiceSubscribed });
154
+ console.log('# init Hub Service');
155
+ if (!this.isHubServicePaired) {
149
156
  yield this.pair();
150
157
  }
151
- if (!this.isSubscribed) {
158
+ if (!this.isHubServiceSubscribed) {
152
159
  yield this.subscribe();
153
- this.isSubscribed = true;
160
+ this.isHubServiceSubscribed = true;
154
161
  }
155
- return new Promise((done) => {
162
+ this.initHubServicePromise = new Promise((done) => {
156
163
  let timeout = setTimeout(() => {
157
164
  done(false);
158
165
  }, 2000);
@@ -163,7 +170,9 @@ class BleZwiftPlaySensor extends sensor_1.TBleSensor {
163
170
  }
164
171
  this.isHubServiceActive = true;
165
172
  console.log('# init hub service completed');
173
+ this.logEvent({ message: 'init hub service done', paired: this.paired, subscribed: this.isHubServiceSubscribed });
166
174
  if (setSimulation) {
175
+ this.logEvent({ message: 'hub: send initial simulation data' });
167
176
  this.setSimulationData().then(() => {
168
177
  done(true);
169
178
  })
@@ -186,6 +195,7 @@ class BleZwiftPlaySensor extends sensor_1.TBleSensor {
186
195
  this.logEvent({ message: 'could not init hub service', reason: err.message });
187
196
  });
188
197
  });
198
+ return this.initHubServicePromise;
189
199
  });
190
200
  }
191
201
  sendHubRequest(request) {
@@ -344,7 +354,7 @@ class BleZwiftPlaySensor extends sensor_1.TBleSensor {
344
354
  pair() {
345
355
  return __awaiter(this, void 0, void 0, function* () {
346
356
  var _a, _b;
347
- if (this.isPaired)
357
+ if (this.isHubServicePaired)
348
358
  return true;
349
359
  let manufacturerData;
350
360
  try {
@@ -380,12 +390,12 @@ class BleZwiftPlaySensor extends sensor_1.TBleSensor {
380
390
  message = Buffer.concat([Buffer.from('RideOn'), Buffer.from([0x01, 0x02]), this.publicKey]);
381
391
  }
382
392
  yield this.write((0, utils_1.fullUUID)('00000003-19ca-4651-86e5-fa29dcdd09d1'), message, { withoutResponse: true });
383
- this.isPaired = true;
393
+ this.isHubServicePaired = true;
384
394
  return true;
385
395
  }
386
396
  catch (err) {
387
397
  this.logEvent({ message: 'error', fn: 'pair', error: err.message, stack: err.stack });
388
- this.isPaired = false;
398
+ this.isHubServicePaired = false;
389
399
  return false;
390
400
  }
391
401
  });
@@ -406,6 +416,10 @@ class BleZwiftPlaySensor extends sensor_1.TBleSensor {
406
416
  this.paired = false;
407
417
  this.encrypted = false;
408
418
  this.deviceKey = null;
419
+ this.isHubServicePaired = false;
420
+ this.isHubServiceSubscribed = false;
421
+ this.isHubServiceActive = false;
422
+ delete this.initHubServicePromise;
409
423
  }
410
424
  getManufacturerData() {
411
425
  const data = this.peripheral.getManufacturerData();
@@ -154,6 +154,7 @@ class DirectConnectPeripheral {
154
154
  if (this.subscribed.includes(uuid)) {
155
155
  return true;
156
156
  }
157
+ console.log('# subscribe ', characteristicUUID);
157
158
  const seqNo = this.getNextSeqNo();
158
159
  const message = new messages_1.EnableCharacteristicNotificationsMessage();
159
160
  const request = message.createRequest(seqNo, { characteristicUUID: (0, utils_1.parseUUID)(characteristicUUID), enable: true });
@@ -83,7 +83,7 @@ class SmartTrainerCyclingMode extends power_base_1.default {
83
83
  virtshift.default = 'SmartTrainer';
84
84
  }
85
85
  if (!startGear) {
86
- startGear = { key: 'startGear', name: 'Initial Gear', description: 'Initial Gear', type: types_1.CyclingModeProperyType.Integer, default: 10, min: 1, max: 24, condition: (s) => (s === null || s === void 0 ? void 0 : s.virtshift) === 'Incyclist' || (s === null || s === void 0 ? void 0 : s.virtshift) === 'SmartTrainer' };
86
+ startGear = { key: 'startGear', name: 'Initial Gear', description: 'Initial Gear', type: types_1.CyclingModeProperyType.Integer, default: 12, min: 1, max: 24, condition: (s) => (s === null || s === void 0 ? void 0 : s.virtshift) === 'Incyclist' || (s === null || s === void 0 ? void 0 : s.virtshift) === 'SmartTrainer' };
87
87
  config.properties.push(startGear);
88
88
  }
89
89
  return config;
@@ -102,7 +102,10 @@ class SmartTrainerCyclingMode extends power_base_1.default {
102
102
  }
103
103
  }
104
104
  checkSlopeWithAdapterShifting(request, newRequest = {}) {
105
- return this.checkSlopeNoShiftig(request, newRequest);
105
+ var _a;
106
+ this.checkSlopeNoShiftig(request, newRequest);
107
+ const gear = (_a = this.gear) !== null && _a !== void 0 ? _a : this.getSetting('startGear');
108
+ newRequest.gearRatio = this.gearRatios[gear - 1];
106
109
  }
107
110
  getSlopeDelta() {
108
111
  return this.gearDelta * 0.5;
@@ -122,7 +125,7 @@ class SmartTrainerCyclingMode extends power_base_1.default {
122
125
  }
123
126
  }
124
127
  checkSlopeWithSimulatedShifting(request, newRequest = {}) {
125
- var _a, _b, _c, _d;
128
+ var _a, _b, _c, _d, _e;
126
129
  if (this.gear === undefined) {
127
130
  this.checkSlopeNoShiftig(request, newRequest);
128
131
  return;
@@ -138,15 +141,34 @@ class SmartTrainerCyclingMode extends power_base_1.default {
138
141
  if (slopeAdj !== undefined)
139
142
  this.simSlope = this.simSlope * slopeAdj / 100;
140
143
  }
141
- catch (_e) {
144
+ catch (_f) {
142
145
  }
143
- if (this.data.slope !== prev) {
144
- const virtualSpeed = (0, calculations_1.calculateVirtualSpeed)(this.data.pedalRpm, this.gearRatios[this.gear - 1]);
145
- const m = (_c = (_b = this.adapter) === null || _b === void 0 ? void 0 : _b.getWeight()) !== null && _c !== void 0 ? _c : 85;
146
- this.simPower = calculations_1.default.calculatePower(m, virtualSpeed, (_d = this.simSlope) !== null && _d !== void 0 ? _d : 0);
147
- this.verifySimPower();
148
- this.logger.logEvent({ message: 'set simulater power', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope });
146
+ const virtualSpeed = (0, calculations_1.calculateVirtualSpeed)(this.data.pedalRpm, this.gearRatios[this.gear - 1]);
147
+ const m = (_c = (_b = this.adapter) === null || _b === void 0 ? void 0 : _b.getWeight()) !== null && _c !== void 0 ? _c : 85;
148
+ const vCurrent = this.data.speed * 1000 / 3600;
149
+ const eKinCurrent = m * vCurrent * vCurrent / 2;
150
+ const newPower = calculations_1.default.calculatePower(m, virtualSpeed, (_d = this.simSlope) !== null && _d !== void 0 ? _d : 0);
151
+ const prevPower = this.data.power;
152
+ if (this.data.speed < 10 && this.data.isPedalling && (this.data.slope < 1 || this.data.speed === 0)) {
153
+ this.simPower = Math.max(newPower, prevPower);
154
+ this.logger.logEvent({ message: 'set simulater power', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, prevPower, newPower });
149
155
  }
156
+ else if (this.data.slope === prev && newPower < prevPower) {
157
+ this.simPower = prevPower;
158
+ this.logger.logEvent({ message: 'set simulater power', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, prevPower, newPower });
159
+ }
160
+ else {
161
+ const powerDiff = newPower - prevPower;
162
+ const vTarget = virtualSpeed * 1000 / 3600;
163
+ const eKinTarget = m * vTarget * vTarget / 2;
164
+ const eKinPrev = eKinCurrent;
165
+ const delta = eKinTarget - eKinPrev;
166
+ const eKinAfter1sec = eKinPrev - powerDiff * 1;
167
+ const vAfter1sec = Math.sqrt(2 * eKinAfter1sec / m) * 3600 / 1000;
168
+ this.simPower = calculations_1.default.calculatePower(m, vAfter1sec / 3.6, (_e = this.simSlope) !== null && _e !== void 0 ? _e : 0);
169
+ this.logger.logEvent({ message: 'set simulater power', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, eKinPrev, eKinTarget, delta, prevPower, newPower });
170
+ }
171
+ this.verifySimPower();
150
172
  }
151
173
  newRequest.targetPower = this.simPower;
152
174
  }
@@ -195,13 +217,17 @@ class SmartTrainerCyclingMode extends power_base_1.default {
195
217
  this.gear = this.gearRatios.length;
196
218
  }
197
219
  delete request.gearDelta;
198
- const virtualSpeed = (0, calculations_1.calculateVirtualSpeed)(this.data.pedalRpm, this.gearRatios[this.gear - 1]);
199
- const m = (_b = (_a = this.adapter) === null || _a === void 0 ? void 0 : _a.getWeight()) !== null && _b !== void 0 ? _b : 85;
200
- this.simPower = calculations_1.default.calculatePower(m, virtualSpeed, (_d = (_c = this.simSlope) !== null && _c !== void 0 ? _c : this.data.slope) !== null && _d !== void 0 ? _d : 0);
201
- this.verifySimPower();
202
- this.logger.logEvent({ message: 'set simulater power', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope });
203
- this.adapter.sendUpdate({ targetPower: this.simPower }).then(() => {
204
- });
220
+ if (this.data.pedalRpm > 0) {
221
+ const virtualSpeed = (0, calculations_1.calculateVirtualSpeed)(this.data.pedalRpm, this.gearRatios[this.gear - 1]);
222
+ const m = (_b = (_a = this.adapter) === null || _a === void 0 ? void 0 : _a.getWeight()) !== null && _b !== void 0 ? _b : 85;
223
+ this.simPower = calculations_1.default.calculatePower(m, virtualSpeed, (_d = (_c = this.simSlope) !== null && _c !== void 0 ? _c : this.data.slope) !== null && _d !== void 0 ? _d : 0);
224
+ this.verifySimPower();
225
+ this.logger.logEvent({ message: 'set simulater power', power: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope });
226
+ this.adapter.sendUpdate({ targetPower: this.simPower }).then(() => { });
227
+ }
228
+ else {
229
+ delete this.simPower;
230
+ }
205
231
  }
206
232
  break;
207
233
  case 'Adapter':
@@ -258,6 +284,9 @@ class SmartTrainerCyclingMode extends power_base_1.default {
258
284
  if (this.data.pedalRpm > 0 && this.simPower < MIN_POWER) {
259
285
  this.simPower = MIN_POWER;
260
286
  }
287
+ if (!this.data.isPedalling) {
288
+ delete this.simPower;
289
+ }
261
290
  }
262
291
  checkEmptyRequest(newRequest) {
263
292
  if (Object.keys(newRequest).length === 0) {
@@ -339,14 +368,21 @@ class SmartTrainerCyclingMode extends power_base_1.default {
339
368
  return newRequest;
340
369
  }
341
370
  getGearString() {
371
+ var _a, _b, _c, _d;
342
372
  const mode = this.getVirtualShiftMode();
343
373
  if (mode === "Disabled")
344
374
  return undefined;
345
- if (mode === 'Simulated' && (this.gear === undefined || this.gear === null))
346
- return '';
375
+ if (mode === 'Simulated') {
376
+ this.gear = (_b = (_a = this.gear) !== null && _a !== void 0 ? _a : this.getSetting('startGear')) !== null && _b !== void 0 ? _b : 0;
377
+ return this.gear.toString();
378
+ }
347
379
  if (mode === "SlopeDelta")
348
380
  return this.gearDelta > 0 ? `+${this.gearDelta}` : `${this.gearDelta}`;
349
- return this.gear.toString();
381
+ if (mode === 'Adapter') {
382
+ this.gear = (_c = this.gear) !== null && _c !== void 0 ? _c : this.getSetting('startGear');
383
+ return this.gear.toString();
384
+ }
385
+ return (_d = this.gear) === null || _d === void 0 ? void 0 : _d.toString();
350
386
  }
351
387
  }
352
388
  SmartTrainerCyclingMode.config = {
@@ -179,6 +179,7 @@ class PowerBasedCyclingModeBase extends base_1.CyclingModeBase {
179
179
  }
180
180
  copyBikeData(data, bikeData) {
181
181
  var _a;
182
+ const prevCadence = data.pedalRpm;
182
183
  const keys = Object.keys(bikeData);
183
184
  keys.forEach(key => {
184
185
  if (bikeData[key] === null)
@@ -195,7 +196,10 @@ class PowerBasedCyclingModeBase extends base_1.CyclingModeBase {
195
196
  if (data.slope === undefined)
196
197
  data.slope = 0;
197
198
  if (bikeData.isPedalling === undefined)
198
- data.isPedalling = data.pedalRpm > 0;
199
+ (data.isPedalling = data.pedalRpm > 0 || data.power > 0);
200
+ if (bikeData.pedalRpm === 0 && bikeData.power > 0 && prevCadence !== undefined) {
201
+ data.pedalRpm = prevCadence;
202
+ }
199
203
  if (((_a = this.prevRequest) === null || _a === void 0 ? void 0 : _a.slope) !== undefined) {
200
204
  data.slope = this.prevRequest.slope;
201
205
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "2.3.35",
3
+ "version": "2.3.37",
4
4
  "dependencies": {
5
5
  "@protobuf-ts/runtime": "^2.11.1",
6
6
  "@serialport/bindings-interface": "^1.2.2",