incyclist-devices 2.0.0-beta.1 → 2.0.0

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 (114) hide show
  1. package/README.MD +238 -0
  2. package/lib/adapters.d.ts +1 -0
  3. package/lib/adapters.js +19 -0
  4. package/lib/antv2/adapter-factory.d.ts +8 -7
  5. package/lib/antv2/adapter-factory.js +4 -2
  6. package/lib/antv2/adapter.d.ts +3 -2
  7. package/lib/antv2/adapter.js +15 -4
  8. package/lib/antv2/ant-interface.d.ts +6 -2
  9. package/lib/antv2/ant-interface.js +27 -21
  10. package/lib/antv2/binding.d.ts +1 -1
  11. package/lib/antv2/binding.js +1 -1
  12. package/lib/antv2/fe/adapter.d.ts +12 -9
  13. package/lib/antv2/fe/adapter.js +67 -27
  14. package/lib/antv2/hr/adapter.d.ts +6 -5
  15. package/lib/antv2/hr/adapter.js +19 -16
  16. package/lib/antv2/index.d.ts +2 -2
  17. package/lib/antv2/pwr/adapter.d.ts +6 -4
  18. package/lib/antv2/pwr/adapter.js +24 -16
  19. package/lib/antv2/sensor-factory.d.ts +2 -2
  20. package/lib/antv2/types.d.ts +5 -2
  21. package/lib/antv2/types.js +3 -0
  22. package/lib/antv2/utils.d.ts +3 -0
  23. package/lib/antv2/utils.js +12 -1
  24. package/lib/base/adpater.d.ts +14 -2
  25. package/lib/base/adpater.js +43 -4
  26. package/lib/ble/adapter-factory.d.ts +18 -16
  27. package/lib/ble/adapter-factory.js +54 -45
  28. package/lib/ble/base/adapter.d.ts +53 -0
  29. package/lib/ble/{adapter.js → base/adapter.js} +111 -9
  30. package/lib/ble/base/comms-utils.d.ts +7 -0
  31. package/lib/ble/base/comms-utils.js +91 -0
  32. package/lib/ble/{ble-comms.d.ts → base/comms.d.ts} +27 -17
  33. package/lib/ble/{ble-comms.js → base/comms.js} +179 -53
  34. package/lib/ble/bindings/index.d.ts +2 -0
  35. package/lib/ble/bindings/index.js +8 -0
  36. package/lib/ble/bindings/linux.d.ts +15 -0
  37. package/lib/ble/bindings/linux.js +39 -0
  38. package/lib/ble/bindings/mock.d.ts +9 -0
  39. package/lib/ble/bindings/mock.js +108 -0
  40. package/lib/ble/bindings/types.d.ts +57 -0
  41. package/lib/ble/bindings/types.js +96 -0
  42. package/lib/ble/ble-interface.d.ts +34 -46
  43. package/lib/ble/ble-interface.js +242 -345
  44. package/lib/ble/ble-peripheral.d.ts +4 -2
  45. package/lib/ble/ble-peripheral.js +39 -8
  46. package/lib/ble/consts.d.ts +1 -0
  47. package/lib/ble/consts.js +2 -1
  48. package/lib/ble/cp/adapter.d.ts +1 -2
  49. package/lib/ble/cp/adapter.js +2 -15
  50. package/lib/ble/cp/comm.d.ts +8 -5
  51. package/lib/ble/cp/comm.js +12 -27
  52. package/lib/ble/elite/adapter.d.ts +1 -2
  53. package/lib/ble/elite/adapter.js +12 -19
  54. package/lib/ble/elite/comms.d.ts +8 -4
  55. package/lib/ble/elite/comms.js +12 -25
  56. package/lib/ble/fm/adapter.d.ts +3 -2
  57. package/lib/ble/fm/adapter.js +129 -70
  58. package/lib/ble/fm/comms.d.ts +8 -8
  59. package/lib/ble/fm/comms.js +33 -55
  60. package/lib/ble/fm/types.d.ts +5 -0
  61. package/lib/ble/hr/adapter.d.ts +1 -4
  62. package/lib/ble/hr/adapter.js +1 -18
  63. package/lib/ble/hr/comm.d.ts +6 -2
  64. package/lib/ble/hr/comm.js +6 -2
  65. package/lib/ble/hr/mock.d.ts +7 -0
  66. package/lib/ble/hr/mock.js +47 -0
  67. package/lib/ble/index.d.ts +2 -1
  68. package/lib/ble/index.js +5 -5
  69. package/lib/ble/peripheral-cache.d.ts +43 -0
  70. package/lib/ble/peripheral-cache.js +107 -0
  71. package/lib/ble/tacx/adapter.d.ts +1 -1
  72. package/lib/ble/tacx/adapter.js +20 -14
  73. package/lib/ble/tacx/comms.d.ts +6 -6
  74. package/lib/ble/tacx/comms.js +10 -43
  75. package/lib/ble/types.d.ts +54 -27
  76. package/lib/ble/types.js +0 -17
  77. package/lib/ble/utils.d.ts +15 -5
  78. package/lib/ble/utils.js +25 -66
  79. package/lib/ble/wahoo/adapter.d.ts +1 -1
  80. package/lib/ble/wahoo/adapter.js +12 -10
  81. package/lib/ble/wahoo/comms.d.ts +7 -6
  82. package/lib/ble/wahoo/comms.js +15 -17
  83. package/lib/index.d.ts +10 -7
  84. package/lib/index.js +21 -25
  85. package/lib/interfaces.d.ts +2 -1
  86. package/lib/interfaces.js +4 -0
  87. package/lib/modes/power-base.js +4 -0
  88. package/lib/serial/adapter.d.ts +5 -0
  89. package/lib/serial/adapter.js +19 -0
  90. package/lib/serial/bindings/tcp.d.ts +2 -1
  91. package/lib/serial/bindings/tcp.js +19 -5
  92. package/lib/serial/daum/DaumAdapter.d.ts +1 -1
  93. package/lib/serial/daum/DaumAdapter.js +16 -10
  94. package/lib/serial/daum/premium/adapter.d.ts +1 -0
  95. package/lib/serial/daum/premium/adapter.js +9 -2
  96. package/lib/serial/daum/premium/comms.js +10 -3
  97. package/lib/serial/daum/premium/mock.js +0 -1
  98. package/lib/serial/index.d.ts +3 -3
  99. package/lib/serial/index.js +2 -2
  100. package/lib/serial/kettler/ergo-racer/adapter.d.ts +1 -4
  101. package/lib/serial/kettler/ergo-racer/adapter.js +15 -39
  102. package/lib/serial/serial-interface.d.ts +3 -1
  103. package/lib/serial/serial-interface.js +43 -17
  104. package/lib/simulator/Simulator.d.ts +2 -0
  105. package/lib/simulator/Simulator.js +8 -5
  106. package/lib/types/adapter.d.ts +10 -3
  107. package/lib/types/device.d.ts +3 -0
  108. package/lib/types/interface.d.ts +7 -3
  109. package/package.json +3 -5
  110. package/lib/ble/adapter.d.ts +0 -41
  111. package/lib/ble/ble.d.ts +0 -57
  112. package/lib/ble/ble.js +0 -48
  113. package/lib/device.d.ts +0 -0
  114. package/lib/device.js +0 -0
@@ -17,7 +17,7 @@ const power_meter_1 = __importDefault(require("../../modes/power-meter"));
17
17
  const ble_st_mode_1 = __importDefault(require("../../modes/ble-st-mode"));
18
18
  const ble_erg_mode_1 = __importDefault(require("../../modes/ble-erg-mode"));
19
19
  const comms_1 = __importDefault(require("./comms"));
20
- const adapter_1 = require("../adapter");
20
+ const adapter_1 = require("../base/adapter");
21
21
  const consts_1 = require("./consts");
22
22
  const utils_1 = require("../../utils/utils");
23
23
  const capabilities_1 = require("../../types/capabilities");
@@ -50,23 +50,27 @@ class BleFmAdapter extends adapter_1.BleControllableAdapter {
50
50
  return this.getName();
51
51
  }
52
52
  getSupportedCyclingModes() {
53
- return [ble_st_mode_1.default, ble_erg_mode_1.default, power_meter_1.default];
53
+ var _a;
54
+ const modes = [power_meter_1.default];
55
+ const features = (_a = this.getComms()) === null || _a === void 0 ? void 0 : _a.features;
56
+ if (!features)
57
+ return [power_meter_1.default, ble_st_mode_1.default, ble_erg_mode_1.default];
58
+ if (features.setPower === undefined || features.setPower)
59
+ modes.push(ble_erg_mode_1.default);
60
+ if (features.setSlope === undefined || features.setSlope)
61
+ modes.push(ble_st_mode_1.default);
62
+ return modes;
54
63
  }
55
64
  getDefaultCyclingMode() {
56
- return new ble_st_mode_1.default(this);
57
- }
58
- onDeviceData(deviceData) {
59
- super.onDeviceData(deviceData);
60
- if (!this.started || this.paused || !this.onDataFn)
61
- return;
62
- this.logger.logEvent({ message: 'onDeviceData', data: deviceData });
63
- if (!this.lastUpdate || (Date.now() - this.lastUpdate) > this.updateFrequency) {
64
- let incyclistData = this.mapData(deviceData);
65
- incyclistData = this.getCyclingMode().updateData(incyclistData);
66
- this.data = this.transformData(incyclistData);
67
- this.onDataFn(this.data);
68
- this.lastUpdate = Date.now();
69
- }
65
+ var _a;
66
+ const features = (_a = this.getComms()) === null || _a === void 0 ? void 0 : _a.features;
67
+ if (!features)
68
+ return new ble_st_mode_1.default(this);
69
+ if (features.setSlope === undefined || features.setSlope)
70
+ return new ble_st_mode_1.default(this);
71
+ if (features.setPower === undefined || features.setPower)
72
+ return new ble_erg_mode_1.default(this);
73
+ return new power_meter_1.default(this);
70
74
  }
71
75
  mapData(deviceData) {
72
76
  const data = {
@@ -83,6 +87,7 @@ class BleFmAdapter extends adapter_1.BleControllableAdapter {
83
87
  data.pedalRpm = (deviceData.cadence !== undefined ? deviceData.cadence : data.pedalRpm);
84
88
  data.time = (deviceData.time !== undefined ? deviceData.time : data.time);
85
89
  data.isPedalling = data.pedalRpm > 0 || (data.pedalRpm === undefined && data.power > 0);
90
+ data.heartrate = deviceData.heartrate || data.heartrate;
86
91
  return data;
87
92
  }
88
93
  transformData(bikeData) {
@@ -100,73 +105,104 @@ class BleFmAdapter extends adapter_1.BleControllableAdapter {
100
105
  power: bikeData.power !== undefined ? Math.round(bikeData.power) : undefined,
101
106
  cadence: bikeData.pedalRpm !== undefined ? Math.round(bikeData.pedalRpm) : undefined,
102
107
  distance,
108
+ heartrate: bikeData.heartrate,
103
109
  timestamp: Date.now()
104
110
  };
105
111
  return data;
106
112
  }
107
113
  start(props = {}) {
108
114
  return __awaiter(this, void 0, void 0, function* () {
109
- if (this.started)
115
+ const wasPaused = this.paused;
116
+ this.resume();
117
+ if (this.started && !wasPaused)
110
118
  return true;
111
- this.logger.logEvent({ message: 'start requested', protocol: this.getProtocolName(), props });
112
- const { restart } = props;
113
- if (!restart && this.ble.isScanning())
114
- yield this.ble.stopScan();
115
- try {
116
- let bleDevice;
117
- if (!this.device || !restart) {
118
- bleDevice = (yield this.ble.connectDevice(this.device));
119
- this.device = bleDevice;
119
+ this.logEvent(Object.assign(Object.assign({ message: 'start requested' }, this.getSettings()), { protocol: this.getProtocolName(), props }));
120
+ const { restart = wasPaused } = props;
121
+ if (!restart && this.ble.isScanning() && !this.getComms().isConnected()) {
122
+ }
123
+ let scanOnly = props.scanOnly;
124
+ if (this.ble.isScanning() && this.getComms().isConnected()) {
125
+ scanOnly = true;
126
+ }
127
+ else {
128
+ const { timeout = 20000 } = props || {};
129
+ if (!this.connectPromise)
130
+ this.connectPromise = this.connect();
131
+ const res = yield Promise.race([
132
+ this.connectPromise.then((connected) => {
133
+ this.connectPromise = undefined;
134
+ return { connected, reason: connected ? null : 'could not connect' };
135
+ }),
136
+ (0, utils_1.sleep)(timeout).then(() => ({ connected: false, reason: 'timeout' }))
137
+ ]);
138
+ const connected = res.connected;
139
+ if (!connected) {
140
+ throw new Error(`could not start device, reason:${res.reason}`);
120
141
  }
121
- else
122
- bleDevice = this.device;
123
- if (bleDevice) {
124
- bleDevice.setLogger(this.logger);
125
- const mode = this.getCyclingMode();
126
- if (mode && mode.getSetting('bikeType')) {
127
- const bikeType = mode.getSetting('bikeType').toLowerCase();
128
- bleDevice.setCrr(consts_1.cRR);
129
- switch (bikeType) {
130
- case 'race':
131
- bleDevice.setCw(consts_1.cwABike.race);
132
- break;
133
- case 'triathlon':
134
- bleDevice.setCw(consts_1.cwABike.triathlon);
135
- break;
136
- case 'mountain':
137
- bleDevice.setCw(consts_1.cwABike.mountain);
138
- break;
142
+ }
143
+ try {
144
+ const comms = this.device;
145
+ if (comms) {
146
+ if (!scanOnly) {
147
+ const mode = this.getCyclingMode();
148
+ if (mode && mode.getSetting('bikeType')) {
149
+ const bikeType = mode.getSetting('bikeType').toLowerCase();
150
+ comms.setCrr(consts_1.cRR);
151
+ switch (bikeType) {
152
+ case 'race':
153
+ comms.setCw(consts_1.cwABike.race);
154
+ break;
155
+ case 'triathlon':
156
+ comms.setCw(consts_1.cwABike.triathlon);
157
+ break;
158
+ case 'mountain':
159
+ comms.setCw(consts_1.cwABike.mountain);
160
+ break;
161
+ }
139
162
  }
140
- }
141
- let hasControl = yield bleDevice.requestControl();
142
- if (!hasControl) {
143
- let retry = 1;
144
- while (!hasControl && retry < 3) {
145
- yield (0, utils_1.sleep)(1000);
146
- hasControl = yield bleDevice.requestControl();
147
- retry++;
163
+ let hasControl = yield comms.requestControl();
164
+ if (!hasControl) {
165
+ let retry = 1;
166
+ while (!hasControl && retry < 3) {
167
+ yield (0, utils_1.sleep)(1000);
168
+ hasControl = yield comms.requestControl();
169
+ retry++;
170
+ }
148
171
  }
172
+ if (!hasControl)
173
+ throw new Error('could not establish control');
174
+ const startRequest = this.getCyclingMode().getBikeInitRequest();
175
+ yield this.sendUpdate(startRequest);
176
+ }
177
+ if (!this.started && !wasPaused) {
178
+ comms.on('data', (data) => {
179
+ this.onDeviceData(data);
180
+ });
181
+ comms.on('disconnected', this.emit);
149
182
  }
150
- if (!hasControl)
151
- throw new Error('could not establish control');
152
- const startRequest = this.getCyclingMode().getBikeInitRequest();
153
- yield this.sendUpdate(startRequest);
154
- bleDevice.on('data', (data) => {
155
- this.onDeviceData(data);
156
- });
157
- bleDevice.on('disconnected', this.emit);
158
- if (bleDevice.isHrm() && !this.hasCapability(capabilities_1.IncyclistCapability.HeartRate)) {
183
+ const before = this.capabilities.join(',');
184
+ if (comms.features.heartrate && !this.hasCapability(capabilities_1.IncyclistCapability.HeartRate)) {
159
185
  this.capabilities.push(capabilities_1.IncyclistCapability.HeartRate);
160
186
  }
187
+ if (comms.features.cadence && !this.hasCapability(capabilities_1.IncyclistCapability.Cadence)) {
188
+ this.capabilities.push(capabilities_1.IncyclistCapability.Cadence);
189
+ }
190
+ if (comms.features.power && !this.hasCapability(capabilities_1.IncyclistCapability.Power)) {
191
+ this.capabilities.push(capabilities_1.IncyclistCapability.Power);
192
+ }
193
+ const after = this.capabilities.join(',');
194
+ if (before !== after) {
195
+ this.emit('device-info', this.getSettings(), { capabilities: this.capabilities });
196
+ }
161
197
  this.resetData();
162
198
  this.stopped = false;
163
199
  this.started = true;
164
- this.paused = false;
200
+ this.resume();
165
201
  return true;
166
202
  }
167
203
  }
168
204
  catch (err) {
169
- this.logger.logEvent({ message: 'start result: error', error: err.message, profile: this.getProfile() });
205
+ this.logEvent({ message: 'start result: error', error: err.message, profile: this.getProfile() });
170
206
  throw new Error(`could not start device, reason:${err.message}`);
171
207
  }
172
208
  });
@@ -175,16 +211,39 @@ class BleFmAdapter extends adapter_1.BleControllableAdapter {
175
211
  return __awaiter(this, void 0, void 0, function* () {
176
212
  if (this.paused || !this.device)
177
213
  return;
178
- const update = this.getCyclingMode().sendBikeUpdate(request);
179
- this.logger.logEvent({ message: 'send bike update requested', profile: this.getProfile(), update, request });
180
- const device = this.device;
181
- if (update.slope !== undefined) {
182
- yield device.setSlope(update.slope);
214
+ try {
215
+ const update = this.getCyclingMode().sendBikeUpdate(request);
216
+ this.logEvent({ message: 'send bike update requested', profile: this.getProfile(), update, request });
217
+ const device = this.device;
218
+ if (update.slope !== undefined) {
219
+ yield device.setSlope(update.slope);
220
+ }
221
+ if (update.targetPower !== undefined) {
222
+ yield device.setTargetPower(update.targetPower);
223
+ }
183
224
  }
184
- if (update.targetPower !== undefined) {
185
- yield device.setTargetPower(update.targetPower);
225
+ catch (err) {
226
+ this.logEvent({ message: 'error', fn: 'sendUpdate()', request, error: err.message, stack: err.stack });
186
227
  }
187
228
  });
188
229
  }
230
+ setCyclingMode(mode, settings) {
231
+ const modeChange = this.cyclingMode.getName() !== mode;
232
+ const prevMode = this.getCyclingMode();
233
+ super.setCyclingMode(mode, settings);
234
+ const isPaused = this.isPaused();
235
+ if (modeChange && this.started && !this.stopped) {
236
+ if (prevMode instanceof ble_st_mode_1.default) {
237
+ const power = this.data.power;
238
+ const request = power ? { targetPower: power } : this.getCyclingMode().getBikeInitRequest();
239
+ if (isPaused)
240
+ this.resume();
241
+ this.sendUpdate(request).then().catch().finally(() => {
242
+ if (isPaused)
243
+ this.pause();
244
+ });
245
+ }
246
+ }
247
+ }
189
248
  }
190
249
  exports.default = BleFmAdapter;
@@ -1,8 +1,10 @@
1
1
  /// <reference types="node" />
2
- import { BleWriteProps, IBlePeripheralConnector } from "../types";
3
- import { BleComms } from "../ble-comms";
2
+ import { BleProtocol, BleWriteProps, IBlePeripheralConnector } from "../types";
4
3
  import { IndoorBikeData, IndoorBikeFeatures } from "./types";
4
+ import { BleComms } from "../base/comms";
5
+ import { LegacyProfile } from "../../antv2/types";
5
6
  export default class BleFitnessMachineDevice extends BleComms {
7
+ static protocol: BleProtocol;
6
8
  static services: string[];
7
9
  static characteristics: string[];
8
10
  static detectionPriority: number;
@@ -16,16 +18,14 @@ export default class BleFitnessMachineDevice extends BleComms {
16
18
  windSpeed: number;
17
19
  wheelSize: number;
18
20
  constructor(props?: any);
19
- isMatching(characteristics: string[]): boolean;
21
+ static isMatching(characteristics: string[]): boolean;
20
22
  subscribeWriteResponse(cuuid: string): Promise<void>;
21
23
  subscribeAll(conn?: IBlePeripheralConnector): Promise<void>;
22
24
  init(): Promise<boolean>;
23
- onDisconnect(): void;
24
- getProfile(): string;
25
+ onDisconnect(): Promise<void>;
26
+ getProfile(): LegacyProfile;
27
+ getProtocol(): BleProtocol;
25
28
  getServiceUUids(): string[];
26
- isBike(): boolean;
27
- isPower(): boolean;
28
- isHrm(): boolean;
29
29
  parseHrm(_data: Uint8Array): IndoorBikeData;
30
30
  setCrr(crr: number): void;
31
31
  getCrr(): number;
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- const ble_comms_1 = require("../ble-comms");
13
12
  const consts_1 = require("../consts");
13
+ const comms_1 = require("../base/comms");
14
14
  const bit = (nr) => (1 << nr);
15
15
  const IndoorBikeDataFlag = {
16
16
  MoreData: bit(0),
@@ -65,7 +65,7 @@ const TargetSettingFeatureFlag = {
65
65
  SpinDownControlSupported: bit(15),
66
66
  TargetedCadenceConfigurationSupported: bit(16)
67
67
  };
68
- class BleFitnessMachineDevice extends ble_comms_1.BleComms {
68
+ class BleFitnessMachineDevice extends comms_1.BleComms {
69
69
  constructor(props) {
70
70
  super(props);
71
71
  this.features = undefined;
@@ -79,7 +79,7 @@ class BleFitnessMachineDevice extends ble_comms_1.BleComms {
79
79
  this.data = {};
80
80
  this.services = BleFitnessMachineDevice.services;
81
81
  }
82
- isMatching(characteristics) {
82
+ static isMatching(characteristics) {
83
83
  if (!characteristics)
84
84
  return false;
85
85
  const hasStatus = characteristics.find(c => c === consts_1.FTMS_STATUS) !== undefined;
@@ -90,7 +90,7 @@ class BleFitnessMachineDevice extends ble_comms_1.BleComms {
90
90
  subscribeWriteResponse(cuuid) {
91
91
  return __awaiter(this, void 0, void 0, function* () {
92
92
  this.logEvent({ message: 'subscribe to CP response', characteristics: cuuid });
93
- const connector = this.ble.getConnector(this.peripheral);
93
+ const connector = this.ble.peripheralCache.getConnector(this.peripheral);
94
94
  const isAlreadySubscribed = connector.isSubscribed(cuuid);
95
95
  if (!isAlreadySubscribed) {
96
96
  connector.removeAllListeners(cuuid);
@@ -110,36 +110,14 @@ class BleFitnessMachineDevice extends ble_comms_1.BleComms {
110
110
  });
111
111
  }
112
112
  subscribeAll(conn) {
113
- return new Promise(resolve => {
114
- const characteristics = [consts_1.INDOOR_BIKE_DATA, consts_1.FTMS_STATUS, consts_1.FTMS_CP];
115
- const timeout = Date.now() + 5500;
116
- const iv = setInterval(() => {
117
- const subscriptionStatus = characteristics.map(c => this.subscribedCharacteristics.find(s => s === c) !== undefined);
118
- const done = subscriptionStatus.filter(s => s === true).length === characteristics.length;
119
- if (done || Date.now() > timeout) {
120
- clearInterval(iv);
121
- resolve();
122
- }
123
- }, 100);
124
- try {
125
- const connector = conn || this.ble.getConnector(this.peripheral);
126
- for (let i = 0; i < characteristics.length; i++) {
127
- const c = characteristics[i];
128
- const isAlreadySubscribed = connector.isSubscribed(c);
129
- if (!isAlreadySubscribed) {
130
- connector.removeAllListeners(c);
131
- connector.on(c, (uuid, data) => {
132
- this.onData(uuid, data);
133
- });
134
- connector.subscribe(c);
135
- this.subscribedCharacteristics.push(c);
136
- }
137
- }
138
- }
139
- catch (err) {
140
- this.logEvent({ message: 'Error', fn: 'subscribeAll()', error: err.message, stack: err.stack });
141
- }
142
- });
113
+ const characteristics = [consts_1.INDOOR_BIKE_DATA, consts_1.FTMS_STATUS, consts_1.FTMS_CP];
114
+ if (!this.features || (this.features && this.features.cadence))
115
+ characteristics.push(consts_1.CSC_MEASUREMENT);
116
+ if (!this.features || (this.features && this.features.power))
117
+ characteristics.push(consts_1.CSP_MEASUREMENT);
118
+ if (!this.features || (this.features && this.features.heartrate))
119
+ characteristics.push(consts_1.HR_MEASUREMENT);
120
+ return this.subscribeMultiple(characteristics, conn);
143
121
  }
144
122
  init() {
145
123
  const _super = Object.create(null, {
@@ -150,39 +128,32 @@ class BleFitnessMachineDevice extends ble_comms_1.BleComms {
150
128
  yield _super.initDevice.call(this);
151
129
  yield this.getFitnessMachineFeatures();
152
130
  this.logEvent({ message: 'device info', deviceInfo: this.deviceInfo, features: this.features });
131
+ return true;
153
132
  }
154
133
  catch (err) {
155
134
  this.logEvent({ message: 'error', fn: 'BleFitnessMachineDevice.init()', error: err.message || err, stack: err.stack });
156
- return Promise.resolve(false);
135
+ return false;
157
136
  }
158
137
  });
159
138
  }
160
139
  onDisconnect() {
161
- super.onDisconnect();
162
- this.hasControl = false;
140
+ const _super = Object.create(null, {
141
+ onDisconnect: { get: () => super.onDisconnect }
142
+ });
143
+ return __awaiter(this, void 0, void 0, function* () {
144
+ _super.onDisconnect.call(this);
145
+ this.hasControl = false;
146
+ });
163
147
  }
164
148
  getProfile() {
165
149
  return 'Smart Trainer';
166
150
  }
151
+ getProtocol() {
152
+ return BleFitnessMachineDevice.protocol;
153
+ }
167
154
  getServiceUUids() {
168
155
  return BleFitnessMachineDevice.services;
169
156
  }
170
- isBike() {
171
- return this.features === undefined ||
172
- ((this.features.targetSettings & TargetSettingFeatureFlag.IndoorBikeSimulationParametersSupported) !== 0);
173
- }
174
- isPower() {
175
- if (this.hasService('1818'))
176
- return true;
177
- if (this.features === undefined)
178
- return false;
179
- const { fitnessMachine } = this.features;
180
- if (fitnessMachine & FitnessMachineFeatureFlag.PowerMeasurementSupported)
181
- return true;
182
- }
183
- isHrm() {
184
- return this.hasService('180d') || (this.features && (this.features.fitnessMachine & FitnessMachineFeatureFlag.HeartRateMeasurementSupported) !== 0);
185
- }
186
157
  parseHrm(_data) {
187
158
  const data = Buffer.from(_data);
188
159
  try {
@@ -327,8 +298,14 @@ class BleFitnessMachineDevice extends ble_comms_1.BleComms {
327
298
  if (buffer) {
328
299
  const fitnessMachine = buffer.readUInt32LE(0);
329
300
  const targetSettings = buffer.readUInt32LE(4);
330
- this.features = { fitnessMachine, targetSettings };
331
- this.logEvent({ message: 'supported Features: ', fatures: this.features });
301
+ const power = (fitnessMachine & FitnessMachineFeatureFlag.PowerMeasurementSupported) !== 0;
302
+ const heartrate = (fitnessMachine & FitnessMachineFeatureFlag.HeartRateMeasurementSupported) !== 0;
303
+ const cadence = (fitnessMachine & FitnessMachineFeatureFlag.CadenceSupported) !== 0;
304
+ const setSlope = (targetSettings & TargetSettingFeatureFlag.IndoorBikeSimulationParametersSupported) !== 0
305
+ || (targetSettings & TargetSettingFeatureFlag.InclinationTargetSettingSupported) !== 0;
306
+ const setPower = (targetSettings & TargetSettingFeatureFlag.PowerTargetSettingSupported) !== 0;
307
+ this.features = { fitnessMachine, targetSettings, power, heartrate, cadence, setPower, setSlope };
308
+ this.logEvent({ message: 'supported Features: ', fatures: this.features, power, heartrate, cadence });
332
309
  }
333
310
  }
334
311
  catch (err) {
@@ -520,6 +497,7 @@ class BleFitnessMachineDevice extends ble_comms_1.BleComms {
520
497
  }
521
498
  }
522
499
  exports.default = BleFitnessMachineDevice;
500
+ BleFitnessMachineDevice.protocol = 'fm';
523
501
  BleFitnessMachineDevice.services = [consts_1.FTMS];
524
502
  BleFitnessMachineDevice.characteristics = ['2acc', consts_1.INDOOR_BIKE_DATA, '2ad6', '2ad8', consts_1.FTMS_CP, consts_1.FTMS_STATUS];
525
503
  BleFitnessMachineDevice.detectionPriority = 100;
@@ -22,4 +22,9 @@ export type IndoorBikeData = {
22
22
  export type IndoorBikeFeatures = {
23
23
  fitnessMachine: number;
24
24
  targetSettings: number;
25
+ power?: boolean;
26
+ heartrate?: boolean;
27
+ cadence?: boolean;
28
+ setSlope?: boolean;
29
+ setPower?: boolean;
25
30
  };
@@ -1,4 +1,4 @@
1
- import BleAdapter from '../adapter';
1
+ import BleAdapter from '../base/adapter';
2
2
  import { DeviceProperties } from '../../types/device';
3
3
  import { BleDeviceSettings } from '../types';
4
4
  import { HrmData } from './types';
@@ -10,8 +10,5 @@ export default class HrmAdapter extends BleAdapter {
10
10
  getProfile(): string;
11
11
  getName(): string;
12
12
  getDisplayName(): string;
13
- getPort(): string;
14
- setIgnoreHrm(ignore: any): void;
15
- onDeviceData(deviceData: HrmData): void;
16
13
  mapData(deviceData: HrmData): DeviceData;
17
14
  }
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const gd_eventlog_1 = require("gd-eventlog");
7
- const adapter_1 = __importDefault(require("../adapter"));
7
+ const adapter_1 = __importDefault(require("../base/adapter"));
8
8
  const comm_1 = __importDefault(require("./comm"));
9
9
  const capabilities_1 = require("../../types/capabilities");
10
10
  class HrmAdapter extends adapter_1.default {
@@ -37,23 +37,6 @@ class HrmAdapter extends adapter_1.default {
37
37
  const hrmStr = hrm ? ` (${hrm})` : '';
38
38
  return `${name}${hrmStr}`;
39
39
  }
40
- getPort() {
41
- return 'ble';
42
- }
43
- setIgnoreHrm(ignore) {
44
- this.ignore = ignore;
45
- }
46
- onDeviceData(deviceData) {
47
- super.onDeviceData(deviceData);
48
- if (!this.started || this.paused || !this.onDataFn)
49
- return;
50
- if (!this.lastUpdate || (Date.now() - this.lastUpdate) > this.updateFrequency) {
51
- this.logger.logEvent({ message: 'onDeviceData', data: deviceData });
52
- this.data = this.mapData(this.deviceData);
53
- this.onDataFn(this.data);
54
- this.lastUpdate = Date.now();
55
- }
56
- }
57
40
  mapData(deviceData) {
58
41
  const { heartrate } = deviceData;
59
42
  return { heartrate };
@@ -1,14 +1,18 @@
1
1
  /// <reference types="node" />
2
- import { BleComms } from '../ble-comms';
2
+ import { LegacyProfile } from '../../antv2/types';
3
+ import { BleComms } from '../base/comms';
4
+ import { BleProtocol } from '../types';
3
5
  import { HrmData } from './types';
4
6
  export default class BleHrmDevice extends BleComms {
7
+ static protocol: BleProtocol;
5
8
  static services: string[];
6
9
  static characteristics: string[];
7
10
  static detectionPriority: number;
8
11
  heartrate: number;
9
12
  rr: number;
10
13
  constructor(props?: any);
11
- getProfile(): string;
14
+ getProfile(): LegacyProfile;
15
+ getProtocol(): BleProtocol;
12
16
  getServiceUUids(): string[];
13
17
  parseHrm(_data: Uint8Array): HrmData;
14
18
  onData(characteristic: string, data: Buffer): boolean;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const ble_comms_1 = require("../ble-comms");
4
- class BleHrmDevice extends ble_comms_1.BleComms {
3
+ const comms_1 = require("../base/comms");
4
+ class BleHrmDevice extends comms_1.BleComms {
5
5
  constructor(props) {
6
6
  super(props);
7
7
  this.heartrate = undefined;
@@ -10,6 +10,9 @@ class BleHrmDevice extends ble_comms_1.BleComms {
10
10
  getProfile() {
11
11
  return 'Heartrate Monitor';
12
12
  }
13
+ getProtocol() {
14
+ return BleHrmDevice.protocol;
15
+ }
13
16
  getServiceUUids() {
14
17
  return BleHrmDevice.services;
15
18
  }
@@ -47,6 +50,7 @@ class BleHrmDevice extends ble_comms_1.BleComms {
47
50
  }
48
51
  }
49
52
  exports.default = BleHrmDevice;
53
+ BleHrmDevice.protocol = 'hr';
50
54
  BleHrmDevice.services = ['180d'];
51
55
  BleHrmDevice.characteristics = ['2a37', '2a38', '2a39', '2a3c'];
52
56
  BleHrmDevice.detectionPriority = 1;
@@ -0,0 +1,7 @@
1
+ import { BleMockPeripheral } from "../bindings/mock";
2
+ interface BleHrMockPeripheral extends BleMockPeripheral {
3
+ setNotifyFrequency: (ms: number) => void;
4
+ setHeartrate: (hr: number) => void;
5
+ }
6
+ export declare const HrMock: BleHrMockPeripheral;
7
+ export {};
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HrMock = void 0;
4
+ const types_1 = require("../bindings/types");
5
+ class HeartRateMeasuremenCharacteristic extends types_1.StaticNotifyCharacteristic {
6
+ constructor(uuid, description, heartrate = 0) {
7
+ super(uuid, description);
8
+ this.heartrate = heartrate;
9
+ this.value = Buffer.from(this.heartrate.toString());
10
+ }
11
+ notify() {
12
+ const buffer = Buffer.alloc(2);
13
+ buffer.writeUInt8(0, 0);
14
+ buffer.writeUInt8(this.heartrate, 1);
15
+ this.emit('data', buffer);
16
+ }
17
+ }
18
+ const HR = {
19
+ uuid: "180d",
20
+ characteristics: [
21
+ new HeartRateMeasuremenCharacteristic('2a37', 'Heart Rate Measurement', 60)
22
+ ]
23
+ };
24
+ const DIS = {
25
+ uuid: '180a',
26
+ characteristics: [
27
+ new types_1.StaticReadCharacteristic('2a23', 'System Id', '0'),
28
+ new types_1.StaticReadCharacteristic('2a24', 'Model Number', '1'),
29
+ new types_1.StaticReadCharacteristic('2a25', 'Serial Number', '4711'),
30
+ new types_1.StaticReadCharacteristic('2a26', 'Firmware Revision', '1'),
31
+ new types_1.StaticReadCharacteristic('2a27', 'Hardware Revision', '1'),
32
+ new types_1.StaticReadCharacteristic('2a28', 'Software Revision', '1'),
33
+ new types_1.StaticReadCharacteristic('2a29', 'Manufacturer Name', 'Incyclist')
34
+ ]
35
+ };
36
+ exports.HrMock = {
37
+ services: [HR, DIS],
38
+ id: "a87b6100820d48b1401bf83a8cf6f046",
39
+ name: "HRM-Mock",
40
+ address: "a87b6100820d48b1401bf83a8cf6f046",
41
+ setNotifyFrequency: (ms) => {
42
+ HR.characteristics[0].notifyFrequency = ms;
43
+ },
44
+ setHeartrate: (hr) => {
45
+ HR.characteristics[0].heartrate = hr;
46
+ }
47
+ };
@@ -5,4 +5,5 @@ import { BlePwrAdapter } from './cp';
5
5
  import { BleFmAdapter } from './fm';
6
6
  import { BleWahooAdapter } from './wahoo';
7
7
  import { BleTacxAdapter } from './tacx';
8
- export { BleAdapterFactory, BleInterface, BleHrmAdapter, BlePwrAdapter, BleFmAdapter, BleWahooAdapter, BleTacxAdapter };
8
+ import { BleDeviceSettings, BleInterfaceProps } from './types';
9
+ export { BleAdapterFactory, BleInterface, BleInterfaceProps, BleDeviceSettings, BleHrmAdapter, BlePwrAdapter, BleFmAdapter, BleWahooAdapter, BleTacxAdapter };
package/lib/ble/index.js CHANGED
@@ -19,8 +19,8 @@ Object.defineProperty(exports, "BleWahooAdapter", { enumerable: true, get: funct
19
19
  const tacx_1 = require("./tacx");
20
20
  Object.defineProperty(exports, "BleTacxAdapter", { enumerable: true, get: function () { return tacx_1.BleTacxAdapter; } });
21
21
  const af = adapter_factory_1.default.getInstance();
22
- af.register('hr', 'Heartrate Monitor', hr_1.BleHrmAdapter, hr_1.BleHrmComms);
23
- af.register('cp', 'Power Meter', cp_1.BlePwrAdapter, cp_1.BlePwrComms);
24
- af.register('fm', 'Smart Trainer', fm_1.BleFmAdapter, fm_1.BleFmComms);
25
- af.register('wahoo', 'Smart Trainer', wahoo_1.BleWahooAdapter, wahoo_1.BleWahooComms);
26
- af.register('tacx', 'Smart Trainer', tacx_1.BleTacxAdapter, tacx_1.BleTacxComms);
22
+ af.register('hr', hr_1.BleHrmAdapter, hr_1.BleHrmComms);
23
+ af.register('cp', cp_1.BlePwrAdapter, cp_1.BlePwrComms);
24
+ af.register('fm', fm_1.BleFmAdapter, fm_1.BleFmComms);
25
+ af.register('wahoo', wahoo_1.BleWahooAdapter, wahoo_1.BleWahooComms);
26
+ af.register('tacx', tacx_1.BleTacxAdapter, tacx_1.BleTacxComms);