incyclist-devices 3.0.7 → 3.0.9

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.
@@ -144,6 +144,9 @@ class AntInterface extends node_events_1.EventEmitter {
144
144
  this.connected = false;
145
145
  return closed;
146
146
  }
147
+ async terminate() {
148
+ await this.disconnect();
149
+ }
147
150
  onError(profile, error) {
148
151
  this.logEvent({ message: 'ANT+ERROR:', profile, error });
149
152
  }
@@ -15,6 +15,7 @@ class BleAdapter extends adpater_js_1.default {
15
15
  device;
16
16
  onDeviceDataHandler = this.onDeviceData.bind(this);
17
17
  onDeviceDisconnectHandler = this.emit.bind(this);
18
+ onDisconnectDoneHandler = this.onDisconnectDone.bind(this);
18
19
  startTask;
19
20
  constructor(settings, props) {
20
21
  super(settings, props);
@@ -198,7 +199,7 @@ class BleAdapter extends adpater_js_1.default {
198
199
  await this.stop();
199
200
  }
200
201
  const ble = this.getBle();
201
- ble.once('disconnect-done', this.onDisconnectDone.bind(this));
202
+ ble.once('disconnect-done', this.onDisconnectDoneHandler);
202
203
  this.startTask = new task_js_1.InteruptableTask(this.startAdapter(startProps), {
203
204
  timeout: startProps?.timeout,
204
205
  name: 'start',
@@ -206,6 +207,9 @@ class BleAdapter extends adpater_js_1.default {
206
207
  log: this.logEvent.bind(this)
207
208
  });
208
209
  const res = await this.startTask.run();
210
+ if (!res) {
211
+ ble.removeListener('disconnect-done', this.onDisconnectDoneHandler);
212
+ }
209
213
  return res;
210
214
  }
211
215
  isStarting() {
@@ -303,6 +307,8 @@ class BleAdapter extends adpater_js_1.default {
303
307
  this.logEvent({ message: 'start result: error', error: err.message, device: this.getName(), interface: this.getInterface(), protocol: this.getProtocolName() });
304
308
  this.started = false;
305
309
  this.stopped = true;
310
+ const ble = this.getBle();
311
+ ble.removeListener('disconnect-done', this.onDisconnectDoneHandler);
306
312
  return false;
307
313
  }
308
314
  }
@@ -380,6 +386,8 @@ class BleAdapter extends adpater_js_1.default {
380
386
  sensor.off('data', this.onDeviceDataHandler);
381
387
  sensor.off('disconnected', this.onDeviceDisconnectHandler);
382
388
  sensor.off('error', console.log);
389
+ const ble = this.getBle();
390
+ ble.removeListener('disconnect-done', this.onDisconnectDoneHandler);
383
391
  sensor.reset();
384
392
  this.resetData();
385
393
  this.stopped = true;
@@ -36,6 +36,7 @@ class BleInterface extends node_events_1.EventEmitter {
36
36
  emitted = [];
37
37
  confirmedBleState;
38
38
  currentBleState;
39
+ isAutoStart = false;
39
40
  stateChangeEventHandler = null;
40
41
  static getInstance(props = {}) {
41
42
  if (BleInterface._instance === undefined)
@@ -93,9 +94,16 @@ class BleInterface extends node_events_1.EventEmitter {
93
94
  return this.binding;
94
95
  }
95
96
  async autoConnect() {
96
- await this.connect();
97
+ this.isAutoStart = true;
98
+ await this.connectInternal();
97
99
  }
98
100
  async connect(reconnect) {
101
+ if (this.isAutoStart)
102
+ return this.isConnected();
103
+ else
104
+ return this.connectInternal(reconnect);
105
+ }
106
+ async connectInternal(reconnect) {
99
107
  if (this.isConnected())
100
108
  return true;
101
109
  if (!this.stateChangeEventHandler) {
@@ -107,7 +115,6 @@ class BleInterface extends node_events_1.EventEmitter {
107
115
  return false;
108
116
  }
109
117
  if (this.isConnecting()) {
110
- this.logEvent({ message: 'BLE connect - already connecting' });
111
118
  return this.connectTask.getPromise();
112
119
  }
113
120
  this.logEvent({ message: 'BLE connect request' });
@@ -161,6 +168,7 @@ class BleInterface extends node_events_1.EventEmitter {
161
168
  this.getBinding()?.on('error', this.onError.bind(this));
162
169
  this.logEvent({ message: 'interface disconnected', interface: 'BLE' });
163
170
  this.confirmedBleState = 'poweredOff';
171
+ this.emit('disconnect');
164
172
  return true;
165
173
  };
166
174
  if (this.isDisconnecting()) {
@@ -175,6 +183,9 @@ class BleInterface extends node_events_1.EventEmitter {
175
183
  const success = await this.disconnectTask.run().catch(() => false);
176
184
  return success;
177
185
  }
186
+ async terminate() {
187
+ await this.disconnect();
188
+ }
178
189
  isConnected() {
179
190
  return this.confirmedBleState === 'poweredOn';
180
191
  }
@@ -301,7 +312,7 @@ class BleInterface extends node_events_1.EventEmitter {
301
312
  }
302
313
  this.logEvent({ message: 'reconnecting interface', stack: error.stack });
303
314
  await this.disconnect();
304
- await this.connect(true);
315
+ await this.connectInternal(true);
305
316
  }
306
317
  async startPeripheralScan(retry = false) {
307
318
  if (!this.isConnected() || this.isDiscovering()) {
@@ -580,8 +591,9 @@ class BleInterface extends node_events_1.EventEmitter {
580
591
  addKnownDevice(_settings) {
581
592
  }
582
593
  async connectBle() {
583
- this.currentBleState = this.getBinding()?.state;
584
- if (this.currentBleState === 'poweredOn') {
594
+ const prev = this.currentBleState;
595
+ this.currentBleState = this.currentBleState ?? this.getBinding()?.state;
596
+ if (this.currentBleState === 'poweredOn' && prev !== 'poweredOn') {
585
597
  this.onConnected();
586
598
  return true;
587
599
  }
@@ -599,13 +611,16 @@ class BleInterface extends node_events_1.EventEmitter {
599
611
  });
600
612
  this.on('ble-state-change', (state) => {
601
613
  try {
614
+ this.currentBleState = state;
602
615
  if (state === 'poweredOn') {
603
616
  this.onConnected();
604
617
  this.removeAllListeners('ble-state-change');
618
+ this.currentBleState = state;
605
619
  return done(true);
606
620
  }
607
621
  if (state === 'unauthorized') {
608
622
  this.removeAllListeners('ble-state-change');
623
+ this.currentBleState = state;
609
624
  return done(false);
610
625
  }
611
626
  }
@@ -616,6 +631,9 @@ class BleInterface extends node_events_1.EventEmitter {
616
631
  });
617
632
  }
618
633
  onError(err) {
634
+ if (typeof err === 'string') {
635
+ this.logError(new Error(err), 'BLE connect');
636
+ }
619
637
  this.logError(err, 'BLE connect');
620
638
  }
621
639
  async onConnected() {
@@ -656,7 +674,7 @@ class BleInterface extends node_events_1.EventEmitter {
656
674
  if (this.isDisconnecting()) {
657
675
  await this.disconnectTask.getPromise();
658
676
  }
659
- this.connect();
677
+ this.connectInternal();
660
678
  }
661
679
  }
662
680
  getAdapterFactory() {
@@ -144,10 +144,16 @@ class DirectConnectInterface extends node_events_1.EventEmitter {
144
144
  return true;
145
145
  this.logEvent({ message: 'Disconnecting from Direct Connect' });
146
146
  await this.stopScan();
147
+ return true;
148
+ }
149
+ async terminate() {
150
+ await this.disconnect();
147
151
  this.getBinding()?.mdns?.disconnect();
148
152
  this.internalEvents.removeAllListeners();
149
153
  this.connected = false;
150
- return !this.isConnected();
154
+ const disconnected = !this.isConnected();
155
+ if (disconnected)
156
+ this.emit('disconnect');
151
157
  }
152
158
  isConnected() {
153
159
  return this.connected && this.getBinding()?.mdns !== undefined && this.binding.mdns !== null;
@@ -156,7 +162,7 @@ class DirectConnectInterface extends node_events_1.EventEmitter {
156
162
  this.logDisabled = false;
157
163
  if (this.isScanning()) {
158
164
  this.logEvent({ message: 'starting scan - already scanning' });
159
- await this.scanTask.getPromise();
165
+ await this.scanTask?.getPromise();
160
166
  }
161
167
  this.logEvent({ message: 'starting scan ..' });
162
168
  await this.reconnect();
@@ -174,7 +180,7 @@ class DirectConnectInterface extends node_events_1.EventEmitter {
174
180
  if (!this.isScanning())
175
181
  return true;
176
182
  this.logEvent({ message: 'stopping scan ...', interface: 'wifi' });
177
- const res = await this.scanTask.stop();
183
+ const res = await this.scanTask?.stop();
178
184
  delete this.scanTask;
179
185
  return (res === true);
180
186
  }
@@ -414,7 +414,7 @@ class SmartTrainerCyclingMode extends power_base_js_1.default {
414
414
  this.tsStart = Date.now();
415
415
  }
416
416
  if (this.gear === undefined && this.tsStart && data.power > 0 && (Date.now() - this.tsStart > 3000)) {
417
- this.gear = Number(this.getSetting('startGear')) ?? 0;
417
+ this.gear = Number(this.getSetting('startGear') ?? 0);
418
418
  data.gearStr = this.getGearString();
419
419
  }
420
420
  return data;
@@ -118,6 +118,9 @@ class SerialInterface extends node_events_1.EventEmitter {
118
118
  this.connected = false;
119
119
  return true;
120
120
  }
121
+ async terminate() {
122
+ await this.disconnect();
123
+ }
121
124
  async openPort(path) {
122
125
  this.logEvent({ message: 'opening port', port: path });
123
126
  const existing = this.ports.findIndex(p => p.path === path);
@@ -139,6 +139,9 @@ export default class AntInterface extends EventEmitter {
139
139
  this.connected = false;
140
140
  return closed;
141
141
  }
142
+ async terminate() {
143
+ await this.disconnect();
144
+ }
142
145
  onError(profile, error) {
143
146
  this.logEvent({ message: 'ANT+ERROR:', profile, error });
144
147
  }
@@ -10,6 +10,7 @@ export default class BleAdapter extends IncyclistDevice {
10
10
  device;
11
11
  onDeviceDataHandler = this.onDeviceData.bind(this);
12
12
  onDeviceDisconnectHandler = this.emit.bind(this);
13
+ onDisconnectDoneHandler = this.onDisconnectDone.bind(this);
13
14
  startTask;
14
15
  constructor(settings, props) {
15
16
  super(settings, props);
@@ -193,7 +194,7 @@ export default class BleAdapter extends IncyclistDevice {
193
194
  await this.stop();
194
195
  }
195
196
  const ble = this.getBle();
196
- ble.once('disconnect-done', this.onDisconnectDone.bind(this));
197
+ ble.once('disconnect-done', this.onDisconnectDoneHandler);
197
198
  this.startTask = new InteruptableTask(this.startAdapter(startProps), {
198
199
  timeout: startProps?.timeout,
199
200
  name: 'start',
@@ -201,6 +202,9 @@ export default class BleAdapter extends IncyclistDevice {
201
202
  log: this.logEvent.bind(this)
202
203
  });
203
204
  const res = await this.startTask.run();
205
+ if (!res) {
206
+ ble.removeListener('disconnect-done', this.onDisconnectDoneHandler);
207
+ }
204
208
  return res;
205
209
  }
206
210
  isStarting() {
@@ -298,6 +302,8 @@ export default class BleAdapter extends IncyclistDevice {
298
302
  this.logEvent({ message: 'start result: error', error: err.message, device: this.getName(), interface: this.getInterface(), protocol: this.getProtocolName() });
299
303
  this.started = false;
300
304
  this.stopped = true;
305
+ const ble = this.getBle();
306
+ ble.removeListener('disconnect-done', this.onDisconnectDoneHandler);
301
307
  return false;
302
308
  }
303
309
  }
@@ -375,6 +381,8 @@ export default class BleAdapter extends IncyclistDevice {
375
381
  sensor.off('data', this.onDeviceDataHandler);
376
382
  sensor.off('disconnected', this.onDeviceDisconnectHandler);
377
383
  sensor.off('error', console.log);
384
+ const ble = this.getBle();
385
+ ble.removeListener('disconnect-done', this.onDisconnectDoneHandler);
378
386
  sensor.reset();
379
387
  this.resetData();
380
388
  this.stopped = true;
@@ -33,6 +33,7 @@ export class BleInterface extends EventEmitter {
33
33
  emitted = [];
34
34
  confirmedBleState;
35
35
  currentBleState;
36
+ isAutoStart = false;
36
37
  stateChangeEventHandler = null;
37
38
  static getInstance(props = {}) {
38
39
  if (BleInterface._instance === undefined)
@@ -90,9 +91,16 @@ export class BleInterface extends EventEmitter {
90
91
  return this.binding;
91
92
  }
92
93
  async autoConnect() {
93
- await this.connect();
94
+ this.isAutoStart = true;
95
+ await this.connectInternal();
94
96
  }
95
97
  async connect(reconnect) {
98
+ if (this.isAutoStart)
99
+ return this.isConnected();
100
+ else
101
+ return this.connectInternal(reconnect);
102
+ }
103
+ async connectInternal(reconnect) {
96
104
  if (this.isConnected())
97
105
  return true;
98
106
  if (!this.stateChangeEventHandler) {
@@ -104,7 +112,6 @@ export class BleInterface extends EventEmitter {
104
112
  return false;
105
113
  }
106
114
  if (this.isConnecting()) {
107
- this.logEvent({ message: 'BLE connect - already connecting' });
108
115
  return this.connectTask.getPromise();
109
116
  }
110
117
  this.logEvent({ message: 'BLE connect request' });
@@ -158,6 +165,7 @@ export class BleInterface extends EventEmitter {
158
165
  this.getBinding()?.on('error', this.onError.bind(this));
159
166
  this.logEvent({ message: 'interface disconnected', interface: 'BLE' });
160
167
  this.confirmedBleState = 'poweredOff';
168
+ this.emit('disconnect');
161
169
  return true;
162
170
  };
163
171
  if (this.isDisconnecting()) {
@@ -172,6 +180,9 @@ export class BleInterface extends EventEmitter {
172
180
  const success = await this.disconnectTask.run().catch(() => false);
173
181
  return success;
174
182
  }
183
+ async terminate() {
184
+ await this.disconnect();
185
+ }
175
186
  isConnected() {
176
187
  return this.confirmedBleState === 'poweredOn';
177
188
  }
@@ -298,7 +309,7 @@ export class BleInterface extends EventEmitter {
298
309
  }
299
310
  this.logEvent({ message: 'reconnecting interface', stack: error.stack });
300
311
  await this.disconnect();
301
- await this.connect(true);
312
+ await this.connectInternal(true);
302
313
  }
303
314
  async startPeripheralScan(retry = false) {
304
315
  if (!this.isConnected() || this.isDiscovering()) {
@@ -577,8 +588,9 @@ export class BleInterface extends EventEmitter {
577
588
  addKnownDevice(_settings) {
578
589
  }
579
590
  async connectBle() {
580
- this.currentBleState = this.getBinding()?.state;
581
- if (this.currentBleState === 'poweredOn') {
591
+ const prev = this.currentBleState;
592
+ this.currentBleState = this.currentBleState ?? this.getBinding()?.state;
593
+ if (this.currentBleState === 'poweredOn' && prev !== 'poweredOn') {
582
594
  this.onConnected();
583
595
  return true;
584
596
  }
@@ -596,13 +608,16 @@ export class BleInterface extends EventEmitter {
596
608
  });
597
609
  this.on('ble-state-change', (state) => {
598
610
  try {
611
+ this.currentBleState = state;
599
612
  if (state === 'poweredOn') {
600
613
  this.onConnected();
601
614
  this.removeAllListeners('ble-state-change');
615
+ this.currentBleState = state;
602
616
  return done(true);
603
617
  }
604
618
  if (state === 'unauthorized') {
605
619
  this.removeAllListeners('ble-state-change');
620
+ this.currentBleState = state;
606
621
  return done(false);
607
622
  }
608
623
  }
@@ -613,6 +628,9 @@ export class BleInterface extends EventEmitter {
613
628
  });
614
629
  }
615
630
  onError(err) {
631
+ if (typeof err === 'string') {
632
+ this.logError(new Error(err), 'BLE connect');
633
+ }
616
634
  this.logError(err, 'BLE connect');
617
635
  }
618
636
  async onConnected() {
@@ -653,7 +671,7 @@ export class BleInterface extends EventEmitter {
653
671
  if (this.isDisconnecting()) {
654
672
  await this.disconnectTask.getPromise();
655
673
  }
656
- this.connect();
674
+ this.connectInternal();
657
675
  }
658
676
  }
659
677
  getAdapterFactory() {
@@ -141,10 +141,16 @@ export default class DirectConnectInterface extends EventEmitter {
141
141
  return true;
142
142
  this.logEvent({ message: 'Disconnecting from Direct Connect' });
143
143
  await this.stopScan();
144
+ return true;
145
+ }
146
+ async terminate() {
147
+ await this.disconnect();
144
148
  this.getBinding()?.mdns?.disconnect();
145
149
  this.internalEvents.removeAllListeners();
146
150
  this.connected = false;
147
- return !this.isConnected();
151
+ const disconnected = !this.isConnected();
152
+ if (disconnected)
153
+ this.emit('disconnect');
148
154
  }
149
155
  isConnected() {
150
156
  return this.connected && this.getBinding()?.mdns !== undefined && this.binding.mdns !== null;
@@ -153,7 +159,7 @@ export default class DirectConnectInterface extends EventEmitter {
153
159
  this.logDisabled = false;
154
160
  if (this.isScanning()) {
155
161
  this.logEvent({ message: 'starting scan - already scanning' });
156
- await this.scanTask.getPromise();
162
+ await this.scanTask?.getPromise();
157
163
  }
158
164
  this.logEvent({ message: 'starting scan ..' });
159
165
  await this.reconnect();
@@ -171,7 +177,7 @@ export default class DirectConnectInterface extends EventEmitter {
171
177
  if (!this.isScanning())
172
178
  return true;
173
179
  this.logEvent({ message: 'stopping scan ...', interface: 'wifi' });
174
- const res = await this.scanTask.stop();
180
+ const res = await this.scanTask?.stop();
175
181
  delete this.scanTask;
176
182
  return (res === true);
177
183
  }
@@ -376,7 +376,7 @@ export default class SmartTrainerCyclingMode extends PowerBasedCyclingModeBase {
376
376
  this.tsStart = Date.now();
377
377
  }
378
378
  if (this.gear === undefined && this.tsStart && data.power > 0 && (Date.now() - this.tsStart > 3000)) {
379
- this.gear = Number(this.getSetting('startGear')) ?? 0;
379
+ this.gear = Number(this.getSetting('startGear') ?? 0);
380
380
  data.gearStr = this.getGearString();
381
381
  }
382
382
  return data;
@@ -113,6 +113,9 @@ export default class SerialInterface extends EventEmitter {
113
113
  this.connected = false;
114
114
  return true;
115
115
  }
116
+ async terminate() {
117
+ await this.disconnect();
118
+ }
116
119
  async openPort(path) {
117
120
  this.logEvent({ message: 'opening port', port: path });
118
121
  const existing = this.ports.findIndex(p => p.path === path);
@@ -39,6 +39,7 @@ export default class AntInterface extends EventEmitter implements IncyclistInter
39
39
  isConnected(): boolean;
40
40
  connect(): Promise<boolean>;
41
41
  disconnect(): Promise<boolean>;
42
+ terminate(): Promise<void>;
42
43
  onError(profile: any, error: any): void;
43
44
  onData(profile: any, id: any, data: any, tag: any): void;
44
45
  getReconnectPause(): number;
@@ -13,6 +13,7 @@ export default class BleAdapter<TDeviceData extends BleDeviceData, TDevice exten
13
13
  protected device: TDevice;
14
14
  protected onDeviceDataHandler: any;
15
15
  protected onDeviceDisconnectHandler: any;
16
+ protected onDisconnectDoneHandler: any;
16
17
  protected startTask: InteruptableTask<TaskState, boolean>;
17
18
  constructor(settings: BleDeviceSettings, props?: DeviceProperties);
18
19
  getUniqueName(): string;
@@ -40,6 +40,7 @@ export declare class BleInterface extends EventEmitter implements IBleInterface<
40
40
  protected emitted: BlePeripheralAnnouncement[];
41
41
  protected confirmedBleState: BleInterfaceState;
42
42
  protected currentBleState: BleInterfaceState;
43
+ protected isAutoStart: boolean;
43
44
  protected stateChangeEventHandler: TStateChangeHandler | null;
44
45
  static getInstance(props?: InterfaceProps): BleInterface;
45
46
  protected constructor(props: InterfaceProps);
@@ -51,7 +52,9 @@ export declare class BleInterface extends EventEmitter implements IBleInterface<
51
52
  getBinding(): BleBinding;
52
53
  protected autoConnect(): Promise<void>;
53
54
  connect(reconnect?: boolean): Promise<boolean>;
55
+ connectInternal(reconnect?: boolean): Promise<boolean>;
54
56
  disconnect(connectionLost?: boolean): Promise<boolean>;
57
+ terminate(): Promise<void>;
55
58
  isConnected(): boolean;
56
59
  registerConnected(peripheral: IBlePeripheral, id: string): void;
57
60
  unregisterConnected(id: string): void;
@@ -99,7 +102,7 @@ export declare class BleInterface extends EventEmitter implements IBleInterface<
99
102
  addKnownDevice(_settings: BleDeviceSettings): void;
100
103
  protected connectBle(): Promise<boolean>;
101
104
  protected waitForBleConnected(): Promise<boolean>;
102
- protected onError(err: Error): void;
105
+ protected onError(err: Error | string): void;
103
106
  protected onConnected(): Promise<void>;
104
107
  protected onDisconnected(): Promise<void>;
105
108
  protected onBleStateChange(state: BleInterfaceState): Promise<void>;
@@ -24,7 +24,7 @@ export default class DirectConnectInterface extends EventEmitter implements IBle
24
24
  protected logDisabled: boolean;
25
25
  protected internalEvents: EventEmitter;
26
26
  protected services: Announcement[];
27
- protected scanTask: InteruptableTask<TaskState, DeviceSettings[]>;
27
+ protected scanTask: InteruptableTask<TaskState, DeviceSettings[]> | undefined;
28
28
  protected matching?: Array<string>;
29
29
  protected instance: number;
30
30
  protected connected: boolean;
@@ -43,6 +43,7 @@ export default class DirectConnectInterface extends EventEmitter implements IBle
43
43
  autoConnect(): void;
44
44
  connect(reconnect?: boolean): Promise<boolean>;
45
45
  disconnect(): Promise<boolean>;
46
+ terminate(): Promise<void>;
46
47
  isConnected(): boolean;
47
48
  scan(props: DirectConnectScanProps): Promise<DeviceSettings[]>;
48
49
  stopScan(): Promise<boolean>;
@@ -26,6 +26,7 @@ export default class SerialInterface extends EventEmitter implements IncyclistIn
26
26
  releaseInUse(path: string): void;
27
27
  connect(): Promise<boolean>;
28
28
  disconnect(): Promise<boolean>;
29
+ terminate(): Promise<void>;
29
30
  openPort(path: string): Promise<SerialPortStream | null>;
30
31
  closePort(path: string): Promise<boolean>;
31
32
  scan(props: SerialScannerProps): Promise<SerialDeviceSettings[]>;
@@ -12,6 +12,7 @@ export interface IncyclistInterface extends EventEmitter {
12
12
  setBinding(binding: any): void;
13
13
  connect(): Promise<boolean>;
14
14
  disconnect(): Promise<boolean>;
15
+ terminate(): Promise<void>;
15
16
  isConnected(): boolean;
16
17
  scan(props: IncyclistScanProps): Promise<DeviceSettings[]>;
17
18
  stopScan(): Promise<boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-devices",
3
- "version": "3.0.7",
3
+ "version": "3.0.9",
4
4
  "scripts": {
5
5
  "lint": "eslint . --ext .ts",
6
6
  "build": "npm run build:esm && npm run build:cjs",