From 7d56aec2450ef225774208e475f6becd89ff16f6 Mon Sep 17 00:00:00 2001 From: David Bieber Date: Mon, 14 Apr 2025 17:57:04 +0000 Subject: [PATCH 1/7] Fix Wi-Fi network configuration in settings server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The settings UI was correctly updating Wi-Fi networks in Redis, but not properly calling wifi.save_networks() which ensures proper handling before updating wpa_supplicant configuration. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- gonotego/settings/server.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/gonotego/settings/server.py b/gonotego/settings/server.py index a32f81a..874451b 100644 --- a/gonotego/settings/server.py +++ b/gonotego/settings/server.py @@ -163,6 +163,13 @@ def do_POST(self): post_data = self.rfile.read(content_length).decode("utf-8") settings_data = json.loads(post_data) + # Write all settings being processed to debug file + with open('/tmp/wifi_debug.log', 'a') as f: + f.write("===== SETTINGS UPDATE =====\n") + for k, v in settings_data.items(): + f.write(f"Key: {k}, Value type: {type(v)}, Value: {v}\n") + f.write("========================\n") + # Update settings for key, value in settings_data.items(): # Skip masked values - we don't want to overwrite with placeholder text @@ -175,9 +182,21 @@ def do_POST(self): try: settings.set(key, value) - # If we're updating WiFi networks, update the wpa_supplicant.conf file + # If we're updating WiFi networks, save networks and update the wpa_supplicant.conf file if key == 'WIFI_NETWORKS': try: + # Write debug info to a file that can be checked later + with open('/tmp/wifi_debug.log', 'a') as f: + f.write(f"WIFI_NETWORKS value type: {type(value)}, value: {value}\n") + # Parse the value to ensure it's in the correct format + if isinstance(value, str): + networks = json.loads(value) + else: + networks = value + + # Save networks using the wifi module's function + wifi.save_networks(networks) + # Update wpa_supplicant configuration using the wifi module wifi.update_wpa_supplicant_config() wifi.reconfigure_wifi() From 64ca9b0171bd9e73dcc7da883a290b1c4afbc23c Mon Sep 17 00:00:00 2001 From: David Bieber Date: Mon, 14 Apr 2025 18:19:09 +0000 Subject: [PATCH 2/7] Add additional debugging for Wi-Fi configuration issue --- gonotego/settings/server.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/gonotego/settings/server.py b/gonotego/settings/server.py index 874451b..bda823e 100644 --- a/gonotego/settings/server.py +++ b/gonotego/settings/server.py @@ -156,6 +156,13 @@ def do_POST(self): """Handle POST requests.""" parsed_path = urlparse(self.path) + # Early debug log to see if we're getting to this point + try: + with open('/tmp/wifi_debug_start.log', 'a') as f: + f.write(f"POST request received to {parsed_path.path}\n") + except Exception as e: + print(f"Error writing to start debug log: {e}") + if parsed_path.path == "/api/settings": try: # Read the request body @@ -164,11 +171,14 @@ def do_POST(self): settings_data = json.loads(post_data) # Write all settings being processed to debug file - with open('/tmp/wifi_debug.log', 'a') as f: + try: + with open('/tmp/wifi_debug.log', 'a') as f: f.write("===== SETTINGS UPDATE =====\n") for k, v in settings_data.items(): - f.write(f"Key: {k}, Value type: {type(v)}, Value: {v}\n") + f.write(f"Key: {k}, Value type: {type(v)}, Value: {v}\n") f.write("========================\n") + except Exception as e: + print(f"Error writing to debug log: {e}") # Update settings for key, value in settings_data.items(): @@ -186,8 +196,11 @@ def do_POST(self): if key == 'WIFI_NETWORKS': try: # Write debug info to a file that can be checked later - with open('/tmp/wifi_debug.log', 'a') as f: + try: + with open('/tmp/wifi_debug.log', 'a') as f: f.write(f"WIFI_NETWORKS value type: {type(value)}, value: {value}\n") + except Exception as e: + print(f"Error writing to wifi debug log: {e}") # Parse the value to ensure it's in the correct format if isinstance(value, str): networks = json.loads(value) From c492b074443b62e7f76df1b91c3ab97b1aa45838 Mon Sep 17 00:00:00 2001 From: David Bieber Date: Mon, 14 Apr 2025 18:19:36 +0000 Subject: [PATCH 3/7] Simplify debugging by removing try-except blocks --- gonotego/settings/server.py | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/gonotego/settings/server.py b/gonotego/settings/server.py index bda823e..e1c5cef 100644 --- a/gonotego/settings/server.py +++ b/gonotego/settings/server.py @@ -157,11 +157,8 @@ def do_POST(self): parsed_path = urlparse(self.path) # Early debug log to see if we're getting to this point - try: - with open('/tmp/wifi_debug_start.log', 'a') as f: - f.write(f"POST request received to {parsed_path.path}\n") - except Exception as e: - print(f"Error writing to start debug log: {e}") + with open('/tmp/wifi_debug_start.log', 'a') as f: + f.write(f"POST request received to {parsed_path.path}\n") if parsed_path.path == "/api/settings": try: @@ -171,14 +168,11 @@ def do_POST(self): settings_data = json.loads(post_data) # Write all settings being processed to debug file - try: - with open('/tmp/wifi_debug.log', 'a') as f: - f.write("===== SETTINGS UPDATE =====\n") - for k, v in settings_data.items(): - f.write(f"Key: {k}, Value type: {type(v)}, Value: {v}\n") - f.write("========================\n") - except Exception as e: - print(f"Error writing to debug log: {e}") + with open('/tmp/wifi_debug.log', 'a') as f: + f.write("===== SETTINGS UPDATE =====\n") + for k, v in settings_data.items(): + f.write(f"Key: {k}, Value type: {type(v)}, Value: {v}\n") + f.write("========================\n") # Update settings for key, value in settings_data.items(): @@ -196,11 +190,8 @@ def do_POST(self): if key == 'WIFI_NETWORKS': try: # Write debug info to a file that can be checked later - try: - with open('/tmp/wifi_debug.log', 'a') as f: - f.write(f"WIFI_NETWORKS value type: {type(value)}, value: {value}\n") - except Exception as e: - print(f"Error writing to wifi debug log: {e}") + with open('/tmp/wifi_debug.log', 'a') as f: + f.write(f"WIFI_NETWORKS value type: {type(value)}, value: {value}\n") # Parse the value to ensure it's in the correct format if isinstance(value, str): networks = json.loads(value) From 6cc39f53bc256b9fa1c992650c01ec66d4247407 Mon Sep 17 00:00:00 2001 From: David Bieber Date: Mon, 14 Apr 2025 18:25:32 +0000 Subject: [PATCH 4/7] Improve Wi-Fi configuration in settings UI - Remove debug code from server.py - Fix Wi-Fi network save process by using proper wifi.save_networks() function - Add unsaved changes indicator to Save button in settings UI - Disable Save button when there are no changes to save --- gonotego/settings-server/src/App.tsx | 37 +++++++++++++++++++++++----- gonotego/settings/server.py | 15 ----------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/gonotego/settings-server/src/App.tsx b/gonotego/settings-server/src/App.tsx index a3b6a46..2797722 100644 --- a/gonotego/settings-server/src/App.tsx +++ b/gonotego/settings-server/src/App.tsx @@ -55,6 +55,9 @@ const SettingsUI = () => { CUSTOM_COMMAND_PATHS: [], }); + // Keep track of the original settings to detect changes + const [originalSettings, setOriginalSettings] = useState({}); + const [newWifiNetwork, setNewWifiNetwork] = useState({ ssid: '', psk: '' @@ -90,10 +93,14 @@ const SettingsUI = () => { }, {}); // Update settings state with fetched data - setSettings(prev => ({ - ...prev, + const updatedSettings = { + ...settings, ...validSettings - })); + }; + setSettings(updatedSettings); + + // Store the original settings to detect changes + setOriginalSettings(JSON.parse(JSON.stringify(updatedSettings))); } catch (error) { console.error('Error fetching settings:', error); setLoadError(true); @@ -105,6 +112,20 @@ const SettingsUI = () => { fetchSettings(); }, []); + // Function to detect if there are unsaved changes + const hasUnsavedChanges = () => { + // Check if the settings object has the same structure as originalSettings + if (Object.keys(originalSettings).length === 0) return false; + + // Compare original and current settings using deep comparison + try { + return JSON.stringify(settings) !== JSON.stringify(originalSettings); + } catch (e) { + // If comparison fails (e.g., circular references), default to true + return true; + } + }; + const handleChange = (key, value) => { setSettings(prev => ({ ...prev, @@ -135,6 +156,10 @@ const SettingsUI = () => { } setSaveStatus('saved'); + + // Update the original settings after saving + setOriginalSettings(JSON.parse(JSON.stringify(settings))); + setTimeout(() => setSaveStatus(null), 2000); } catch (error) { console.error('Error saving settings:', error); @@ -736,15 +761,15 @@ const SettingsUI = () => { )} diff --git a/gonotego/settings/server.py b/gonotego/settings/server.py index e1c5cef..7919df1 100644 --- a/gonotego/settings/server.py +++ b/gonotego/settings/server.py @@ -155,11 +155,6 @@ def do_GET(self): def do_POST(self): """Handle POST requests.""" parsed_path = urlparse(self.path) - - # Early debug log to see if we're getting to this point - with open('/tmp/wifi_debug_start.log', 'a') as f: - f.write(f"POST request received to {parsed_path.path}\n") - if parsed_path.path == "/api/settings": try: # Read the request body @@ -167,13 +162,6 @@ def do_POST(self): post_data = self.rfile.read(content_length).decode("utf-8") settings_data = json.loads(post_data) - # Write all settings being processed to debug file - with open('/tmp/wifi_debug.log', 'a') as f: - f.write("===== SETTINGS UPDATE =====\n") - for k, v in settings_data.items(): - f.write(f"Key: {k}, Value type: {type(v)}, Value: {v}\n") - f.write("========================\n") - # Update settings for key, value in settings_data.items(): # Skip masked values - we don't want to overwrite with placeholder text @@ -189,9 +177,6 @@ def do_POST(self): # If we're updating WiFi networks, save networks and update the wpa_supplicant.conf file if key == 'WIFI_NETWORKS': try: - # Write debug info to a file that can be checked later - with open('/tmp/wifi_debug.log', 'a') as f: - f.write(f"WIFI_NETWORKS value type: {type(value)}, value: {value}\n") # Parse the value to ensure it's in the correct format if isinstance(value, str): networks = json.loads(value) From e342a9920211458690844eefa6dc970e3fa7acbc Mon Sep 17 00:00:00 2001 From: David Bieber Date: Mon, 14 Apr 2025 18:27:14 +0000 Subject: [PATCH 5/7] Refactor WiFi settings saving to avoid redundant calls --- gonotego/settings/server.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gonotego/settings/server.py b/gonotego/settings/server.py index 7919df1..52f66d6 100644 --- a/gonotego/settings/server.py +++ b/gonotego/settings/server.py @@ -173,8 +173,7 @@ def do_POST(self): continue try: - settings.set(key, value) - # If we're updating WiFi networks, save networks and update the wpa_supplicant.conf file + # Handle WiFi networks specially if key == 'WIFI_NETWORKS': try: # Parse the value to ensure it's in the correct format @@ -184,6 +183,7 @@ def do_POST(self): networks = value # Save networks using the wifi module's function + # This already calls settings.set() internally wifi.save_networks(networks) # Update wpa_supplicant configuration using the wifi module @@ -191,6 +191,9 @@ def do_POST(self): wifi.reconfigure_wifi() except Exception as e: print(f"Error updating WiFi configuration: {e}") + else: + # For all other settings, just use settings.set + settings.set(key, value) except Exception as e: print(f"Error setting {key}: {e}") From 46ab2db2c2c2e4a9fcb8b1af4731f0943fa8ca10 Mon Sep 17 00:00:00 2001 From: David Bieber Date: Mon, 14 Apr 2025 18:30:18 +0000 Subject: [PATCH 6/7] Simplify WiFi network handling in settings server --- gonotego/settings/server.py | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/gonotego/settings/server.py b/gonotego/settings/server.py index 52f66d6..7d3df9e 100644 --- a/gonotego/settings/server.py +++ b/gonotego/settings/server.py @@ -175,22 +175,10 @@ def do_POST(self): try: # Handle WiFi networks specially if key == 'WIFI_NETWORKS': - try: - # Parse the value to ensure it's in the correct format - if isinstance(value, str): - networks = json.loads(value) - else: - networks = value - - # Save networks using the wifi module's function - # This already calls settings.set() internally - wifi.save_networks(networks) - - # Update wpa_supplicant configuration using the wifi module - wifi.update_wpa_supplicant_config() - wifi.reconfigure_wifi() - except Exception as e: - print(f"Error updating WiFi configuration: {e}") + networks = json.loads(value) + wifi.save_networks(networks) + wifi.update_wpa_supplicant_config() + wifi.reconfigure_wifi() else: # For all other settings, just use settings.set settings.set(key, value) From f15b13278f9b2043d3ceb56950c18a7f1fb9c5cc Mon Sep 17 00:00:00 2001 From: David Bieber Date: Mon, 14 Apr 2025 18:31:06 +0000 Subject: [PATCH 7/7] Pass value directly to save_networks without JSON parsing --- gonotego/settings/server.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gonotego/settings/server.py b/gonotego/settings/server.py index 7d3df9e..41f26cf 100644 --- a/gonotego/settings/server.py +++ b/gonotego/settings/server.py @@ -175,8 +175,7 @@ def do_POST(self): try: # Handle WiFi networks specially if key == 'WIFI_NETWORKS': - networks = json.loads(value) - wifi.save_networks(networks) + wifi.save_networks(value) wifi.update_wpa_supplicant_config() wifi.reconfigure_wifi() else: