incyclist-devices 2.1.2 → 2.1.4

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.
@@ -55,7 +55,6 @@ export default class AntAdapter<TDeviceData extends BaseDeviceData> extends Incy
55
55
  checkCapabilities(): Promise<void>;
56
56
  initControl(): Promise<void>;
57
57
  getDefaultStartupTimeout(): number;
58
- sendUpdate(request: any): void;
59
58
  startPreChecks(props: AntDeviceProperties): Promise<'done' | 'connected' | 'connection-failed'>;
60
59
  resetStartStatus(): void;
61
60
  isStartSuccess(): boolean;
@@ -48,6 +48,9 @@ class AntAdapter extends adpater_1.default {
48
48
  this.updateFrequency = consts_1.DEFAULT_UPDATE_FREQUENCY;
49
49
  this.channel = undefined;
50
50
  this.ant = interface_1.default.getInstance();
51
+ if (this.isDebugEnabled()) {
52
+ this.ant.setLogger(this);
53
+ }
51
54
  }
52
55
  getProfileName() {
53
56
  const C = this.constructor;
@@ -116,12 +119,10 @@ class AntAdapter extends adpater_1.default {
116
119
  if (!ManId && deviceData.ManId) {
117
120
  this.emit('device-info', this.getSettings(), { manufacturer: (0, utils_2.getBrand)(deviceData.ManId) });
118
121
  }
119
- if (!this.started || this.isStopped())
120
- return;
121
- if (!this.canEmitData())
122
- return;
123
122
  const logData = this.getLogData(deviceData, ['PairedDevices', 'RawData']);
124
123
  this.logEvent({ message: 'onDeviceData', data: logData, paused: this.paused });
124
+ if (!this.started || this.isStopped() || !this.canEmitData())
125
+ return;
125
126
  if (this.isControllable()) {
126
127
  let incyclistData = this.mapData(deviceData);
127
128
  incyclistData = this.getCyclingMode().updateData(incyclistData);
@@ -148,6 +149,7 @@ class AntAdapter extends adpater_1.default {
148
149
  resolve(true);
149
150
  }
150
151
  if (!this.promiseWaitForData) {
152
+ resolve(false);
151
153
  clearInterval(iv);
152
154
  }
153
155
  }, 10);
@@ -172,9 +174,9 @@ class AntAdapter extends adpater_1.default {
172
174
  }
173
175
  try {
174
176
  this.promiseWaitForData = (0, utils_1.runWithTimeout)(this._wait(), timeout);
175
- yield this.promiseWaitForData;
177
+ const hasData = yield this.promiseWaitForData;
176
178
  this.promiseWaitForData = null;
177
- return true;
179
+ return hasData;
178
180
  }
179
181
  catch (err) {
180
182
  this.promiseWaitForData = null;
@@ -188,10 +190,11 @@ class AntAdapter extends adpater_1.default {
188
190
  return id.toString();
189
191
  }
190
192
  getName() {
193
+ var _a;
191
194
  if (this.settings.name)
192
195
  return this.settings.name;
193
- const deviceID = this.sensor.getDeviceID();
194
- const profile = this.sensor.getProfile();
196
+ const deviceID = this.getID();
197
+ const profile = (_a = this.sensor) === null || _a === void 0 ? void 0 : _a.getProfile();
195
198
  return `Ant+${profile} ${deviceID}`;
196
199
  }
197
200
  getUniqueName() {
@@ -250,16 +253,6 @@ class AntAdapter extends adpater_1.default {
250
253
  getDefaultStartupTimeout() {
251
254
  return 20000;
252
255
  }
253
- sendUpdate(request) {
254
- if (!this.isControllable())
255
- return;
256
- if (this.isPaused() || this.isStopped())
257
- return;
258
- if (!this.hasCapability(types_2.IncyclistCapability.Control))
259
- this.getCyclingMode().sendBikeUpdate(request);
260
- else
261
- throw new Error('method not implemented');
262
- }
263
256
  startPreChecks(props) {
264
257
  return __awaiter(this, void 0, void 0, function* () {
265
258
  const wasPaused = this.paused;
@@ -294,7 +287,7 @@ class AntAdapter extends adpater_1.default {
294
287
  reportStartStatus() {
295
288
  const success = this.isStartSuccess();
296
289
  if (success) {
297
- this.logEvent({ message: 'start device success' });
290
+ this.logEvent({ message: 'start device success', device: this.getName() });
298
291
  this.started = true;
299
292
  this.paused = false;
300
293
  return true;
@@ -302,18 +295,20 @@ class AntAdapter extends adpater_1.default {
302
295
  else {
303
296
  this.started = false;
304
297
  const { sensorStarted, hasData, interrupted } = this.startStatus;
305
- if (interrupted)
306
- return;
298
+ if (interrupted) {
299
+ this.logEvent({ message: 'start device interrupted', device: this.getName() });
300
+ return false;
301
+ }
307
302
  if (!sensorStarted) {
308
- this.logEvent({ message: 'start device failed', reason: 'could not connect' });
303
+ this.logEvent({ message: 'start device failed', device: this.getName(), reason: 'could not connect' });
309
304
  throw new Error('could not start device, reason:could not connect');
310
305
  }
311
306
  else if (!hasData) {
312
- this.logEvent({ message: 'start device failed', reason: 'no data received' });
307
+ this.logEvent({ message: 'start device failed', device: this.getName(), reason: 'no data received' });
313
308
  throw new Error('could not start device, reason:no data received');
314
309
  }
315
310
  else {
316
- this.logEvent({ message: 'start device failed', reason: 'could not send FE commands' });
311
+ this.logEvent({ message: 'start device failed', device: this.getName(), reason: 'could not send FE commands' });
317
312
  throw new Error('could not start device, reason:could not send FE commands');
318
313
  }
319
314
  }
@@ -323,10 +318,10 @@ class AntAdapter extends adpater_1.default {
323
318
  const { sensorStarted, hasData, timeout } = this.startStatus;
324
319
  if ((sensorStarted && hasData) || !sensorStarted || timeout)
325
320
  return;
326
- this.logEvent({ message: 'wait for sensor data', });
321
+ this.logEvent({ message: 'wait for sensor data', device: this.getName() });
327
322
  this.startStatus.hasData = yield this.waitForData(startupTimeout);
328
323
  if (this.startStatus.hasData)
329
- this.logEvent({ message: 'sensor data received', });
324
+ this.logEvent({ message: 'sensor data received', device: this.getName() });
330
325
  });
331
326
  }
332
327
  initSensor(props) {
@@ -334,7 +329,7 @@ class AntAdapter extends adpater_1.default {
334
329
  this.startStatus.sensorStarted = this.sensorConnected;
335
330
  if (this.startStatus.sensorStarted || this.startStatus.sensorStarted)
336
331
  return;
337
- this.logEvent({ message: 'start sensor', props });
332
+ this.logEvent({ message: 'start sensor', device: this.getName(), props });
338
333
  try {
339
334
  this.sensorConnected = yield this.startSensor();
340
335
  if (this.sensorConnected) {
@@ -343,7 +338,7 @@ class AntAdapter extends adpater_1.default {
343
338
  }
344
339
  }
345
340
  catch (err) {
346
- this.logEvent({ message: 'start sensor failed', reason: err.message, props });
341
+ this.logEvent({ message: 'start sensor failed', device: this.getName(), reason: err.message, props });
347
342
  }
348
343
  });
349
344
  }
@@ -354,7 +349,7 @@ class AntAdapter extends adpater_1.default {
354
349
  return this.started;
355
350
  if (preCheckResult === 'connection-failed')
356
351
  throw new Error(`could not start device, reason:could not connect`);
357
- this.logEvent({ message: 'starting device', props, isStarted: this.started });
352
+ this.logEvent({ message: 'starting device', device: this.getName(), props, isStarted: this.started });
358
353
  this.resetStartStatus();
359
354
  this.resetData();
360
355
  const { startupTimeout = this.getDefaultStartupTimeout() } = props || {};
@@ -371,7 +366,7 @@ class AntAdapter extends adpater_1.default {
371
366
  yield this.checkCapabilities();
372
367
  if (this.hasCapability(types_2.IncyclistCapability.Control))
373
368
  yield this.initControl();
374
- if (!this.startStatus.hasData) {
369
+ if (!this.startStatus.hasData && !this.startStatus.interrupted) {
375
370
  yield this.stopSensor();
376
371
  yield (0, utils_1.sleep)(retryDelay);
377
372
  continue;
@@ -379,7 +374,7 @@ class AntAdapter extends adpater_1.default {
379
374
  success = this.isStartSuccess();
380
375
  }
381
376
  catch (err) {
382
- this.logEvent({ message: 'error', fn: 'start#doStart', error: err.message, stack: err.stack });
377
+ this.logEvent({ message: 'error', fn: 'start#doStart', device: this.getName(), error: err.message, stack: err.stack });
383
378
  }
384
379
  }
385
380
  this.reportStartStatus();
@@ -392,19 +387,24 @@ class AntAdapter extends adpater_1.default {
392
387
  if (err.message === 'Timeout') {
393
388
  this.started = false;
394
389
  this.startStatus.timeout = true;
390
+ this.logEvent({ message: 'start device failed', device: this.getName(), reason: 'timeout' });
395
391
  throw new Error(`could not start device, reason:timeout`);
396
392
  }
397
393
  throw err;
398
394
  }
399
- return true;
395
+ return this.started;
400
396
  });
401
397
  }
402
398
  stop() {
403
399
  return __awaiter(this, void 0, void 0, function* () {
404
400
  let stopped;
401
+ this.logger.logEvent({ message: 'stopping device', device: this.getName() });
405
402
  this.promiseWaitForData = null;
406
- if (this.startStatus)
403
+ if (this.startStatus) {
407
404
  this.startStatus.interrupted = true;
405
+ console.log('~~~ still starting');
406
+ yield (0, utils_1.sleep)(20);
407
+ }
408
408
  try {
409
409
  stopped = yield this.ant.stopSensor(this.sensor);
410
410
  }
@@ -416,6 +416,7 @@ class AntAdapter extends adpater_1.default {
416
416
  this.stopped = true;
417
417
  this.paused = false;
418
418
  this.removeAllListeners();
419
+ this.logEvent({ message: 'stopping device finished', device: this.getName(), stopped });
419
420
  return stopped;
420
421
  });
421
422
  }
@@ -134,6 +134,7 @@ class AntInterface extends events_1.default {
134
134
  return 1000;
135
135
  }
136
136
  scannerWaitForConnection() {
137
+ var _a;
137
138
  return __awaiter(this, void 0, void 0, function* () {
138
139
  let scanFinished = false;
139
140
  let scanStopRequested = false;
@@ -152,7 +153,7 @@ class AntInterface extends events_1.default {
152
153
  }
153
154
  if (scanStopRequested)
154
155
  this.emit('scan stopped', true);
155
- this.activeScan.emitter.removeAllListeners();
156
+ (_a = this.activeScan) === null || _a === void 0 ? void 0 : _a.emitter.removeAllListeners();
156
157
  });
157
158
  }
158
159
  scan(props = {}) {
@@ -162,8 +163,8 @@ class AntInterface extends events_1.default {
162
163
  return yield this.scanPromise;
163
164
  }
164
165
  this.activeScan = { emitter: new events_1.default() };
166
+ const detected = [];
165
167
  const _scan = () => new Promise((done) => __awaiter(this, void 0, void 0, function* () {
166
- const detected = [];
167
168
  const onDetected = (profile, deviceID) => {
168
169
  if (deviceID && detected.find(s => s.deviceID === deviceID && s.profile === profile) === undefined) {
169
170
  try {
@@ -222,19 +223,23 @@ class AntInterface extends events_1.default {
222
223
  }));
223
224
  this.activeScan.emitter.on('timeout', () => __awaiter(this, void 0, void 0, function* () {
224
225
  this.activeScan.emitter.removeAllListeners();
226
+ yield this.activeScan.channel.stopScanner();
225
227
  this.emit('stop-scan');
226
228
  removeListeners(channel);
229
+ this.logEvent({ message: 'scan finished(timeout) ..' });
227
230
  done(detected);
228
231
  }));
229
232
  }));
230
233
  const { timeout } = props;
231
234
  this.scanPromise = _scan();
232
235
  if (timeout) {
233
- const res = yield (0, utils_1.waitWithTimeout)(this.scanPromise, timeout, () => {
236
+ yield (0, utils_1.waitWithTimeout)(this.scanPromise, timeout, () => {
234
237
  var _a;
235
238
  (_a = this.activeScan) === null || _a === void 0 ? void 0 : _a.emitter.emit('timeout');
236
239
  });
237
- return res || [];
240
+ this.scanPromise = null;
241
+ this.activeScan = null;
242
+ return detected;
238
243
  }
239
244
  else {
240
245
  const res = yield this.scanPromise;
@@ -255,6 +260,7 @@ class AntInterface extends events_1.default {
255
260
  return new Promise(done => {
256
261
  this.activeScan.emitter.emit('stop');
257
262
  this.once('scan stopped', (res) => {
263
+ this.logEvent({ message: 'stopping scan done ..' });
258
264
  done(res);
259
265
  });
260
266
  });
@@ -5,6 +5,7 @@ import { AntDeviceProperties, AntDeviceSettings, LegacyProfile } from "../types"
5
5
  import { IncyclistBikeData, ControllerConfig } from "../../types";
6
6
  interface AntFEStartDeviceProperties extends AntDeviceProperties {
7
7
  reconnect?: boolean;
8
+ restart?: boolean;
8
9
  reconnectTimeout?: number;
9
10
  }
10
11
  export default class AntFEAdapter extends AntAdapter<FitnessEquipmentSensorState> {
@@ -42,7 +42,7 @@ class AntFEAdapter extends adapter_1.default {
42
42
  return;
43
43
  let isReset = request.reset && Object.keys(request).length === 1;
44
44
  const update = isReset ? this.getCyclingMode().getBikeInitRequest() : this.getCyclingMode().sendBikeUpdate(request);
45
- this.logEvent({ message: 'send bike update requested', update, request });
45
+ this.logEvent({ message: 'send bike update requested', device: this.getName(), update, request });
46
46
  try {
47
47
  const fe = this.sensor;
48
48
  if (update.slope !== undefined) {
@@ -59,7 +59,7 @@ class AntFEAdapter extends adapter_1.default {
59
59
  yield this.reconnect();
60
60
  }
61
61
  }
62
- this.logEvent({ message: 'sendBikeUpdate() error', error: err.message });
62
+ this.logEvent({ message: 'sendBikeUpdate() error', device: this.getName(), error: err.message });
63
63
  }
64
64
  });
65
65
  }
@@ -123,12 +123,18 @@ class AntFEAdapter extends adapter_1.default {
123
123
  resetStartStatus() {
124
124
  const props = this.startProps;
125
125
  const isReconnect = props.reconnect || false;
126
+ const isRestart = props.restart || false;
126
127
  super.resetStartStatus();
127
128
  if (isReconnect) {
128
129
  delete props.reconnect;
129
130
  this.startStatus.userInitialized = true;
130
131
  this.startStatus.controlInitialized = true;
131
132
  }
133
+ if (isRestart) {
134
+ delete props.restart;
135
+ this.startStatus.sensorStarted = true;
136
+ this.startStatus.hasData = true;
137
+ }
132
138
  }
133
139
  startPreChecks(props) {
134
140
  const _super = Object.create(null, {
@@ -137,6 +143,11 @@ class AntFEAdapter extends adapter_1.default {
137
143
  return __awaiter(this, void 0, void 0, function* () {
138
144
  this.startProps = props;
139
145
  this.setFEDefaultTimeout();
146
+ if (this.started && this.paused) {
147
+ this.resume();
148
+ props.restart = true;
149
+ return 'connected';
150
+ }
140
151
  return yield _super.startPreChecks.call(this, props);
141
152
  });
142
153
  }
@@ -164,7 +175,7 @@ class AntFEAdapter extends adapter_1.default {
164
175
  this.startStatus.userInitialized = yield fe.sendUserConfiguration(userWeight, bikeWeight, args.wheelDiameter, args.gearRatio);
165
176
  }
166
177
  catch (err) {
167
- this.logEvent({ message: 'sending FE message error', error: err.message });
178
+ this.logEvent({ message: 'sending FE message error', device: this.getName(), error: err.message });
168
179
  this.startStatus.userInitialized = false;
169
180
  }
170
181
  });
@@ -193,7 +204,7 @@ class AntFEAdapter extends adapter_1.default {
193
204
  }
194
205
  }
195
206
  catch (err) {
196
- this.logEvent({ message: 'sending FE message error', error: err.message });
207
+ this.logEvent({ message: 'sending FE message error', device: this.getName(), error: err.message });
197
208
  this.startStatus.controlInitialized = false;
198
209
  }
199
210
  });
@@ -209,7 +220,7 @@ class AntFEAdapter extends adapter_1.default {
209
220
  }
210
221
  reconnect() {
211
222
  return __awaiter(this, void 0, void 0, function* () {
212
- this.logEvent({ message: 'reconnect to device' });
223
+ this.logEvent({ message: 'reconnect to device', device: this.getName() });
213
224
  if (this.promiseReconnect) {
214
225
  return yield this.promiseReconnect;
215
226
  }
@@ -218,11 +229,11 @@ class AntFEAdapter extends adapter_1.default {
218
229
  yield this.stop();
219
230
  yield this.start(Object.assign(Object.assign({}, this.startProps), { reconnect: true }));
220
231
  this.started = true;
221
- this.logEvent({ message: 'reconnect success' });
232
+ this.logEvent({ message: 'reconnect success', device: this.getName() });
222
233
  return true;
223
234
  }
224
235
  catch (err) {
225
- this.logEvent({ message: 'reconnect failed' });
236
+ this.logEvent({ message: 'reconnect failed', device: this.getName() });
226
237
  return false;
227
238
  }
228
239
  });
@@ -20,6 +20,7 @@ export default class IncyclistDevice<P extends DeviceProperties> extends EventEm
20
20
  protected data: IncyclistAdapterData;
21
21
  constructor(settings: DeviceSettings, props?: P);
22
22
  getLogger(): EventLogger;
23
+ isDebugEnabled(): boolean;
23
24
  logEvent(event: any): void;
24
25
  getName(): string;
25
26
  getID(): string;
@@ -12,6 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
+ const types_1 = require("../types");
15
16
  const events_1 = __importDefault(require("events"));
16
17
  const consts_1 = require("./consts");
17
18
  class IncyclistDevice extends events_1.default {
@@ -29,12 +30,18 @@ class IncyclistDevice extends events_1.default {
29
30
  this.cyclingMode = this.getDefaultCyclingMode();
30
31
  }
31
32
  getLogger() { return this.logger; }
33
+ isDebugEnabled() {
34
+ const w = global.window;
35
+ if ((w === null || w === void 0 ? void 0 : w.DEVICE_DEBUG) || process.env.BLE_DEBUG || process.env.ANT_DEBUG) {
36
+ return true;
37
+ }
38
+ return false;
39
+ }
32
40
  logEvent(event) {
33
41
  if (!this.logger || this.paused)
34
42
  return;
35
43
  this.logger.logEvent(event);
36
- const w = global.window;
37
- if ((w === null || w === void 0 ? void 0 : w.DEVICE_DEBUG) || process.env.BLE_DEBUG || process.env.ANT_DEBUG) {
44
+ if (this.isDebugEnabled()) {
38
45
  const logText = `~~~ ${this.getInterface()}: ${this.logger.getName()}`;
39
46
  console.log(logText, event);
40
47
  }
@@ -42,7 +49,7 @@ class IncyclistDevice extends events_1.default {
42
49
  getName() {
43
50
  return this.settings.name;
44
51
  }
45
- getID() { throw new Error('not implemented'); }
52
+ getID() { return ''; }
46
53
  getUniqueName() {
47
54
  throw new Error("Method not implemented.");
48
55
  }
@@ -62,12 +69,16 @@ class IncyclistDevice extends events_1.default {
62
69
  stop() { throw new Error("Method not implemented."); }
63
70
  pause() {
64
71
  return __awaiter(this, void 0, void 0, function* () {
72
+ if (this.isStarted() && !this.isStopped())
73
+ this.logEvent({ message: 'pausing device', device: this.getName() });
65
74
  this.paused = true;
66
75
  return true;
67
76
  });
68
77
  }
69
78
  resume() {
70
79
  return __awaiter(this, void 0, void 0, function* () {
80
+ if (this.isStarted() && !this.isStopped())
81
+ this.logger.logEvent({ message: 'resuming device', device: this.getName() });
71
82
  this.paused = false;
72
83
  return true;
73
84
  });
@@ -170,7 +181,12 @@ class IncyclistDevice extends events_1.default {
170
181
  sendUpdate(request) {
171
182
  if (!this.isControllable())
172
183
  return;
173
- throw new Error("Method not implemented.");
184
+ if (this.isPaused() || this.isStopped())
185
+ return;
186
+ if (!this.hasCapability(types_1.IncyclistCapability.Control))
187
+ this.getCyclingMode().sendBikeUpdate(request);
188
+ else
189
+ throw new Error('method not implemented');
174
190
  }
175
191
  setUser(user) {
176
192
  this.user = user;
@@ -2,29 +2,30 @@ import BleAdapter from "./base/adapter";
2
2
  import { BleDeviceSettings, BleProtocol } from "./types";
3
3
  import { DeviceProperties } from "../types";
4
4
  import { BleComms } from "./base/comms";
5
+ import { BleDeviceData } from "./base/types";
5
6
  export interface BleAdapterInfo {
6
7
  protocol: BleProtocol;
7
- Adapter: typeof BleAdapter;
8
+ Adapter: typeof BleAdapter<BleDeviceData, BleComms>;
8
9
  Comm: typeof BleComms;
9
10
  }
10
11
  export default class BleAdapterFactory {
11
12
  static _instance: BleAdapterFactory;
12
13
  implementations: BleAdapterInfo[];
13
- instances: Array<BleAdapter>;
14
+ instances: Array<BleAdapter<BleDeviceData, BleComms>>;
14
15
  static getInstance(): BleAdapterFactory;
15
16
  constructor();
16
17
  getAdapterInfo(protocol: BleProtocol): BleAdapterInfo;
17
18
  getAll(): BleAdapterInfo[];
18
- createInstance(settings: BleDeviceSettings, props?: DeviceProperties): BleAdapter;
19
+ createInstance(settings: BleDeviceSettings, props?: DeviceProperties): BleAdapter<BleDeviceData, BleComms>;
19
20
  removeInstance(query: {
20
21
  settings?: BleDeviceSettings;
21
- adapter?: BleAdapter;
22
+ adapter?: BleAdapter<BleDeviceData, BleComms>;
22
23
  }): void;
23
- find(settings?: BleDeviceSettings): BleAdapter;
24
- register(protocol: BleProtocol, Adapter: typeof BleAdapter, Comm: typeof BleComms): void;
25
- getAllInstances(): Array<BleAdapter>;
24
+ find(settings?: BleDeviceSettings): BleAdapter<BleDeviceData, BleComms>;
25
+ register(protocol: BleProtocol, Adapter: typeof BleAdapter<BleDeviceData, BleComms>, Comm: typeof BleComms): void;
26
+ getAllInstances(): Array<BleAdapter<BleDeviceData, BleComms>>;
26
27
  getAllSupportedComms(): (typeof BleComms)[];
27
- getAllSupportedAdapters(): Array<(typeof BleAdapter)>;
28
+ getAllSupportedAdapters(): Array<(typeof BleAdapter<BleDeviceData, BleComms>)>;
28
29
  getAllSupportedServices(): string[];
29
30
  getDeviceClasses(peripheral: any, props?: {
30
31
  protocol?: BleProtocol;
@@ -3,28 +3,31 @@ import { BleComms } from "./comms";
3
3
  import BleInterface from "../ble-interface";
4
4
  import { BleDeviceProperties, BleDeviceSettings, BleStartProperties } from "../types";
5
5
  import { IAdapter, IncyclistBikeData, IncyclistAdapterData, DeviceProperties } from "../../types";
6
- export default class BleAdapter extends IncyclistDevice<BleDeviceProperties> {
7
- ble: BleInterface;
8
- deviceData: any;
9
- data: IncyclistAdapterData;
10
- dataMsgCount: number;
11
- lastDataTS: number;
12
- device: BleComms;
6
+ import { BleDeviceData } from "./types";
7
+ import { LegacyProfile } from "../../antv2/types";
8
+ export default class BleAdapter<TDeviceData extends BleDeviceData, TDevice extends BleComms> extends IncyclistDevice<BleDeviceProperties> {
9
+ protected ble: BleInterface;
10
+ protected deviceData: TDeviceData;
11
+ protected data: IncyclistAdapterData;
12
+ protected dataMsgCount: number;
13
+ protected lastDataTS: number;
14
+ protected device: TDevice;
13
15
  constructor(settings: BleDeviceSettings, props?: DeviceProperties);
14
16
  getUniqueName(): string;
15
17
  connect(): Promise<boolean>;
16
18
  close(): Promise<boolean>;
17
- getComms(): BleComms;
19
+ getComms(): TDevice;
18
20
  isEqual(settings: BleDeviceSettings): boolean;
19
21
  isSame(adapter: IAdapter): boolean;
20
22
  isConnected(): boolean;
21
23
  resetData(): void;
22
24
  getInterface(): string;
25
+ getProfile(): LegacyProfile;
23
26
  getProtocolName(): string;
24
27
  getID(): string;
25
28
  getName(): string;
26
- onDeviceData(deviceData: any): void;
27
- mapData(deviceData: any): IncyclistAdapterData | IncyclistBikeData;
29
+ onDeviceData(deviceData: TDeviceData): void;
30
+ mapData(deviceData: TDeviceData): IncyclistAdapterData | IncyclistBikeData;
28
31
  transformData(data: IncyclistBikeData): IncyclistAdapterData;
29
32
  getSettings(): BleDeviceSettings;
30
33
  setProperties(props: BleDeviceProperties): void;
@@ -27,9 +27,10 @@ class BleAdapter extends adpater_1.default {
27
27
  this.ble = ble_interface_1.default.getInstance();
28
28
  }
29
29
  getUniqueName() {
30
+ var _a;
30
31
  const settings = this.settings;
31
- if (settings.name.match(/[0-9]/g) || settings.address === undefined)
32
- return this.settings.name;
32
+ if (((_a = settings.name) === null || _a === void 0 ? void 0 : _a.match(/[0-9]/g)) || settings.address === undefined)
33
+ return this.getName();
33
34
  else {
34
35
  const addressHash = settings.address.substring(0, 2) + settings.address.slice(-2);
35
36
  return `${this.getName()} ${addressHash}`;
@@ -56,11 +57,7 @@ class BleAdapter extends adpater_1.default {
56
57
  return __awaiter(this, void 0, void 0, function* () {
57
58
  if (!this.device || !this.isConnected())
58
59
  return true;
59
- if (this.device) {
60
- yield this.device.disconnect();
61
- this.ble.removeConnectedDevice(this);
62
- return true;
63
- }
60
+ return yield this.device.disconnect();
64
61
  });
65
62
  }
66
63
  getComms() {
@@ -94,13 +91,17 @@ class BleAdapter extends adpater_1.default {
94
91
  getInterface() {
95
92
  return INTERFACE_NAME;
96
93
  }
94
+ getProfile() {
95
+ const C = this.constructor;
96
+ return C['INCYCLIST_PROFILE_NAME'];
97
+ }
97
98
  getProtocolName() {
98
99
  const settings = this.settings;
99
100
  return settings.protocol;
100
101
  }
101
102
  getID() {
102
103
  const settings = this.settings;
103
- return settings.id;
104
+ return settings.id || settings.address;
104
105
  }
105
106
  getName() {
106
107
  const settings = this.settings;
@@ -0,0 +1,2 @@
1
+ export interface BleDeviceData {
2
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -5,7 +5,6 @@ import BleAdapterFactory from './adapter-factory';
5
5
  import { BleInterfaceProps, BlePeripheral, BleDeviceSettings, BleProtocol, BleBinding, BleInterfaceState, BleScanProps, BleCharacteristic } from './types';
6
6
  import { BleComms } from './base/comms';
7
7
  import { IncyclistInterface, IncyclistScanProps } from '../types';
8
- import BleAdapter from './base/adapter';
9
8
  import BlePeripheralCache from './peripheral-cache';
10
9
  import EventEmitter from 'events';
11
10
  export interface ScanState {
@@ -39,7 +38,6 @@ export default class BleInterface extends EventEmitter implements IncyclistInter
39
38
  logger: EventLogger;
40
39
  props: BleInterfaceProps;
41
40
  binding: BleBinding;
42
- connectedDevices: Array<BleAdapter>;
43
41
  sensorIsConnecting: boolean;
44
42
  emittingAdapters: {
45
43
  comms: BleComms;
@@ -78,6 +76,4 @@ export default class BleInterface extends EventEmitter implements IncyclistInter
78
76
  scan(props?: BleScanProps): Promise<BleDeviceSettings[]>;
79
77
  stopScan(): Promise<boolean>;
80
78
  isScanning(): boolean;
81
- addConnectedDevice(device: BleAdapter): void;
82
- removeConnectedDevice(device: BleAdapter): void;
83
79
  }
@@ -47,7 +47,6 @@ class BleInterface extends events_1.default {
47
47
  if (props.binding)
48
48
  this.setBinding(props.binding);
49
49
  this.peripheralCache = new peripheral_cache_1.default();
50
- this.connectedDevices = [];
51
50
  if (props.logger)
52
51
  this.logger = props.logger;
53
52
  else
@@ -542,15 +541,5 @@ class BleInterface extends events_1.default {
542
541
  isScanning() {
543
542
  return this.scanState.isScanning === true;
544
543
  }
545
- addConnectedDevice(device) {
546
- const idx = this.connectedDevices.findIndex(d => d.isSame(device));
547
- if (idx === -1)
548
- this.connectedDevices.push(device);
549
- }
550
- removeConnectedDevice(device) {
551
- const idx = this.connectedDevices.findIndex(d => d.isSame(device));
552
- if (idx !== -1)
553
- this.connectedDevices.splice(idx);
554
- }
555
544
  }
556
545
  exports.default = BleInterface;
@@ -1,17 +1,19 @@
1
+ import BleCyclingPowerDevice from './comm';
1
2
  import BleAdapter from '../base/adapter';
2
3
  import { PowerData } from './types';
3
4
  import { BleDeviceSettings } from '../types';
4
5
  import { DeviceProperties, IncyclistBikeData, IncyclistAdapterData, ControllerConfig, IAdapter } from '../../types';
5
- export default class PwrAdapter extends BleAdapter {
6
+ import { LegacyProfile } from '../../antv2/types';
7
+ export default class PwrAdapter extends BleAdapter<PowerData, BleCyclingPowerDevice> {
8
+ protected static INCYCLIST_PROFILE_NAME: LegacyProfile;
6
9
  protected static controllers: ControllerConfig;
7
10
  distanceInternal: number;
8
11
  constructor(settings: BleDeviceSettings, props?: DeviceProperties);
9
12
  isSame(device: IAdapter): boolean;
10
- getProfile(): string;
13
+ getProfile(): LegacyProfile;
11
14
  getName(): string;
12
15
  getDisplayName(): string;
13
16
  mapData(deviceData: PowerData): IncyclistBikeData;
14
17
  transformData(bikeData: IncyclistBikeData): IncyclistAdapterData;
15
- sendUpdate(request: any): Promise<void>;
16
18
  stop(): Promise<boolean>;
17
19
  }
@@ -82,13 +82,6 @@ class PwrAdapter extends adapter_1.default {
82
82
  };
83
83
  return data;
84
84
  }
85
- sendUpdate(request) {
86
- return __awaiter(this, void 0, void 0, function* () {
87
- if (this.paused)
88
- return;
89
- this.getCyclingMode().sendBikeUpdate(request);
90
- });
91
- }
92
85
  stop() {
93
86
  const _super = Object.create(null, {
94
87
  stop: { get: () => super.stop }
@@ -101,6 +94,7 @@ class PwrAdapter extends adapter_1.default {
101
94
  });
102
95
  }
103
96
  }
97
+ PwrAdapter.INCYCLIST_PROFILE_NAME = 'Power Meter';
104
98
  PwrAdapter.controllers = {
105
99
  modes: [power_meter_1.default],
106
100
  default: power_meter_1.default
@@ -1,19 +1,21 @@
1
1
  import BleAdapter from '../base/adapter';
2
+ import BleEliteDevice from './comms';
2
3
  import ICyclingMode from '../../modes/types';
3
4
  import { PowerData } from '../cp';
4
5
  import { DeviceProperties, IncyclistAdapterData, IncyclistBikeData, ControllerConfig, IAdapter } from '../../types';
5
6
  import { BleDeviceSettings } from '../types';
6
- export default class BleEliteAdapter extends BleAdapter {
7
+ import { LegacyProfile } from '../../antv2/types';
8
+ export default class BleEliteAdapter extends BleAdapter<PowerData, BleEliteDevice> {
9
+ protected static INCYCLIST_PROFILE_NAME: LegacyProfile;
7
10
  protected static controllers: ControllerConfig;
8
11
  distanceInternal: number;
9
12
  constructor(settings: BleDeviceSettings, props?: DeviceProperties);
10
13
  isSame(device: IAdapter): boolean;
11
- getProfile(): string;
14
+ getProfile(): LegacyProfile;
12
15
  getName(): string;
13
16
  getDefaultCyclingMode(): ICyclingMode;
14
17
  getSupportedCyclingModes(): any[];
15
18
  mapData(deviceData: PowerData): IncyclistBikeData;
16
19
  transformData(bikeData: IncyclistBikeData): IncyclistAdapterData;
17
20
  start(props?: any): Promise<any>;
18
- sendUpdate(request: any): Promise<void>;
19
21
  }
@@ -109,14 +109,8 @@ class BleEliteAdapter extends adapter_1.default {
109
109
  }
110
110
  });
111
111
  }
112
- sendUpdate(request) {
113
- return __awaiter(this, void 0, void 0, function* () {
114
- if (this.paused)
115
- return;
116
- this.getCyclingMode().sendBikeUpdate(request);
117
- });
118
- }
119
112
  }
113
+ BleEliteAdapter.INCYCLIST_PROFILE_NAME = 'Smart Trainer';
120
114
  BleEliteAdapter.controllers = {
121
115
  modes: [power_meter_1.default],
122
116
  default: power_meter_1.default
@@ -1,16 +1,17 @@
1
+ import BleFitnessMachineDevice from './comms';
1
2
  import BleAdapter from '../base/adapter';
2
3
  import ICyclingMode, { CyclingMode } from '../../modes/types';
3
4
  import { IndoorBikeData } from './types';
4
5
  import { BleDeviceProperties, BleDeviceSettings, BleStartProperties } from '../types';
5
6
  import { IAdapter, IncyclistAdapterData, IncyclistBikeData } from '../../types';
6
- export default class BleFmAdapter extends BleAdapter {
7
+ import { LegacyProfile } from '../../antv2/types';
8
+ export default class BleFmAdapter extends BleAdapter<IndoorBikeData, BleFitnessMachineDevice> {
9
+ protected static INCYCLIST_PROFILE_NAME: LegacyProfile;
7
10
  distanceInternal: number;
8
11
  connectPromise: Promise<boolean>;
9
12
  constructor(settings: BleDeviceSettings, props?: BleDeviceProperties);
10
13
  isSame(device: IAdapter): boolean;
11
- getProfile(): string;
12
14
  getName(): string;
13
- getDisplayName(): string;
14
15
  isControllable(): boolean;
15
16
  getSupportedCyclingModes(): Array<typeof CyclingMode>;
16
17
  getDefaultCyclingMode(): ICyclingMode;
@@ -40,15 +40,9 @@ class BleFmAdapter extends adapter_1.default {
40
40
  return false;
41
41
  return this.isEqual(device.settings);
42
42
  }
43
- getProfile() {
44
- return 'Smart Trainer';
45
- }
46
43
  getName() {
47
44
  return `${this.device.name}`;
48
45
  }
49
- getDisplayName() {
50
- return this.getName();
51
- }
52
46
  isControllable() {
53
47
  return true;
54
48
  }
@@ -258,4 +252,5 @@ class BleFmAdapter extends adapter_1.default {
258
252
  });
259
253
  }
260
254
  }
255
+ BleFmAdapter.INCYCLIST_PROFILE_NAME = 'Smart Trainer';
261
256
  exports.default = BleFmAdapter;
@@ -1,12 +1,14 @@
1
1
  import BleAdapter from '../base/adapter';
2
+ import BleHrmDevice from './comm';
2
3
  import { IncyclistAdapterData, IAdapter, DeviceProperties } from '../../types';
3
4
  import { BleDeviceSettings } from '../types';
4
5
  import { HrmData } from './types';
5
- export default class HrmAdapter extends BleAdapter {
6
+ import { LegacyProfile } from '../../antv2/types';
7
+ export default class HrmAdapter extends BleAdapter<HrmData, BleHrmDevice> {
8
+ protected static INCYCLIST_PROFILE_NAME: LegacyProfile;
6
9
  ignore: boolean;
7
10
  constructor(settings: BleDeviceSettings, props?: DeviceProperties);
8
11
  isSame(device: IAdapter): boolean;
9
- getProfile(): string;
10
12
  getName(): string;
11
13
  getDisplayName(): string;
12
14
  mapData(deviceData: HrmData): IncyclistAdapterData;
@@ -25,9 +25,6 @@ class HrmAdapter extends adapter_1.default {
25
25
  return false;
26
26
  return this.isEqual(device.settings);
27
27
  }
28
- getProfile() {
29
- return 'Heartrate Monitor';
30
- }
31
28
  getName() {
32
29
  return `${this.device.name}`;
33
30
  }
@@ -42,4 +39,5 @@ class HrmAdapter extends adapter_1.default {
42
39
  return { heartrate };
43
40
  }
44
41
  }
42
+ HrmAdapter.INCYCLIST_PROFILE_NAME = 'Heartrate Monitor';
45
43
  exports.default = HrmAdapter;
@@ -1,4 +1,6 @@
1
1
  import BleAdapter from "./base/adapter";
2
+ import { BleComms } from "./base/comms";
3
+ import { BleDeviceData } from "./base/types";
2
4
  import BlePeripheralConnector from "./ble-peripheral";
3
5
  import { BleCharacteristic, BlePeripheral } from "./types";
4
6
  export interface PeripheralState {
@@ -18,7 +20,7 @@ export interface PeripheralCacheItem {
18
20
  }
19
21
  export default class BlePeripheralCache {
20
22
  peripherals: PeripheralCacheItem[];
21
- findAdapter(adapter: BleAdapter): PeripheralCacheItem;
23
+ findAdapter(adapter: BleAdapter<BleDeviceData, BleComms>): PeripheralCacheItem;
22
24
  getConnector(peripheral: BlePeripheral): BlePeripheralConnector;
23
25
  getPeripheral(query: {
24
26
  id?: string;
@@ -1,9 +1,11 @@
1
1
  import { BleFmAdapter } from '../fm';
2
2
  import { BleDeviceSettings, BleStartProperties } from '../types';
3
3
  import { DeviceProperties, IAdapter } from '../../types';
4
+ import { LegacyProfile } from '../../antv2/types';
4
5
  export default class BleTacxFEAdapter extends BleFmAdapter {
6
+ protected static INCYCLIST_PROFILE_NAME: LegacyProfile;
5
7
  constructor(settings: BleDeviceSettings, props?: DeviceProperties);
6
8
  isSame(device: IAdapter): boolean;
7
- getProfile(): string;
9
+ getProfile(): LegacyProfile;
8
10
  start(props?: BleStartProperties): Promise<any>;
9
11
  }
@@ -102,4 +102,5 @@ class BleTacxFEAdapter extends fm_1.BleFmAdapter {
102
102
  });
103
103
  }
104
104
  }
105
+ BleTacxFEAdapter.INCYCLIST_PROFILE_NAME = 'Smart Trainer';
105
106
  exports.default = BleTacxFEAdapter;
@@ -1,9 +1,11 @@
1
1
  import { BleFmAdapter } from '../fm';
2
2
  import { BleDeviceProperties, BleDeviceSettings, BleStartProperties } from '../types';
3
3
  import { IAdapter } from '../../types';
4
+ import { LegacyProfile } from '../../antv2/types';
4
5
  export default class BleWahooAdapter extends BleFmAdapter {
6
+ protected static INCYCLIST_PROFILE_NAME: LegacyProfile;
5
7
  constructor(settings: BleDeviceSettings, props?: BleDeviceProperties);
6
8
  isSame(device: IAdapter): boolean;
7
- getProfile(): string;
9
+ getProfile(): LegacyProfile;
8
10
  start(props?: BleStartProperties): Promise<any>;
9
11
  }
@@ -97,4 +97,5 @@ class BleWahooAdapter extends fm_1.BleFmAdapter {
97
97
  });
98
98
  }
99
99
  }
100
+ BleWahooAdapter.INCYCLIST_PROFILE_NAME = 'Smart Trainer';
100
101
  exports.default = BleWahooAdapter;
@@ -22,10 +22,7 @@ class PowerBasedCyclingModeBase extends base_1.CyclingModeBase {
22
22
  return slope || 0;
23
23
  }
24
24
  initLogger(defaultLogName) {
25
- const a = this.adapter;
26
- this.logger = a.getLogger();
27
- if (!this.logger)
28
- this.logger = new gd_eventlog_1.EventLogger(defaultLogName);
25
+ this.logger = new gd_eventlog_1.EventLogger(defaultLogName);
29
26
  }
30
27
  getWeight() {
31
28
  const a = this.adapter;
@@ -36,7 +36,7 @@ class Simulator extends adpater_1.default {
36
36
  this.setCyclingMode(name, modeSettings);
37
37
  this.capabilities = [
38
38
  types_1.IncyclistCapability.Power, types_1.IncyclistCapability.Speed, types_1.IncyclistCapability.Cadence, types_1.IncyclistCapability.Gear,
39
- types_1.IncyclistCapability.Control
39
+ types_1.IncyclistCapability.Control, types_1.IncyclistCapability.HeartRate
40
40
  ];
41
41
  }
42
42
  isEqual(settings) {
@@ -53,12 +53,13 @@ class Simulator extends adpater_1.default {
53
53
  start(props) {
54
54
  return __awaiter(this, void 0, void 0, function* () {
55
55
  this.startProps = props;
56
+ this.stopped = false;
56
57
  this.paused = false;
57
58
  if (props)
58
59
  this.setBikeProps(props);
59
60
  return new Promise((resolve) => {
60
61
  if (!this.isBot)
61
- this.logger.logEvent({ message: 'start', iv: this.iv });
62
+ this.logEvent({ message: 'starting device', device: this.getName(), props });
62
63
  if (this.started) {
63
64
  return resolve(true);
64
65
  }
@@ -94,32 +95,31 @@ class Simulator extends adpater_1.default {
94
95
  });
95
96
  }
96
97
  pause() {
97
- return new Promise((resolve, reject) => {
98
- if (!this.started)
99
- return reject(new Error('illegal state - pause() has been called before start()'));
100
- if (!this.isBot)
101
- this.logger.logEvent({ message: 'pause', iv: this.iv });
98
+ return __awaiter(this, void 0, void 0, function* () {
99
+ if (!this.isBot && this.isStarted())
100
+ this.logEvent({ message: 'pausing device', device: this.getName() });
102
101
  this.paused = true;
103
- resolve(true);
102
+ return true;
104
103
  });
105
104
  }
106
105
  resume() {
107
- return new Promise((resolve, reject) => {
108
- if (!this.started)
109
- reject(new Error('illegal state - resume() has been called before start()'));
110
- if (!this.isBot)
111
- this.logger.logEvent({ message: 'resume', iv: this.iv });
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ if (!this.isBot && this.isStarted())
108
+ this.logger.logEvent({ message: 'resuming device', device: this.getName() });
112
109
  this.paused = false;
113
- resolve(true);
110
+ return true;
114
111
  });
115
112
  }
116
113
  toggle() {
117
- if (this.started) {
118
- return this.stop();
119
- }
120
- else {
121
- return this.start().then(() => { return true; });
122
- }
114
+ return __awaiter(this, void 0, void 0, function* () {
115
+ if (this.started) {
116
+ return yield this.stop();
117
+ }
118
+ else {
119
+ yield this.start();
120
+ return true;
121
+ }
122
+ });
123
123
  }
124
124
  faster() {
125
125
  if (this.speed < 15)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "dependencies": {
5
5
  "@serialport/bindings-interface": "^1.2.2",
6
6
  "@serialport/parser-byte-length": "^9.0.1",