tauri-plugin-serialplugin-api 2.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.spdx +20 -0
- package/README.md +1678 -0
- package/dist-js/auto-reconnect-manager.d.ts +69 -0
- package/dist-js/index.cjs +1114 -0
- package/dist-js/index.d.ts +372 -0
- package/dist-js/index.js +1112 -0
- package/dist-js/listener-manager.d.ts +34 -0
- package/package.json +55 -0
|
@@ -0,0 +1,1114 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@tauri-apps/api/core');
|
|
4
|
+
var event = require('@tauri-apps/api/event');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Auto-reconnect manager for serial ports
|
|
8
|
+
* Handles automatic reconnection logic with configurable settings
|
|
9
|
+
*/
|
|
10
|
+
class AutoReconnectManager {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.enabled = false;
|
|
13
|
+
this.interval = 5000; // 5 seconds default
|
|
14
|
+
this.maxAttempts = 10; // 10 attempts default, null for infinite
|
|
15
|
+
this.currentAttempts = 0;
|
|
16
|
+
this.timer = null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* @description Enables auto-reconnect functionality
|
|
20
|
+
* @param {Object} options Auto-reconnect configuration options
|
|
21
|
+
* @param {number} [options.interval=5000] Reconnection interval in milliseconds
|
|
22
|
+
* @param {number | null} [options.maxAttempts=10] Maximum number of reconnection attempts (null for infinite)
|
|
23
|
+
* @param {Function} [options.onReconnect] Callback function called on each reconnection attempt
|
|
24
|
+
* @param {Function} options.reconnectFunction Function that performs the actual reconnection
|
|
25
|
+
* @returns {Promise<void>} A promise that resolves when auto-reconnect is enabled
|
|
26
|
+
*/
|
|
27
|
+
async enable(options) {
|
|
28
|
+
if (this.enabled) {
|
|
29
|
+
console.warn('Auto-reconnect is already enabled');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
this.enabled = true;
|
|
33
|
+
this.interval = options.interval || 5000;
|
|
34
|
+
this.maxAttempts = options.maxAttempts === undefined ? 10 : options.maxAttempts;
|
|
35
|
+
this.currentAttempts = 0;
|
|
36
|
+
this.callback = options.onReconnect;
|
|
37
|
+
this.reconnectFunction = options.reconnectFunction;
|
|
38
|
+
console.log(`Auto-reconnect enabled: interval=${this.interval}ms, maxAttempts=${this.maxAttempts === null ? 'infinite' : this.maxAttempts}`);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* @description Disables auto-reconnect functionality
|
|
42
|
+
* @returns {Promise<void>} A promise that resolves when auto-reconnect is disabled
|
|
43
|
+
*/
|
|
44
|
+
async disable() {
|
|
45
|
+
if (!this.enabled) {
|
|
46
|
+
console.warn('Auto-reconnect is not enabled');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.enabled = false;
|
|
50
|
+
this.currentAttempts = 0;
|
|
51
|
+
this.callback = undefined;
|
|
52
|
+
this.reconnectFunction = undefined;
|
|
53
|
+
// Clear any pending reconnect timer
|
|
54
|
+
if (this.timer) {
|
|
55
|
+
clearTimeout(this.timer);
|
|
56
|
+
this.timer = null;
|
|
57
|
+
}
|
|
58
|
+
console.log('Auto-reconnect disabled');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* @description Gets auto-reconnect status and configuration
|
|
62
|
+
* @returns {Object} Auto-reconnect information
|
|
63
|
+
*/
|
|
64
|
+
getInfo() {
|
|
65
|
+
return {
|
|
66
|
+
enabled: this.enabled,
|
|
67
|
+
interval: this.interval,
|
|
68
|
+
maxAttempts: this.maxAttempts,
|
|
69
|
+
currentAttempts: this.currentAttempts,
|
|
70
|
+
hasCallback: !!this.callback
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* @description Starts the auto-reconnect process
|
|
75
|
+
* @returns {Promise<void>} A promise that resolves when auto-reconnect process starts
|
|
76
|
+
*/
|
|
77
|
+
async start() {
|
|
78
|
+
if (!this.enabled || !this.reconnectFunction) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this.currentAttempts = 0;
|
|
82
|
+
await this.performAttempt();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* @description Stops the auto-reconnect process (clears timer but keeps enabled)
|
|
86
|
+
* @returns {Promise<void>} A promise that resolves when auto-reconnect process stops
|
|
87
|
+
*/
|
|
88
|
+
async stop() {
|
|
89
|
+
if (this.timer) {
|
|
90
|
+
clearTimeout(this.timer);
|
|
91
|
+
this.timer = null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* @description Resets the attempt counter
|
|
96
|
+
* @returns {Promise<void>} A promise that resolves when counter is reset
|
|
97
|
+
*/
|
|
98
|
+
async reset() {
|
|
99
|
+
this.currentAttempts = 0;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* @description Internal method to perform a single reconnection attempt
|
|
103
|
+
* @returns {Promise<void>} A promise that resolves when the attempt is complete
|
|
104
|
+
*/
|
|
105
|
+
async performAttempt() {
|
|
106
|
+
if (!this.enabled || !this.reconnectFunction) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// Проверяем лимит ДО увеличения счётчика
|
|
110
|
+
if (this.maxAttempts !== null && this.currentAttempts >= this.maxAttempts) {
|
|
111
|
+
console.error(`Auto-reconnect failed after ${this.maxAttempts} attempts`);
|
|
112
|
+
if (this.callback) {
|
|
113
|
+
this.callback(false, this.currentAttempts);
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.currentAttempts++;
|
|
118
|
+
console.log(`Auto-reconnect attempt ${this.currentAttempts}${this.maxAttempts !== null ? `/${this.maxAttempts}` : ''}`);
|
|
119
|
+
try {
|
|
120
|
+
const success = await this.reconnectFunction();
|
|
121
|
+
if (success) {
|
|
122
|
+
console.log('Auto-reconnect successful');
|
|
123
|
+
this.currentAttempts = 0; // Reset counter on success
|
|
124
|
+
if (this.callback) {
|
|
125
|
+
this.callback(true, this.currentAttempts);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
throw new Error('Reconnect function returned false');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
console.error(`Auto-reconnect attempt ${this.currentAttempts} failed:`, error);
|
|
134
|
+
if (this.callback) {
|
|
135
|
+
this.callback(false, this.currentAttempts);
|
|
136
|
+
}
|
|
137
|
+
// Schedule next attempt
|
|
138
|
+
if (this.enabled) {
|
|
139
|
+
this.timer = setTimeout(() => {
|
|
140
|
+
this.performAttempt();
|
|
141
|
+
}, this.interval);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
isEnabled() {
|
|
146
|
+
return this.enabled;
|
|
147
|
+
}
|
|
148
|
+
getInterval() {
|
|
149
|
+
return this.interval;
|
|
150
|
+
}
|
|
151
|
+
getMaxAttempts() {
|
|
152
|
+
return this.maxAttempts;
|
|
153
|
+
}
|
|
154
|
+
getCurrentAttempts() {
|
|
155
|
+
return this.currentAttempts;
|
|
156
|
+
}
|
|
157
|
+
hasCallback() {
|
|
158
|
+
return !!this.callback;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
class ListenerManager {
|
|
163
|
+
constructor() {
|
|
164
|
+
this.listeners = new Map();
|
|
165
|
+
this.listenerIdCounter = 0;
|
|
166
|
+
}
|
|
167
|
+
add(type, unlisten) {
|
|
168
|
+
const id = `${type}_${++this.listenerIdCounter}`;
|
|
169
|
+
this.listeners.set(id, { unlisten, type });
|
|
170
|
+
return () => {
|
|
171
|
+
try {
|
|
172
|
+
this.delete(id);
|
|
173
|
+
if (typeof unlisten === 'function') {
|
|
174
|
+
unlisten();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
console.warn(`Error in unlisten function for ${id}:`, error);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
set(id, listener) {
|
|
183
|
+
this.listeners.set(id, listener);
|
|
184
|
+
return () => {
|
|
185
|
+
try {
|
|
186
|
+
this.delete(id);
|
|
187
|
+
if (typeof listener.unlisten === 'function') {
|
|
188
|
+
listener.unlisten();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
console.warn(`Error in unlisten function for ${id}:`, error);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
delete(id) {
|
|
197
|
+
this.listeners.delete(id);
|
|
198
|
+
}
|
|
199
|
+
entries() {
|
|
200
|
+
return this.listeners.entries();
|
|
201
|
+
}
|
|
202
|
+
filterByType(type) {
|
|
203
|
+
return Array.from(this.listeners.entries()).filter(([_, l]) => l.type === type);
|
|
204
|
+
}
|
|
205
|
+
all() {
|
|
206
|
+
return Array.from(this.listeners.entries());
|
|
207
|
+
}
|
|
208
|
+
clear() {
|
|
209
|
+
this.listeners.clear();
|
|
210
|
+
}
|
|
211
|
+
getInfo() {
|
|
212
|
+
const all = this.all();
|
|
213
|
+
const data = all.filter(([_, l]) => l.type === 'data');
|
|
214
|
+
const disconnect = all.filter(([_, l]) => l.type === 'disconnect');
|
|
215
|
+
return {
|
|
216
|
+
total: all.length,
|
|
217
|
+
data: data.length,
|
|
218
|
+
disconnect: disconnect.length,
|
|
219
|
+
ids: all.map(([id]) => id)
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
get(id) {
|
|
223
|
+
return this.listeners.get(id);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
exports.DataBits = void 0;
|
|
228
|
+
(function (DataBits) {
|
|
229
|
+
DataBits["Five"] = "Five";
|
|
230
|
+
DataBits["Six"] = "Six";
|
|
231
|
+
DataBits["Seven"] = "Seven";
|
|
232
|
+
DataBits["Eight"] = "Eight";
|
|
233
|
+
})(exports.DataBits || (exports.DataBits = {}));
|
|
234
|
+
exports.FlowControl = void 0;
|
|
235
|
+
(function (FlowControl) {
|
|
236
|
+
FlowControl["None"] = "None";
|
|
237
|
+
FlowControl["Software"] = "Software";
|
|
238
|
+
FlowControl["Hardware"] = "Hardware";
|
|
239
|
+
})(exports.FlowControl || (exports.FlowControl = {}));
|
|
240
|
+
exports.Parity = void 0;
|
|
241
|
+
(function (Parity) {
|
|
242
|
+
Parity["None"] = "None";
|
|
243
|
+
Parity["Odd"] = "Odd";
|
|
244
|
+
Parity["Even"] = "Even";
|
|
245
|
+
})(exports.Parity || (exports.Parity = {}));
|
|
246
|
+
exports.StopBits = void 0;
|
|
247
|
+
(function (StopBits) {
|
|
248
|
+
StopBits["One"] = "One";
|
|
249
|
+
StopBits["Two"] = "Two";
|
|
250
|
+
})(exports.StopBits || (exports.StopBits = {}));
|
|
251
|
+
exports.ClearBuffer = void 0;
|
|
252
|
+
(function (ClearBuffer) {
|
|
253
|
+
ClearBuffer["Input"] = "Input";
|
|
254
|
+
ClearBuffer["Output"] = "Output";
|
|
255
|
+
ClearBuffer["All"] = "All";
|
|
256
|
+
})(exports.ClearBuffer || (exports.ClearBuffer = {}));
|
|
257
|
+
class SerialPort {
|
|
258
|
+
constructor(options) {
|
|
259
|
+
this.listeners = new ListenerManager();
|
|
260
|
+
this.autoReconnectManager = new AutoReconnectManager();
|
|
261
|
+
this.isOpen = false;
|
|
262
|
+
this.encoding = options.encoding || 'utf-8';
|
|
263
|
+
this.options = {
|
|
264
|
+
path: options.path,
|
|
265
|
+
baudRate: options.baudRate,
|
|
266
|
+
dataBits: options.dataBits || exports.DataBits.Eight,
|
|
267
|
+
flowControl: options.flowControl || exports.FlowControl.None,
|
|
268
|
+
parity: options.parity || exports.Parity.None,
|
|
269
|
+
stopBits: options.stopBits || exports.StopBits.One,
|
|
270
|
+
size: options.size || 1024,
|
|
271
|
+
timeout: options.timeout || 200,
|
|
272
|
+
};
|
|
273
|
+
this.size = options.size || 1024;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* @description Lists all available serial ports
|
|
277
|
+
* @returns {Promise<{ [key: string]: PortInfo }>} A promise that resolves to a map of port names to port information
|
|
278
|
+
*/
|
|
279
|
+
static async available_ports() {
|
|
280
|
+
try {
|
|
281
|
+
const result = await core.invoke('plugin:serialplugin|available_ports');
|
|
282
|
+
return Promise.resolve(result);
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
return Promise.reject(error);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* @description Lists all available serial ports using platform-specific commands
|
|
290
|
+
* @returns {Promise<{ [key: string]: PortInfo }>} A promise that resolves to a map of port names to port information
|
|
291
|
+
*/
|
|
292
|
+
static async available_ports_direct() {
|
|
293
|
+
try {
|
|
294
|
+
const result = await core.invoke('plugin:serialplugin|available_ports_direct');
|
|
295
|
+
return Promise.resolve(result);
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
return Promise.reject(error);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* @description Lists all managed serial ports (ports that are currently open and managed by the application).
|
|
303
|
+
* @returns {Promise<string[]>} A promise that resolves to an array of port paths (names).
|
|
304
|
+
*/
|
|
305
|
+
static async managed_ports() {
|
|
306
|
+
try {
|
|
307
|
+
const result = await core.invoke('plugin:serialplugin|managed_ports');
|
|
308
|
+
return Promise.resolve(result);
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
return Promise.reject(error);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* @description Forcefully closes a specific serial port
|
|
316
|
+
* @param {string} path The path of the serial port to close
|
|
317
|
+
* @returns {Promise<void>} A promise that resolves when the port is closed
|
|
318
|
+
*/
|
|
319
|
+
static async forceClose(path) {
|
|
320
|
+
return await core.invoke('plugin:serialplugin|force_close', { path });
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* @description Closes all open serial ports
|
|
324
|
+
* @returns {Promise<void>} A promise that resolves when all ports are closed
|
|
325
|
+
*/
|
|
326
|
+
static async closeAll() {
|
|
327
|
+
return await core.invoke('plugin:serialplugin|close_all');
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* @description Gets the full serial number for a specific port
|
|
331
|
+
* On Windows, this can fix truncated serial numbers (e.g., "B4" → "B4:3D:4D:B1:5A:C8" for ESP32 devices)
|
|
332
|
+
* @param {string} path The port path (e.g., "COM3", "/dev/ttyUSB0")
|
|
333
|
+
* @returns {Promise<string>} A promise that resolves to the full serial number, or "Unknown" if not found
|
|
334
|
+
*/
|
|
335
|
+
static async get_full_serial_number(path) {
|
|
336
|
+
try {
|
|
337
|
+
const result = await core.invoke('plugin:serialplugin|get_full_serial_number', { path });
|
|
338
|
+
return Promise.resolve(result);
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
return Promise.reject(error);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* @description Cancels listening for serial port data (does not affect disconnect listeners)
|
|
346
|
+
* @returns {Promise<void>} A promise that resolves when listening is cancelled
|
|
347
|
+
*/
|
|
348
|
+
async cancelListen() {
|
|
349
|
+
try {
|
|
350
|
+
// Cancel only data listeners - disconnect listeners remain active
|
|
351
|
+
const dataListeners = this.listeners.filterByType('data');
|
|
352
|
+
for (const [id, listener] of dataListeners) {
|
|
353
|
+
try {
|
|
354
|
+
if (typeof listener.unlisten === 'function') {
|
|
355
|
+
listener.unlisten();
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
console.warn(`Error unlistening data listener ${id}:`, error);
|
|
360
|
+
}
|
|
361
|
+
// Remove from map regardless of success/failure
|
|
362
|
+
this.listeners.delete(id);
|
|
363
|
+
}
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
return Promise.reject('Failed to cancel serial monitoring: ' + error);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* @description Cancels all listeners (both data and disconnect listeners)
|
|
372
|
+
* @returns {Promise<void>} A promise that resolves when all listeners are cancelled
|
|
373
|
+
*/
|
|
374
|
+
async cancelAllListeners() {
|
|
375
|
+
try {
|
|
376
|
+
const allListeners = this.listeners.all();
|
|
377
|
+
for (const [id, listener] of allListeners) {
|
|
378
|
+
try {
|
|
379
|
+
if (typeof listener.unlisten === 'function') {
|
|
380
|
+
listener.unlisten();
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
console.warn(`Error unlistening listener ${id}:`, error);
|
|
385
|
+
}
|
|
386
|
+
// Remove from map regardless of success/failure
|
|
387
|
+
this.listeners.delete(id);
|
|
388
|
+
}
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
catch (error) {
|
|
392
|
+
return Promise.reject('Failed to cancel all listeners: ' + error);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* @description Gets information about active listeners (for debugging)
|
|
397
|
+
* @returns {Object} Information about active listeners
|
|
398
|
+
*/
|
|
399
|
+
getListenersInfo() {
|
|
400
|
+
return this.listeners.getInfo();
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* @description Cancels reading data from the serial port
|
|
404
|
+
* @returns {Promise<void>} A promise that resolves when reading is cancelled
|
|
405
|
+
*/
|
|
406
|
+
async cancelRead() {
|
|
407
|
+
try {
|
|
408
|
+
await core.invoke('plugin:serialplugin|cancel_read', {
|
|
409
|
+
path: this.options.path,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
return Promise.reject(error instanceof Error ? error : new Error(String(error)));
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* @description Changes the serial port configuration
|
|
418
|
+
* @param {object} options Configuration options
|
|
419
|
+
* @param {string} [options.path] New port path
|
|
420
|
+
* @param {number} [options.baudRate] New baud rate
|
|
421
|
+
* @returns {Promise<void>} A promise that resolves when configuration is changed
|
|
422
|
+
*/
|
|
423
|
+
async change(options) {
|
|
424
|
+
try {
|
|
425
|
+
let isOpened = false;
|
|
426
|
+
if (this.isOpen) {
|
|
427
|
+
isOpened = true;
|
|
428
|
+
await this.close();
|
|
429
|
+
}
|
|
430
|
+
if (options.path) {
|
|
431
|
+
this.options.path = options.path;
|
|
432
|
+
}
|
|
433
|
+
if (options.baudRate) {
|
|
434
|
+
this.options.baudRate = options.baudRate;
|
|
435
|
+
}
|
|
436
|
+
if (isOpened) {
|
|
437
|
+
await this.open();
|
|
438
|
+
}
|
|
439
|
+
return Promise.resolve();
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
return Promise.reject(error);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* @description Closes the currently open serial port
|
|
447
|
+
* @returns {Promise<void>} A promise that resolves when the port is closed
|
|
448
|
+
*/
|
|
449
|
+
async close() {
|
|
450
|
+
try {
|
|
451
|
+
if (!this.isOpen) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
// Stop auto-reconnect temporarily to prevent conflicts
|
|
455
|
+
const wasAutoReconnectEnabled = this.autoReconnectManager.isEnabled();
|
|
456
|
+
if (wasAutoReconnectEnabled) {
|
|
457
|
+
await this.autoReconnectManager.stop();
|
|
458
|
+
}
|
|
459
|
+
// First we cancel the reading
|
|
460
|
+
try {
|
|
461
|
+
await this.cancelRead();
|
|
462
|
+
}
|
|
463
|
+
catch (cancelReadError) {
|
|
464
|
+
console.warn('Error during cancelRead:', cancelReadError);
|
|
465
|
+
}
|
|
466
|
+
// Closing the port
|
|
467
|
+
let res = undefined;
|
|
468
|
+
try {
|
|
469
|
+
res = await core.invoke('plugin:serialplugin|close', {
|
|
470
|
+
path: this.options.path,
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
catch (closeError) {
|
|
474
|
+
console.warn('Error during port close:', closeError);
|
|
475
|
+
}
|
|
476
|
+
// Cancel all listeners
|
|
477
|
+
try {
|
|
478
|
+
await this.cancelAllListeners();
|
|
479
|
+
}
|
|
480
|
+
catch (cancelListenError) {
|
|
481
|
+
console.warn('Error during cancelAllListeners:', cancelListenError);
|
|
482
|
+
// Try to clear listeners manually as fallback
|
|
483
|
+
try {
|
|
484
|
+
this.listeners.clear();
|
|
485
|
+
}
|
|
486
|
+
catch (clearError) {
|
|
487
|
+
console.warn('Error during manual listener clear:', clearError);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
this.isOpen = false;
|
|
491
|
+
return res;
|
|
492
|
+
}
|
|
493
|
+
catch (error) {
|
|
494
|
+
return Promise.reject(error);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* @description Sets up a listener for port disconnection events
|
|
499
|
+
* @param {Function} fn Callback function to handle disconnection
|
|
500
|
+
* @returns {Promise<void>} A promise that resolves when the listener is set up
|
|
501
|
+
*/
|
|
502
|
+
async disconnected(fn) {
|
|
503
|
+
let sub_path = this.options.path?.toString().replaceAll(".", "-").replaceAll("/", "-");
|
|
504
|
+
let checkEvent = `plugin-serialplugin-disconnected-${sub_path}`;
|
|
505
|
+
console.log('listen event: ' + checkEvent);
|
|
506
|
+
const unListenResult = await event.listen(checkEvent, () => {
|
|
507
|
+
try {
|
|
508
|
+
fn();
|
|
509
|
+
}
|
|
510
|
+
catch (error) {
|
|
511
|
+
console.error(error);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
if (typeof unListenResult === 'function') {
|
|
515
|
+
this.listeners.add('disconnect', unListenResult);
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
console.warn('disconnected() did not return a valid unlisten function');
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* @description Enables auto-reconnect functionality
|
|
523
|
+
* @param {Object} options Auto-reconnect configuration options
|
|
524
|
+
* @param {number} [options.interval=5000] Reconnection interval in milliseconds
|
|
525
|
+
* @param {number | null} [options.maxAttempts=10] Maximum number of reconnection attempts (null for infinite)
|
|
526
|
+
* @param {Function} [options.onReconnect] Callback function called on each reconnection attempt
|
|
527
|
+
* @returns {Promise<void>} A promise that resolves when auto-reconnect is enabled
|
|
528
|
+
*/
|
|
529
|
+
async enableAutoReconnect(options = {}) {
|
|
530
|
+
try {
|
|
531
|
+
await this.autoReconnectManager.enable({
|
|
532
|
+
...options,
|
|
533
|
+
reconnectFunction: async () => {
|
|
534
|
+
if (this.isOpen) {
|
|
535
|
+
return true;
|
|
536
|
+
}
|
|
537
|
+
try {
|
|
538
|
+
await this.open();
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
catch (error) {
|
|
542
|
+
return false;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
// Set up disconnect listener that triggers auto-reconnect
|
|
547
|
+
await this.disconnected(async () => {
|
|
548
|
+
this.isOpen = false;
|
|
549
|
+
if (this.autoReconnectManager.isEnabled()) {
|
|
550
|
+
await this.autoReconnectManager.start();
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
catch (error) {
|
|
555
|
+
return Promise.reject(error);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* @description Disables auto-reconnect functionality
|
|
560
|
+
* @returns {Promise<void>} A promise that resolves when auto-reconnect is disabled
|
|
561
|
+
*/
|
|
562
|
+
async disableAutoReconnect() {
|
|
563
|
+
try {
|
|
564
|
+
await this.autoReconnectManager.disable();
|
|
565
|
+
}
|
|
566
|
+
catch (error) {
|
|
567
|
+
return Promise.reject(error);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* @description Gets auto-reconnect status and configuration
|
|
572
|
+
* @returns {Object} Auto-reconnect information
|
|
573
|
+
*/
|
|
574
|
+
getAutoReconnectInfo() {
|
|
575
|
+
return {
|
|
576
|
+
enabled: this.autoReconnectManager.isEnabled(),
|
|
577
|
+
interval: this.autoReconnectManager.getInterval(),
|
|
578
|
+
maxAttempts: this.autoReconnectManager.getMaxAttempts(),
|
|
579
|
+
currentAttempts: this.autoReconnectManager.getCurrentAttempts(),
|
|
580
|
+
hasCallback: this.autoReconnectManager.hasCallback(),
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* @description Manually triggers a reconnection attempt
|
|
585
|
+
* @returns {Promise<boolean>} A promise that resolves to true if reconnection was successful
|
|
586
|
+
*/
|
|
587
|
+
async manualReconnect() {
|
|
588
|
+
try {
|
|
589
|
+
if (this.isOpen) {
|
|
590
|
+
console.log('Port is already open, no need to reconnect');
|
|
591
|
+
return true;
|
|
592
|
+
}
|
|
593
|
+
console.log('Manual reconnection attempt...');
|
|
594
|
+
await this.open();
|
|
595
|
+
console.log('Manual reconnection successful');
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
598
|
+
catch (error) {
|
|
599
|
+
console.error('Manual reconnection failed:', error);
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* @description Monitors serial port data
|
|
605
|
+
* @param {Function} fn Callback function to handle received data
|
|
606
|
+
* @param {boolean} [isDecode=true] Whether to decode the received data
|
|
607
|
+
* @returns {Promise<UnlistenFn>} A promise that resolves to an unlisten function
|
|
608
|
+
*/
|
|
609
|
+
async listen(fn, isDecode = true) {
|
|
610
|
+
try {
|
|
611
|
+
if (!this.isOpen) {
|
|
612
|
+
return Promise.reject('Port is not open');
|
|
613
|
+
}
|
|
614
|
+
let sub_path = this.options.path?.toString().replaceAll(".", "-").replaceAll("/", "-");
|
|
615
|
+
let readEvent = `plugin-serialplugin-read-${sub_path}`;
|
|
616
|
+
console.log('listen event: ' + readEvent);
|
|
617
|
+
try {
|
|
618
|
+
const unListenResult = await event.listen(readEvent, ({ payload }) => {
|
|
619
|
+
try {
|
|
620
|
+
if (isDecode) {
|
|
621
|
+
const uint8Array = new Uint8Array(payload.data);
|
|
622
|
+
try {
|
|
623
|
+
const decoder = new TextDecoder(this.encoding);
|
|
624
|
+
const textData = decoder.decode(uint8Array);
|
|
625
|
+
fn(textData);
|
|
626
|
+
}
|
|
627
|
+
catch (error) {
|
|
628
|
+
console.error('Error converting to text with configured encoding:', error);
|
|
629
|
+
try {
|
|
630
|
+
const fallbackDecoder = new TextDecoder('utf-8');
|
|
631
|
+
const textData = fallbackDecoder.decode(uint8Array);
|
|
632
|
+
fn(textData);
|
|
633
|
+
}
|
|
634
|
+
catch (fallbackError) {
|
|
635
|
+
console.error('Fallback decoding also failed:', fallbackError);
|
|
636
|
+
fn(String.fromCharCode(...uint8Array));
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
fn(new Uint8Array(payload.data));
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
catch (error) {
|
|
645
|
+
console.error(error);
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
if (typeof unListenResult === 'function') {
|
|
649
|
+
return this.listeners.add('data', unListenResult);
|
|
650
|
+
}
|
|
651
|
+
else {
|
|
652
|
+
console.warn('listen() did not return a valid unlisten function');
|
|
653
|
+
return Promise.reject('Failed to get unlisten function');
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
catch (listenError) {
|
|
657
|
+
console.error('Error setting up listener:', listenError);
|
|
658
|
+
throw listenError;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
catch (error) {
|
|
662
|
+
return Promise.reject('Failed to monitor serial port data: ' + error);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* @description Opens the serial port with current settings
|
|
667
|
+
* @returns {Promise<void>} A promise that resolves when the port is opened
|
|
668
|
+
*/
|
|
669
|
+
async open() {
|
|
670
|
+
try {
|
|
671
|
+
if (!this.options.path) {
|
|
672
|
+
return Promise.reject(`path Can not be empty!`);
|
|
673
|
+
}
|
|
674
|
+
if (!this.options.baudRate) {
|
|
675
|
+
return Promise.reject(`baudRate Can not be empty!`);
|
|
676
|
+
}
|
|
677
|
+
if (this.isOpen) {
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
const res = await core.invoke('plugin:serialplugin|open', {
|
|
681
|
+
path: this.options.path,
|
|
682
|
+
baudRate: this.options.baudRate,
|
|
683
|
+
dataBits: this.options.dataBits,
|
|
684
|
+
flowControl: this.options.flowControl,
|
|
685
|
+
parity: this.options.parity,
|
|
686
|
+
stopBits: this.options.stopBits,
|
|
687
|
+
timeout: this.options.timeout,
|
|
688
|
+
});
|
|
689
|
+
this.isOpen = true;
|
|
690
|
+
this.disconnected(() => {
|
|
691
|
+
this.isOpen = false;
|
|
692
|
+
}).catch(err => console.error(err));
|
|
693
|
+
return Promise.resolve(res);
|
|
694
|
+
}
|
|
695
|
+
catch (error) {
|
|
696
|
+
return Promise.reject(error);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Starts listening for data on the serial port
|
|
701
|
+
* The port will continuously monitor for incoming data and emit events
|
|
702
|
+
* @returns {Promise<void>} A promise that resolves when listening starts
|
|
703
|
+
* @throws {Error} If starting listener fails or port is not open
|
|
704
|
+
* @example
|
|
705
|
+
* const port = new SerialPort({ path: '/dev/ttyUSB0' });
|
|
706
|
+
* await port.startListening();
|
|
707
|
+
* // Listen for data events
|
|
708
|
+
* port.listen((data) => {
|
|
709
|
+
* console.log('listen', data)
|
|
710
|
+
* receivedData += data;
|
|
711
|
+
* });
|
|
712
|
+
*/
|
|
713
|
+
async startListening() {
|
|
714
|
+
try {
|
|
715
|
+
await core.invoke('plugin:serialplugin|start_listening', {
|
|
716
|
+
path: this.options.path,
|
|
717
|
+
size: this.options.size,
|
|
718
|
+
timeout: this.options.timeout,
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
catch (error) {
|
|
722
|
+
return Promise.reject(error);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Stops listening for data on the serial port
|
|
727
|
+
* Cleans up event listeners and monitoring threads
|
|
728
|
+
* @returns {Promise<void>} A promise that resolves when listening stops
|
|
729
|
+
* @throws {Error} If stopping listener fails or port is not open
|
|
730
|
+
* @example
|
|
731
|
+
* await port.stopListening();
|
|
732
|
+
*/
|
|
733
|
+
async stopListening() {
|
|
734
|
+
try {
|
|
735
|
+
await core.invoke('plugin:serialplugin|stop_listening', {
|
|
736
|
+
path: this.options.path,
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
catch (error) {
|
|
740
|
+
return Promise.reject(error);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* @description Reads data from the serial port
|
|
745
|
+
* @param {ReadOptions} [options] Read options
|
|
746
|
+
* @returns {Promise<void>} A promise that resolves when data is read
|
|
747
|
+
*/
|
|
748
|
+
async read(options) {
|
|
749
|
+
try {
|
|
750
|
+
if (!this.isOpen) {
|
|
751
|
+
return Promise.reject('Port is not open');
|
|
752
|
+
}
|
|
753
|
+
return await core.invoke('plugin:serialplugin|read', {
|
|
754
|
+
path: this.options.path,
|
|
755
|
+
timeout: options?.timeout || this.options.timeout,
|
|
756
|
+
size: options?.size || this.size,
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
catch (error) {
|
|
760
|
+
return Promise.reject(error);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* @description Reads binary data from the serial port
|
|
765
|
+
* @param {ReadOptions} [options] Read options
|
|
766
|
+
* @returns {Promise<Uint8Array>} A promise that resolves with binary data
|
|
767
|
+
*/
|
|
768
|
+
async readBinary(options) {
|
|
769
|
+
try {
|
|
770
|
+
const result = await core.invoke('plugin:serialplugin|read_binary', {
|
|
771
|
+
path: this.options.path,
|
|
772
|
+
timeout: options?.timeout || this.options.timeout,
|
|
773
|
+
size: options?.size || this.size,
|
|
774
|
+
});
|
|
775
|
+
return new Uint8Array(result);
|
|
776
|
+
}
|
|
777
|
+
catch (error) {
|
|
778
|
+
return Promise.reject(error);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* @description Sets the baud rate of the serial port
|
|
783
|
+
* @param {number} value The new baud rate
|
|
784
|
+
* @returns {Promise<void>} A promise that resolves when baud rate is set
|
|
785
|
+
*/
|
|
786
|
+
async setBaudRate(value) {
|
|
787
|
+
try {
|
|
788
|
+
return await core.invoke('plugin:serialplugin|set_baud_rate', {
|
|
789
|
+
path: this.options.path,
|
|
790
|
+
baudRate: value
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
catch (error) {
|
|
794
|
+
return Promise.reject(error);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* @description Sets the data bits configuration
|
|
799
|
+
* @param {DataBits} value The new data bits setting
|
|
800
|
+
* @returns {Promise<void>} A promise that resolves when data bits are set
|
|
801
|
+
*/
|
|
802
|
+
async setDataBits(value) {
|
|
803
|
+
try {
|
|
804
|
+
return await core.invoke('plugin:serialplugin|set_data_bits', {
|
|
805
|
+
path: this.options.path,
|
|
806
|
+
dataBits: value
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
catch (error) {
|
|
810
|
+
return Promise.reject(error);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* @description Sets the flow control mode
|
|
815
|
+
* @param {FlowControl} value The new flow control setting
|
|
816
|
+
* @returns {Promise<void>} A promise that resolves when flow control is set
|
|
817
|
+
*/
|
|
818
|
+
async setFlowControl(value) {
|
|
819
|
+
try {
|
|
820
|
+
return await core.invoke('plugin:serialplugin|set_flow_control', {
|
|
821
|
+
path: this.options.path,
|
|
822
|
+
flowControl: value
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
catch (error) {
|
|
826
|
+
return Promise.reject(error);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* @description Sets the parity checking mode
|
|
831
|
+
* @param {Parity} value The new parity setting
|
|
832
|
+
* @returns {Promise<void>} A promise that resolves when parity is set
|
|
833
|
+
*/
|
|
834
|
+
async setParity(value) {
|
|
835
|
+
try {
|
|
836
|
+
return await core.invoke('plugin:serialplugin|set_parity', {
|
|
837
|
+
path: this.options.path,
|
|
838
|
+
parity: value
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
catch (error) {
|
|
842
|
+
return Promise.reject(error);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* @description Sets the number of stop bits
|
|
847
|
+
* @param {StopBits} value The new stop bits setting
|
|
848
|
+
* @returns {Promise<void>} A promise that resolves when stop bits are set
|
|
849
|
+
*/
|
|
850
|
+
async setStopBits(value) {
|
|
851
|
+
try {
|
|
852
|
+
return await core.invoke('plugin:serialplugin|set_stop_bits', {
|
|
853
|
+
path: this.options.path,
|
|
854
|
+
stopBits: value
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
catch (error) {
|
|
858
|
+
return Promise.reject(error);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* @description Sets the timeout duration
|
|
863
|
+
* @param {number} value The new timeout in milliseconds
|
|
864
|
+
* @returns {Promise<void>} A promise that resolves when timeout is set
|
|
865
|
+
*/
|
|
866
|
+
async setTimeout(value) {
|
|
867
|
+
try {
|
|
868
|
+
return await core.invoke('plugin:serialplugin|set_timeout', {
|
|
869
|
+
path: this.options.path,
|
|
870
|
+
timeout: value
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
catch (error) {
|
|
874
|
+
return Promise.reject(error);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* @description Sets the RTS (Request To Send) control signal
|
|
879
|
+
* @param {boolean} value The signal level to set
|
|
880
|
+
* @returns {Promise<void>} A promise that resolves when RTS is set
|
|
881
|
+
*/
|
|
882
|
+
async setRequestToSend(value) {
|
|
883
|
+
try {
|
|
884
|
+
return await core.invoke('plugin:serialplugin|write_request_to_send', {
|
|
885
|
+
path: this.options.path,
|
|
886
|
+
level: value
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
catch (error) {
|
|
890
|
+
return Promise.reject(error);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* @description Sets the DTR (Data Terminal Ready) control signal
|
|
895
|
+
* @param {boolean} value The signal level to set
|
|
896
|
+
* @returns {Promise<void>} A promise that resolves when DTR is set
|
|
897
|
+
*/
|
|
898
|
+
async setDataTerminalReady(value) {
|
|
899
|
+
try {
|
|
900
|
+
return await core.invoke('plugin:serialplugin|write_data_terminal_ready', {
|
|
901
|
+
path: this.options.path,
|
|
902
|
+
level: value
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
catch (error) {
|
|
906
|
+
return Promise.reject(error);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
/**
|
|
910
|
+
* @description Writes the RTS (Request To Send) control signal
|
|
911
|
+
* @param {boolean} level The signal level to set
|
|
912
|
+
* @returns {Promise<void>} A promise that resolves when RTS is set
|
|
913
|
+
*/
|
|
914
|
+
async writeRequestToSend(level) {
|
|
915
|
+
try {
|
|
916
|
+
return await core.invoke('plugin:serialplugin|write_request_to_send', {
|
|
917
|
+
path: this.options.path,
|
|
918
|
+
level: level
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
catch (error) {
|
|
922
|
+
return Promise.reject(error);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* @description Writes the DTR (Data Terminal Ready) control signal
|
|
927
|
+
* @param {boolean} level The signal level to set
|
|
928
|
+
* @returns {Promise<void>} A promise that resolves when DTR is set
|
|
929
|
+
*/
|
|
930
|
+
async writeDataTerminalReady(level) {
|
|
931
|
+
try {
|
|
932
|
+
return await core.invoke('plugin:serialplugin|write_data_terminal_ready', {
|
|
933
|
+
path: this.options.path,
|
|
934
|
+
level: level
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
catch (error) {
|
|
938
|
+
return Promise.reject(error);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* @description Reads the CTS (Clear To Send) control signal state
|
|
943
|
+
* @returns {Promise<boolean>} A promise that resolves to the CTS state
|
|
944
|
+
*/
|
|
945
|
+
async readClearToSend() {
|
|
946
|
+
try {
|
|
947
|
+
return await core.invoke('plugin:serialplugin|read_clear_to_send', {
|
|
948
|
+
path: this.options.path
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
catch (error) {
|
|
952
|
+
return Promise.reject(error);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* @description Reads the DSR (Data Set Ready) control signal state
|
|
957
|
+
* @returns {Promise<boolean>} A promise that resolves to the DSR state
|
|
958
|
+
*/
|
|
959
|
+
async readDataSetReady() {
|
|
960
|
+
try {
|
|
961
|
+
return await core.invoke('plugin:serialplugin|read_data_set_ready', {
|
|
962
|
+
path: this.options.path
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
catch (error) {
|
|
966
|
+
return Promise.reject(error);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* @description Reads the RI (Ring Indicator) control signal state
|
|
971
|
+
* @returns {Promise<boolean>} A promise that resolves to the RI state
|
|
972
|
+
*/
|
|
973
|
+
async readRingIndicator() {
|
|
974
|
+
try {
|
|
975
|
+
return await core.invoke('plugin:serialplugin|read_ring_indicator', {
|
|
976
|
+
path: this.options.path
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
catch (error) {
|
|
980
|
+
return Promise.reject(error);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* @description Reads the CD (Carrier Detect) control signal state
|
|
985
|
+
* @returns {Promise<boolean>} A promise that resolves to the CD state
|
|
986
|
+
*/
|
|
987
|
+
async readCarrierDetect() {
|
|
988
|
+
try {
|
|
989
|
+
return await core.invoke('plugin:serialplugin|read_carrier_detect', {
|
|
990
|
+
path: this.options.path
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
catch (error) {
|
|
994
|
+
return Promise.reject(error);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* @description Gets the number of bytes available to read
|
|
999
|
+
* @returns {Promise<number>} A promise that resolves to the number of bytes
|
|
1000
|
+
*/
|
|
1001
|
+
async bytesToRead() {
|
|
1002
|
+
try {
|
|
1003
|
+
return await core.invoke('plugin:serialplugin|bytes_to_read', {
|
|
1004
|
+
path: this.options.path
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
catch (error) {
|
|
1008
|
+
return Promise.reject(error);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* @description Gets the number of bytes waiting to be written
|
|
1013
|
+
* @returns {Promise<number>} A promise that resolves to the number of bytes
|
|
1014
|
+
*/
|
|
1015
|
+
async bytesToWrite() {
|
|
1016
|
+
try {
|
|
1017
|
+
return await core.invoke('plugin:serialplugin|bytes_to_write', {
|
|
1018
|
+
path: this.options.path
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
catch (error) {
|
|
1022
|
+
return Promise.reject(error);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* @description Clears the specified buffer
|
|
1027
|
+
* @param {ClearBuffer} buffer The buffer to clear
|
|
1028
|
+
* @returns {Promise<void>} A promise that resolves when the buffer is cleared
|
|
1029
|
+
*/
|
|
1030
|
+
async clearBuffer(buffer) {
|
|
1031
|
+
try {
|
|
1032
|
+
return await core.invoke('plugin:serialplugin|clear_buffer', {
|
|
1033
|
+
path: this.options.path,
|
|
1034
|
+
bufferType: buffer
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
catch (error) {
|
|
1038
|
+
return Promise.reject(error);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* @description Starts transmitting a break signal
|
|
1043
|
+
* @returns {Promise<void>} A promise that resolves when break signal starts
|
|
1044
|
+
*/
|
|
1045
|
+
async setBreak() {
|
|
1046
|
+
try {
|
|
1047
|
+
return await core.invoke('plugin:serialplugin|set_break', {
|
|
1048
|
+
path: this.options.path
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
catch (error) {
|
|
1052
|
+
return Promise.reject(error);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* @description Stops transmitting a break signal
|
|
1057
|
+
* @returns {Promise<void>} A promise that resolves when break signal stops
|
|
1058
|
+
*/
|
|
1059
|
+
async clearBreak() {
|
|
1060
|
+
try {
|
|
1061
|
+
return await core.invoke('plugin:serialplugin|clear_break', {
|
|
1062
|
+
path: this.options.path
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
catch (error) {
|
|
1066
|
+
return Promise.reject(error);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
/**
|
|
1070
|
+
* @description Writes string data to the serial port
|
|
1071
|
+
* @param {string} value The data to write
|
|
1072
|
+
* @returns {Promise<number>} A promise that resolves to the number of bytes written
|
|
1073
|
+
*/
|
|
1074
|
+
async write(value) {
|
|
1075
|
+
try {
|
|
1076
|
+
if (!this.isOpen) {
|
|
1077
|
+
return Promise.reject(`serial port ${this.options.path} not opened!`);
|
|
1078
|
+
}
|
|
1079
|
+
return await core.invoke('plugin:serialplugin|write', {
|
|
1080
|
+
value,
|
|
1081
|
+
path: this.options.path,
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
catch (error) {
|
|
1085
|
+
return Promise.reject(error);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
1089
|
+
* @description Writes binary data to the serial port
|
|
1090
|
+
* @param {Uint8Array | number[]} value The binary data to write
|
|
1091
|
+
* @returns {Promise<number>} A promise that resolves to the number of bytes written
|
|
1092
|
+
*/
|
|
1093
|
+
async writeBinary(value) {
|
|
1094
|
+
try {
|
|
1095
|
+
if (!this.isOpen) {
|
|
1096
|
+
return Promise.reject(`serial port ${this.options.path} not opened!`);
|
|
1097
|
+
}
|
|
1098
|
+
if (value instanceof Uint8Array || value instanceof Array) {
|
|
1099
|
+
return await core.invoke('plugin:serialplugin|write_binary', {
|
|
1100
|
+
value: Array.from(value),
|
|
1101
|
+
path: this.options.path,
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1104
|
+
else {
|
|
1105
|
+
return Promise.reject('value Argument type error! Expected type: string, Uint8Array, number[]');
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
catch (error) {
|
|
1109
|
+
return Promise.reject(error);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
exports.SerialPort = SerialPort;
|