elm327
Version:
Node.js/TypeScript library for ELM327 OBD2 adapters over USB, Bluetooth and WiFi
132 lines • 4.82 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SerialConnection = void 0;
const serialport_1 = require("serialport");
const connection_1 = require("./connection");
const errors_1 = require("./errors");
/**
* Serial (USB/RS232) connection to an ELM327 adapter.
* The most reliable connection method for OBD2 communication.
*
* Updated to use ResponseMatcher for better request/response matching.
*/
class SerialConnection extends connection_1.OBD2Connection {
port;
buffer = '';
lineEnding;
constructor(config) {
super(config);
if (!config.port) {
throw new Error('Serial port path is required for serial connections');
}
this.lineEnding = config.lineEnding || '\r';
}
async connect() {
return new Promise((resolve, reject) => {
this.port = new serialport_1.SerialPort({
path: this.config.port,
baudRate: this.config.baudRate || 38400,
autoOpen: false,
});
this.port.open((error) => {
if (error) {
reject(new errors_1.ConnectionError(`Failed to open serial port: ${error.message}`));
return;
}
this.isConnected = true;
this.setupEventHandlers();
this.emit('connected');
resolve();
});
});
}
async disconnect() {
return new Promise((resolve) => {
this.rejectAllPending(new errors_1.ConnectionError('Disconnected'));
if (this.port && this.port.isOpen) {
this.port.close(() => {
this.isConnected = false;
this.emit('disconnected');
resolve();
});
}
else {
this.isConnected = false;
resolve();
}
});
}
async sendRaw(data) {
if (!this.port) {
throw new errors_1.ConnectionError('Not connected to serial port');
}
return new Promise((resolve, reject) => {
this.port.write(data + this.lineEnding, (error) => {
if (error) {
reject(new errors_1.ConnectionError(`Failed to send data: ${error.message}`));
}
else {
// Only flush write buffer, don't close the port
this.port.drain((drainError) => {
if (drainError) {
reject(new errors_1.ConnectionError(`Failed to drain serial port: ${drainError.message}`));
}
else {
resolve();
}
});
}
});
});
}
isConnectionOpen() {
return this.port ? this.port.isOpen : false;
}
setupEventHandlers() {
if (!this.port)
return;
this.port.on('data', (data) => {
const chunk = data.toString();
this.buffer += chunk;
// Process complete responses (terminated by '>')
let idx;
while ((idx = this.buffer.indexOf('>')) !== -1) {
// Include the '>' prompt in the data passed to handleIncomingData
const raw = this.buffer.slice(0, idx + 1);
this.buffer = this.buffer.slice(idx + 1);
if (raw.trim().length > 0) {
// Send to ResponseMatcher for request matching (with '>' included)
this.handleIncomingData(raw);
// Also emit raw data event (without '>' for compatibility)
this.emit('data', raw.replace('>', '').trim());
}
}
});
this.port.on('error', (error) => {
const err = new errors_1.ConnectionError(`Serial port error: ${error.message}`);
this.rejectAllPending(err);
this.emit('error', err);
});
this.port.on('close', () => {
this.isConnected = false;
this.rejectAllPending(new errors_1.ConnectionError('Serial port closed'));
this.emit('disconnected');
});
}
clearBuffer() {
this.buffer = '';
}
/**
* Lists all available serial ports on the system.
*/
static async listPorts() {
const ports = await serialport_1.SerialPort.list();
return ports.map((port) => ({
path: port.path,
manufacturer: port.manufacturer ?? undefined,
serialNumber: port.serialNumber ?? undefined,
}));
}
}
exports.SerialConnection = SerialConnection;
//# sourceMappingURL=serial-connection.js.map