/** * Caliper Connection Manager * Web Serial API integration for USB digital calipers * Supports standard SPC/Digimatic protocol */ function caliperConnection() { return { connected: false, status: 'disconnected', // disconnected, connecting, connected, error lastReading: null, port: null, reader: null, readController: null, get isSupported() { return 'serial' in navigator; }, async connect() { if (!this.isSupported) { this.status = 'error'; console.error('Web Serial API not supported'); return; } try { this.status = 'connecting'; // Request port selection this.port = await navigator.serial.requestPort(); // Open port with standard caliper settings await this.port.open({ baudRate: 9600, dataBits: 8, stopBits: 1, parity: 'none', flowControl: 'none' }); this.connected = true; this.status = 'connected'; // Start reading loop this.readLoop(); } catch (err) { this.status = 'error'; this.connected = false; console.error('Caliper connection error:', err); } }, async readLoop() { if (!this.port || !this.port.readable) return; const reader = this.port.readable.getReader(); this.reader = reader; try { while (true) { const { value, done } = await reader.read(); if (done) { console.log('Reader closed'); break; } this.parseData(value); } } catch (err) { if (err.name !== 'NetworkError') { console.error('Read error:', err); } } finally { reader.releaseLock(); } }, parseData(data) { try { // Decode buffer to text const text = new TextDecoder().decode(data); // Standard digital caliper protocol patterns // Format: typically " XX.XXX mm\r\n" or similar // Try multiple patterns for compatibility // Pattern 1: Standard with units let match = text.match(/([+-]?\s*\d+\.?\d*)\s*mm/i); // Pattern 2: Just number with optional sign if (!match) { match = text.match(/([+-]?\s*\d+\.?\d*)/); } if (match) { // Clean whitespace and parse const valueStr = match[1].replace(/\s+/g, ''); const value = parseFloat(valueStr); if (!isNaN(value)) { this.lastReading = value; // Dispatch event for other components this.$dispatch('caliper-reading', { value: value, timestamp: new Date().toISOString() }); } } } catch (err) { console.error('Parse error:', err); } }, async disconnect() { try { // Cancel reader if (this.reader) { await this.reader.cancel(); this.reader = null; } // Close port if (this.port) { await this.port.close(); this.port = null; } } catch (err) { console.error('Disconnect error:', err); } finally { this.connected = false; this.status = 'disconnected'; } }, // Cleanup on component destroy destroy() { this.disconnect(); } }; }