incyclist-devices 1.4.94 → 1.4.96

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.
@@ -18,8 +18,7 @@ const utils_1 = require("../utils");
18
18
  const utils_2 = require("../../utils");
19
19
  const ant_fe_st_mode_1 = __importDefault(require("./ant-fe-st-mode"));
20
20
  const ant_fe_erg_mode_1 = __importDefault(require("./ant-fe-erg-mode"));
21
- const floatVal = (d) => d ? parseFloat(d) : d;
22
- const intVal = (d) => d ? parseInt(d) : d;
21
+ const ant_fe_adv_st_mode_1 = __importDefault(require("./ant-fe-adv-st-mode"));
23
22
  const hex = (v) => Math.abs(v).toString(16).toUpperCase();
24
23
  const TIMEOUT_ACK = 5000;
25
24
  const TIMEOUT_START = 10000;
@@ -58,7 +57,7 @@ class AntFEAdapter extends AntAdapter_1.default {
58
57
  return `${(0, utils_1.getBrand)(ManId)} FE ${DeviceID}${hrmStr}`;
59
58
  }
60
59
  getSupportedCyclingModes() {
61
- return [ant_fe_st_mode_1.default, ant_fe_erg_mode_1.default];
60
+ return [ant_fe_st_mode_1.default, ant_fe_erg_mode_1.default, ant_fe_adv_st_mode_1.default];
62
61
  }
63
62
  setCyclingMode(mode, settings) {
64
63
  let selectedMode;
@@ -0,0 +1,9 @@
1
+ import FtmsCyclingMode from "../../ble/ble-st-mode";
2
+ import { UpdateRequest } from "../../CyclingMode";
3
+ import { DeviceAdapter } from "../../Device";
4
+ export default class AntAdvSimCyclingMode extends FtmsCyclingMode {
5
+ constructor(adapter: DeviceAdapter, props?: any);
6
+ getName(): string;
7
+ getDescription(): string;
8
+ sendBikeUpdate(request: UpdateRequest): UpdateRequest;
9
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const ble_st_mode_1 = __importDefault(require("../../ble/ble-st-mode"));
7
+ const MAX_DEVIATION = 10;
8
+ class AntAdvSimCyclingMode extends ble_st_mode_1.default {
9
+ constructor(adapter, props) {
10
+ super(adapter, props);
11
+ this.initLogger('AntAdvSimMode');
12
+ }
13
+ getName() {
14
+ return 'Advanced Smart Trainer';
15
+ }
16
+ getDescription() {
17
+ return 'Sends Slope to device. Respects Limits (from workout or settings). Calculates speed based on power and slope. ';
18
+ }
19
+ sendBikeUpdate(request) {
20
+ const getData = () => {
21
+ if (!this.data)
22
+ return {};
23
+ const { gear, pedalRpm, slope, power, speed } = this.data;
24
+ return { gear, pedalRpm, slope, power, speed };
25
+ };
26
+ this.logger.logEvent({ message: "processing update request", request, prev: this.prevRequest, data: getData() });
27
+ let newRequest = {};
28
+ if (request.slope === undefined && request.targetPower === undefined && request.refresh && this.prevRequest) {
29
+ return this.prevRequest;
30
+ }
31
+ if (request.slope !== undefined) {
32
+ newRequest.slope = parseFloat(request.slope.toFixed(1));
33
+ this.data.slope = newRequest.slope;
34
+ }
35
+ if (this.data && this.data.power) {
36
+ const { minPower, maxPower } = request;
37
+ let { targetPower } = request;
38
+ if (minPower !== undefined && maxPower !== undefined && minPower === maxPower)
39
+ targetPower = maxPower;
40
+ if (targetPower !== undefined && Math.abs(this.data.power - targetPower) > MAX_DEVIATION)
41
+ newRequest.targetPower = targetPower;
42
+ else if (minPower !== undefined && this.data.power < minPower)
43
+ newRequest.targetPower = minPower;
44
+ else if (request.maxPower !== undefined && this.data.power > request.maxPower)
45
+ newRequest.targetPower = maxPower;
46
+ }
47
+ this.prevRequest = JSON.parse(JSON.stringify(newRequest));
48
+ return newRequest;
49
+ }
50
+ }
51
+ exports.default = AntAdvSimCyclingMode;
@@ -1,5 +1,6 @@
1
1
  import BleERGCyclingMode from "../../ble/ble-erg-mode";
2
2
  import { DeviceAdapter } from "../../Device";
3
3
  export default class AntFeERGCyclingMode extends BleERGCyclingMode {
4
+ static isERG: boolean;
4
5
  constructor(adapter: DeviceAdapter, props?: any);
5
6
  }
@@ -11,3 +11,4 @@ class AntFeERGCyclingMode extends ble_erg_mode_1.default {
11
11
  }
12
12
  }
13
13
  exports.default = AntFeERGCyclingMode;
14
+ AntFeERGCyclingMode.isERG = true;
@@ -0,0 +1,7 @@
1
+ import FtmsCyclingMode from "../../ble/ble-st-mode";
2
+ import { UpdateRequest } from "../../CyclingMode";
3
+ import { DeviceAdapter } from "../../Device";
4
+ export default class AntStCyclingMode extends FtmsCyclingMode {
5
+ constructor(adapter: DeviceAdapter, props?: any);
6
+ sendBikeUpdate(request: UpdateRequest): UpdateRequest;
7
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const ble_st_mode_1 = __importDefault(require("../../ble/ble-st-mode"));
7
+ class AntStCyclingMode extends ble_st_mode_1.default {
8
+ constructor(adapter, props) {
9
+ super(adapter, props);
10
+ this.initLogger('AntSTMode');
11
+ }
12
+ sendBikeUpdate(request) {
13
+ console.log('~~~ SIMMode:sendBikeUpdate reuqest', request);
14
+ const getData = () => {
15
+ if (!this.data)
16
+ return {};
17
+ const { gear, pedalRpm, slope, power, speed } = this.data;
18
+ return { gear, pedalRpm, slope, power, speed };
19
+ };
20
+ const event = {};
21
+ if (this.data === undefined)
22
+ event.noData = true;
23
+ if (request.slope !== undefined && (event.noData || Math.abs(request.slope - this.data.slope) >= 0.1))
24
+ event.slopeUpdate = true;
25
+ if (this.prevRequest === undefined)
26
+ event.initialCall = true;
27
+ this.logger.logEvent({ message: "processing update request", request, prev: this.prevRequest, data: getData(), event });
28
+ let newRequest = {};
29
+ if (request.slope === undefined && request.targetPower === undefined && request.refresh && this.prevRequest) {
30
+ return this.prevRequest;
31
+ }
32
+ if (request.slope !== undefined) {
33
+ newRequest.slope = parseFloat(request.slope.toFixed(1));
34
+ this.data.slope = newRequest.slope;
35
+ }
36
+ if (request.targetPower !== undefined) {
37
+ newRequest.targetPower = request.targetPower;
38
+ }
39
+ if (request.minPower && request.maxPower && request.minPower === request.maxPower) {
40
+ newRequest.targetPower = request.minPower;
41
+ }
42
+ const prevData = this.data;
43
+ if (newRequest.targetPower === undefined && prevData && prevData.power) {
44
+ if (request.minPower !== undefined && prevData.power < request.minPower)
45
+ newRequest.targetPower = request.minPower;
46
+ if (request.maxPower !== undefined && prevData.power > request.maxPower)
47
+ newRequest.targetPower = request.maxPower;
48
+ }
49
+ this.prevRequest = JSON.parse(JSON.stringify(newRequest));
50
+ console.log('~~~ SimMode:sendBikeUpdate result', newRequest);
51
+ return newRequest;
52
+ }
53
+ }
54
+ exports.default = AntStCyclingMode;
@@ -1,7 +1,5 @@
1
1
  import FtmsCyclingMode from "../../ble/ble-st-mode";
2
- import { UpdateRequest } from "../../CyclingMode";
3
2
  import { DeviceAdapter } from "../../Device";
4
3
  export default class AntStCyclingMode extends FtmsCyclingMode {
5
4
  constructor(adapter: DeviceAdapter, props?: any);
6
- sendBikeUpdate(request: UpdateRequest): UpdateRequest;
7
5
  }
@@ -7,46 +7,7 @@ const ble_st_mode_1 = __importDefault(require("../../ble/ble-st-mode"));
7
7
  class AntStCyclingMode extends ble_st_mode_1.default {
8
8
  constructor(adapter, props) {
9
9
  super(adapter, props);
10
- this.initLogger('AntSTMode');
11
- }
12
- sendBikeUpdate(request) {
13
- const getData = () => {
14
- if (!this.data)
15
- return {};
16
- const { gear, pedalRpm, slope, power, speed } = this.data;
17
- return { gear, pedalRpm, slope, power, speed };
18
- };
19
- const event = {};
20
- if (this.data === undefined)
21
- event.noData = true;
22
- if (request.slope !== undefined && (event.noData || Math.abs(request.slope - this.data.slope) >= 0.1))
23
- event.slopeUpdate = true;
24
- if (this.prevRequest === undefined)
25
- event.initialCall = true;
26
- this.logger.logEvent({ message: "processing update request", request, prev: this.prevRequest, data: getData(), event });
27
- let newRequest = {};
28
- if (request.slope === undefined && request.targetPower === undefined && request.refresh && this.prevRequest) {
29
- return this.prevRequest;
30
- }
31
- if (request.slope !== undefined) {
32
- newRequest.slope = parseFloat(request.slope.toFixed(1));
33
- this.data.slope = newRequest.slope;
34
- }
35
- if (request.targetPower !== undefined) {
36
- newRequest.targetPower = request.targetPower;
37
- }
38
- if (request.minPower && request.maxPower && request.minPower === request.maxPower) {
39
- newRequest.targetPower = request.minPower;
40
- }
41
- const prevData = this.data;
42
- if (newRequest.targetPower === undefined && prevData && prevData.power) {
43
- if (request.minPower !== undefined && prevData.power < request.minPower)
44
- newRequest.targetPower = request.minPower;
45
- if (request.maxPower !== undefined && prevData.power > request.maxPower)
46
- newRequest.targetPower = request.maxPower;
47
- }
48
- this.prevRequest = JSON.parse(JSON.stringify(newRequest));
49
- return newRequest;
10
+ this.initLogger('AntSimMode');
50
11
  }
51
12
  }
52
13
  exports.default = AntStCyclingMode;
@@ -2,6 +2,7 @@ import CyclingMode, { CyclingModeProperty, IncyclistBikeData, UpdateRequest } fr
2
2
  import { DeviceAdapter } from "../Device";
3
3
  import PowerBasedCyclingModeBase from "../modes/power-base";
4
4
  export default class BleERGCyclingMode extends PowerBasedCyclingModeBase implements CyclingMode {
5
+ static isERG: boolean;
5
6
  prevRequest: UpdateRequest;
6
7
  hasBikeUpdate: boolean;
7
8
  chain: number[];
@@ -50,21 +50,15 @@ class BleERGCyclingMode extends power_base_1.default {
50
50
  this.prevRequest = {};
51
51
  return request.reset ? { reset: true } : {};
52
52
  }
53
+ delete request.slope;
53
54
  const prevData = this.data || {};
54
55
  if (request.targetPower !== undefined) {
55
- delete request.slope;
56
56
  delete request.refresh;
57
57
  }
58
58
  if (request.refresh) {
59
59
  delete request.refresh;
60
60
  newRequest.targetPower = this.prevRequest.targetPower;
61
61
  }
62
- if (request.slope !== undefined) {
63
- if (!this.data)
64
- this.data = {};
65
- this.data.slope = request.slope;
66
- delete request.slope;
67
- }
68
62
  if (request.maxPower !== undefined && request.minPower !== undefined && request.maxPower === request.minPower) {
69
63
  request.targetPower = request.maxPower;
70
64
  newRequest.targetPower = request.targetPower;
@@ -130,3 +124,4 @@ class BleERGCyclingMode extends power_base_1.default {
130
124
  }
131
125
  }
132
126
  exports.default = BleERGCyclingMode;
127
+ BleERGCyclingMode.isERG = true;
@@ -71,9 +71,6 @@ class BleInterface extends ble_1.BleInterfaceClass {
71
71
  }
72
72
  connect(props = {}) {
73
73
  const timeout = props.timeout || 2000;
74
- const runBackgroundScan = () => {
75
- return;
76
- };
77
74
  return new Promise((resolve, reject) => {
78
75
  if (this.connectState.isConnected) {
79
76
  return resolve(true);
@@ -122,7 +119,6 @@ class BleInterface extends ble_1.BleInterfaceClass {
122
119
  this.connectState.isConnecting = false;
123
120
  this.logEvent({ message: 'connect result: success' });
124
121
  resolve(true);
125
- runBackgroundScan();
126
122
  return;
127
123
  }
128
124
  else {
@@ -142,7 +138,6 @@ class BleInterface extends ble_1.BleInterfaceClass {
142
138
  this.connectState.isConnected = true;
143
139
  this.connectState.isConnecting = false;
144
140
  this.logEvent({ message: 'connect result: success' });
145
- runBackgroundScan();
146
141
  return resolve(true);
147
142
  }
148
143
  else {
@@ -489,7 +484,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
489
484
  }
490
485
  scan(props) {
491
486
  return __awaiter(this, void 0, void 0, function* () {
492
- const { timeout = DEFAULT_SCAN_TIMEOUT, deviceTypes = [], requested, isBackgroundScan } = props;
487
+ const { timeout = DEFAULT_SCAN_TIMEOUT, deviceTypes = [], requested } = props;
493
488
  let profile;
494
489
  if (requested)
495
490
  profile = requested instanceof ble_1.BleDeviceClass ?
@@ -497,7 +492,7 @@ class BleInterface extends ble_1.BleInterfaceClass {
497
492
  requested.profile;
498
493
  const { id, address, name } = requested || {};
499
494
  const scanForDevice = (requested !== null && requested !== undefined);
500
- const services = (props.isBackgroundScan || !deviceTypes || deviceTypes.length === 0) ? this.getAllSupportedServices() : this.getServicesFromDeviceTypes(deviceTypes);
495
+ const services = (!deviceTypes || deviceTypes.length === 0) ? this.getAllSupportedServices() : this.getServicesFromDeviceTypes(deviceTypes);
501
496
  const bleBinding = this.getBinding();
502
497
  if (!bleBinding)
503
498
  return Promise.reject(new Error('no binding defined'));
@@ -506,18 +501,14 @@ class BleInterface extends ble_1.BleInterfaceClass {
506
501
  }
507
502
  const peripheralsProcessed = [];
508
503
  const devicesProcessed = [];
509
- this.logEvent({ message: 'scan()', props: { timeout, isBackgroundScan }, scanState: this.scanState,
504
+ this.logEvent({ message: 'scan()', props: { timeout }, scanState: this.scanState,
510
505
  peripheralCache: this.peripheralCache.map(i => ({ address: i.address, ts: i.ts, name: i.peripheral ? i.peripheral.advertisement.localName : '' })),
511
506
  deviceCache: this.devices.map(i => ({ address: i.device.address, profile: i.device.getProfile(), isConnected: i.isConnected }))
512
507
  });
513
- if (!props.isBackgroundScan && this.scanState.isBackgroundScan) {
514
- yield this.stopScan();
515
- this.scanState.isBackgroundScan = false;
516
- }
517
508
  let opStr;
518
509
  if (scanForDevice) {
519
510
  opStr = 'search device';
520
- this.logEvent({ message: 'search device request', device: { id, address, name }, deviceTypes });
511
+ this.logEvent({ message: 'search device request', services, device: { id, address, name }, deviceTypes });
521
512
  }
522
513
  else {
523
514
  opStr = 'scan';
@@ -536,8 +527,6 @@ class BleInterface extends ble_1.BleInterfaceClass {
536
527
  }
537
528
  return new Promise((resolve, reject) => {
538
529
  this.scanState.isScanning = true;
539
- if (props.isBackgroundScan)
540
- this.scanState.isBackgroundScan = true;
541
530
  if (scanForDevice) {
542
531
  if (this.devices && this.devices.length > 0) {
543
532
  const knownDevices = this.devices.map(i => ({ name: i.device.name, address: i.device.address, isConnected: i.isConnected, connectState: i.device.getConnectState() }));
@@ -566,8 +555,9 @@ class BleInterface extends ble_1.BleInterfaceClass {
566
555
  const onPeripheralFound = (peripheral, fromCache = false) => __awaiter(this, void 0, void 0, function* () {
567
556
  if (!peripheral || !peripheral.advertisement || !peripheral.advertisement.localName || !peripheral.advertisement.serviceUuids || peripheral.advertisement.serviceUuids.length === 0)
568
557
  return;
569
- if (fromCache)
558
+ if (fromCache) {
570
559
  this.logEvent({ message: 'adding from Cache', peripheral: peripheral.address });
560
+ }
571
561
  else {
572
562
  const { id, name, address, advertisement = {} } = peripheral;
573
563
  this.logEvent({ message: 'BLE scan: found device', peripheral: { id, name, address, services: advertisement.serviceUuids } });
@@ -584,66 +574,62 @@ class BleInterface extends ble_1.BleInterfaceClass {
584
574
  const services = connectedServices ? connectedServices.map(cs => cs.uuid) : undefined;
585
575
  const connectedPeripheral = connector.getPeripheral();
586
576
  const { id, name, address, advertisement = {} } = connectedPeripheral;
587
- const DeviceClasses = this.getDeviceClasses(connectedPeripheral, { profile, services });
577
+ const DeviceClasses = this.getDeviceClasses(connectedPeripheral, { profile, services }) || [];
588
578
  this.logEvent({ message: 'BLE scan: device connected', peripheral: { id, name, address, services: advertisement.serviceUuids }, services, classes: DeviceClasses.map(c => c.prototype.constructor.name) });
589
579
  let cntFound = 0;
590
- DeviceClasses.forEach((DeviceClass) => __awaiter(this, void 0, void 0, function* () {
591
- if (!DeviceClass)
592
- return;
593
- if (scanForDevice && cntFound > 0)
594
- return;
595
- const d = this.createDevice(DeviceClass, peripheral, characteristics);
596
- if (!d) {
597
- this.logEvent({ message: `${opStr}: could not create device `, DeviceClass });
598
- return;
599
- }
600
- try {
601
- this.logEvent({ message: `${opStr}: connecting `, device: d.name, profile: d.getProfile(), address: d.address });
602
- yield d.connect();
603
- }
604
- catch (err) {
605
- this.logEvent({ message: 'error', fn: 'onPeripheralFound()', error: err.message || err, stack: err.stack });
606
- }
607
- if (scanForDevice) {
608
- if ((id && id !== '' && d.id === id) ||
609
- (address && address !== '' && d.address === address) ||
610
- (name && name !== '' && d.name === name))
611
- cntFound++;
612
- }
613
- else
580
+ const DeviceClass = DeviceClasses.sort((a, b) => (a.detectionPriority || 0 - b.detectionPriority || 0))[0];
581
+ if (!DeviceClass)
582
+ return;
583
+ if (scanForDevice && cntFound > 0)
584
+ return;
585
+ const d = this.createDevice(DeviceClass, peripheral, characteristics);
586
+ if (!d) {
587
+ this.logEvent({ message: `${opStr}: could not create device `, DeviceClass });
588
+ return;
589
+ }
590
+ try {
591
+ this.logEvent({ message: `${opStr}: connecting `, device: d.name, profile: d.getProfile(), address: d.address });
592
+ yield d.connect();
593
+ }
594
+ catch (err) {
595
+ this.logEvent({ message: 'error', fn: 'onPeripheralFound()', error: err.message || err, stack: err.stack });
596
+ }
597
+ if (scanForDevice) {
598
+ if ((id && id !== '' && d.id === id) ||
599
+ (address && address !== '' && d.address === address) ||
600
+ (name && name !== '' && d.name === name))
614
601
  cntFound++;
615
- const existing = devicesProcessed.find(device => device.id === d.id && device.getProfile() === d.getProfile());
616
- if (!scanForDevice && cntFound > 0 && !existing) {
617
- this.logEvent({ message: `${opStr}: device found`, device: d.name, profile: d.getProfile(), address: d.address, services: d.services.join(',') });
618
- this.addDeviceToCache(d, peripheral.state === 'connected');
619
- devicesProcessed.push(d);
620
- this.emit('device', d);
621
- return;
622
- }
623
- if (scanForDevice && cntFound > 0) {
624
- this.logEvent({ message: `${opStr}: device found`, device: d.name, profile: d.getProfile(), address: d.address, services: d.services.join(',') });
625
- this.addDeviceToCache(d, peripheral.state === 'connected');
626
- devicesProcessed.push(d);
627
- this.emit('device', d);
628
- process.nextTick(() => {
629
- if (this.scanState.timeout) {
630
- clearTimeout(this.scanState.timeout);
631
- this.scanState.timeout = null;
632
- }
633
- this.logEvent({ message: `${opStr}: stop scanning`, requested: scanForDevice ? { name, address, profile } : undefined, });
634
- bleBinding.stopScanning(() => {
635
- this.getBinding().removeAllListeners('discover');
636
- this.scanState.isScanning = false;
637
- resolve([d]);
638
- });
602
+ }
603
+ else
604
+ cntFound++;
605
+ const existing = devicesProcessed.find(device => device.id === d.id && device.getProfile() === d.getProfile());
606
+ if (!scanForDevice && cntFound > 0 && !existing) {
607
+ this.logEvent({ message: `${opStr}: device found`, device: d.name, profile: d.getProfile(), address: d.address, services: d.services.join(',') });
608
+ this.addDeviceToCache(d, peripheral.state === 'connected');
609
+ devicesProcessed.push(d);
610
+ this.emit('device', d);
611
+ return;
612
+ }
613
+ if (scanForDevice && cntFound > 0) {
614
+ this.logEvent({ message: `${opStr}: device found`, device: d.name, profile: d.getProfile(), address: d.address, services: d.services.join(',') });
615
+ this.addDeviceToCache(d, peripheral.state === 'connected');
616
+ devicesProcessed.push(d);
617
+ this.emit('device', d);
618
+ process.nextTick(() => {
619
+ if (this.scanState.timeout) {
620
+ clearTimeout(this.scanState.timeout);
621
+ this.scanState.timeout = null;
622
+ }
623
+ this.logEvent({ message: `${opStr}: stop scanning`, requested: scanForDevice ? { name, address, profile } : undefined, });
624
+ bleBinding.stopScanning(() => {
625
+ this.getBinding().removeAllListeners('discover');
626
+ this.scanState.isScanning = false;
627
+ resolve([d]);
639
628
  });
640
- }
641
- }));
629
+ });
630
+ }
642
631
  });
643
632
  this.logEvent({ message: `${opStr}: start scanning`, requested: scanForDevice ? { name, address, profile } : undefined, timeout });
644
- this.peripheralCache.forEach(i => {
645
- onPeripheralFound(i.peripheral, true);
646
- });
647
633
  let services = [];
648
634
  if (scanForDevice) {
649
635
  if (props.requested instanceof ble_1.BleDeviceClass) {
package/lib/ble/fm.d.ts CHANGED
@@ -45,6 +45,7 @@ declare type IndoorBikeFeatures = {
45
45
  export default class BleFitnessMachineDevice extends BleDevice {
46
46
  static services: string[];
47
47
  static characteristics: string[];
48
+ static detectionPriority: number;
48
49
  data: IndoorBikeData;
49
50
  features: IndoorBikeFeatures;
50
51
  hasControl: boolean;
package/lib/ble/fm.js CHANGED
@@ -21,6 +21,7 @@ const power_meter_1 = __importDefault(require("../modes/power-meter"));
21
21
  const ble_st_mode_1 = __importDefault(require("./ble-st-mode"));
22
22
  const ble_erg_mode_1 = __importDefault(require("./ble-erg-mode"));
23
23
  const consts_1 = require("./consts");
24
+ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
24
25
  const cwABike = {
25
26
  race: 0.35,
26
27
  triathlon: 0.29,
@@ -101,7 +102,6 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
101
102
  const hasStatus = characteristics.find(c => c === consts_1.FTMS_STATUS) !== undefined;
102
103
  const hasCP = characteristics.find(c => c === consts_1.FTMS_CP) !== undefined;
103
104
  const hasIndoorBike = characteristics.find(c => c === consts_1.INDOOR_BIKE_DATA) !== undefined;
104
- const hasTacx = characteristics.find(c => c === consts_1.TACX_FE_C_RX) !== undefined && characteristics.find(c => c === consts_1.TACX_FE_C_TX) !== undefined;
105
105
  return hasStatus && hasCP && hasIndoorBike;
106
106
  }
107
107
  subscribeWriteResponse(cuuid) {
@@ -185,8 +185,8 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
185
185
  return BleFitnessMachineDevice.services;
186
186
  }
187
187
  isBike() {
188
- return this.features !== undefined &&
189
- (this.features.targetSettings & TargetSettingFeatureFlag.IndoorBikeSimulationParametersSupported) !== 0;
188
+ return this.features === undefined ||
189
+ ((this.features.targetSettings & TargetSettingFeatureFlag.IndoorBikeSimulationParametersSupported) !== 0);
190
190
  }
191
191
  isPower() {
192
192
  if (this.hasService('1818'))
@@ -539,6 +539,7 @@ class BleFitnessMachineDevice extends ble_device_1.BleDevice {
539
539
  exports.default = BleFitnessMachineDevice;
540
540
  BleFitnessMachineDevice.services = [consts_1.FTMS];
541
541
  BleFitnessMachineDevice.characteristics = ['2acc', consts_1.INDOOR_BIKE_DATA, '2ad6', '2ad8', consts_1.FTMS_CP, consts_1.FTMS_STATUS];
542
+ BleFitnessMachineDevice.detectionPriority = 100;
542
543
  ble_interface_1.default.register('BleFitnessMachineDevice', 'fm', BleFitnessMachineDevice, BleFitnessMachineDevice.services);
543
544
  class FmAdapter extends Device_1.default {
544
545
  constructor(device, protocol) {
@@ -685,7 +686,17 @@ class FmAdapter extends Device_1.default {
685
686
  break;
686
687
  }
687
688
  }
688
- yield this.device.requestControl();
689
+ let hasControl = yield this.device.requestControl();
690
+ if (!hasControl) {
691
+ let retry = 1;
692
+ while (!hasControl && retry < 3) {
693
+ yield sleep(1000);
694
+ hasControl = yield this.device.requestControl();
695
+ retry++;
696
+ }
697
+ }
698
+ if (!hasControl)
699
+ throw new Error('could not establish control');
689
700
  const startRequest = this.getCyclingMode().getBikeInitRequest();
690
701
  yield this.sendUpdate(startRequest);
691
702
  bleDevice.on('data', (data) => {
package/lib/ble/hrm.d.ts CHANGED
@@ -14,6 +14,7 @@ declare type HrmData = {
14
14
  export default class BleHrmDevice extends BleDevice {
15
15
  static services: string[];
16
16
  static characteristics: string[];
17
+ static detectionPriority: number;
17
18
  heartrate: number;
18
19
  rr: number;
19
20
  constructor(props?: any);
package/lib/ble/hrm.js CHANGED
@@ -65,6 +65,7 @@ class BleHrmDevice extends ble_device_1.BleDevice {
65
65
  exports.default = BleHrmDevice;
66
66
  BleHrmDevice.services = ['180d'];
67
67
  BleHrmDevice.characteristics = ['2a37', '2a38', '2a39', '2a3c'];
68
+ BleHrmDevice.detectionPriority = 1;
68
69
  ble_interface_1.default.register('BleHrmDevice', 'hr', BleHrmDevice, BleHrmDevice.services);
69
70
  class HrmAdapter extends Device_1.default {
70
71
  constructor(device, protocol) {
package/lib/ble/pwr.d.ts CHANGED
@@ -24,6 +24,7 @@ declare type CrankData = {
24
24
  export default class BleCyclingPowerDevice extends BleDevice {
25
25
  static services: string[];
26
26
  static characteristics: string[];
27
+ static detectionPriority: number;
27
28
  instantaneousPower: number;
28
29
  balance: number;
29
30
  accTorque: number;
package/lib/ble/pwr.js CHANGED
@@ -163,6 +163,7 @@ class BleCyclingPowerDevice extends ble_device_1.BleDevice {
163
163
  exports.default = BleCyclingPowerDevice;
164
164
  BleCyclingPowerDevice.services = [consts_1.CSP];
165
165
  BleCyclingPowerDevice.characteristics = [consts_1.CSP_MEASUREMENT, consts_1.CSP_FEATURE, '2a5d', '2a3c'];
166
+ BleCyclingPowerDevice.detectionPriority = 1;
166
167
  ble_interface_1.default.register('BleCyclingPowerDevice', 'cp', BleCyclingPowerDevice, BleCyclingPowerDevice.services);
167
168
  class PwrAdapter extends Device_1.default {
168
169
  constructor(device, protocol) {
package/lib/ble/tacx.d.ts CHANGED
@@ -28,6 +28,7 @@ export default class TacxAdvancedFitnessMachineDevice extends BleFitnessMachineD
28
28
  static services: string[];
29
29
  static characteristics: string[];
30
30
  static PROFILE: string;
31
+ static detectionPriority: number;
31
32
  prevCrankData: CrankData;
32
33
  currentCrankData: CrankData;
33
34
  timeOffset: number;
package/lib/ble/tacx.js CHANGED
@@ -84,7 +84,6 @@ class TacxAdvancedFitnessMachineDevice extends fm_1.default {
84
84
  return false;
85
85
  const hasTacxCP = characteristics.find(c => (0, ble_1.matches)(c, consts_1.TACX_FE_C_RX)) !== undefined &&
86
86
  characteristics.find(c => (0, ble_1.matches)(c, consts_1.TACX_FE_C_TX)) !== undefined;
87
- const hasFTMS = characteristics.find(c => (0, ble_1.matches)(c, consts_1.FTMS_CP)) !== undefined;
88
87
  return hasTacxCP;
89
88
  }
90
89
  setCharacteristicUUIDs(uuids) {
@@ -658,6 +657,7 @@ exports.default = TacxAdvancedFitnessMachineDevice;
658
657
  TacxAdvancedFitnessMachineDevice.services = [consts_1.TACX_FE_C_BLE];
659
658
  TacxAdvancedFitnessMachineDevice.characteristics = ['2acc', '2ad2', '2ad6', '2ad8', '2ad9', '2ada', consts_1.TACX_FE_C_RX, consts_1.TACX_FE_C_TX];
660
659
  TacxAdvancedFitnessMachineDevice.PROFILE = PROFILE_ID;
660
+ TacxAdvancedFitnessMachineDevice.detectionPriority = 10;
661
661
  ble_interface_1.default.register('TacxBleFEDevice', 'tacx-ble-fec', TacxAdvancedFitnessMachineDevice, TacxAdvancedFitnessMachineDevice.services);
662
662
  class TacxBleFEAdapter extends fm_1.FmAdapter {
663
663
  constructor(device, protocol) {
@@ -42,6 +42,7 @@ declare type CrankData = {
42
42
  export default class WahooAdvancedFitnessMachineDevice extends BleFitnessMachineDevice {
43
43
  static services: string[];
44
44
  static characteristics: string[];
45
+ static detectionPriority: number;
45
46
  prevCrankData: CrankData;
46
47
  currentCrankData: CrankData;
47
48
  timeOffset: number;
@@ -424,6 +424,7 @@ class WahooAdvancedFitnessMachineDevice extends fm_1.default {
424
424
  exports.default = WahooAdvancedFitnessMachineDevice;
425
425
  WahooAdvancedFitnessMachineDevice.services = [consts_1.CSP];
426
426
  WahooAdvancedFitnessMachineDevice.characteristics = ['2acc', '2ad2', '2ad6', '2ad8', '2ad9', '2ada', consts_1.WAHOO_ADVANCED_TRAINER_CP];
427
+ WahooAdvancedFitnessMachineDevice.detectionPriority = 5;
427
428
  ble_interface_1.default.register('WahooAdvancedFitnessMachineDevice', 'wahoo-fm', WahooAdvancedFitnessMachineDevice, WahooAdvancedFitnessMachineDevice.services);
428
429
  class WahooAdvancedFmAdapter extends fm_1.FmAdapter {
429
430
  constructor(device, protocol) {
@@ -13,6 +13,7 @@ export default class ERGCyclingMode extends PowerBasedCyclingModeBase implements
13
13
  chain: number[];
14
14
  cassette: number[];
15
15
  event: ERGEvent;
16
+ static isERG: boolean;
16
17
  constructor(adapter: DaumAdapter, props?: any);
17
18
  getName(): string;
18
19
  getDescription(): string;
@@ -198,3 +198,4 @@ class ERGCyclingMode extends power_base_1.default {
198
198
  }
199
199
  }
200
200
  exports.default = ERGCyclingMode;
201
+ ERGCyclingMode.isERG = true;
@@ -8,6 +8,7 @@ export declare type ERGEvent = {
8
8
  tsStart?: number;
9
9
  };
10
10
  export default class ERGCyclingMode extends PowerBasedCyclingModeBase implements CyclingMode {
11
+ static isERG: boolean;
11
12
  prevRequest: UpdateRequest;
12
13
  hasBikeUpdate: boolean;
13
14
  chain: number[];
@@ -142,3 +142,4 @@ class ERGCyclingMode extends power_base_1.default {
142
142
  }
143
143
  }
144
144
  exports.default = ERGCyclingMode;
145
+ ERGCyclingMode.isERG = true;
@@ -9,6 +9,7 @@ export declare type ERGEvent = {
9
9
  tsStart?: number;
10
10
  };
11
11
  export default class SimulatorCyclingMode extends PowerBasedCyclingModeBase {
12
+ static isERG: boolean;
12
13
  logger: EventLogger;
13
14
  data: IncyclistBikeData;
14
15
  prevRequest: UpdateRequest;
@@ -137,3 +137,4 @@ class SimulatorCyclingMode extends power_base_1.default {
137
137
  }
138
138
  }
139
139
  exports.default = SimulatorCyclingMode;
140
+ SimulatorCyclingMode.isERG = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "1.4.94",
3
+ "version": "1.4.96",
4
4
  "dependencies": {
5
5
  "@serialport/parser-byte-length": "^9.0.1",
6
6
  "@serialport/parser-delimiter": "^9.0.1",