incyclist-devices 3.0.5 → 3.0.7
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.
- package/lib/cjs/antv2/base/adapter.js +13 -7
- package/lib/cjs/antv2/base/interface.js +4 -4
- package/lib/cjs/base/adpater.js +2 -5
- package/lib/cjs/ble/base/adapter.js +14 -2
- package/lib/cjs/ble/base/interface.js +68 -36
- package/lib/cjs/ble/base/peripheral.js +25 -9
- package/lib/cjs/ble/base/sensor.js +40 -6
- package/lib/cjs/ble/bindings/linux.js +2 -5
- package/lib/cjs/ble/bindings/mock.js +3 -6
- package/lib/cjs/ble/bindings/types.js +2 -5
- package/lib/cjs/ble/fm/sensor.js +11 -0
- package/lib/cjs/direct-connect/base/interface.js +4 -6
- package/lib/cjs/direct-connect/base/peripheral.js +17 -3
- package/lib/cjs/serial/base/serial-interface.js +9 -9
- package/lib/cjs/serial/base/serial-provider.js +113 -0
- package/lib/cjs/serial/daum/DaumAdapter.js +3 -3
- package/lib/cjs/serial/daum/classic/mock.js +2 -2
- package/lib/cjs/serial/index.js +3 -3
- package/lib/cjs/serial/kettler/comms.js +2 -5
- package/lib/cjs/utils/task.js +2 -5
- package/lib/esm/antv2/base/adapter.js +12 -6
- package/lib/esm/antv2/base/interface.js +2 -2
- package/lib/esm/base/adpater.js +1 -1
- package/lib/esm/ble/base/adapter.js +14 -2
- package/lib/esm/ble/base/interface.js +66 -31
- package/lib/esm/ble/base/peripheral.js +25 -9
- package/lib/esm/ble/base/sensor.js +40 -6
- package/lib/esm/ble/bindings/linux.js +1 -1
- package/lib/esm/ble/bindings/mock.js +1 -1
- package/lib/esm/ble/bindings/types.js +1 -1
- package/lib/esm/ble/fm/sensor.js +11 -0
- package/lib/esm/direct-connect/base/interface.js +2 -1
- package/lib/esm/direct-connect/base/peripheral.js +16 -2
- package/lib/esm/serial/base/serial-interface.js +2 -2
- package/lib/esm/serial/base/serial-provider.js +75 -0
- package/lib/esm/serial/base/serialport.js +0 -2
- package/lib/esm/serial/daum/DaumAdapter.js +1 -1
- package/lib/esm/serial/daum/classic/mock.js +1 -1
- package/lib/esm/serial/index.js +1 -1
- package/lib/esm/serial/kettler/comms.js +1 -1
- package/lib/esm/utils/task.js +1 -1
- package/lib/types/antv2/base/adapter.d.ts +2 -2
- package/lib/types/antv2/base/binding.d.ts +1 -1
- package/lib/types/antv2/base/interface.d.ts +2 -2
- package/lib/types/antv2/types.d.ts +1 -1
- package/lib/types/base/adpater.d.ts +1 -1
- package/lib/types/ble/base/interface.d.ts +4 -2
- package/lib/types/ble/base/peripheral.d.ts +2 -2
- package/lib/types/ble/base/sensor.d.ts +9 -3
- package/lib/types/ble/bindings/linux.d.ts +1 -1
- package/lib/types/ble/bindings/types.d.ts +1 -1
- package/lib/types/ble/fm/sensor.d.ts +2 -1
- package/lib/types/ble/types.d.ts +1 -1
- package/lib/types/ble/zwift/play/sensor.d.ts +1 -1
- package/lib/types/direct-connect/base/interface.d.ts +1 -1
- package/lib/types/direct-connect/base/peripheral.d.ts +2 -1
- package/lib/types/direct-connect/bindings/types.d.ts +1 -1
- package/lib/types/serial/base/serial-interface.d.ts +1 -1
- package/lib/types/serial/base/serial-provider.d.ts +16 -0
- package/lib/types/serial/daum/DaumAdapter.d.ts +1 -1
- package/lib/types/serial/index.d.ts +1 -1
- package/lib/types/serial/kettler/comms.d.ts +1 -1
- package/lib/types/types/adapter.d.ts +1 -1
- package/lib/types/types/interface.d.ts +1 -1
- package/lib/types/utils/task.d.ts +1 -1
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ const utils_js_2 = require("../utils.js");
|
|
|
12
12
|
const consts_js_1 = require("../consts.js");
|
|
13
13
|
const sensor_factory_js_1 = __importDefault(require("../factories/sensor-factory.js"));
|
|
14
14
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
15
|
-
const node_events_1 =
|
|
15
|
+
const node_events_1 = require("node:events");
|
|
16
16
|
const INTERFACE_NAME = 'ant';
|
|
17
17
|
const MAX_RETRIES = 3;
|
|
18
18
|
class AntAdapter extends adpater_js_1.default {
|
|
@@ -30,7 +30,7 @@ class AntAdapter extends adpater_js_1.default {
|
|
|
30
30
|
sensorConnected;
|
|
31
31
|
startStatus;
|
|
32
32
|
startupRetryPause = 1000;
|
|
33
|
-
internalEmitter = new node_events_1.
|
|
33
|
+
internalEmitter = new node_events_1.EventEmitter();
|
|
34
34
|
constructor(settings, props) {
|
|
35
35
|
super(settings, props);
|
|
36
36
|
const profile = this.getProfileName();
|
|
@@ -334,21 +334,27 @@ class AntAdapter extends adpater_js_1.default {
|
|
|
334
334
|
async initSensor(props) {
|
|
335
335
|
this.startStatus.sensorStarted = this.sensorConnected;
|
|
336
336
|
if (this.startStatus.sensorStarted)
|
|
337
|
-
return;
|
|
338
|
-
|
|
337
|
+
return true;
|
|
338
|
+
const logProps = structuredClone(props ?? {});
|
|
339
|
+
logProps.routeName = logProps?.route?.title;
|
|
340
|
+
logProps.routeId = logProps?.route?.id;
|
|
341
|
+
delete logProps.route;
|
|
342
|
+
this.logEvent({ message: 'start sensor', device: this.getName(), props: logProps });
|
|
339
343
|
try {
|
|
340
344
|
this.sensorConnected = await this.startSensor();
|
|
341
345
|
if (this.sensorConnected) {
|
|
342
|
-
this.logEvent({ message: 'sensor started', device: this.getName(),
|
|
346
|
+
this.logEvent({ message: 'sensor started', device: this.getName(), channelNo: this.sensor?.getChannel()?.getChannelNo(), props: logProps });
|
|
343
347
|
this.startStatus.sensorStarted = true;
|
|
348
|
+
return true;
|
|
344
349
|
}
|
|
345
350
|
else {
|
|
346
|
-
this.logEvent({ message: 'start sensor failed', device: this.getName(), reason: 'unknown', props });
|
|
351
|
+
this.logEvent({ message: 'start sensor failed', device: this.getName(), reason: 'unknown', props: logProps });
|
|
347
352
|
}
|
|
348
353
|
}
|
|
349
354
|
catch (err) {
|
|
350
|
-
this.logEvent({ message: 'start sensor failed', device: this.getName(), reason: err.message, props });
|
|
355
|
+
this.logEvent({ message: 'start sensor failed', device: this.getName(), reason: err.message, props: logProps });
|
|
351
356
|
}
|
|
357
|
+
return false;
|
|
352
358
|
}
|
|
353
359
|
getLogProps(startProps) {
|
|
354
360
|
const { user, userWeight, bikeWeight, startupTimeout, automaticReconnect } = startProps ?? {};
|
|
@@ -3,12 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const node_events_1 =
|
|
6
|
+
const node_events_1 = require("node:events");
|
|
7
7
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
8
8
|
const sensor_factory_js_1 = __importDefault(require("../factories/sensor-factory.js"));
|
|
9
9
|
const utils_js_1 = require("../../utils/utils.js");
|
|
10
10
|
const adapter_factory_js_1 = __importDefault(require("../factories/adapter-factory.js"));
|
|
11
|
-
class AntInterface extends node_events_1.
|
|
11
|
+
class AntInterface extends node_events_1.EventEmitter {
|
|
12
12
|
static _instance = undefined;
|
|
13
13
|
static INTERFACE_NAME = 'ant';
|
|
14
14
|
static getInstance(props = {}) {
|
|
@@ -178,7 +178,7 @@ class AntInterface extends node_events_1.default {
|
|
|
178
178
|
if (this.isScanning()) {
|
|
179
179
|
return await this.scanPromise;
|
|
180
180
|
}
|
|
181
|
-
this.activeScan = { emitter: new node_events_1.
|
|
181
|
+
this.activeScan = { emitter: new node_events_1.EventEmitter() };
|
|
182
182
|
const detected = [];
|
|
183
183
|
const _scan = () => new Promise(async (done) => {
|
|
184
184
|
const onDetected = (profile, deviceID) => {
|
|
@@ -340,7 +340,7 @@ class AntInterface extends node_events_1.default {
|
|
|
340
340
|
this.logEvent({ message: 'could not start sensor' });
|
|
341
341
|
channel.off('data', onData);
|
|
342
342
|
}
|
|
343
|
-
this.logEvent({ message: 'sensor started',
|
|
343
|
+
this.logEvent({ message: 'sensor started', channelNo: sensor.getChannel()?.getChannelNo(), profile: sensor.getProfile(), deviceID: sensor.getDeviceID() });
|
|
344
344
|
return started;
|
|
345
345
|
}
|
|
346
346
|
catch (err) {
|
package/lib/cjs/base/adpater.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
const index_js_1 = require("../types/index.js");
|
|
7
|
-
const node_events_1 =
|
|
4
|
+
const node_events_1 = require("node:events");
|
|
8
5
|
const consts_js_1 = require("./consts.js");
|
|
9
6
|
const utils_js_1 = require("../utils/utils.js");
|
|
10
|
-
class IncyclistDevice extends node_events_1.
|
|
7
|
+
class IncyclistDevice extends node_events_1.EventEmitter {
|
|
11
8
|
onDataFn;
|
|
12
9
|
settings;
|
|
13
10
|
lastUpdate;
|
|
@@ -349,9 +349,21 @@ class BleAdapter extends adpater_js_1.default {
|
|
|
349
349
|
}
|
|
350
350
|
async restart(pause) {
|
|
351
351
|
const sensor = this.getSensor();
|
|
352
|
+
sensor.off('data', this.onDeviceDataHandler);
|
|
353
|
+
let connected = false;
|
|
354
|
+
if (sensor.isReconnectBusy()) {
|
|
355
|
+
connected = await sensor.reconnectSensor();
|
|
356
|
+
}
|
|
357
|
+
if (connected) {
|
|
358
|
+
sensor.on('data', this.onDeviceDataHandler);
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
352
361
|
await sensor.getPeripheral().disconnect();
|
|
353
|
-
const
|
|
354
|
-
|
|
362
|
+
const success = await super.restart(pause);
|
|
363
|
+
if (success) {
|
|
364
|
+
sensor.on('data', this.onDeviceDataHandler);
|
|
365
|
+
}
|
|
366
|
+
return success;
|
|
355
367
|
}
|
|
356
368
|
async stop() {
|
|
357
369
|
this.logEvent({ message: 'stopping device', device: this.getName(), interface: this.getInterface() });
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.BleInterfaceFactory = exports.BleInterface = void 0;
|
|
7
|
-
const node_events_1 =
|
|
4
|
+
const node_events_1 = require("node:events");
|
|
8
5
|
const gd_eventlog_1 = require("gd-eventlog");
|
|
9
6
|
const task_js_1 = require("../../utils/task.js");
|
|
10
7
|
const peripheral_js_1 = require("./peripheral.js");
|
|
@@ -14,7 +11,7 @@ const index_js_1 = require("../factories/index.js");
|
|
|
14
11
|
const BLE_EXPIRATION_TIMEOUT = 10 * 1000 * 60;
|
|
15
12
|
const BLE_DEFAULT_CONNECT_TIMEOUT = 30 * 1000;
|
|
16
13
|
let instanceCount = 0;
|
|
17
|
-
class BleInterface extends node_events_1.
|
|
14
|
+
class BleInterface extends node_events_1.EventEmitter {
|
|
18
15
|
static _instance;
|
|
19
16
|
static INTERFACE_NAME = 'ble';
|
|
20
17
|
logger;
|
|
@@ -39,6 +36,7 @@ class BleInterface extends node_events_1.default {
|
|
|
39
36
|
emitted = [];
|
|
40
37
|
confirmedBleState;
|
|
41
38
|
currentBleState;
|
|
39
|
+
stateChangeEventHandler = null;
|
|
42
40
|
static getInstance(props = {}) {
|
|
43
41
|
if (BleInterface._instance === undefined)
|
|
44
42
|
BleInterface._instance = new BleInterface(props);
|
|
@@ -66,7 +64,7 @@ class BleInterface extends node_events_1.default {
|
|
|
66
64
|
if (binding) {
|
|
67
65
|
this.setBinding(binding);
|
|
68
66
|
}
|
|
69
|
-
this.internalEvents = new node_events_1.
|
|
67
|
+
this.internalEvents = new node_events_1.EventEmitter();
|
|
70
68
|
this.onDiscovered = this.onPeripheralFound.bind(this);
|
|
71
69
|
const { enabled = true } = props;
|
|
72
70
|
if (this.binding && enabled)
|
|
@@ -94,10 +92,16 @@ class BleInterface extends node_events_1.default {
|
|
|
94
92
|
getBinding() {
|
|
95
93
|
return this.binding;
|
|
96
94
|
}
|
|
97
|
-
autoConnect() {
|
|
98
|
-
this.connect();
|
|
95
|
+
async autoConnect() {
|
|
96
|
+
await this.connect();
|
|
99
97
|
}
|
|
100
98
|
async connect(reconnect) {
|
|
99
|
+
if (this.isConnected())
|
|
100
|
+
return true;
|
|
101
|
+
if (!this.stateChangeEventHandler) {
|
|
102
|
+
this.stateChangeEventHandler = this.onBleStateChange.bind(this);
|
|
103
|
+
this.getBinding()?.on('stateChange', this.stateChangeEventHandler);
|
|
104
|
+
}
|
|
101
105
|
if (!this.getBinding()) {
|
|
102
106
|
this.logEvent({ message: 'BLE not available' });
|
|
103
107
|
return false;
|
|
@@ -106,8 +110,6 @@ class BleInterface extends node_events_1.default {
|
|
|
106
110
|
this.logEvent({ message: 'BLE connect - already connecting' });
|
|
107
111
|
return this.connectTask.getPromise();
|
|
108
112
|
}
|
|
109
|
-
if (this.isConnected())
|
|
110
|
-
return true;
|
|
111
113
|
this.logEvent({ message: 'BLE connect request' });
|
|
112
114
|
this.connectTask = new task_js_1.InteruptableTask(this.connectBle(), {
|
|
113
115
|
timeout: this.getConnectTimeout(),
|
|
@@ -116,6 +118,9 @@ class BleInterface extends node_events_1.default {
|
|
|
116
118
|
log: this.logEvent.bind(this),
|
|
117
119
|
});
|
|
118
120
|
const success = await this.connectTask.run().catch(() => false);
|
|
121
|
+
this.removeAllListeners('ble-state-change');
|
|
122
|
+
if (success)
|
|
123
|
+
this.emit('connected');
|
|
119
124
|
return success;
|
|
120
125
|
}
|
|
121
126
|
async disconnect(connectionLost) {
|
|
@@ -126,7 +131,7 @@ class BleInterface extends node_events_1.default {
|
|
|
126
131
|
this.confirmedBleState = 'poweredOff';
|
|
127
132
|
return false;
|
|
128
133
|
}
|
|
129
|
-
this.getBinding()
|
|
134
|
+
this.getBinding()?.removeAllListeners('error');
|
|
130
135
|
if (!this.isConnected() && !connectionLost) {
|
|
131
136
|
this.confirmedBleState = 'poweredOff';
|
|
132
137
|
return true;
|
|
@@ -144,9 +149,16 @@ class BleInterface extends node_events_1.default {
|
|
|
144
149
|
if (this.isConnecting())
|
|
145
150
|
await this.connectTask?.stop();
|
|
146
151
|
this.emit('disconnect-done');
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
152
|
+
if (connectionLost) {
|
|
153
|
+
this.getBinding()?.removeAllListeners('stateChange');
|
|
154
|
+
this.stateChangeEventHandler = this.stateChangeEventHandler ?? this.onBleStateChange.bind(this);
|
|
155
|
+
this.getBinding()?.on('stateChange', this.stateChangeEventHandler);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
this.getBinding()?.removeAllListeners('stateChange');
|
|
159
|
+
this.stateChangeEventHandler = null;
|
|
160
|
+
}
|
|
161
|
+
this.getBinding()?.on('error', this.onError.bind(this));
|
|
150
162
|
this.logEvent({ message: 'interface disconnected', interface: 'BLE' });
|
|
151
163
|
this.confirmedBleState = 'poweredOff';
|
|
152
164
|
return true;
|
|
@@ -156,7 +168,7 @@ class BleInterface extends node_events_1.default {
|
|
|
156
168
|
}
|
|
157
169
|
this.disconnectTask = new task_js_1.InteruptableTask(performDisconnect(), {
|
|
158
170
|
timeout: this.getConnectTimeout(),
|
|
159
|
-
name: 'BLE
|
|
171
|
+
name: 'BLE disconnect',
|
|
160
172
|
errorOnTimeout: false,
|
|
161
173
|
log: this.logEvent.bind(this),
|
|
162
174
|
});
|
|
@@ -225,13 +237,13 @@ class BleInterface extends node_events_1.default {
|
|
|
225
237
|
this.logEvent({ message: 'pausing logging' });
|
|
226
238
|
this.logDisabled = true;
|
|
227
239
|
try {
|
|
228
|
-
this.getBinding()
|
|
240
|
+
this.getBinding()?.pauseLogging();
|
|
229
241
|
}
|
|
230
242
|
catch { }
|
|
231
243
|
}
|
|
232
244
|
resumeLogging() {
|
|
233
245
|
try {
|
|
234
|
-
this.getBinding()
|
|
246
|
+
this.getBinding()?.resumeLogging();
|
|
235
247
|
}
|
|
236
248
|
catch { }
|
|
237
249
|
this.logDisabled = false;
|
|
@@ -568,27 +580,37 @@ class BleInterface extends node_events_1.default {
|
|
|
568
580
|
addKnownDevice(_settings) {
|
|
569
581
|
}
|
|
570
582
|
async connectBle() {
|
|
571
|
-
this.currentBleState = this.getBinding()
|
|
583
|
+
this.currentBleState = this.getBinding()?.state;
|
|
572
584
|
if (this.currentBleState === 'poweredOn') {
|
|
573
585
|
this.onConnected();
|
|
574
586
|
return true;
|
|
575
587
|
}
|
|
588
|
+
else if (this.currentBleState === 'unauthorized' || this.currentBleState === 'unsupported') {
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
576
591
|
const res = await this.waitForBleConnected();
|
|
577
592
|
return res;
|
|
578
593
|
}
|
|
579
594
|
waitForBleConnected() {
|
|
580
595
|
return new Promise((done) => {
|
|
581
|
-
this.getBinding()
|
|
596
|
+
this.getBinding()?.once('error', (err) => {
|
|
582
597
|
this.logEvent({ message: 'Ble connect result: error', error: err.message });
|
|
583
598
|
return done(false);
|
|
584
599
|
});
|
|
585
|
-
this.
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
600
|
+
this.on('ble-state-change', (state) => {
|
|
601
|
+
try {
|
|
602
|
+
if (state === 'poweredOn') {
|
|
603
|
+
this.onConnected();
|
|
604
|
+
this.removeAllListeners('ble-state-change');
|
|
605
|
+
return done(true);
|
|
606
|
+
}
|
|
607
|
+
if (state === 'unauthorized') {
|
|
608
|
+
this.removeAllListeners('ble-state-change');
|
|
609
|
+
return done(false);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
catch (err) {
|
|
613
|
+
console.log('# BLE waitForBleConnected error', err);
|
|
592
614
|
}
|
|
593
615
|
});
|
|
594
616
|
});
|
|
@@ -599,13 +621,16 @@ class BleInterface extends node_events_1.default {
|
|
|
599
621
|
async onConnected() {
|
|
600
622
|
if (this.isConnected())
|
|
601
623
|
return;
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
624
|
+
try {
|
|
625
|
+
this.confirmedBleState = 'poweredOn';
|
|
626
|
+
this.getBinding()?.removeAllListeners('error');
|
|
627
|
+
this.getBinding()?.on('error', this.onError.bind(this));
|
|
628
|
+
this.logEvent({ message: 'BLE connected' });
|
|
629
|
+
this.startPeripheralScan();
|
|
630
|
+
}
|
|
631
|
+
catch (err) {
|
|
632
|
+
console.log('# BLE onConnected error', err);
|
|
633
|
+
}
|
|
609
634
|
}
|
|
610
635
|
async onDisconnected() {
|
|
611
636
|
if (this.isDisconnecting() || !this.isConnected())
|
|
@@ -616,15 +641,22 @@ class BleInterface extends node_events_1.default {
|
|
|
616
641
|
async onBleStateChange(state) {
|
|
617
642
|
if (state === this.currentBleState)
|
|
618
643
|
return;
|
|
644
|
+
this.logEvent({ message: 'BLE state change', state });
|
|
619
645
|
this.currentBleState = state;
|
|
620
|
-
if (
|
|
621
|
-
this.
|
|
646
|
+
if (this.isConnecting()) {
|
|
647
|
+
this.emit('ble-state-change', state);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
if (state === 'poweredOff' || state === 'unauthorized') {
|
|
651
|
+
if (this.isConnected()) {
|
|
652
|
+
this.onDisconnected();
|
|
653
|
+
}
|
|
622
654
|
}
|
|
623
655
|
else {
|
|
624
656
|
if (this.isDisconnecting()) {
|
|
625
657
|
await this.disconnectTask.getPromise();
|
|
626
658
|
}
|
|
627
|
-
this.
|
|
659
|
+
this.connect();
|
|
628
660
|
}
|
|
629
661
|
}
|
|
630
662
|
getAdapterFactory() {
|
|
@@ -29,7 +29,7 @@ class BlePeripheral {
|
|
|
29
29
|
return this.announcement.serviceUUIDs.map(s => (0, utils_js_1.beautifyUUID)(s));
|
|
30
30
|
}
|
|
31
31
|
getDiscoveredServices() {
|
|
32
|
-
return this.discoveredServiceUUIds;
|
|
32
|
+
return this.discoveredServiceUUIds ?? [];
|
|
33
33
|
}
|
|
34
34
|
getInfo() {
|
|
35
35
|
return {
|
|
@@ -47,17 +47,24 @@ class BlePeripheral {
|
|
|
47
47
|
this.connectPromise = new Promise((done) => {
|
|
48
48
|
const peripheral = this.getPeripheral();
|
|
49
49
|
this.connected = false;
|
|
50
|
+
if (!peripheral?.id)
|
|
51
|
+
return done();
|
|
52
|
+
const peripheralId = peripheral.id;
|
|
50
53
|
this.ble.unregisterConnected(peripheral.id);
|
|
51
54
|
if (!this.ble.isConnected()) {
|
|
52
55
|
return done();
|
|
53
56
|
}
|
|
54
57
|
this.logEvent({ message: 'connect peripheral', address: peripheral.address });
|
|
55
58
|
peripheral.connectAsync().then(() => {
|
|
56
|
-
this.ble.registerConnected(this,
|
|
59
|
+
this.ble.registerConnected(this, peripheralId);
|
|
57
60
|
peripheral.once('disconnect', () => { this.onPeripheralDisconnect(); });
|
|
58
61
|
peripheral.on('error', this.onErrorHandler);
|
|
59
62
|
this.connected = true;
|
|
60
63
|
done();
|
|
64
|
+
})
|
|
65
|
+
.catch(() => {
|
|
66
|
+
this.connected = false;
|
|
67
|
+
done();
|
|
61
68
|
});
|
|
62
69
|
});
|
|
63
70
|
await this.connectPromise;
|
|
@@ -66,10 +73,9 @@ class BlePeripheral {
|
|
|
66
73
|
}
|
|
67
74
|
async disconnect(connectionLost = false) {
|
|
68
75
|
this.disconnecting = true;
|
|
69
|
-
if (
|
|
70
|
-
|
|
76
|
+
if (this.isConnected()) {
|
|
77
|
+
await this.unsubscribeAll(connectionLost);
|
|
71
78
|
}
|
|
72
|
-
await this.unsubscribeAll(connectionLost);
|
|
73
79
|
Object.keys(this.characteristics).forEach(uuid => {
|
|
74
80
|
const c = this.characteristics[uuid];
|
|
75
81
|
c.removeAllListeners();
|
|
@@ -85,7 +91,8 @@ class BlePeripheral {
|
|
|
85
91
|
return new Promise((done) => { this.getPeripheral().disconnect(() => { done(); }); });
|
|
86
92
|
};
|
|
87
93
|
}
|
|
88
|
-
await this.getPeripheral().disconnectAsync()
|
|
94
|
+
await this.getPeripheral().disconnectAsync()
|
|
95
|
+
.catch(() => { });
|
|
89
96
|
}
|
|
90
97
|
peripheral.removeAllListeners();
|
|
91
98
|
}
|
|
@@ -113,6 +120,7 @@ class BlePeripheral {
|
|
|
113
120
|
if (this.disconnectedSignalled || this.disconnecting)
|
|
114
121
|
return;
|
|
115
122
|
this.disconnectedSignalled = true;
|
|
123
|
+
this.getPeripheral().removeAllListeners();
|
|
116
124
|
this.ble.resumeLogging();
|
|
117
125
|
this.logEvent({ message: 'peripheral disconnected', address: this.getPeripheral()?.address });
|
|
118
126
|
try {
|
|
@@ -131,14 +139,21 @@ class BlePeripheral {
|
|
|
131
139
|
return [];
|
|
132
140
|
if (this.getPeripheral().discoverServicesAsync) {
|
|
133
141
|
this.logEvent({ message: 'discover services', address: this.getPeripheral().address });
|
|
134
|
-
const
|
|
142
|
+
const peripheral = this.getPeripheral();
|
|
143
|
+
let services = [];
|
|
144
|
+
if (peripheral?.discoverServicesAsync) {
|
|
145
|
+
services = await peripheral.discoverServicesAsync([])
|
|
146
|
+
.catch(() => []);
|
|
147
|
+
}
|
|
135
148
|
this.discoveredServiceUUIds = services.map(s => (0, utils_js_1.beautifyUUID)(s.uuid));
|
|
149
|
+
this.logEvent({ message: 'discover services result', address: this.getPeripheral().address, services: this.discoveredServiceUUIds });
|
|
136
150
|
return services.map(s => s.uuid);
|
|
137
151
|
}
|
|
138
152
|
else {
|
|
139
153
|
this.logEvent({ message: 'discover services and characteristics', address: this.getPeripheral().address });
|
|
140
154
|
const res = await this.getPeripheral().discoverSomeServicesAndCharacteristicsAsync([], []);
|
|
141
155
|
this.discoveredServiceUUIds = res.services.map(s => (0, utils_js_1.beautifyUUID)(s.uuid));
|
|
156
|
+
this.logEvent({ message: 'discover services result', address: this.getPeripheral().address, services: this.discoveredServiceUUIds });
|
|
142
157
|
return res.services.map(s => s.uuid);
|
|
143
158
|
}
|
|
144
159
|
}
|
|
@@ -146,7 +161,8 @@ class BlePeripheral {
|
|
|
146
161
|
if (!this.getPeripheral())
|
|
147
162
|
return [];
|
|
148
163
|
this.logEvent({ message: 'discover services and characteristics', service: serviceUUID, address: this.getPeripheral().address });
|
|
149
|
-
const res = await this.getPeripheral().discoverSomeServicesAndCharacteristicsAsync([serviceUUID], [])
|
|
164
|
+
const res = await this.getPeripheral().discoverSomeServicesAndCharacteristicsAsync([serviceUUID], [])
|
|
165
|
+
.catch(() => ({ services: [], characteristics: [] }));
|
|
150
166
|
res.characteristics.forEach(c => this.characteristics[(0, utils_js_1.beautifyUUID)(c.uuid)] = c);
|
|
151
167
|
return res.characteristics.map(c => {
|
|
152
168
|
const { uuid, properties, name, _serviceUuid } = c;
|
|
@@ -173,7 +189,7 @@ class BlePeripheral {
|
|
|
173
189
|
}
|
|
174
190
|
return true;
|
|
175
191
|
}
|
|
176
|
-
let c = await this.queryRawCharacteristic(characteristicUUID);
|
|
192
|
+
let c = await this.queryRawCharacteristic(characteristicUUID).catch(() => null);
|
|
177
193
|
if (!c) {
|
|
178
194
|
return false;
|
|
179
195
|
}
|
|
@@ -9,7 +9,9 @@ class TBleSensor extends node_events_1.EventEmitter {
|
|
|
9
9
|
peripheral;
|
|
10
10
|
static protocol;
|
|
11
11
|
logger;
|
|
12
|
-
stopRequested;
|
|
12
|
+
stopRequested = false;
|
|
13
|
+
subscribeSuccess = false;
|
|
14
|
+
reconnectPromise;
|
|
13
15
|
onDataHandler;
|
|
14
16
|
logEvent(event, ...args) {
|
|
15
17
|
this.logger.logEvent(event, ...args);
|
|
@@ -82,39 +84,65 @@ class TBleSensor extends node_events_1.EventEmitter {
|
|
|
82
84
|
async subscribe() {
|
|
83
85
|
const selected = this.getRequiredCharacteristics();
|
|
84
86
|
if (selected === null) {
|
|
85
|
-
const res = await this.peripheral.subscribeAll(this.onDataHandler);
|
|
87
|
+
const res = this.peripheral?.subscribeAll ? await this.peripheral.subscribeAll(this.onDataHandler) : false;
|
|
88
|
+
this.subscribeSuccess = res;
|
|
86
89
|
return res;
|
|
87
90
|
}
|
|
88
91
|
if (selected.length === 0) {
|
|
92
|
+
this.subscribeSuccess = true;
|
|
89
93
|
return true;
|
|
90
94
|
}
|
|
91
95
|
const res = await this.peripheral.subscribeSelected(selected, this.onDataHandler);
|
|
96
|
+
this.subscribeSuccess = res;
|
|
92
97
|
return res;
|
|
93
98
|
}
|
|
94
99
|
async stopSensor() {
|
|
100
|
+
this.onDisconnect();
|
|
95
101
|
this.removeAllListeners();
|
|
96
102
|
if (!this.peripheral)
|
|
97
103
|
return true;
|
|
98
104
|
this.stopRequested = true;
|
|
99
105
|
return await this.peripheral.disconnect();
|
|
100
106
|
}
|
|
107
|
+
isReconnectBusy() {
|
|
108
|
+
return (this.reconnectPromise !== undefined);
|
|
109
|
+
}
|
|
101
110
|
async reconnectSensor() {
|
|
111
|
+
if (this.reconnectPromise !== undefined) {
|
|
112
|
+
return await this.reconnectPromise;
|
|
113
|
+
}
|
|
114
|
+
this.reconnectPromise = this.doReconnectSensor();
|
|
115
|
+
const res = await this.reconnectPromise;
|
|
116
|
+
delete this.reconnectPromise;
|
|
117
|
+
return res;
|
|
118
|
+
}
|
|
119
|
+
async doReconnectSensor() {
|
|
120
|
+
this.onDisconnect();
|
|
102
121
|
this.logEvent({ message: 'reconnect sensor' });
|
|
103
122
|
let connected = false;
|
|
104
123
|
let subscribed = false;
|
|
105
124
|
let success = false;
|
|
125
|
+
await (0, utils_js_1.sleep)(500);
|
|
106
126
|
do {
|
|
107
|
-
|
|
108
|
-
|
|
127
|
+
try {
|
|
128
|
+
if (!connected) {
|
|
129
|
+
connected = await this.startSensor(true);
|
|
130
|
+
}
|
|
131
|
+
if (connected && !subscribed) {
|
|
132
|
+
subscribed = await this.subscribe();
|
|
133
|
+
}
|
|
109
134
|
}
|
|
110
|
-
|
|
111
|
-
subscribed = await this.subscribe();
|
|
135
|
+
catch {
|
|
112
136
|
}
|
|
113
137
|
success = connected && subscribed;
|
|
114
138
|
if (!success) {
|
|
115
139
|
await (0, utils_js_1.sleep)(1000);
|
|
116
140
|
}
|
|
141
|
+
if (!this.stopRequested)
|
|
142
|
+
this.logEvent({ message: 'reconnect sensor retry' });
|
|
117
143
|
} while (!success || this.stopRequested);
|
|
144
|
+
this.logEvent({ message: 'reconnect sensor completed', success, stopRequested: this.stopRequested });
|
|
145
|
+
return success;
|
|
118
146
|
}
|
|
119
147
|
reset() {
|
|
120
148
|
throw new Error("Method not implemented.");
|
|
@@ -122,6 +150,12 @@ class TBleSensor extends node_events_1.EventEmitter {
|
|
|
122
150
|
isConnected() {
|
|
123
151
|
return this.peripheral?.isConnected();
|
|
124
152
|
}
|
|
153
|
+
isSubscribed() {
|
|
154
|
+
return this.subscribeSuccess;
|
|
155
|
+
}
|
|
156
|
+
onDisconnect() {
|
|
157
|
+
this.subscribeSuccess = false;
|
|
158
|
+
}
|
|
125
159
|
read(characteristicUUID) {
|
|
126
160
|
if (!this.isConnected()) {
|
|
127
161
|
return Promise.reject(new Error('not connected'));
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.BleLinuxBinding = void 0;
|
|
7
|
-
const events_1 =
|
|
8
|
-
class BleLinuxBinding extends events_1.
|
|
4
|
+
const events_1 = require("events");
|
|
5
|
+
class BleLinuxBinding extends events_1.EventEmitter {
|
|
9
6
|
static _instance;
|
|
10
7
|
_bindings;
|
|
11
8
|
state;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const events_1 =
|
|
3
|
+
const events_1 = require("events");
|
|
7
4
|
const utils_js_1 = require("../../utils/utils.js");
|
|
8
|
-
class Binding extends events_1.
|
|
5
|
+
class Binding extends events_1.EventEmitter {
|
|
9
6
|
static _instance;
|
|
10
7
|
_bindings;
|
|
11
8
|
state;
|
|
@@ -64,7 +61,7 @@ class Binding extends events_1.default {
|
|
|
64
61
|
callback();
|
|
65
62
|
}
|
|
66
63
|
}
|
|
67
|
-
class MockPeripheral extends events_1.
|
|
64
|
+
class MockPeripheral extends events_1.EventEmitter {
|
|
68
65
|
id;
|
|
69
66
|
address;
|
|
70
67
|
name;
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.StaticNotifyCharacteristic = exports.StaticWriteCharacteristic = exports.StaticReadCharacteristic = exports.MockCharacteristic = exports.RESULT_UNLIKELY_ERROR = exports.RESULT_INVALID_ATTRIBUTE_LENGTH = exports.RESULT_ATTR_NOT_LONG = exports.RESULT_INVALID_OFFSET = exports.RESULT_SUCCESS = void 0;
|
|
7
|
-
const node_events_1 =
|
|
4
|
+
const node_events_1 = require("node:events");
|
|
8
5
|
exports.RESULT_SUCCESS = 0x00;
|
|
9
6
|
exports.RESULT_INVALID_OFFSET = 0x07;
|
|
10
7
|
exports.RESULT_ATTR_NOT_LONG = 0x0b;
|
|
11
8
|
exports.RESULT_INVALID_ATTRIBUTE_LENGTH = 0x0d;
|
|
12
9
|
exports.RESULT_UNLIKELY_ERROR = 0x0e;
|
|
13
|
-
class MockCharacteristic extends node_events_1.
|
|
10
|
+
class MockCharacteristic extends node_events_1.EventEmitter {
|
|
14
11
|
uuid;
|
|
15
12
|
properties;
|
|
16
13
|
secure;
|
package/lib/cjs/ble/fm/sensor.js
CHANGED
|
@@ -76,10 +76,15 @@ class BleFitnessMachineDevice extends sensor_js_1.TBleSensor {
|
|
|
76
76
|
getCw() { return this.cw; }
|
|
77
77
|
setWindSpeed(windSpeed) { this.windSpeed = windSpeed; }
|
|
78
78
|
getWindSpeed() { return this.windSpeed; }
|
|
79
|
+
onDisconnect() {
|
|
80
|
+
this.hasControl = false;
|
|
81
|
+
}
|
|
79
82
|
async requestControl() {
|
|
80
83
|
if (this.hasControl) {
|
|
81
84
|
return true;
|
|
82
85
|
}
|
|
86
|
+
if (!this.isSubscribed())
|
|
87
|
+
return false;
|
|
83
88
|
if (this.features?.setPower === false && this.features?.setSlope === false && this.features?.setResistance === false) {
|
|
84
89
|
return true;
|
|
85
90
|
}
|
|
@@ -98,6 +103,8 @@ class BleFitnessMachineDevice extends sensor_js_1.TBleSensor {
|
|
|
98
103
|
return this.hasControl;
|
|
99
104
|
}
|
|
100
105
|
async setTargetPower(power) {
|
|
106
|
+
if (!this.isSubscribed())
|
|
107
|
+
return false;
|
|
101
108
|
this.logEvent({ message: 'setTargetPower', device: this.getName(), power, skip: (this.data.targetPower !== undefined && this.data.targetPower === power) });
|
|
102
109
|
if (this.data.targetPower !== undefined && this.data.targetPower === power)
|
|
103
110
|
return true;
|
|
@@ -116,6 +123,8 @@ class BleFitnessMachineDevice extends sensor_js_1.TBleSensor {
|
|
|
116
123
|
return (res === 1);
|
|
117
124
|
}
|
|
118
125
|
async setTargetResistanceLevel(resistanceLevel) {
|
|
126
|
+
if (!this.isSubscribed())
|
|
127
|
+
return false;
|
|
119
128
|
this.logEvent({ message: 'setTargetResistanceLevel', device: this.getName(), resistanceLevel, skip: (this.data.resistanceLevel !== undefined && this.data.resistanceLevel === resistanceLevel) });
|
|
120
129
|
if (this.data.resistanceLevel !== undefined && this.data.resistanceLevel === resistanceLevel)
|
|
121
130
|
return true;
|
|
@@ -136,6 +145,8 @@ class BleFitnessMachineDevice extends sensor_js_1.TBleSensor {
|
|
|
136
145
|
return (res === 1);
|
|
137
146
|
}
|
|
138
147
|
async setSlope(slope) {
|
|
148
|
+
if (!this.isSubscribed())
|
|
149
|
+
return false;
|
|
139
150
|
this.logEvent({ message: 'setSlope', device: this.getName(), slope });
|
|
140
151
|
const { windSpeed, crr, cw } = this;
|
|
141
152
|
return await this.setIndoorBikeSimulation(windSpeed, slope, crr, cw);
|