incyclist-devices 2.1.0 → 2.1.2
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/adapters.d.ts +1 -1
- package/lib/antv2/adapter-factory.d.ts +4 -15
- package/lib/antv2/adapter.d.ts +15 -15
- package/lib/antv2/adapter.js +67 -21
- package/lib/antv2/ant-interface.d.ts +3 -11
- package/lib/antv2/ant-interface.js +1 -1
- package/lib/antv2/base/adapter.d.ts +69 -0
- package/lib/antv2/base/adapter.js +439 -0
- package/lib/antv2/base/ant-interface.d.ts +35 -0
- package/lib/antv2/base/ant-interface.js +285 -0
- package/lib/antv2/base/binding.d.ts +13 -0
- package/lib/antv2/base/binding.js +27 -0
- package/lib/antv2/base/interface.d.ts +46 -0
- package/lib/antv2/base/interface.js +337 -0
- package/lib/antv2/cad/adapter.d.ts +10 -0
- package/lib/antv2/cad/adapter.js +25 -0
- package/lib/antv2/cad/index.d.ts +2 -0
- package/lib/antv2/cad/index.js +7 -0
- package/lib/antv2/consts.d.ts +2 -0
- package/lib/antv2/consts.js +5 -0
- package/lib/antv2/factories/adapter-factory.d.ts +14 -0
- package/lib/antv2/factories/adapter-factory.js +73 -0
- package/lib/antv2/factories/sensor-factory.d.ts +5 -0
- package/lib/antv2/factories/sensor-factory.js +22 -0
- package/lib/antv2/fe/adapter.d.ts +21 -30
- package/lib/antv2/fe/adapter.js +139 -251
- package/lib/antv2/hr/adapter.d.ts +6 -15
- package/lib/antv2/hr/adapter.js +7 -55
- package/lib/antv2/hr copy/adapter.d.ts +11 -0
- package/lib/antv2/hr copy/adapter.js +30 -0
- package/lib/antv2/hr copy/index.d.ts +2 -0
- package/lib/antv2/hr copy/index.js +7 -0
- package/lib/antv2/index.d.ts +5 -4
- package/lib/antv2/index.js +5 -3
- package/lib/antv2/pwr/adapter.d.ts +9 -33
- package/lib/antv2/pwr/adapter.js +19 -140
- package/lib/antv2/types.d.ts +32 -4
- package/lib/base/adpater.d.ts +39 -60
- package/lib/base/adpater.js +139 -161
- package/lib/base/consts.d.ts +4 -0
- package/lib/base/consts.js +9 -0
- package/lib/ble/adapter-factory.d.ts +10 -11
- package/lib/ble/base/adapter.d.ts +7 -14
- package/lib/ble/base/adapter.js +2 -36
- package/lib/ble/ble-interface.d.ts +5 -7
- package/lib/ble/cp/adapter.d.ts +6 -8
- package/lib/ble/cp/adapter.js +8 -27
- package/lib/ble/elite/adapter.d.ts +7 -8
- package/lib/ble/elite/adapter.js +5 -25
- package/lib/ble/fm/adapter.d.ts +6 -7
- package/lib/ble/fm/adapter.js +13 -34
- package/lib/ble/hr/adapter.d.ts +5 -8
- package/lib/ble/hr/adapter.js +2 -2
- package/lib/ble/peripheral-cache.d.ts +2 -3
- package/lib/ble/tacx/adapter.d.ts +2 -3
- package/lib/ble/tacx/adapter.js +8 -8
- package/lib/ble/types.d.ts +1 -2
- package/lib/ble/wahoo/adapter.d.ts +2 -2
- package/lib/ble/wahoo/adapter.js +6 -6
- package/lib/ble/wahoo/comms.js +16 -16
- package/lib/factories/adapters.d.ts +7 -0
- package/lib/factories/adapters.js +49 -0
- package/lib/factories/index.d.ts +3 -0
- package/lib/factories/index.js +10 -0
- package/lib/factories/interfaces.d.ts +7 -0
- package/lib/factories/interfaces.js +27 -0
- package/lib/index.d.ts +5 -6
- package/lib/index.js +4 -9
- package/lib/interfaces.d.ts +1 -1
- package/lib/modes/ant-fe-adv-st-mode.d.ts +1 -1
- package/lib/modes/antble-erg.d.ts +1 -1
- package/lib/modes/antble-smarttrainer.d.ts +2 -2
- package/lib/modes/base.d.ts +5 -5
- package/lib/modes/daum-classic-standard.d.ts +3 -2
- package/lib/modes/daum-erg.d.ts +3 -3
- package/lib/modes/daum-premium-standard.d.ts +3 -2
- package/lib/modes/daum-smarttrainer.d.ts +3 -2
- package/lib/modes/kettler-erg.d.ts +3 -3
- package/lib/modes/power-base.d.ts +3 -3
- package/lib/modes/power-base.js +2 -2
- package/lib/modes/power-meter.d.ts +3 -2
- package/lib/modes/simulator.d.ts +2 -1
- package/lib/modes/types.d.ts +2 -13
- package/lib/serial/SinglePathScanner.d.ts +17 -0
- package/lib/serial/SinglePathScanner.js +87 -0
- package/lib/serial/adapter-factory.d.ts +6 -6
- package/lib/serial/adapter.d.ts +6 -11
- package/lib/serial/base/adapter.d.ts +17 -0
- package/lib/serial/base/adapter.js +67 -0
- package/lib/serial/base/comms.d.ts +62 -0
- package/lib/serial/base/comms.js +280 -0
- package/lib/serial/base/serial-interface.d.ts +36 -0
- package/lib/serial/base/serial-interface.js +288 -0
- package/lib/serial/base/serial-scanner.d.ts +16 -0
- package/lib/serial/base/serial-scanner.js +87 -0
- package/lib/serial/base/serialport.d.ts +17 -0
- package/lib/serial/base/serialport.js +87 -0
- package/lib/serial/comms.d.ts +2 -2
- package/lib/serial/daum/DaumAdapter.d.ts +12 -24
- package/lib/serial/daum/DaumAdapter.js +40 -59
- package/lib/serial/daum/classic/PROTOCOL_NAME.d.ts +2 -0
- package/lib/serial/daum/classic/PROTOCOL_NAME.js +5 -0
- package/lib/serial/daum/classic/adapter.d.ts +8 -20
- package/lib/serial/daum/classic/adapter.js +28 -58
- package/lib/serial/daum/classic/comms.d.ts +4 -6
- package/lib/serial/daum/classic/comms.js +2 -2
- package/lib/serial/daum/classic/consts.d.ts +2 -0
- package/lib/serial/daum/classic/consts.js +5 -0
- package/lib/serial/daum/classic/mock.js +5 -4
- package/lib/serial/daum/classic/types.d.ts +8 -10
- package/lib/serial/daum/classic/utils.d.ts +1 -2
- package/lib/serial/daum/consts.d.ts +0 -19
- package/lib/serial/daum/consts.js +0 -22
- package/lib/serial/daum/premium/adapter.d.ts +8 -11
- package/lib/serial/daum/premium/adapter.js +27 -53
- package/lib/serial/daum/premium/comms.d.ts +4 -7
- package/lib/serial/daum/premium/comms.js +23 -22
- package/lib/serial/daum/premium/mock.d.ts +1 -1
- package/lib/serial/daum/premium/mock.js +2 -2
- package/lib/serial/daum/premium/types.d.ts +32 -17
- package/lib/serial/daum/premium/types.js +8 -8
- package/lib/serial/daum/premium/utils.d.ts +2 -3
- package/lib/serial/daum/premium/utils.js +3 -3
- package/lib/serial/daum/types.d.ts +4 -1
- package/lib/serial/daum/types.js +9 -1
- package/lib/serial/factories/adapter-factory.d.ts +14 -0
- package/lib/serial/factories/adapter-factory.js +30 -0
- package/lib/serial/index.d.ts +8 -5
- package/lib/serial/index.js +15 -15
- package/lib/serial/kettler/comms.d.ts +1 -1
- package/lib/serial/kettler/ergo-racer/adapter.d.ts +11 -18
- package/lib/serial/kettler/ergo-racer/adapter.js +9 -21
- package/lib/serial/kettler/types.d.ts +8 -0
- package/lib/serial/kettler/types.js +2 -0
- package/lib/serial/serial-interface.d.ts +2 -32
- package/lib/serial/serial-interface.js +3 -76
- package/lib/serial/serial-scanner.d.ts +16 -0
- package/lib/serial/serial-scanner.js +87 -0
- package/lib/serial/serialport.d.ts +1 -13
- package/lib/serial/types.d.ts +45 -0
- package/lib/serial/types.js +9 -0
- package/lib/simulator/Simulator.d.ts +10 -13
- package/lib/simulator/Simulator.js +11 -23
- package/lib/types/Command.d.ts +8 -0
- package/lib/types/Command.js +2 -0
- package/lib/types/adapter.d.ts +22 -33
- package/lib/types/adapter.js +0 -68
- package/lib/types/command.d.ts +0 -8
- package/lib/types/command.js +0 -2
- package/lib/types/data.d.ts +12 -1
- package/lib/types/device.d.ts +8 -23
- package/lib/types/device.js +9 -8
- package/lib/types/index.d.ts +6 -0
- package/lib/types/index.js +22 -0
- package/lib/types/route.d.ts +0 -19
- package/lib/types/route.js +0 -2
- package/lib/types/types.d.ts +8 -0
- package/lib/types/types.js +2 -0
- package/lib/utils/utils.d.ts +2 -0
- package/lib/utils/utils.js +39 -4
- package/package.json +1 -1
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const gd_eventlog_1 = require("gd-eventlog");
|
|
13
|
+
const utils_1 = require("../daum/premium/utils");
|
|
14
|
+
const utils_2 = require("../../utils/utils");
|
|
15
|
+
const DEFAULT_BUSY_TIMEOUT = 5000;
|
|
16
|
+
class SerialPortComms {
|
|
17
|
+
constructor(props) {
|
|
18
|
+
this.props = props;
|
|
19
|
+
const { logger, serial, path } = props;
|
|
20
|
+
this.serial = serial;
|
|
21
|
+
this.path = this.validatePath(path);
|
|
22
|
+
const w = global.window;
|
|
23
|
+
this.logger = logger || ((w === null || w === void 0 ? void 0 : w.DEVICE_DEBUG) || process.env.DEBUG ? utils_1.DEBUG_LOGGER : new gd_eventlog_1.EventLogger(this.getDefaultLoggerName()));
|
|
24
|
+
this.resetState();
|
|
25
|
+
}
|
|
26
|
+
getBusyTimeout() {
|
|
27
|
+
return DEFAULT_BUSY_TIMEOUT;
|
|
28
|
+
}
|
|
29
|
+
getDefaultLoggerName() {
|
|
30
|
+
return 'Serial';
|
|
31
|
+
}
|
|
32
|
+
getInitialCommsState() {
|
|
33
|
+
return { data: new utils_2.Queue() };
|
|
34
|
+
}
|
|
35
|
+
validatePath(path) {
|
|
36
|
+
return path;
|
|
37
|
+
}
|
|
38
|
+
getInterface() {
|
|
39
|
+
var _a;
|
|
40
|
+
return (_a = this.serial) === null || _a === void 0 ? void 0 : _a.ifaceName;
|
|
41
|
+
}
|
|
42
|
+
getPort() {
|
|
43
|
+
return this.path;
|
|
44
|
+
}
|
|
45
|
+
isConnected() {
|
|
46
|
+
return this.connectState === 'Connected' || this.connectState === 'Disconnecting';
|
|
47
|
+
}
|
|
48
|
+
pauseLogging() {
|
|
49
|
+
this.isLoggingPaused = true;
|
|
50
|
+
}
|
|
51
|
+
resumeLogging() {
|
|
52
|
+
this.isLoggingPaused = false;
|
|
53
|
+
}
|
|
54
|
+
logEvent(e) {
|
|
55
|
+
if (this.isLoggingPaused)
|
|
56
|
+
return;
|
|
57
|
+
this.logger.logEvent(e);
|
|
58
|
+
const w = global.window;
|
|
59
|
+
if (w === null || w === void 0 ? void 0 : w.DEVICE_DEBUG) {
|
|
60
|
+
console.log(`~~~ ${this.getDefaultLoggerName()}`, e);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
connect() {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
if (this.isConnected() && this.sp) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
if (this.connectState === 'Connecting') {
|
|
69
|
+
if (this.connectPromise) {
|
|
70
|
+
try {
|
|
71
|
+
yield this.connectPromise;
|
|
72
|
+
}
|
|
73
|
+
catch (_a) {
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return this.isConnected();
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
this.connectState = 'Connecting';
|
|
80
|
+
this.connectPromise = this.serial.openPort(this.path);
|
|
81
|
+
const port = yield this.connectPromise;
|
|
82
|
+
this.connectPromise = null;
|
|
83
|
+
if (port !== null) {
|
|
84
|
+
this.connectState = 'Connected';
|
|
85
|
+
this.sp = port;
|
|
86
|
+
this.sp.on('close', this.onPortClose.bind(this));
|
|
87
|
+
this.sp.on('error', this.onPortError.bind(this));
|
|
88
|
+
this.onConnected();
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
this.connectState = 'Disconnected';
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (_b) {
|
|
97
|
+
this.connectState = 'Disconnected';
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
onConnected() {
|
|
103
|
+
}
|
|
104
|
+
portFlush() {
|
|
105
|
+
if (this.sp)
|
|
106
|
+
this.sp.flush();
|
|
107
|
+
}
|
|
108
|
+
portPipe(destination, options) {
|
|
109
|
+
if (this.sp)
|
|
110
|
+
return this.sp.pipe(destination, options);
|
|
111
|
+
}
|
|
112
|
+
portUnpipe(destination) {
|
|
113
|
+
if (this.sp)
|
|
114
|
+
this.sp.unpipe(destination);
|
|
115
|
+
}
|
|
116
|
+
closePort() {
|
|
117
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
118
|
+
if (!this.sp)
|
|
119
|
+
return true;
|
|
120
|
+
try {
|
|
121
|
+
yield this.flush();
|
|
122
|
+
yield this.serial.closePort(this.path);
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
this.logEvent({ message: 'could not close ', reason: err.message });
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
resetState(isDisconnected = true) {
|
|
132
|
+
this.isLoggingPaused = false;
|
|
133
|
+
this.recvState = this.getInitialCommsState();
|
|
134
|
+
this.connectPromise = null;
|
|
135
|
+
this.disconnectPromise = null;
|
|
136
|
+
this.writePromise = null;
|
|
137
|
+
this.sendCmdPromise = null;
|
|
138
|
+
if (isDisconnected)
|
|
139
|
+
this.connectState = 'Disconnected';
|
|
140
|
+
}
|
|
141
|
+
cleanupPort(isDisconnected = true) {
|
|
142
|
+
if (this.sp) {
|
|
143
|
+
this.sp.removeAllListeners();
|
|
144
|
+
}
|
|
145
|
+
this.sp = null;
|
|
146
|
+
this.resetState(isDisconnected);
|
|
147
|
+
}
|
|
148
|
+
close() {
|
|
149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
let isDisconnected = false;
|
|
151
|
+
if (this.disconnectPromise) {
|
|
152
|
+
try {
|
|
153
|
+
isDisconnected = yield this.disconnectPromise;
|
|
154
|
+
}
|
|
155
|
+
catch (_a) {
|
|
156
|
+
}
|
|
157
|
+
return isDisconnected;
|
|
158
|
+
}
|
|
159
|
+
if (this.connectState === 'Disconnected') {
|
|
160
|
+
this.cleanupPort();
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
else if (this.connectState === 'Disconnecting' || this.connectState === 'Connected' || this.connectState === 'Connecting') {
|
|
164
|
+
this.connectState = 'Disconnecting';
|
|
165
|
+
this.disconnectPromise = this.closePort();
|
|
166
|
+
isDisconnected = yield this.disconnectPromise;
|
|
167
|
+
if (isDisconnected) {
|
|
168
|
+
this.connectState = 'Disconnected';
|
|
169
|
+
this.logEvent({ message: "port closed:", port: this.path });
|
|
170
|
+
}
|
|
171
|
+
this.cleanupPort(isDisconnected);
|
|
172
|
+
}
|
|
173
|
+
return isDisconnected;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
flush() {
|
|
177
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
+
if (this.writePromise) {
|
|
179
|
+
yield (0, utils_2.waitWithTimeout)(this.writePromise, 1000);
|
|
180
|
+
this.writePromise = null;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
onPortClose() {
|
|
185
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
186
|
+
if (this.connectState !== 'Disconnected' && this.connectState !== 'Disconnecting')
|
|
187
|
+
this.logEvent({ message: "port closed:", port: this.path });
|
|
188
|
+
this.connectState = 'Disconnected';
|
|
189
|
+
this.cleanupPort();
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
onPortError(error) {
|
|
193
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
194
|
+
if (this.connectState === 'Disconnecting' || this.connectState === 'Disconnected') {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
this.logEvent({ message: "port error:", port: this.path, error: error.message, connected: this.isConnected(), state: this.connectState });
|
|
198
|
+
if (this.isSending()) {
|
|
199
|
+
this.rejectCurrent(error);
|
|
200
|
+
}
|
|
201
|
+
if (this.connectState === 'Connected')
|
|
202
|
+
this.close();
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
isSending() {
|
|
206
|
+
return (this.writePromise !== undefined && this.writePromise !== null) || (this.sendCmdPromise !== null && this.sendCmdPromise !== undefined);
|
|
207
|
+
}
|
|
208
|
+
rejectCurrent(error) {
|
|
209
|
+
this.recvState.data.enqueue({ type: 'Error', error });
|
|
210
|
+
}
|
|
211
|
+
getTimeoutValue() {
|
|
212
|
+
throw new Error('method not implemented');
|
|
213
|
+
}
|
|
214
|
+
onData(data, depth = 0) {
|
|
215
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
send(command) {
|
|
219
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
220
|
+
throw new Error('method not implemented');
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
portWrite(buffer) {
|
|
224
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
225
|
+
if (!this.sp) {
|
|
226
|
+
this.logEvent({ message: 'write failed', error: 'port is not opened' });
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
try {
|
|
230
|
+
yield this.sp.write(buffer);
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
this.logEvent({ message: 'write failed', error: err.message });
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
write(buffer) {
|
|
238
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
239
|
+
if (this.writePromise) {
|
|
240
|
+
try {
|
|
241
|
+
yield this.writePromise;
|
|
242
|
+
}
|
|
243
|
+
catch (_a) {
|
|
244
|
+
}
|
|
245
|
+
this.writePromise = null;
|
|
246
|
+
}
|
|
247
|
+
this.writePromise = this.portWrite(buffer);
|
|
248
|
+
yield this.writePromise;
|
|
249
|
+
this.writePromise = null;
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
ensurePrevCmdFinish(logPayload) {
|
|
253
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
254
|
+
if (this.sendCmdPromise) {
|
|
255
|
+
const tsRequest = Date.now();
|
|
256
|
+
this.logEvent(Object.assign({ message: 'sendCommand:waiting:' }, logPayload));
|
|
257
|
+
let busyTimedOut = false;
|
|
258
|
+
const onTimeout = () => {
|
|
259
|
+
this.logEvent(Object.assign(Object.assign({ message: 'sendCommand:error:' }, logPayload), { error: 'BUSY timeout', duration: Date.now() - tsRequest }));
|
|
260
|
+
busyTimedOut = true;
|
|
261
|
+
};
|
|
262
|
+
yield (0, utils_2.waitWithTimeout)(this.sendCmdPromise, this.getBusyTimeout(), onTimeout);
|
|
263
|
+
this.sendCmdPromise = null;
|
|
264
|
+
if (busyTimedOut)
|
|
265
|
+
throw new Error('BUSY timeout');
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
ensureConnection() {
|
|
270
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
271
|
+
if (!this.isConnected()) {
|
|
272
|
+
const connected = yield this.connect();
|
|
273
|
+
if (!connected) {
|
|
274
|
+
throw new Error('not connected');
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
exports.default = SerialPortComms;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import EventEmitter from "events";
|
|
4
|
+
import { BindingInterface } from "@serialport/bindings-interface";
|
|
5
|
+
import { SerialPortStream } from '@serialport/stream';
|
|
6
|
+
import { SerialDeviceSettings, SerialScannerProps, PortMapping, SerialInterfaceProps } from "../types";
|
|
7
|
+
import { IncyclistInterface } from "../../types";
|
|
8
|
+
import { EventLogger } from "gd-eventlog";
|
|
9
|
+
export default class SerialInterface extends EventEmitter implements IncyclistInterface {
|
|
10
|
+
ifaceName: string;
|
|
11
|
+
binding: BindingInterface;
|
|
12
|
+
ports: PortMapping[];
|
|
13
|
+
isScanning: boolean;
|
|
14
|
+
isStopScanRequested: boolean;
|
|
15
|
+
scanEvents: EventEmitter;
|
|
16
|
+
logger: EventLogger;
|
|
17
|
+
toScan: NodeJS.Timeout;
|
|
18
|
+
connected: boolean;
|
|
19
|
+
inUse: string[];
|
|
20
|
+
static _instances: SerialInterface[];
|
|
21
|
+
static getInstance(props: SerialInterfaceProps): SerialInterface;
|
|
22
|
+
static _add(instance: SerialInterface): void;
|
|
23
|
+
constructor(props: SerialInterfaceProps);
|
|
24
|
+
logEvent(event: any): void;
|
|
25
|
+
setBinding(binding: BindingInterface): void;
|
|
26
|
+
getName(): string;
|
|
27
|
+
isConnected(): boolean;
|
|
28
|
+
setInUse(path: string): void;
|
|
29
|
+
releaseInUse(path: string): void;
|
|
30
|
+
connect(): Promise<boolean>;
|
|
31
|
+
disconnect(): Promise<boolean>;
|
|
32
|
+
openPort(path: string): Promise<SerialPortStream | null>;
|
|
33
|
+
closePort(path: string): Promise<Boolean>;
|
|
34
|
+
scan(props: SerialScannerProps): Promise<SerialDeviceSettings[]>;
|
|
35
|
+
stopScan(): Promise<boolean>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const events_1 = __importDefault(require("events"));
|
|
16
|
+
const serialport_1 = __importDefault(require("./serialport"));
|
|
17
|
+
const gd_eventlog_1 = require("gd-eventlog");
|
|
18
|
+
const utils_1 = require("../../utils/utils");
|
|
19
|
+
const adapter_factory_1 = __importDefault(require("../factories/adapter-factory"));
|
|
20
|
+
const serial_scanner_1 = require("./serial-scanner");
|
|
21
|
+
const DEFAULT_SCAN_TIMEOUT = 10000;
|
|
22
|
+
class SerialInterface extends events_1.default {
|
|
23
|
+
static getInstance(props) {
|
|
24
|
+
const { ifaceName, binding, logger } = props;
|
|
25
|
+
let instance = SerialInterface._instances.find(i => i.ifaceName === ifaceName);
|
|
26
|
+
if (!instance) {
|
|
27
|
+
if (binding)
|
|
28
|
+
instance = new SerialInterface(props);
|
|
29
|
+
else {
|
|
30
|
+
instance = new SerialInterface({ ifaceName, binding: serialport_1.default.getInstance().getBinding(ifaceName), logger });
|
|
31
|
+
if (instance)
|
|
32
|
+
SerialInterface._instances.push(instance);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return instance;
|
|
36
|
+
}
|
|
37
|
+
static _add(instance) {
|
|
38
|
+
let existingIdx = SerialInterface._instances.findIndex(i => i.ifaceName === instance.ifaceName);
|
|
39
|
+
if (existingIdx !== -1)
|
|
40
|
+
SerialInterface._instances[existingIdx] = instance;
|
|
41
|
+
else
|
|
42
|
+
SerialInterface._instances.push(instance);
|
|
43
|
+
}
|
|
44
|
+
constructor(props) {
|
|
45
|
+
super();
|
|
46
|
+
const { ifaceName, binding } = props;
|
|
47
|
+
this.ifaceName = ifaceName;
|
|
48
|
+
this.binding = undefined;
|
|
49
|
+
this.ports = [];
|
|
50
|
+
this.inUse = [];
|
|
51
|
+
this.isScanning = false;
|
|
52
|
+
this.isStopScanRequested = false;
|
|
53
|
+
this.scanEvents = new events_1.default();
|
|
54
|
+
this.scanEvents.setMaxListeners(100);
|
|
55
|
+
this.logger = props.logger || new gd_eventlog_1.EventLogger(`Serial:${ifaceName}`);
|
|
56
|
+
this.connected = false;
|
|
57
|
+
this.logEvent({ message: 'new serial interface', ifaceName });
|
|
58
|
+
if (binding) {
|
|
59
|
+
this.setBinding(binding);
|
|
60
|
+
}
|
|
61
|
+
SerialInterface._add(this);
|
|
62
|
+
}
|
|
63
|
+
logEvent(event) {
|
|
64
|
+
if (this.logger) {
|
|
65
|
+
this.logger.logEvent(event);
|
|
66
|
+
}
|
|
67
|
+
const w = global.window;
|
|
68
|
+
if ((w === null || w === void 0 ? void 0 : w.DEVICE_DEBUG) || process.env.SERIAL_DEBUG || process.env.ANT_DEBUG || process.env.BLE_DEBUG) {
|
|
69
|
+
console.log('~~~ Serial', event);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
setBinding(binding) {
|
|
73
|
+
this.binding = binding;
|
|
74
|
+
serialport_1.default.getInstance().setBinding(this.ifaceName, binding);
|
|
75
|
+
}
|
|
76
|
+
getName() {
|
|
77
|
+
return this.ifaceName;
|
|
78
|
+
}
|
|
79
|
+
isConnected() {
|
|
80
|
+
return this.connected;
|
|
81
|
+
}
|
|
82
|
+
setInUse(path) {
|
|
83
|
+
this.logEvent({ message: 'block port for further scans', port: path });
|
|
84
|
+
if (!this.inUse.includes(path))
|
|
85
|
+
this.inUse.push(path);
|
|
86
|
+
}
|
|
87
|
+
releaseInUse(path) {
|
|
88
|
+
if (this.inUse.includes(path)) {
|
|
89
|
+
this.logEvent({ message: 're-enable port for further scans', port: path });
|
|
90
|
+
const idx = this.inUse.findIndex(r => r === path);
|
|
91
|
+
this.inUse.splice(idx, 1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
connect() {
|
|
95
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
this.logEvent({ message: 'connecting', interface: this.ifaceName });
|
|
97
|
+
const binding = serialport_1.default.getInstance().getBinding(this.ifaceName);
|
|
98
|
+
if (!binding || !this.binding) {
|
|
99
|
+
this.connected = false;
|
|
100
|
+
this.logEvent({ message: 'connecting error', interface: this.ifaceName, reason: 'no binfing found' });
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const SerialPort = this.binding;
|
|
105
|
+
yield SerialPort.list();
|
|
106
|
+
this.connected = true;
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
this.logEvent({ message: 'connecting error', interface: this.ifaceName, reason: err.message });
|
|
111
|
+
this.connected = false;
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
disconnect() {
|
|
117
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
118
|
+
this.connected = false;
|
|
119
|
+
return true;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
openPort(path) {
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
this.logEvent({ message: 'opening port', port: path });
|
|
125
|
+
const existing = this.ports.findIndex(p => p.path === path);
|
|
126
|
+
if (existing !== -1) {
|
|
127
|
+
const port = this.ports[existing].port;
|
|
128
|
+
if (port.isOpen) {
|
|
129
|
+
this.logEvent({ message: 'opening port - port already exists', port: path });
|
|
130
|
+
return port;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
this.ports.splice(existing, 1);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const port = serialport_1.default.getInstance().getSerialPort(this.ifaceName, { path });
|
|
137
|
+
if (!port) {
|
|
138
|
+
this.logEvent({ message: 'opening port - port does not exist', port: path });
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
return new Promise((resolve) => {
|
|
142
|
+
port.once('error', (err) => {
|
|
143
|
+
this.logEvent({ message: 'error', path, error: err.message || err, stack: err.stack });
|
|
144
|
+
port.removeAllListeners();
|
|
145
|
+
resolve(null);
|
|
146
|
+
});
|
|
147
|
+
port.once('open', () => {
|
|
148
|
+
this.logEvent({ message: 'port opened', path });
|
|
149
|
+
port.removeAllListeners();
|
|
150
|
+
this.ports.push({ path, port });
|
|
151
|
+
resolve(port);
|
|
152
|
+
});
|
|
153
|
+
port.open();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
closePort(path) {
|
|
158
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
159
|
+
this.logEvent({ message: 'closing port', port: path });
|
|
160
|
+
const existing = this.ports.findIndex(p => p.path === path);
|
|
161
|
+
if (existing === -1)
|
|
162
|
+
return true;
|
|
163
|
+
const port = this.ports[existing].port;
|
|
164
|
+
if (!port.isOpen)
|
|
165
|
+
return true;
|
|
166
|
+
port.on('error', () => { });
|
|
167
|
+
try {
|
|
168
|
+
port.flush();
|
|
169
|
+
yield port.drain();
|
|
170
|
+
}
|
|
171
|
+
catch (_a) { }
|
|
172
|
+
return new Promise(resolve => {
|
|
173
|
+
port.close(err => {
|
|
174
|
+
if (!err) {
|
|
175
|
+
this.ports.splice(existing, 1);
|
|
176
|
+
port.removeAllListeners();
|
|
177
|
+
resolve(true);
|
|
178
|
+
}
|
|
179
|
+
resolve(false);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
scan(props) {
|
|
185
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
186
|
+
if (this.isScanning)
|
|
187
|
+
return [];
|
|
188
|
+
if (!this.isConnected())
|
|
189
|
+
yield this.connect();
|
|
190
|
+
const binding = serialport_1.default.getInstance().getBinding(this.ifaceName);
|
|
191
|
+
if (!binding || !this.binding)
|
|
192
|
+
return [];
|
|
193
|
+
const { port, timeout = DEFAULT_SCAN_TIMEOUT } = props;
|
|
194
|
+
let paths;
|
|
195
|
+
const detected = [];
|
|
196
|
+
let timeOutExpired = false;
|
|
197
|
+
let toExpiresAt = Date.now() + timeout;
|
|
198
|
+
if (timeout) {
|
|
199
|
+
this.toScan = setTimeout(() => {
|
|
200
|
+
timeOutExpired = true;
|
|
201
|
+
this.scanEvents.emit('timeout');
|
|
202
|
+
}, timeout);
|
|
203
|
+
}
|
|
204
|
+
this.isScanning = true;
|
|
205
|
+
let attemptNo = 0;
|
|
206
|
+
const isTcpip = this.getName() === 'tcpip';
|
|
207
|
+
do {
|
|
208
|
+
if (attemptNo === 0)
|
|
209
|
+
this.logEvent({ message: 'checking for ports', interface: this.ifaceName, port, excludes: this.inUse });
|
|
210
|
+
else
|
|
211
|
+
this.logEvent({ message: 'checking for ports retry', interface: this.ifaceName, retry: attemptNo });
|
|
212
|
+
attemptNo++;
|
|
213
|
+
try {
|
|
214
|
+
if (isTcpip) {
|
|
215
|
+
const _binding = binding;
|
|
216
|
+
paths = (yield _binding.list(port, this.inUse)) || [];
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
paths = (yield binding.list()) || [];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
this.logEvent({ message: 'error', fn: 'scan#detect ports', error: err.message, interface: this.ifaceName, port, excludes: this.inUse });
|
|
224
|
+
}
|
|
225
|
+
paths = paths.filter(p => !this.inUse.includes(p.path));
|
|
226
|
+
if (!paths || paths.length === 0) {
|
|
227
|
+
this.logEvent({ message: 'scanning: no ports detected', interface: this.ifaceName, paths: paths.map(p => p.path), timeout });
|
|
228
|
+
yield (0, utils_1.sleep)(1000);
|
|
229
|
+
}
|
|
230
|
+
if (Date.now() > toExpiresAt)
|
|
231
|
+
timeOutExpired = true;
|
|
232
|
+
} while (this.isScanning && !timeOutExpired && paths.length === 0);
|
|
233
|
+
if (paths.length === 0) {
|
|
234
|
+
this.logEvent({ message: 'nothing to scan ' });
|
|
235
|
+
if (this.toScan) {
|
|
236
|
+
clearTimeout(this.toScan);
|
|
237
|
+
this.toScan = null;
|
|
238
|
+
}
|
|
239
|
+
return [];
|
|
240
|
+
}
|
|
241
|
+
this.logEvent({ message: 'scanning on ', interface: this.ifaceName, paths: paths.map(p => p.path).join(','), timeout });
|
|
242
|
+
const scanners = paths.map(p => new serial_scanner_1.SinglePathScanner(p.path, this, Object.assign(Object.assign({}, props), { logger: this.logger })));
|
|
243
|
+
try {
|
|
244
|
+
yield Promise.all(scanners.map(s => s.scan()
|
|
245
|
+
.then((device) => __awaiter(this, void 0, void 0, function* () {
|
|
246
|
+
if (device) {
|
|
247
|
+
const adapter = adapter_factory_1.default.getInstance().createInstance(device);
|
|
248
|
+
const path = adapter.getPort();
|
|
249
|
+
this.inUse.push(path);
|
|
250
|
+
yield adapter.pause();
|
|
251
|
+
detected.push(device);
|
|
252
|
+
this.emit('device', device);
|
|
253
|
+
}
|
|
254
|
+
}))
|
|
255
|
+
.catch()));
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
this.logEvent({ message: 'error', fn: 'scan()', error: err.message || err, stack: err.stack });
|
|
259
|
+
}
|
|
260
|
+
if (this.toScan) {
|
|
261
|
+
clearTimeout(this.toScan);
|
|
262
|
+
this.toScan = null;
|
|
263
|
+
}
|
|
264
|
+
this.isScanning = false;
|
|
265
|
+
this.logEvent({ message: 'scan finished on', interface: this.ifaceName, paths: paths.map(p => p.path), devices: detected.map(d => {
|
|
266
|
+
const res = Object.assign({}, d);
|
|
267
|
+
res.interface = this.ifaceName;
|
|
268
|
+
return res;
|
|
269
|
+
}) });
|
|
270
|
+
return detected;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
stopScan() {
|
|
274
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
275
|
+
if (!this.isScanning)
|
|
276
|
+
return true;
|
|
277
|
+
if (this.toScan) {
|
|
278
|
+
clearTimeout(this.toScan);
|
|
279
|
+
this.toScan = null;
|
|
280
|
+
}
|
|
281
|
+
this.isScanning = false;
|
|
282
|
+
this.scanEvents.emit('stop');
|
|
283
|
+
return true;
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
SerialInterface._instances = [];
|
|
288
|
+
exports.default = SerialInterface;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EventLogger } from "gd-eventlog";
|
|
2
|
+
import SerialInterface from "./serial-interface";
|
|
3
|
+
import { SerialDeviceSettings, SerialScannerProps } from "../types";
|
|
4
|
+
export declare class SinglePathScanner {
|
|
5
|
+
path: string;
|
|
6
|
+
serial: SerialInterface;
|
|
7
|
+
result: SerialDeviceSettings;
|
|
8
|
+
isScanning: boolean;
|
|
9
|
+
props: SerialScannerProps;
|
|
10
|
+
logger: EventLogger;
|
|
11
|
+
isFound: boolean;
|
|
12
|
+
constructor(path: string, serial: SerialInterface, props: SerialScannerProps);
|
|
13
|
+
logEvent(event: any): void;
|
|
14
|
+
onStopRequest(resolve: any): Promise<void>;
|
|
15
|
+
scan(): Promise<SerialDeviceSettings | undefined>;
|
|
16
|
+
}
|