209 lines
5.9 KiB
JavaScript
Executable File
209 lines
5.9 KiB
JavaScript
Executable File
import { exec } from 'node:child_process';
|
|
import _ from 'lodash';
|
|
import EventsBase from './events-base.js';
|
|
import { CURRENT_PLANTFORM, SERVER_MODE } from './config.js';
|
|
|
|
|
|
let SerialPort, ReadlineParser, ByteLengthParser;
|
|
|
|
if (SERVER_MODE === 'all') {
|
|
const serial = await import('serialport');
|
|
SerialPort = serial.SerialPort;
|
|
ReadlineParser = serial.ReadlineParser;
|
|
ByteLengthParser = serial.ByteLengthParser;
|
|
}
|
|
|
|
|
|
export default class Serial extends EventsBase {
|
|
static {
|
|
this.portsName = [];
|
|
|
|
this.getCurrentPortsName = function () {
|
|
return this.portsName;
|
|
}
|
|
|
|
this.getPorts = async function () {
|
|
return new Promise((resolve, reject) => {
|
|
if (CURRENT_PLANTFORM === 'linux') {
|
|
exec('ls /dev/ttyACM* /dev/tty*USB*', (error, stdout) => {
|
|
let portsName = _.uniq(stdout.split('\n'));
|
|
let newPorts = [];
|
|
for (let i = 0; i < portsName.length; i++) {
|
|
if (!portsName[i]) {
|
|
continue;
|
|
}
|
|
newPorts.push({
|
|
vendorId: null,
|
|
productId: null,
|
|
name: portsName[i]
|
|
});
|
|
}
|
|
resolve(newPorts);
|
|
});
|
|
} else {
|
|
SerialPort.list().then(ports => {
|
|
let newPorts = [];
|
|
for (let i = 0; i < ports.length; i++) {
|
|
let port = ports[i];
|
|
newPorts.push({
|
|
vendorId: port.vendorId,
|
|
productId: port.productId,
|
|
name: port.path
|
|
});
|
|
}
|
|
resolve(newPorts);
|
|
}).catch(reject);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
#serialport_ = null;
|
|
#parserBytes_ = null;
|
|
#parserLine_ = null;
|
|
#port_ = null;
|
|
#isOpened_ = false;
|
|
|
|
constructor(port) {
|
|
super();
|
|
this.#port_ = port;
|
|
this.addEventsType(['buffer', 'string', 'error', 'open', 'close']);
|
|
}
|
|
|
|
#addEventsListener_() {
|
|
this.#parserBytes_.on('data', (buffer) => {
|
|
const arr = [];
|
|
for (let i = 0; i < buffer.length; i++) {
|
|
arr.push(buffer[i]);
|
|
}
|
|
this.runEvent('buffer', arr);
|
|
});
|
|
|
|
this.#parserLine_.on('data', (str) => {
|
|
this.runEvent('string', str);
|
|
});
|
|
|
|
this.#serialport_.on('error', (error) => {
|
|
this.runEvent('error', error.toString());
|
|
});
|
|
|
|
this.#serialport_.on('open', () => {
|
|
this.#isOpened_ = true;
|
|
this.runEvent('open');
|
|
});
|
|
|
|
this.#serialport_.on('close', () => {
|
|
this.#isOpened_ = false;
|
|
this.runEvent('close');
|
|
});
|
|
}
|
|
|
|
isOpened() {
|
|
return this.#isOpened_;
|
|
}
|
|
|
|
getPortName() {
|
|
return this.#port_;
|
|
}
|
|
|
|
async open(baud) {
|
|
return new Promise((resolve, reject) => {
|
|
if (this.isOpened()) {
|
|
resolve();
|
|
return;
|
|
}
|
|
this.#serialport_ = new SerialPort({
|
|
path: this.getPortName(),
|
|
baudRate: baud,
|
|
dataBits: 8,
|
|
parity: 'none',
|
|
stopBits: 1,
|
|
flowControl: false,
|
|
autoOpen: false
|
|
}, false);
|
|
this.#parserBytes_ = this.#serialport_.pipe(new ByteLengthParser({ length: 1 }));
|
|
this.#parserLine_ = this.#serialport_.pipe(new ReadlineParser());
|
|
this.#addEventsListener_();
|
|
this.#serialport_.open((error) => {
|
|
if (error) {
|
|
reject(error.toString());
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
async close() {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.isOpened()) {
|
|
resolve();
|
|
return;
|
|
}
|
|
this.#serialport_.close((error) => {
|
|
if (error) {
|
|
reject(error.toString());
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
async setBaudRate(baud) {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.isOpened()) {
|
|
resolve();
|
|
return;
|
|
}
|
|
this.#serialport_.update({ baudRate: baud }, (error) => {
|
|
if (error) {
|
|
reject(error.toString());
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
async send(data) {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.isOpened()) {
|
|
resolve();
|
|
return;
|
|
}
|
|
this.#serialport_.write(data, (error) => {
|
|
if (error) {
|
|
reject(error.toString());
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
async setDTRAndRTS(dtr, rts) {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.isOpened()) {
|
|
resolve();
|
|
return;
|
|
}
|
|
this.#serialport_.set({ dtr, rts }, (error) => {
|
|
if (error) {
|
|
reject(error.toString());
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
async dispose() {
|
|
await this.close();
|
|
super.dispose();
|
|
this.#serialport_ = null;
|
|
this.#parserBytes_ = null;
|
|
this.#parserLine_ = null;
|
|
this.#port_ = null;
|
|
}
|
|
} |