UNPKG

elm327

Version:

Node.js/TypeScript library for ELM327 OBD2 adapters over USB, Bluetooth and WiFi

132 lines 4.82 kB
"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