elm327
Version:
Node.js/TypeScript library for ELM327 OBD2 adapters over USB, Bluetooth and WiFi
133 lines • 5.26 kB
TypeScript
import { EventEmitter } from 'events';
import { ResponseMatcher } from './response-matcher';
import { ConnectionConfig, DiagnosticRequestConfig, DiagnosticResponse, OBD2AdapterInfo } from './types';
/**
* Abstract base class for all OBD2 connection types.
* Provides common initialization, validation, and response cleaning logic.
*
* Inspired by OpenXC's controller implementation with improved
* response matching and multi-frame support.
*/
export declare abstract class OBD2Connection extends EventEmitter {
protected config: ConnectionConfig;
protected isConnected: boolean;
protected isInitialized: boolean;
protected timeout: number;
protected responseMatcher: ResponseMatcher;
protected multiframeMessages: Map<number, MultiframeMessage>;
protected commandLock: Promise<void>;
protected monitorMode: boolean;
constructor(config: ConnectionConfig);
abstract connect(): Promise<void>;
abstract disconnect(): Promise<void>;
abstract sendRaw(data: string): Promise<void>;
abstract isConnectionOpen(): boolean;
/**
* Validates an adapter response and throws on known error patterns.
*/
protected validateResponse(response: string): void;
/**
* Sends a command and waits for response using the ResponseMatcher.
* Similar to OpenXC's complex_request pattern.
* Uses a mutex to prevent parallel commands from corrupting responses.
*/
sendCommand(command: string, customTimeout?: number): Promise<string>;
/**
* Sends a diagnostic request with matching support.
* Similar to OpenXC's create_diagnostic_request.
*/
sendDiagnosticRequest(request: DiagnosticRequestConfig, waitForResponse?: boolean): Promise<DiagnosticResponse | null>;
/**
* Builds a diagnostic command string from config.
*/
protected buildDiagnosticCommand(request: DiagnosticRequestConfig): string;
/**
* Parses a raw response into a DiagnosticResponse.
*/
protected parseDiagnosticResponse(rawResponse: string, request: DiagnosticRequestConfig): DiagnosticResponse;
/**
* Handles incoming data and routes to ResponseMatcher.
* Should be called by subclasses when data is received.
* Handles multi-frame ISO-TP messages (like VIN).
* In monitor mode, emits 'canData' events for all received frames.
*/
protected handleIncomingData(data: string): void;
/**
* Rejects all pending requests (useful on disconnect/error).
*/
protected rejectAllPending(error: Error): void;
/**
* Cleans a response by removing common ELM327 artifacts.
* Uses fast string operations instead of regex for better performance.
* Removes \r, \n, >, and normalizes spaces (no double spaces).
*/
protected cleanResponse(response: string): string;
/**
* Initializes the ELM327 adapter with standard AT commands.
* Must be called after a successful connection.
* Includes retry logic for ATZ (up to 3 attempts).
*/
initialize(): Promise<OBD2AdapterInfo>;
protected clearBuffer(): void;
protected delay(ms: number): Promise<void>;
getConnectionStatus(): boolean;
/**
* Resets the adapter using ATZ command without disconnecting/reconnecting.
* Useful for recovering from communication errors or changing protocols.
* This is an independent reset that doesn't recreate the socket/connection.
*/
reset(): Promise<void>;
/**
* Starts monitoring all CAN traffic (AT MA mode).
* In this mode, the adapter forwards all CAN frames without filtering.
* Use stopMonitor() to exit this mode.
* Data is emitted via the 'canData' event.
*/
startMonitor(): Promise<void>;
/**
* Stops CAN monitoring mode.
* Sends AT command to exit monitor mode.
*/
stopMonitor(): Promise<void>;
/**
* Monitor mode with filter (AT CF - CAN Filter + AT CM - CAN Mask).
* Filters frames by specific CAN ID (not PID filter like AT MP).
* Use stopMonitor() to exit this mode.
*/
startMonitorWithFilter(canId: string): Promise<void>;
}
/**
* Multiframe message accumulator
* Similar to OpenXC's MultiframeDiagnosticMessage
* Used for ISO-TP multi-frame responses (like VIN)
*/
export declare class MultiframeMessage {
readonly id: number;
readonly bus?: number | undefined;
private frames;
private _totalFrames;
private _isComplete;
mode?: number;
pid?: number;
constructor(id: number, mode?: number, pid?: number, bus?: number | undefined);
/**
* Adds a frame to the multiframe message
* For ISO-TP: first frame (10) has total frames, consecutive frames (21, 22, etc.)
*/
addFrame(response: string): void;
/**
* Gets the combined payload from all frames in correct order
* Only returns frames that are actually present (skip missing)
*/
getCombinedPayload(): string;
/**
* Checks if all frames have been received contiguously
* Verifies that frames 0, 1, 2... (totalFrames-1) are all present
*/
get isComplete(): boolean;
/**
* Gets the total number of frames received
*/
get frameCount(): number;
}
//# sourceMappingURL=connection.d.ts.map