UNPKG

obd-node

Version:

A Node.js library for communicating with OBD2 (On-Board Diagnostics) systems in vehicles

168 lines 6.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BluetoothConnection = void 0; const connection_1 = require("./connection"); const types_1 = require("./types"); class BluetoothConnection extends connection_1.OBD2Connection { constructor(config) { super(config); this.responseQueue = []; this.buffer = ''; if (!config.address) { throw new Error('Bluetooth address is required for Bluetooth connection'); } } async connect() { try { // For web browsers, we would use Web Bluetooth API if (typeof navigator !== 'undefined' && 'bluetooth' in navigator) { await this.connectWebBluetooth(); } else { // For Node.js, we would use a native Bluetooth library await this.connectNativeBluetooth(); } this.isConnected = true; this.emit('connected'); } catch (error) { throw new types_1.ConnectionError(`Failed to connect via Bluetooth: ${error}`); } } async disconnect() { if (this.socket) { try { if (typeof this.socket.close === 'function') { this.socket.close(); } else if (typeof this.socket.disconnect === 'function') { this.socket.disconnect(); } } catch (error) { // Ignore disconnect errors } this.socket = undefined; } this.isConnected = false; this.emit('disconnected'); // Reject any pending commands while (this.responseQueue.length > 0) { const { reject } = this.responseQueue.shift(); reject(new types_1.ConnectionError('Connection closed')); } } async sendCommand(command) { if (!this.socket) { throw new types_1.ConnectionError('Not connected via Bluetooth'); } return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { reject(new types_1.TimeoutError(`Command timeout: ${command}`)); }, this.timeout); this.responseQueue.push({ resolve: (response) => { clearTimeout(timeoutId); try { this.validateResponse(response); resolve(this.cleanResponse(response)); } catch (error) { reject(error); } }, reject: (error) => { clearTimeout(timeoutId); reject(error); } }); const commandWithCR = command + '\r'; try { if (this.socket.send) { this.socket.send(commandWithCR); } else if (this.socket.write) { this.socket.write(commandWithCR); } else { throw new Error('Socket does not support sending data'); } } catch (error) { clearTimeout(timeoutId); this.responseQueue.pop(); reject(new types_1.ConnectionError(`Failed to send command: ${error}`)); } }); } isConnectionOpen() { return this.socket !== undefined && this.isConnected; } async connectWebBluetooth() { if (typeof navigator === 'undefined' || !('bluetooth' in navigator)) { throw new Error('Web Bluetooth API not available'); } try { // Request Bluetooth device const device = await navigator.bluetooth.requestDevice({ filters: [{ services: ['0000fff0-0000-1000-8000-00805f9b34fb'] }], // OBD2 service UUID optionalServices: ['0000fff0-0000-1000-8000-00805f9b34fb'] }); // Connect to GATT Server const server = await device.gatt.connect(); // Get the service const service = await server.getPrimaryService('0000fff0-0000-1000-8000-00805f9b34fb'); // Get characteristics const characteristic = await service.getCharacteristic('0000fff1-0000-1000-8000-00805f9b34fb'); // Setup notifications await characteristic.startNotifications(); characteristic.addEventListener('characteristicvaluechanged', this.handleBluetoothData.bind(this)); this.socket = { send: (data) => { const encoder = new TextEncoder(); return characteristic.writeValue(encoder.encode(data)); }, close: () => { device.gatt.disconnect(); } }; } catch (error) { throw new types_1.ConnectionError(`Web Bluetooth connection failed: ${error}`); } } async connectNativeBluetooth() { // This would require a native Bluetooth library for Node.js // For now, we'll throw an error indicating it's not implemented throw new Error('Native Bluetooth connection not implemented. Please use serial connection or web environment.'); } handleBluetoothData(event) { const decoder = new TextDecoder(); const data = decoder.decode(event.target.value); this.buffer += data; // Process complete lines while (this.buffer.includes('\r')) { const lineEnd = this.buffer.indexOf('\r'); const line = this.buffer.substring(0, lineEnd); this.buffer = this.buffer.substring(lineEnd + 1); if (line.trim()) { this.processResponse(line.trim()); } } } processResponse(response) { if (this.responseQueue.length > 0) { const { resolve } = this.responseQueue.shift(); resolve(response); } this.emit('data', response); } static async isBluetoothAvailable() { if (typeof navigator !== 'undefined' && 'bluetooth' in navigator) { return await navigator.bluetooth.getAvailability(); } return false; } } exports.BluetoothConnection = BluetoothConnection; //# sourceMappingURL=bluetooth-connection.js.map