From f4b55dbf62c68464e6374fadc66985b387ac5d01 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 14 Dec 2025 21:14:21 +0000 Subject: [PATCH] Fix connection status UI not updating properly - Ensure isConnected is always updated on main thread - Ensure lastError is always updated on main thread - Disconnect before reconnecting to avoid stale file descriptors - Start update timer on main thread --- AudioVUMeter/AudioVUMeter/SerialManager.swift | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/AudioVUMeter/AudioVUMeter/SerialManager.swift b/AudioVUMeter/AudioVUMeter/SerialManager.swift index f6e66cb..5af637c 100644 --- a/AudioVUMeter/AudioVUMeter/SerialManager.swift +++ b/AudioVUMeter/AudioVUMeter/SerialManager.swift @@ -680,18 +680,30 @@ class SerialManager: ObservableObject { /// Connect to selected serial port func connect() { guard !selectedPortPath.isEmpty else { - lastError = "No port selected" + DispatchQueue.main.async { + self.lastError = "No port selected" + } return } + // Ensure we disconnect first if already connected + if fileDescriptor != -1 { + disconnect() + } + // Open serial port - fileDescriptor = open(selectedPortPath, O_RDWR | O_NOCTTY | O_NONBLOCK) + let fd = open(selectedPortPath, O_RDWR | O_NOCTTY | O_NONBLOCK) - guard fileDescriptor != -1 else { - lastError = "Failed to open port: \(String(cString: strerror(errno)))" + guard fd != -1 else { + DispatchQueue.main.async { + self.lastError = "Failed to open port: \(String(cString: strerror(errno)))" + self.isConnected = false + } return } + fileDescriptor = fd + // Configure serial port var options = termios() tcgetattr(fileDescriptor, &options) @@ -722,13 +734,18 @@ class SerialManager: ObservableObject { // Clear any pending data tcflush(fileDescriptor, TCIOFLUSH) - isConnected = true - lastError = nil + // Update UI on main thread + DispatchQueue.main.async { + self.isConnected = true + self.lastError = nil + } print("Connected to \(selectedPortPath) at \(baudRate) baud") - // Start update timer - startUpdateTimer() + // Start update timer (must be on main thread) + DispatchQueue.main.async { + self.startUpdateTimer() + } // For VU-Server: start response reader and query device info if selectedProtocol == .vuServer { @@ -792,14 +809,20 @@ class SerialManager: ObservableObject { /// Disconnect from serial port func disconnect() { - stopUpdateTimer() + // Stop timer on main thread + DispatchQueue.main.async { + self.stopUpdateTimer() + } if fileDescriptor != -1 { close(fileDescriptor) fileDescriptor = -1 } - isConnected = false + // Update UI on main thread + DispatchQueue.main.async { + self.isConnected = false + } print("Disconnected from serial port") }