obd-node
Version:
A Node.js library for communicating with OBD2 (On-Board Diagnostics) systems in vehicles
168 lines • 6.49 kB
JavaScript
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
;