incyclist-devices 2.3.38 → 2.3.41

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.
Files changed (45) hide show
  1. package/lib/antv2/base/adapter.js +5 -5
  2. package/lib/antv2/base/interface.d.ts +2 -1
  3. package/lib/antv2/base/interface.js +2 -0
  4. package/lib/ble/base/interface.d.ts +1 -0
  5. package/lib/ble/base/interface.js +2 -0
  6. package/lib/ble/cp/sensor.js +1 -1
  7. package/lib/ble/fm/adapter.d.ts +1 -0
  8. package/lib/ble/fm/adapter.js +7 -1
  9. package/lib/ble/hr/sensor.js +1 -1
  10. package/lib/ble/types.d.ts +1 -0
  11. package/lib/ble/utils.js +1 -1
  12. package/lib/ble/zwift/play/sensor.js +0 -1
  13. package/lib/direct-connect/base/interface.d.ts +4 -0
  14. package/lib/direct-connect/base/interface.js +60 -3
  15. package/lib/direct-connect/base/peripheral.js +0 -1
  16. package/lib/direct-connect/messages/DiscoverCharacteristics.d.ts +1 -1
  17. package/lib/direct-connect/messages/DiscoverCharacteristics.js +3 -2
  18. package/lib/direct-connect/messages/DiscoverServices.d.ts +1 -1
  19. package/lib/direct-connect/messages/DiscoverServices.js +5 -3
  20. package/lib/direct-connect/messages/message.d.ts +1 -1
  21. package/lib/direct-connect/messages/message.js +2 -1
  22. package/lib/features/features.d.ts +11 -0
  23. package/lib/features/features.js +29 -0
  24. package/lib/features/index.d.ts +1 -0
  25. package/lib/features/index.js +17 -0
  26. package/lib/index.d.ts +1 -0
  27. package/lib/index.js +1 -0
  28. package/lib/modes/antble-smarttrainer.d.ts +1 -0
  29. package/lib/modes/antble-smarttrainer.js +18 -9
  30. package/lib/modes/daum-premium-standard.js +1 -1
  31. package/lib/modes/daum-smarttrainer.js +7 -7
  32. package/lib/serial/base/serial-interface.d.ts +2 -1
  33. package/lib/serial/base/serial-interface.js +2 -0
  34. package/lib/serial/bindings/tcp.js +8 -8
  35. package/lib/serial/daum/classic/adapter.d.ts +1 -1
  36. package/lib/serial/daum/classic/adapter.js +9 -10
  37. package/lib/serial/daum/classic/mock.js +1 -1
  38. package/lib/serial/daum/premium/comms.js +5 -5
  39. package/lib/serial/daum/premium/mock.js +1 -1
  40. package/lib/serial/daum/premium/utils.js +12 -12
  41. package/lib/serial/kettler/ergo-racer/adapter.d.ts +1 -1
  42. package/lib/serial/kettler/ergo-racer/adapter.js +41 -48
  43. package/lib/types/interface.d.ts +1 -0
  44. package/lib/utils/utils.js +5 -5
  45. package/package.json +1 -1
@@ -171,7 +171,7 @@ class AntAdapter extends adpater_1.default {
171
171
  clearInterval(iv);
172
172
  resolve(true);
173
173
  }
174
- if (!this.promiseWaitForData || this.stopped) {
174
+ if (this.promiseWaitForData === undefined || this.promiseWaitForData === null || this.stopped) {
175
175
  resolve(false);
176
176
  clearInterval(iv);
177
177
  }
@@ -186,7 +186,7 @@ class AntAdapter extends adpater_1.default {
186
186
  return true;
187
187
  }
188
188
  const tsStart = Date.now();
189
- if (this.promiseWaitForData) {
189
+ if (this.promiseWaitForData !== undefined && this.promiseWaitForData !== null) {
190
190
  let hasData = false;
191
191
  try {
192
192
  hasData = yield this.promiseWaitForData;
@@ -201,7 +201,7 @@ class AntAdapter extends adpater_1.default {
201
201
  this.promiseWaitForData = null;
202
202
  return hasData;
203
203
  }
204
- catch (err) {
204
+ catch (_b) {
205
205
  this.promiseWaitForData = null;
206
206
  return false;
207
207
  }
@@ -257,7 +257,7 @@ class AntAdapter extends adpater_1.default {
257
257
  try {
258
258
  return yield this.start();
259
259
  }
260
- catch (error) {
260
+ catch (_a) {
261
261
  return false;
262
262
  }
263
263
  });
@@ -350,7 +350,7 @@ class AntAdapter extends adpater_1.default {
350
350
  return __awaiter(this, void 0, void 0, function* () {
351
351
  var _a, _b;
352
352
  this.startStatus.sensorStarted = this.sensorConnected;
353
- if (this.startStatus.sensorStarted || this.startStatus.sensorStarted)
353
+ if (this.startStatus.sensorStarted)
354
354
  return;
355
355
  this.logEvent({ message: 'start sensor', device: this.getName(), props });
356
356
  try {
@@ -2,7 +2,7 @@ import EventEmitter from "events";
2
2
  import { EventLogger } from "gd-eventlog";
3
3
  import { Channel, IAntDevice, IChannel, ISensor } from "incyclist-ant-plus";
4
4
  import { AntDeviceSettings, AntScanProps, AntInterfaceProps } from "../types";
5
- import { IncyclistInterface } from "../../types";
5
+ import { DeviceSettings, IncyclistInterface } from "../../types";
6
6
  import AntDeviceBinding from "./binding";
7
7
  type ChannelUsage = 'scan' | 'sensor';
8
8
  interface ChannelInfo {
@@ -52,5 +52,6 @@ export default class AntInterface extends EventEmitter implements IncyclistInter
52
52
  private blockChannel;
53
53
  private unblockChannel;
54
54
  stopSensor(sensor: ISensor): Promise<boolean>;
55
+ addKnownDevice(_settings: DeviceSettings): void;
55
56
  }
56
57
  export {};
@@ -412,6 +412,8 @@ class AntInterface extends events_1.default {
412
412
  }
413
413
  });
414
414
  }
415
+ addKnownDevice(_settings) {
416
+ }
415
417
  }
416
418
  AntInterface._instance = undefined;
417
419
  AntInterface.INTERFACE_NAME = 'ant';
@@ -94,6 +94,7 @@ export declare class BleInterface extends EventEmitter implements IBleInterface<
94
94
  protected find(service: BlePeripheralAnnouncement): Announcement;
95
95
  protected getAll(): Announcement[];
96
96
  setDebug(enabled: boolean): void;
97
+ addKnownDevice(_settings: BleDeviceSettings): void;
97
98
  protected connectBle(): Promise<boolean>;
98
99
  protected waitForBleConnected(): Promise<boolean>;
99
100
  protected onError(err: Error): void;
@@ -583,6 +583,8 @@ class BleInterface extends events_1.default {
583
583
  setDebug(enabled) {
584
584
  this.debug = enabled;
585
585
  }
586
+ addKnownDevice(_settings) {
587
+ }
586
588
  connectBle() {
587
589
  return __awaiter(this, void 0, void 0, function* () {
588
590
  this.currentBleState = this.getBinding().state;
@@ -69,7 +69,7 @@ class BleCyclingPowerDevice extends sensor_1.TBleSensor {
69
69
  this.time = time;
70
70
  }
71
71
  }
72
- catch (err) {
72
+ catch (_a) {
73
73
  }
74
74
  const { instantaneousPower, balance, accTorque, rpm, time } = this;
75
75
  return { instantaneousPower, balance, accTorque, rpm, time, raw: `2a63:${data.toString('hex')}` };
@@ -33,4 +33,5 @@ export default class BleFmAdapter extends BleAdapter<IndoorBikeData, BleFitnessM
33
33
  protected updateCapabilitiesFromFeatures(features: IndoorBikeFeatures): void;
34
34
  sendUpdate(request: any, enforced?: boolean): Promise<UpdateRequest | void>;
35
35
  sendInitCommands(): Promise<boolean>;
36
+ protected getFeatureToggle(): import("../../features").FeatureToggle;
36
37
  }
@@ -23,6 +23,7 @@ const types_1 = require("../../types");
23
23
  const utils_1 = require("../../utils/utils");
24
24
  const utils_2 = require("../utils");
25
25
  const play_1 = require("../zwift/play");
26
+ const features_1 = require("../../features");
26
27
  const ZWIFT_PLAY_UUID = '0000000119ca465186e5fa29dcdd09d1';
27
28
  class BleFmAdapter extends adapter_1.default {
28
29
  constructor(settings, props) {
@@ -49,6 +50,8 @@ class BleFmAdapter extends adapter_1.default {
49
50
  }
50
51
  supportsVirtualShifting() {
51
52
  var _a, _b;
53
+ if (!this.getFeatureToggle().has('VirtualShifting'))
54
+ return false;
52
55
  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
56
  }
54
57
  getSupportedCyclingModes() {
@@ -284,7 +287,7 @@ class BleFmAdapter extends adapter_1.default {
284
287
  if (!this.zwiftPlay) {
285
288
  this.initVirtualShifting();
286
289
  }
287
- if (this.zwiftPlay && !isNaN(update.gearRatio)) {
290
+ if (this.zwiftPlay && !Number.isNaN(update.gearRatio)) {
288
291
  let slope = (_a = update.slope) !== null && _a !== void 0 ? _a : 0;
289
292
  if (slope === 0)
290
293
  slope = 0.01;
@@ -335,6 +338,9 @@ class BleFmAdapter extends adapter_1.default {
335
338
  }
336
339
  });
337
340
  }
341
+ getFeatureToggle() {
342
+ return (0, features_1.useFeatureToggle)();
343
+ }
338
344
  }
339
345
  BleFmAdapter.INCYCLIST_PROFILE_NAME = 'Smart Trainer';
340
346
  exports.default = BleFmAdapter;
@@ -20,7 +20,7 @@ class BleHrmDevice extends sensor_1.TBleSensor {
20
20
  this.rr = (data.readUInt16LE(offset)) / 1024;
21
21
  }
22
22
  }
23
- catch (err) {
23
+ catch (_a) {
24
24
  }
25
25
  const { heartrate, rr } = this;
26
26
  return { heartrate, rr, raw: data.toString('hex') };
@@ -72,6 +72,7 @@ export interface BleDeviceSettings extends DeviceSettings {
72
72
  profile?: string;
73
73
  address?: string;
74
74
  name?: string;
75
+ services?: string;
75
76
  }
76
77
  export interface BleDeviceProperties extends DeviceProperties {
77
78
  wheelDiameter?: number;
package/lib/ble/utils.js CHANGED
@@ -24,7 +24,7 @@ function uuid(s) {
24
24
  if (s) {
25
25
  if (s.includes('-')) {
26
26
  const parts = s.split('-');
27
- const uuidNo = parseInt('0x' + parts[0]);
27
+ const uuidNo = Number.parseInt('0x' + parts[0]);
28
28
  return uuidNo.toString(16).toLowerCase();
29
29
  }
30
30
  return s;
@@ -52,7 +52,6 @@ class BleZwiftPlaySensor extends sensor_1.TBleSensor {
52
52
  }
53
53
  onData(characteristic, data, isNotify) {
54
54
  const uuid = (0, utils_1.beautifyUUID)(characteristic).toLowerCase();
55
- console.log('# data', uuid, data === null || data === void 0 ? void 0 : data.toString('hex'));
56
55
  if (uuid === '00000002-19ca-4651-86e5-fa29dcdd09d1') {
57
56
  this.onMeasurement(data);
58
57
  }
@@ -11,6 +11,7 @@ import { InterfaceFactory } from "../../ble/base/types";
11
11
  interface Announcement {
12
12
  service: MulticastDnsAnnouncement;
13
13
  ts: number;
14
+ source?: string;
14
15
  }
15
16
  export default class DirectConnectInterface extends EventEmitter implements IBleInterface<MulticastDnsAnnouncement> {
16
17
  protected static _instance: DirectConnectInterface;
@@ -33,6 +34,7 @@ export default class DirectConnectInterface extends EventEmitter implements IBle
33
34
  createPeripheral(announcement: MulticastDnsAnnouncement): IBlePeripheral;
34
35
  createDeviceSetting(service: MulticastDnsAnnouncement): BleDeviceSettings;
35
36
  createPeripheralFromSettings(settings: DeviceSettings): IBlePeripheral;
37
+ addKnownDevice(settings: BleDeviceSettings): void;
36
38
  getLogger(): EventLogger;
37
39
  setLogger(logger: EventLogger): void;
38
40
  getName(): string;
@@ -66,6 +68,8 @@ export default class DirectConnectInterface extends EventEmitter implements IBle
66
68
  logError(err: Error, fn: string, args?: any): void;
67
69
  protected getProtocol(announcement: MulticastDnsAnnouncement): BleProtocol;
68
70
  protected getBestDeviceMatch(DeviceClasses: (typeof TBleSensor)[]): typeof TBleSensor;
71
+ protected createAnnouncementFromSettings(settings: BleDeviceSettings): MulticastDnsAnnouncement;
72
+ protected getServiceUUIDs(settings: BleDeviceSettings): string[];
69
73
  protected getAdapterFactory(): BleAdapterFactory<any>;
70
74
  }
71
75
  export declare class DirectConnectInterfaceFactory extends InterfaceFactory {
@@ -19,7 +19,10 @@ const task_1 = require("../../utils/task");
19
19
  const peripheral_1 = require("./peripheral");
20
20
  const ble_1 = require("../../ble");
21
21
  const types_1 = require("../../ble/base/types");
22
+ const consts_1 = require("../../ble/consts");
23
+ const consts_2 = require("../../ble/wahoo/consts");
22
24
  const DC_TYPE = 'wahoo-fitness-tnp';
25
+ const DC_PORT = 36866;
23
26
  const DC_EXPIRATION_TIMEOUT = 10 * 1000 * 60;
24
27
  let instanceId = 0;
25
28
  class DirectConnectInterface extends events_1.default {
@@ -66,12 +69,16 @@ class DirectConnectInterface extends events_1.default {
66
69
  return peripheral_1.DirectConnectPeripheral.create(announcement);
67
70
  }
68
71
  createDeviceSetting(service) {
72
+ var _a, _b;
69
73
  try {
70
74
  const name = service.name;
71
75
  const protocol = this.getProtocol(service);
72
- return { interface: DirectConnectInterface.INTERFACE_NAME, name, protocol };
76
+ const address = service.address;
77
+ const services = (_b = (_a = service.serviceUUIDs) === null || _a === void 0 ? void 0 : _a.map(uuid => (0, ble_1.beautifyUUID)(uuid, false))) === null || _b === void 0 ? void 0 : _b.join(',');
78
+ console.log('# created device setting from announcement', name, service.serviceUUIDs, services);
79
+ return { interface: DirectConnectInterface.INTERFACE_NAME, name, protocol, address, services };
73
80
  }
74
- catch (_a) {
81
+ catch (_c) {
75
82
  return null;
76
83
  }
77
84
  }
@@ -81,6 +88,12 @@ class DirectConnectInterface extends events_1.default {
81
88
  return null;
82
89
  return this.createPeripheral(info.service);
83
90
  }
91
+ addKnownDevice(settings) {
92
+ const announcement = this.createAnnouncementFromSettings(settings);
93
+ if (announcement) {
94
+ this.addService(announcement, 'known-device');
95
+ }
96
+ }
84
97
  getLogger() {
85
98
  return this.logger;
86
99
  }
@@ -236,6 +249,7 @@ class DirectConnectInterface extends events_1.default {
236
249
  const device = this.createDeviceSetting(service);
237
250
  if (!device)
238
251
  return;
252
+ console.log('# emitting device', device, service);
239
253
  this.emit('device', device, service);
240
254
  }
241
255
  buildDeviceSettings(matching = []) {
@@ -243,15 +257,22 @@ class DirectConnectInterface extends events_1.default {
243
257
  }
244
258
  addService(service, source) {
245
259
  var _a, _b;
260
+ console.log(`# DirectConnectInterface.addService from ${source}`, service.name, service.serviceUUIDs);
261
+ const src = source === 'known-device' ? 'known-device' : 'mdns';
246
262
  try {
247
263
  service.transport = this.getName();
248
264
  const existing = this.find(service);
249
265
  if (existing) {
250
266
  const idx = this.services.indexOf(existing);
251
267
  this.services[idx] = { ts: Date.now(), service };
268
+ if (src !== 'known-device' && existing.source === 'known-device') {
269
+ this.services[idx].source = src;
270
+ this.logEvent({ message: 'device re-announced', device: service.name, announcement: service, source });
271
+ this.emitDevice(service);
272
+ }
252
273
  }
253
274
  else {
254
- this.services.push({ ts: Date.now(), service });
275
+ this.services.push({ ts: Date.now(), service, source: src });
255
276
  if (!((_a = service.serviceUUIDs) === null || _a === void 0 ? void 0 : _a.length))
256
277
  return;
257
278
  this.logEvent({ message: 'device announced', device: service.name, announcement: service, source });
@@ -306,6 +327,42 @@ class DirectConnectInterface extends events_1.default {
306
327
  details.sort((a, b) => b.priority - a.priority);
307
328
  return details[0].class;
308
329
  }
330
+ createAnnouncementFromSettings(settings) {
331
+ if (settings.protocol && settings.address) {
332
+ const announcement = {
333
+ name: settings.name,
334
+ address: settings.address,
335
+ protocol: 'tcp',
336
+ port: DC_PORT,
337
+ type: DC_TYPE,
338
+ transport: 'wifi',
339
+ serviceUUIDs: this.getServiceUUIDs(settings),
340
+ };
341
+ console.log('# created announcement from settings', announcement);
342
+ return announcement;
343
+ }
344
+ }
345
+ getServiceUUIDs(settings) {
346
+ if (settings.services && settings.services.length > 0) {
347
+ return settings.services.split(',').map(s => s.trim());
348
+ }
349
+ switch (settings.protocol) {
350
+ case 'fm':
351
+ return ['1826'];
352
+ case 'hr':
353
+ return ['180d'];
354
+ case 'wahoo':
355
+ return [consts_1.CSP, consts_2.WAHOO_ADVANCED_FTMS];
356
+ case 'cp':
357
+ return [consts_1.CSP];
358
+ case 'csc':
359
+ return [consts_1.CSC];
360
+ case 'zwift-play':
361
+ return ['0000000119ca465186e5fa29dcdd09d1'];
362
+ default:
363
+ return [];
364
+ }
365
+ }
309
366
  getAdapterFactory() {
310
367
  return ble_1.BleAdapterFactory.getInstance('wifi');
311
368
  }
@@ -154,7 +154,6 @@ class DirectConnectPeripheral {
154
154
  if (this.subscribed.includes(uuid)) {
155
155
  return true;
156
156
  }
157
- console.log('# subscribe ', characteristicUUID);
158
157
  const seqNo = this.getNextSeqNo();
159
158
  const message = new messages_1.EnableCharacteristicNotificationsMessage();
160
159
  const request = message.createRequest(seqNo, { characteristicUUID: (0, utils_1.parseUUID)(characteristicUUID), enable: true });
@@ -18,5 +18,5 @@ export declare class DiscoverCharacteristicsMessage extends Message<TDCDiscoverC
18
18
  parseRequestBody(body: Buffer): TDCDiscoverCharacteristicsRequestBody;
19
19
  buildRequestBody(body: TDCDiscoverCharacteristicsRequestBody): Buffer;
20
20
  buildResponseBody(body: TDCDiscoverCharacteristicsResponseBody): Buffer;
21
- parseResponseBody(body: Buffer): TDCDiscoverCharacteristicsResponseBody;
21
+ parseResponseBody(responseBody: Buffer): TDCDiscoverCharacteristicsResponseBody;
22
22
  }
@@ -25,9 +25,10 @@ class DiscoverCharacteristicsMessage extends message_1.Message {
25
25
  ]));
26
26
  return Buffer.concat([serviceUUIDBuffer, ...characteristicBuffers]);
27
27
  }
28
- parseResponseBody(body) {
28
+ parseResponseBody(responseBody) {
29
+ const body = Buffer.from(responseBody);
29
30
  const length = body.length;
30
- const serviceUUID = body.subarray(0, 16).toString("hex");
31
+ const serviceUUID = Buffer.from(body.subarray(0, 16)).toString("hex");
31
32
  const characteristicDefinitions = [];
32
33
  for (let i = 16; i < length; i += 17) {
33
34
  const characteristicUUID = Buffer.from(body.subarray(i, i + 16)).toString("hex");
@@ -10,6 +10,6 @@ export interface TDCDiscoverServicesResponseBody extends TDCBody {
10
10
  export declare class DiscoverServiceMessage extends Message<EmptyBody, TDCDiscoverServicesResponseBody> {
11
11
  constructor();
12
12
  buildResponseBody(body: TDCDiscoverServicesResponseBody): Buffer;
13
- parseResponseBody(body: Buffer): TDCDiscoverServicesResponseBody;
13
+ parseResponseBody(responseBody: Buffer): TDCDiscoverServicesResponseBody;
14
14
  verifyHeader(header: TDCMessageHeader): boolean;
15
15
  }
@@ -12,13 +12,15 @@ class DiscoverServiceMessage extends message_1.Message {
12
12
  const serviceBuffers = body.serviceDefinitions.map((service) => {
13
13
  return Buffer.from(service.serviceUUID, "hex");
14
14
  });
15
- return Buffer.concat(serviceBuffers);
15
+ const response = Buffer.concat(serviceBuffers);
16
+ return response;
16
17
  }
17
- parseResponseBody(body) {
18
+ parseResponseBody(responseBody) {
19
+ const body = Buffer.from(responseBody);
18
20
  const serviceDefinitions = [];
19
21
  const length = body.length;
20
22
  for (let i = 0; i < length; i += 16) {
21
- const serviceUUID = body.subarray(i, i + 16).toString("hex");
23
+ const serviceUUID = Buffer.from(body.subarray(i, i + 16)).toString("hex");
22
24
  serviceDefinitions.push({ serviceUUID });
23
25
  }
24
26
  return { serviceDefinitions };
@@ -9,7 +9,7 @@ export declare class Message<TReq extends TDCBody, TRes extends TDCBody> {
9
9
  createRequest(seqNum: any, body: TReq): Buffer;
10
10
  parseRequest(buffer: Buffer): TDCRequest<TReq>;
11
11
  prepareResponse(request: TDCRequest<TReq>, respCode: number, body: TRes): TDCResponse<TRes>;
12
- parseResponse(buffer: Buffer): TDCResponse<TRes>;
12
+ parseResponse(response: Buffer): TDCResponse<TRes>;
13
13
  buildHeader(header: TDCMessageHeader, length: number): Buffer;
14
14
  buildResponseBody(body: TRes): Buffer;
15
15
  buildRequestBody(body: TReq): Buffer;
@@ -40,7 +40,8 @@ class Message {
40
40
  const header = Object.assign(Object.assign({}, request.header), { respCode });
41
41
  return { header, body };
42
42
  }
43
- parseResponse(buffer) {
43
+ parseResponse(response) {
44
+ const buffer = Buffer.from(response);
44
45
  const header = (0, exports.parseHeader)(buffer);
45
46
  this.verifyHeader(header);
46
47
  const bodyBuffer = buffer.subarray(6);
@@ -0,0 +1,11 @@
1
+ export type Feature = 'VirtualShifting';
2
+ export declare class FeatureToggle {
3
+ protected static _instance: FeatureToggle;
4
+ static getInstance(): FeatureToggle;
5
+ protected enabled: Array<string>;
6
+ constructor();
7
+ add(feature: Feature): void;
8
+ remove(feature: Feature): void;
9
+ has(feature: Feature): boolean;
10
+ }
11
+ export declare const useFeatureToggle: () => FeatureToggle;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFeatureToggle = exports.FeatureToggle = void 0;
4
+ class FeatureToggle {
5
+ static getInstance() {
6
+ if (!FeatureToggle._instance)
7
+ FeatureToggle._instance = new FeatureToggle();
8
+ return FeatureToggle._instance;
9
+ }
10
+ constructor() {
11
+ this.enabled = [];
12
+ }
13
+ add(feature) {
14
+ this.enabled.push(feature);
15
+ }
16
+ remove(feature) {
17
+ const index = this.enabled.indexOf(feature);
18
+ if (index > -1)
19
+ this.enabled.splice(index, 1);
20
+ }
21
+ has(feature) {
22
+ return this.enabled.includes(feature);
23
+ }
24
+ }
25
+ exports.FeatureToggle = FeatureToggle;
26
+ const useFeatureToggle = () => {
27
+ return FeatureToggle.getInstance();
28
+ };
29
+ exports.useFeatureToggle = useFeatureToggle;
@@ -0,0 +1 @@
1
+ export * from './features';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./features"), exports);
package/lib/index.d.ts CHANGED
@@ -13,4 +13,5 @@ export * from './serial';
13
13
  export * from './ble';
14
14
  export * from './antv2';
15
15
  export * from './direct-connect';
16
+ export * from './features';
16
17
  export { IAdapter, IncyclistDevice, IncyclistDeviceAdapter, DeviceSettings, DeviceProperties, AdapterFactory, InterfaceFactory, IncyclistInterface, INTERFACE, InterfaceProps, ICyclingMode, IncyclistAdapterData as DeviceData, IncyclistCapability, calc, };
package/lib/index.js CHANGED
@@ -35,3 +35,4 @@ __exportStar(require("./serial"), exports);
35
35
  __exportStar(require("./ble"), exports);
36
36
  __exportStar(require("./antv2"), exports);
37
37
  __exportStar(require("./direct-connect"), exports);
38
+ __exportStar(require("./features"), exports);
@@ -55,5 +55,6 @@ export default class SmartTrainerCyclingMode extends PowerBasedCyclingModeBase i
55
55
  protected updateRequired(request?: UpdateRequest): boolean;
56
56
  sendBikeUpdate(incoming: UpdateRequest): UpdateRequest;
57
57
  protected getGearString(): string;
58
+ protected getFeatureToogle(): import("../features").FeatureToggle;
58
59
  }
59
60
  export {};
@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  const types_1 = require("./types");
40
40
  const power_base_1 = __importDefault(require("./power-base"));
41
41
  const calculations_1 = __importStar(require("../utils/calculations"));
42
+ const features_1 = require("../features");
42
43
  const MIN_POWER = 25;
43
44
  class SmartTrainerCyclingMode extends power_base_1.default {
44
45
  constructor(adapter, props) {
@@ -71,6 +72,9 @@ class SmartTrainerCyclingMode extends power_base_1.default {
71
72
  }
72
73
  getConfig() {
73
74
  const config = super.getConfig();
75
+ if (!this.getFeatureToogle().has('VirtualShifting')) {
76
+ return config;
77
+ }
74
78
  let virtshift = config.properties.find(p => p.key === 'virtshift');
75
79
  let startGear = config.properties.find(p => p.key === 'startGear');
76
80
  if (!virtshift) {
@@ -90,7 +94,7 @@ class SmartTrainerCyclingMode extends power_base_1.default {
90
94
  }
91
95
  checkSlopeNoShiftig(request, newRequest = {}) {
92
96
  if (request.slope !== undefined) {
93
- const targetSlope = newRequest.slope = parseFloat(request.slope.toFixed(1));
97
+ const targetSlope = newRequest.slope = Number.parseFloat(request.slope.toFixed(1));
94
98
  this.data.slope = newRequest.slope;
95
99
  try {
96
100
  const slopeAdj = targetSlope >= 0 ? this.getSetting('slopeAdj') : this.getSetting('slopeAdjDown');
@@ -112,7 +116,7 @@ class SmartTrainerCyclingMode extends power_base_1.default {
112
116
  }
113
117
  checkSlopeWithSlopeDelta(request, newRequest = {}) {
114
118
  if (request.slope !== undefined) {
115
- const targetSlope = newRequest.slope = parseFloat(request.slope.toFixed(1));
119
+ const targetSlope = newRequest.slope = Number.parseFloat(request.slope.toFixed(1));
116
120
  this.data.slope = newRequest.slope;
117
121
  const requestedSlope = targetSlope + this.getSlopeDelta();
118
122
  try {
@@ -130,9 +134,13 @@ class SmartTrainerCyclingMode extends power_base_1.default {
130
134
  this.checkSlopeNoShiftig(request, newRequest);
131
135
  return;
132
136
  }
133
- if (request.slope !== undefined) {
137
+ if (request.slope === undefined) {
138
+ console.log('# set simulated power (same slope):', { simPower: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, cadence: this.data.pedalRpm, power: this.data.power });
139
+ this.logger.logEvent({ message: 'set simulated power (same slope)', simPower: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, cadence: this.data.pedalRpm, power: this.data.power });
140
+ }
141
+ else {
134
142
  const prev = (_a = this.data.slope) !== null && _a !== void 0 ? _a : 0;
135
- this.data.slope = parseFloat(request.slope.toFixed(1));
143
+ this.data.slope = Number.parseFloat(request.slope.toFixed(1));
136
144
  delete request.slope;
137
145
  delete newRequest.slope;
138
146
  this.simSlope = this.data.slope;
@@ -173,10 +181,6 @@ class SmartTrainerCyclingMode extends power_base_1.default {
173
181
  }
174
182
  this.verifySimPower();
175
183
  }
176
- else {
177
- console.log('# set simulated power (same slope):', { simPower: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, cadence: this.data.pedalRpm, power: this.data.power });
178
- this.logger.logEvent({ message: 'set simulated power (same slope)', simPower: this.simPower, gear: this.gear, simSlope: this.simSlope, routeSlope: this.data.slope, cadence: this.data.pedalRpm, power: this.data.power });
179
- }
180
184
  newRequest.targetPower = this.simPower;
181
185
  }
182
186
  checkSlope(request, newRequest = {}) {
@@ -342,6 +346,9 @@ class SmartTrainerCyclingMode extends power_base_1.default {
342
346
  }
343
347
  }
344
348
  getVirtualShiftMode() {
349
+ if (!this.getFeatureToogle().has('VirtualShifting')) {
350
+ return 'Disabled';
351
+ }
345
352
  const virtshiftMode = this.getSetting('virtshift');
346
353
  if (virtshiftMode === 'Disabled') {
347
354
  return 'Disabled';
@@ -385,7 +392,6 @@ class SmartTrainerCyclingMode extends power_base_1.default {
385
392
  return Object.assign(Object.assign({}, data), { gearStr });
386
393
  }
387
394
  updateRequired(request) {
388
- console.log('# SmartTrainerCyclingMode updateRequired check');
389
395
  const virtshiftMode = this.getVirtualShiftMode();
390
396
  if (virtshiftMode === 'Adapter' || virtshiftMode === 'Simulated') {
391
397
  return true;
@@ -430,6 +436,9 @@ class SmartTrainerCyclingMode extends power_base_1.default {
430
436
  }
431
437
  return (_d = this.gear) === null || _d === void 0 ? void 0 : _d.toString();
432
438
  }
439
+ getFeatureToogle() {
440
+ return (0, features_1.useFeatureToggle)();
441
+ }
433
442
  }
434
443
  SmartTrainerCyclingMode.config = {
435
444
  name: "Smart Trainer",
@@ -43,7 +43,7 @@ class DaumClassicCyclingMode extends power_meter_1.default {
43
43
  this.distanceOffset = calculateDistance - distanceBike;
44
44
  distanceInternal = calculateDistance;
45
45
  }
46
- data.speed = parseFloat(speed.toFixed(1));
46
+ data.speed = Number.parseFloat(speed.toFixed(1));
47
47
  data.power = Math.round(power);
48
48
  data.distanceInternal = distanceInternal;
49
49
  data.slope = slope;
@@ -53,12 +53,11 @@ class SmartTrainerCyclingMode extends base_1.CyclingModeBase {
53
53
  const minMaxStr = this.getSetting(`${source}Rings`);
54
54
  const values = minMaxStr.split('-');
55
55
  if (values[0] && values[1] && values[0] < values[1]) {
56
- return [parseInt(values[0]), parseInt(values[1])];
56
+ return [Number.parseInt(values[0]), Number.parseInt(values[1])];
57
57
  }
58
58
  if (values[0] && values[1] && values[0] > values[1]) {
59
- return [parseInt(values[1]), parseInt(values[0])];
59
+ return [Number.parseInt(values[1]), Number.parseInt(values[0])];
60
60
  }
61
- return;
62
61
  }
63
62
  sendBikeUpdate(request) {
64
63
  const getData = () => {
@@ -70,7 +69,7 @@ class SmartTrainerCyclingMode extends base_1.CyclingModeBase {
70
69
  const event = Object.assign({}, this.event);
71
70
  if (this.data === undefined)
72
71
  event.noData = true;
73
- const slope = request.slope === undefined ? request.slope : parseFloat(request.slope.toFixed(1));
72
+ const slope = request.slope === undefined ? request.slope : Number.parseFloat(request.slope.toFixed(1));
74
73
  if (slope !== undefined && (event.noData || Math.abs(slope - this.data.slope) >= 0.1))
75
74
  event.slopeUpdate = true;
76
75
  if (this.prevRequest === undefined)
@@ -231,7 +230,7 @@ class SmartTrainerCyclingMode extends base_1.CyclingModeBase {
231
230
  const v = speed / 3.6;
232
231
  distanceInternal += (v * duration);
233
232
  }
234
- data.speed = parseFloat(speed.toFixed(1));
233
+ data.speed = Number.parseFloat(speed.toFixed(1));
235
234
  data.power = Math.round(power);
236
235
  data.distanceInternal = distanceInternal;
237
236
  data.distance = distance;
@@ -294,17 +293,18 @@ class SmartTrainerCyclingMode extends base_1.CyclingModeBase {
294
293
  return speed;
295
294
  }
296
295
  calculateTargetPower(request, speed) {
296
+ var _a, _b;
297
297
  const defaultPower = this.getSetting('startPower');
298
298
  const minPower = this.getSetting('minPower');
299
299
  const bikeType = this.getSetting('bikeType').toLowerCase();
300
300
  const m = this.getWeight();
301
301
  const prevData = this.data || {};
302
- const slope = parseFloat((request.slope === undefined ? prevData.slope || 0 : request.slope).toFixed(1));
302
+ const slope = Number.parseFloat(((_b = (_a = request.slope) !== null && _a !== void 0 ? _a : prevData.slope) !== null && _b !== void 0 ? _b : 0).toFixed(1));
303
303
  let target = request.targetPower || defaultPower;
304
304
  if (prevData.speed !== undefined || speed !== undefined) {
305
305
  const v = speed ? speed / 3.6 : prevData.speed / 3.6;
306
306
  const calculatedPower = calculations_1.default.calculatePower(m, v, slope, { bikeType });
307
- const power = (calculatedPower < minPower) ? minPower : calculatedPower;
307
+ const power = Math.max(calculatedPower, minPower);
308
308
  let belowMin = (calculatedPower < minPower);
309
309
  const powerDelta = power - prevData.power || 0;
310
310
  let target;
@@ -2,7 +2,7 @@ import EventEmitter from "events";
2
2
  import { BindingInterface } from "@serialport/bindings-interface";
3
3
  import { SerialPortStream } from '@serialport/stream';
4
4
  import { SerialDeviceSettings, SerialScannerProps, PortMapping, SerialInterfaceProps } from "../types";
5
- import { IncyclistInterface } from "../../types";
5
+ import { DeviceSettings, IncyclistInterface } from "../../types";
6
6
  import { EventLogger } from "gd-eventlog";
7
7
  export default class SerialInterface extends EventEmitter implements IncyclistInterface {
8
8
  ifaceName: string;
@@ -31,4 +31,5 @@ export default class SerialInterface extends EventEmitter implements IncyclistIn
31
31
  closePort(path: string): Promise<Boolean>;
32
32
  scan(props: SerialScannerProps): Promise<SerialDeviceSettings[]>;
33
33
  stopScan(): Promise<boolean>;
34
+ addKnownDevice(_settings: DeviceSettings): void;
34
35
  }
@@ -289,6 +289,8 @@ class SerialInterface extends events_1.default {
289
289
  return true;
290
290
  });
291
291
  }
292
+ addKnownDevice(_settings) {
293
+ }
292
294
  }
293
295
  SerialInterface._instances = [];
294
296
  exports.default = SerialInterface;
@@ -38,7 +38,7 @@ function scanPort(host, port) {
38
38
  try {
39
39
  socket.destroy();
40
40
  }
41
- catch (err) { }
41
+ catch (_a) { }
42
42
  socket.removeAllListeners();
43
43
  };
44
44
  socket.setTimeout(1000);
@@ -47,7 +47,7 @@ function scanPort(host, port) {
47
47
  socket.on('ready', () => { resolve(true); cleanup(); });
48
48
  socket.connect(port, host);
49
49
  }
50
- catch (err) {
50
+ catch (_a) {
51
51
  resolve(false);
52
52
  }
53
53
  });
@@ -109,10 +109,10 @@ exports.TCPBinding = {
109
109
  return reject(new TypeError('"path" is not valid'));
110
110
  host = res[0];
111
111
  port = Number(res[1]);
112
- if (isNaN(port))
112
+ if (Number.isNaN(port))
113
113
  return reject(new TypeError('"path" is not valid'));
114
114
  }
115
- catch (err) {
115
+ catch (_a) {
116
116
  return reject(new TypeError('"path" is not valid'));
117
117
  }
118
118
  const socket = new net_1.default.Socket();
@@ -207,11 +207,11 @@ class TCPPortBinding {
207
207
  if (!Buffer.isBuffer(buffer)) {
208
208
  throw new TypeError('"buffer" is not a Buffer');
209
209
  }
210
- if (typeof offset !== 'number' || isNaN(offset)) {
211
- throw new TypeError(`"offset" is not an integer got "${isNaN(offset) ? 'NaN' : typeof offset}"`);
210
+ if (typeof offset !== 'number' || Number.isNaN(offset)) {
211
+ throw new TypeError(`"offset" is not an integer got "${Number.isNaN(offset) ? 'NaN' : typeof offset}"`);
212
212
  }
213
- if (typeof length !== 'number' || isNaN(length)) {
214
- throw new TypeError(`"length" is not an integer got "${isNaN(length) ? 'NaN' : typeof length}"`);
213
+ if (typeof length !== 'number' || Number.isNaN(length)) {
214
+ throw new TypeError(`"length" is not an integer got "${Number.isNaN(length) ? 'NaN' : typeof length}"`);
215
215
  }
216
216
  if (buffer.length < offset + length) {
217
217
  throw new Error('buffer is too small');
@@ -4,7 +4,7 @@ import { SerialDeviceSettings, SerialCommProps } from "../../types";
4
4
  import { IncyclistBikeData, ControllerConfig } from "../../../types";
5
5
  import Daum8008 from './comms';
6
6
  export default class DaumClassicAdapter extends DaumAdapter<SerialDeviceSettings, DaumClassicProperties, Daum8008> {
7
- static NAME: string;
7
+ static readonly NAME = "Daum Classic";
8
8
  protected static controllers: ControllerConfig;
9
9
  protected name: string;
10
10
  protected id: string;
@@ -41,7 +41,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
41
41
  else {
42
42
  serial = props.interface;
43
43
  }
44
- if (!serial || !serial.binding)
44
+ if (!(serial === null || serial === void 0 ? void 0 : serial.binding))
45
45
  throw new Error(`unknonwn interface: ${ifaceName}`);
46
46
  const path = `${port}`;
47
47
  return { serial, path };
@@ -57,8 +57,8 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
57
57
  }
58
58
  performCheck() {
59
59
  return __awaiter(this, void 0, void 0, function* () {
60
- var info = {};
61
- const check = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
60
+ const info = {};
61
+ const check = () => __awaiter(this, void 0, void 0, function* () {
62
62
  this.logEvent({ message: "checking device", port: this.getPort() });
63
63
  try {
64
64
  yield this.stop();
@@ -66,8 +66,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
66
66
  this.logEvent({ message: "checking device failed", port: this.getPort(), reason: 'timeout' });
67
67
  });
68
68
  if (!connected) {
69
- resolve(false);
70
- return;
69
+ return false;
71
70
  }
72
71
  this.stopped = false;
73
72
  const address = yield this.getComms().getAddress();
@@ -79,14 +78,14 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
79
78
  this.pause();
80
79
  this.started = false;
81
80
  this.logEvent({ message: "checking device success", port: this.getPort(), info });
82
- resolve(true);
81
+ return true;
83
82
  }
84
83
  catch (err) {
85
84
  this.logEvent({ message: "checking device failed", port: this.getPort(), reason: err.message });
86
- resolve(false);
85
+ return false;
87
86
  }
88
- }));
89
- return yield (0, utils_1.waitWithTimeout)(check, 5000, () => {
87
+ });
88
+ return yield (0, utils_1.waitWithTimeout)(check(), 5000, () => {
90
89
  this.logEvent({ message: "checking device failed", port: this.getPort(), reason: 'Timeout' });
91
90
  return false;
92
91
  });
@@ -128,7 +127,7 @@ class DaumClassicAdapter extends DaumAdapter_1.default {
128
127
  try {
129
128
  yield this.getComms().setBikeType(bikeType.toLowerCase());
130
129
  }
131
- catch (err) {
130
+ catch (_a) {
132
131
  }
133
132
  startState.setBikeType = true;
134
133
  }
@@ -198,7 +198,7 @@ class DaumClassicMockBinding extends binding_mock_1.MockPortBinding {
198
198
  this.simulator.addHandle(to);
199
199
  }
200
200
  }
201
- catch (err) {
201
+ catch (_a) {
202
202
  }
203
203
  this.writeOperation = null;
204
204
  }))();
@@ -405,25 +405,25 @@ class Daum8i extends comms_1.default {
405
405
  return __awaiter(this, void 0, void 0, function* () {
406
406
  const powerStr = typeof power === 'string' ? Number.parseFloat(power).toFixed(2) : power.toFixed(2);
407
407
  const str = yield this.sendStrCommand('setPower', `S23${powerStr}`);
408
- return parseInt(str);
408
+ return Number.parseInt(str);
409
409
  });
410
410
  }
411
411
  getPower() {
412
412
  return __awaiter(this, void 0, void 0, function* () {
413
413
  const str = yield this.sendStrCommand('getPower', 'S23');
414
- return parseInt(str);
414
+ return Number.parseInt(str);
415
415
  });
416
416
  }
417
417
  setGear(gear) {
418
418
  return __awaiter(this, void 0, void 0, function* () {
419
419
  const str = yield this.sendStrCommand('setGear', `M71${gear}`);
420
- return parseInt(str);
420
+ return Number.parseInt(str);
421
421
  });
422
422
  }
423
423
  getGear() {
424
424
  return __awaiter(this, void 0, void 0, function* () {
425
425
  const str = yield this.sendStrCommand('getGear', 'M71');
426
- return parseInt(str);
426
+ return Number.parseInt(str);
427
427
  });
428
428
  }
429
429
  sendReservedDaum8iCommand(logString, command, data) {
@@ -442,7 +442,7 @@ class Daum8i extends comms_1.default {
442
442
  }
443
443
  const cmdData = Uint8Array.from(buffer);
444
444
  const res = yield this.sendBinaryCommand(logString || 'ReservedCommand', 'M70', (0, utils_1.bin2esc)(cmdData));
445
- const resData = Uint8Array.from(res, x => x.charCodeAt(0));
445
+ const resData = Uint8Array.from(res, x => x.codePointAt(0));
446
446
  const cmd = (0, utils_1.esc2bin)(resData);
447
447
  return cmd;
448
448
  });
@@ -224,7 +224,7 @@ class Daum8iMockBinding extends binding_mock_1.MockPortBinding {
224
224
  this.waitingForCommand = true;
225
225
  }
226
226
  }
227
- catch (err) {
227
+ catch (_a) {
228
228
  }
229
229
  }
230
230
  else if (this.waitingForAck) {
@@ -26,7 +26,7 @@ exports.DEBUG_LOGGER = {
26
26
  logEvent: (event) => console.log(JSON.stringify(event))
27
27
  };
28
28
  const GS = 0x1D;
29
- const GS_CHAR = String.fromCharCode(GS);
29
+ const GS_CHAR = String.fromCodePoint(GS);
30
30
  function responseLog(str) {
31
31
  if (str.includes(GS_CHAR)) {
32
32
  return str.split(GS_CHAR).join('/');
@@ -177,7 +177,7 @@ function hexstr(arr, start, len) {
177
177
  return str;
178
178
  }
179
179
  function ascii(c) {
180
- return c.charCodeAt(0);
180
+ return c.codePointAt(0);
181
181
  }
182
182
  function getAsciiArrayFromStr(str) {
183
183
  if (str === undefined || str === null)
@@ -185,7 +185,7 @@ function getAsciiArrayFromStr(str) {
185
185
  const n = str.length;
186
186
  let result = [];
187
187
  for (let i = 0; i < n; i++) {
188
- result.push(str.charCodeAt(i));
188
+ result.push(str.codePointAt(i));
189
189
  }
190
190
  return result;
191
191
  }
@@ -282,16 +282,16 @@ function routeToEpp(route, date) {
282
282
  }
283
283
  function parseTrainingData(payload) {
284
284
  const gearVal = (v) => v > 0 ? v - 1 : undefined;
285
- const vals = payload.split(String.fromCharCode(GS));
285
+ const vals = payload.split(String.fromCodePoint(GS));
286
286
  const data = {
287
- time: parseInt(vals[0]),
288
- heartrate: parseInt(vals[1]),
289
- speed: parseFloat(vals[2]) * 3.6,
290
- slope: parseFloat(vals[3]),
291
- distanceInternal: parseInt(vals[4]),
292
- pedalRpm: parseFloat(vals[5]),
293
- power: parseInt(vals[6]),
294
- gear: gearVal(parseInt(vals[10])),
287
+ time: Number.parseInt(vals[0]),
288
+ heartrate: Number.parseInt(vals[1]),
289
+ speed: Number.parseFloat(vals[2]) * 3.6,
290
+ slope: Number.parseFloat(vals[3]),
291
+ distanceInternal: Number.parseInt(vals[4]),
292
+ pedalRpm: Number.parseFloat(vals[5]),
293
+ power: Number.parseInt(vals[6]),
294
+ gear: gearVal(Number.parseInt(vals[10])),
295
295
  };
296
296
  data.isPedalling = (data.pedalRpm > 0);
297
297
  return data;
@@ -25,7 +25,7 @@ export interface KettlerBikeData {
25
25
  export default class KettlerRacerAdapter extends SerialIncyclistDevice<DeviceProperties> {
26
26
  private id;
27
27
  private iv;
28
- private requests;
28
+ private readonly requests;
29
29
  private internalData;
30
30
  private kettlerData;
31
31
  private updateBusy;
@@ -171,18 +171,13 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
171
171
  }
172
172
  send(logStr, message, timeout) {
173
173
  return __awaiter(this, void 0, void 0, function* () {
174
- return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
175
- try {
176
- const opened = yield this.waitForOpened();
177
- if (!opened) {
178
- reject(new Error('connection error'));
179
- }
180
- }
181
- catch (err) {
182
- reject(err);
183
- }
174
+ const opened = yield this.waitForOpened();
175
+ if (!opened) {
176
+ throw (new Error('connection error'));
177
+ }
178
+ return new Promise((resolve, reject) => {
184
179
  this.comms.send({ logStr, message, onResponse: resolve, onError: reject, timeout });
185
- }));
180
+ });
186
181
  });
187
182
  }
188
183
  parseExtendedStatus(data) {
@@ -193,39 +188,39 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
193
188
  const states = data.split('\t');
194
189
  const result = {};
195
190
  if (states.length === 8) {
196
- const hr = parseInt(states[0]);
197
- if (!isNaN(hr)) {
191
+ const hr = Number.parseInt(states[0]);
192
+ if (!Number.isNaN(hr)) {
198
193
  result.heartrate = hr;
199
194
  }
200
- var cadence = parseInt(states[1]);
201
- if (!isNaN(cadence)) {
195
+ const cadence = Number.parseInt(states[1]);
196
+ if (!Number.isNaN(cadence)) {
202
197
  result.cadence = cadence;
203
198
  }
204
- const speed = parseInt(states[2]);
205
- if (!isNaN(speed)) {
199
+ const speed = Number.parseInt(states[2]);
200
+ if (!Number.isNaN(speed)) {
206
201
  result.speed = speed * 0.1;
207
202
  }
208
- const distance = parseInt(states[3]);
209
- if (!isNaN(distance)) {
203
+ const distance = Number.parseInt(states[3]);
204
+ if (!Number.isNaN(distance)) {
210
205
  result.distance = distance * 100;
211
206
  }
212
- const requestedPower = parseInt(states[4]);
213
- if (!isNaN(requestedPower)) {
207
+ const requestedPower = Number.parseInt(states[4]);
208
+ if (!Number.isNaN(requestedPower)) {
214
209
  result.requestedPower = requestedPower;
215
210
  }
216
- const energy = parseInt(states[5]);
217
- if (!isNaN(energy)) {
211
+ const energy = Number.parseInt(states[5]);
212
+ if (!Number.isNaN(energy)) {
218
213
  result.energy = energy;
219
214
  }
220
215
  const timeStr = states[6];
221
216
  const time = timeStr.split(':');
222
- const hours = parseInt(time[0]);
223
- const minutes = parseInt(time[1]);
224
- if (!isNaN(hours) && !isNaN(minutes)) {
217
+ const hours = Number.parseInt(time[0]);
218
+ const minutes = Number.parseInt(time[1]);
219
+ if (!Number.isNaN(hours) && !Number.isNaN(minutes)) {
225
220
  result.time = hours * 60 + minutes;
226
221
  }
227
- const power = parseInt(states[7]);
228
- if (!isNaN(power)) {
222
+ const power = Number.parseInt(states[7]);
223
+ if (!Number.isNaN(power)) {
229
224
  result.power = power;
230
225
  }
231
226
  result.timestamp = Date.now();
@@ -234,7 +229,7 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
234
229
  }
235
230
  check() {
236
231
  return __awaiter(this, void 0, void 0, function* () {
237
- var info = {};
232
+ const info = {};
238
233
  return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
239
234
  this.logEvent({ message: "checking device", port: this.getPort() });
240
235
  let iv = undefined;
@@ -275,7 +270,7 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
275
270
  return __awaiter(this, void 0, void 0, function* () {
276
271
  const props = this.getStartProps(startProps);
277
272
  this.logEvent({ message: 'start()' });
278
- var info = {};
273
+ const info = {};
279
274
  yield this.waitForOpened(true);
280
275
  return (0, utils_1.runWithRetries)(() => __awaiter(this, void 0, void 0, function* () {
281
276
  try {
@@ -519,25 +514,20 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
519
514
  }
520
515
  waitForOpened() {
521
516
  return __awaiter(this, arguments, void 0, function* (retries = false) {
522
- if (!retries) {
523
- return yield this.comms.open();
524
- }
525
- else {
526
- let opened;
527
- let tries = 0;
528
- while (!opened && tries < 3) {
529
- try {
530
- opened = yield this.comms.open();
531
- if (opened)
532
- return true;
533
- }
534
- catch (err) {
535
- }
536
- tries++;
537
- yield (0, utils_1.sleep)(500);
517
+ const maxTries = retries ? 3 : 1;
518
+ let opened = false;
519
+ let tries = 0;
520
+ while (!opened && tries < maxTries) {
521
+ try {
522
+ opened = yield this.comms.open();
523
+ if (opened)
524
+ return true;
538
525
  }
539
- return false;
526
+ catch (_a) { }
527
+ tries++;
528
+ yield (0, utils_1.sleep)(500);
540
529
  }
530
+ return false;
541
531
  });
542
532
  }
543
533
  waitForClosed() {
@@ -554,7 +544,10 @@ class KettlerRacerAdapter extends adapter_1.SerialIncyclistDevice {
554
544
  resolve(true);
555
545
  cleanup();
556
546
  };
557
- const onError = (err) => { reject(err); cleanup(); };
547
+ const onError = (err) => {
548
+ reject(err);
549
+ cleanup();
550
+ };
558
551
  const onOpen = () => { cleanup(); };
559
552
  this.comms.on('closed', onClose);
560
553
  this.comms.on('opened', onOpen);
@@ -15,4 +15,5 @@ export interface IncyclistInterface extends EventEmitter {
15
15
  isConnected(): boolean;
16
16
  scan(props: IncyclistScanProps): Promise<DeviceSettings[]>;
17
17
  stopScan(): Promise<boolean>;
18
+ addKnownDevice?(settings: DeviceSettings): void;
18
19
  }
@@ -73,16 +73,16 @@ function floatVal(d) {
73
73
  return;
74
74
  if (typeof d === 'number')
75
75
  return d;
76
- const res = parseFloat(d);
77
- return isNaN(res) ? undefined : res;
76
+ const res = Number.parseFloat(d);
77
+ return Number.isNaN(res) ? undefined : res;
78
78
  }
79
79
  function intVal(d) {
80
80
  if (d === undefined)
81
81
  return;
82
82
  if (typeof d === 'number')
83
83
  return Math.floor(d);
84
- const res = parseInt(d);
85
- return isNaN(res) ? undefined : res;
84
+ const res = Number.parseInt(d);
85
+ return Number.isNaN(res) ? undefined : res;
86
86
  }
87
87
  function hexstr(arr, start, len) {
88
88
  let str = "";
@@ -93,7 +93,7 @@ function hexstr(arr, start, len) {
93
93
  endIdx = arr.length;
94
94
  }
95
95
  let added = 0;
96
- for (var i = startIdx; i < endIdx; i++) {
96
+ for (let i = startIdx; i < endIdx; i++) {
97
97
  const hex = Math.abs(arr[i]).toString(16).toUpperCase();
98
98
  if (added !== 0)
99
99
  str += ' ';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "2.3.38",
3
+ "version": "2.3.41",
4
4
  "dependencies": {
5
5
  "@protobuf-ts/runtime": "^2.11.1",
6
6
  "@serialport/bindings-interface": "^1.2.2",