Files
led-controller/src/settings.py

87 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
import os
import binascii
def _settings_path():
"""Path to settings.json in project root (writable without root)."""
try:
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base, "settings.json")
except Exception:
return "settings.json"
class Settings(dict):
SETTINGS_FILE = None # Set in __init__ from _settings_path()
def __init__(self):
super().__init__()
if Settings.SETTINGS_FILE is None:
Settings.SETTINGS_FILE = _settings_path()
self.load() # Load settings from file during initialization
def generate_secret_key(self):
"""Generate a random secret key for session signing."""
try:
# Try to use os.urandom for secure random bytes
random_bytes = os.urandom(32)
return binascii.hexlify(random_bytes).decode('utf-8')
except (AttributeError, NotImplementedError):
# Fallback for MicroPython or systems without os.urandom
try:
import secrets
return secrets.token_hex(32)
except ImportError:
# Last resort: use a combination of time and random
import time
import random
random.seed(time.time())
return binascii.hexlify(bytes([random.randint(0, 255) for _ in range(32)])).decode('utf-8')
def set_defaults(self):
"""Set default settings if they don't exist."""
if 'session_secret_key' not in self:
self['session_secret_key'] = self.generate_secret_key()
# Save immediately when generating a new key
self.save()
# ESP-NOW STA channel (2.4 GHz) for LED drivers / bridge alignment; 111
if 'wifi_channel' not in self:
self['wifi_channel'] = 6
# Wi-Fi LED drivers: controller opens WebSocket to device (firmware serves /ws)
if 'wifi_driver_ws_port' not in self:
self['wifi_driver_ws_port'] = 80
if 'wifi_driver_ws_path' not in self:
self['wifi_driver_ws_path'] = '/ws'
# Seconds between UDP discovery nudges when a Wi-Fi driver WebSocket is
# down (0 disables). Helps drivers that reconnect after seeing traffic on 8766.
if 'wifi_driver_hello_interval_s' not in self:
self['wifi_driver_hello_interval_s'] = 10.0
def save(self):
try:
j = json.dumps(self)
with open(self.SETTINGS_FILE, 'w') as file:
file.write(j)
print("Settings saved successfully.")
except Exception as e:
print(f"Error saving settings: {e}")
def load(self):
loaded_from_file = False
try:
with open(self.SETTINGS_FILE, 'r') as file:
loaded_settings = json.load(file)
self.update(loaded_settings)
loaded_from_file = True
print("Settings loaded successfully.")
except Exception as e:
print(f"Error loading settings")
self.clear()
finally:
# Ensure defaults are set even if file exists but is missing keys
self.set_defaults()
# Only save if file didn't exist or was invalid
if not loaded_from_file:
self.save()