10 Commits

Author SHA1 Message Date
9abd425f46 Add wifi 2025-05-22 22:02:49 +12:00
ee28b5805d Change title and h1 to "name" 2025-05-22 22:02:29 +12:00
ec29dbdd01 Add color order 2025-05-19 22:00:35 +12:00
3fa9377438 Add set_settings to Settings class 2025-05-19 21:59:43 +12:00
ec049b52c0 Only check wifi settings if not connected 2025-05-19 19:35:29 +12:00
a009ea85bc Add wifi settings 2025-05-19 19:32:53 +12:00
bd2e6e56cf Check if ssid, password, ip and gateway are "" 2025-05-19 19:31:30 +12:00
37c7280a15 Get ap password from settings 2025-05-19 19:28:11 +12:00
2f10d4cabd Fix rgb order 2025-05-19 19:24:17 +12:00
385dcffe68 Add led pin in settings 2025-05-19 19:22:38 +12:00
6 changed files with 87 additions and 60 deletions

View File

@@ -5,4 +5,5 @@ from settings import Settings
s = Settings() s = Settings()
name = s.get('name', 'led') name = s.get('name', 'led')
wifi.ap(name, '') password = s.get("ap_password", "")
wifi.ap(name, password)

View File

@@ -1,6 +1,6 @@
import asyncio import asyncio
import aioespnow import aioespnow
from settings import Settings, set_settings from settings import Settings
from web import web from web import web
from patterns import Patterns from patterns import Patterns
import gc import gc
@@ -11,25 +11,16 @@ import wifi
async def main(): async def main():
settings = Settings() settings = Settings()
patterns = Patterns(4, settings["num_leds"], selected=settings["pattern"]) patterns = Patterns(settings["led_pin"], settings["num_leds"], selected=settings["pattern"])
patterns.set_color1(tuple(int(settings["color1"][i:i+2], 16) for i in (1, 5, 3))) if settings["color_order"] == "rbg": color_order = (1, 5, 3)
patterns.set_color2(tuple(int(settings["color2"][i:i+2], 16) for i in (1, 5, 3))) else: color_order = (1, 3, 5)
patterns.set_color1(tuple(int(settings["color1"][i:i+2], 16) for i in color_order))
patterns.set_color2(tuple(int(settings["color2"][i:i+2], 16) for i in color_order))
patterns.set_brightness(int(settings["brightness"])) patterns.set_brightness(int(settings["brightness"]))
patterns.set_delay(int(settings["delay"])) patterns.set_delay(int(settings["delay"]))
w = web(settings, patterns)
print(settings)
# start the server in a bacakground task
print("Starting")
server = asyncio.create_task(w.start_server(host="0.0.0.0", port=80))
#wdt = machine.WDT(timeout=10000)
#wdt.feed()
async def tick(): async def tick():
while True: while True:
patterns.tick() patterns.tick()
@@ -40,9 +31,31 @@ async def main():
e.active(True) e.active(True)
async for mac, msg in e: async for mac, msg in e:
print(msg) print(msg)
set_settings(msg, settings, patterns) settings.set_settings(msg, patterns)
print("should not print") print("should not print")
async def wifi_connect():
for i in range(10):
config = wifi.connect(settings.get("wifi_ssid", ""),
settings.get("wifi_password", ""),
settings.get("wifi_ip", ""),
settings.get("wifi_gateway", "")
)
if config:
print(config)
break
await asyncio.sleep_ms(500)
w = web(settings, patterns)
print(settings)
# start the server in a bacakground task
print("Starting")
server = asyncio.create_task(w.start_server(host="0.0.0.0", port=80))
#wdt = machine.WDT(timeout=10000)
#wdt.feed()
asyncio.create_task(wifi_connect())
asyncio.create_task(tick()) asyncio.create_task(tick())
asyncio.create_task(espnow()) asyncio.create_task(espnow())

View File

@@ -9,16 +9,24 @@ class Settings(dict):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.load() # Load settings from file during initialization self.load() # Load settings from file during initialization
if self["color_order"] == "rbg": self.color_order = (1, 5, 3)
else: self.color_order = (1, 3, 5)
def set_defaults(self): def set_defaults(self):
self["led_pin"] = 10
self["num_leds"] = 50 self["num_leds"] = 50
self["pattern"] = "on" self["pattern"] = "on"
self["color1"] = "#00ff00" self["color1"] = "#00ff00"
self["color2"] = "#ff0000" self["color2"] = "#ff0000"
self["delay"] = 100 self["delay"] = 100
self["brightness"] = 10 self["brightness"] = 10
self["color_order"] = "rgb"
self["name"] = f"led-{ubinascii.hexlify(wifi.get_mac()).decode()}" self["name"] = f"led-{ubinascii.hexlify(wifi.get_mac()).decode()}"
self["ap_password"] = "" self["ap_password"] = ""
self["wifi_ssid"] = ""
self["wifi_password"] = ""
self["wifi_ip"] = ""
self["wifi_gateway"] = ""
def save(self): def save(self):
try: try:
@@ -40,6 +48,43 @@ class Settings(dict):
self.set_defaults() self.set_defaults()
self.save() self.save()
def set_settings(self, raw_json, patterns):
patterns.sync()
try:
data = json.loads(raw_json)
print(data)
for key, value in data.items():
print(key, value)
if key == "color1":
patterns.set_color1(tuple(int(value[i:i+2], 16) for i in self.color_order)) # Convert hex to RGB
elif key == "color2":
patterns.set_color2(tuple(int(value[i:i+2], 16) for i in self.color_order)) # Convert hex to RGB
elif key == "num_leds":
patterns.update_num_leds(4, value)
elif key == "pattern":
if not patterns.select(value):
return "Pattern doesn't exist", 400
elif key == "delay":
delay = int(data["delay"])
patterns.set_delay(delay)
elif key == "brightness":
brightness = int(data["brightness"])
patterns.set_brightness(brightness)
elif key == "name":
self[key] = value
self.save()
machine.reset()
elif key == "color_order":
if value == "rbg": self.color_order = (1, 5, 3)
else: self.color_order = (1, 3, 5)
else:
return "Invalid key", 400
self[key] = value
self.save()
return "OK", 200
except (KeyError, ValueError):
return "Bad request", 400
# Example usage # Example usage
def main(): def main():
settings = Settings() settings = Settings()
@@ -53,39 +98,7 @@ def main():
print(f"Loaded number of LEDs: {new_settings['num_leds']}") print(f"Loaded number of LEDs: {new_settings['num_leds']}")
print(settings) print(settings)
def set_settings(raw_json, settings, patterns):
patterns.sync()
try:
data = json.loads(raw_json)
print(data)
for key, value in data.items():
print(key, value)
if key == "color1":
patterns.set_color1(tuple(int(value[i:i+2], 16) for i in (1, 3, 5))) # Convert hex to RGB
elif key == "color2":
patterns.set_color2(tuple(int(value[i:i+2], 16) for i in (1, 3, 5))) # Convert hex to RGB
elif key == "num_leds":
patterns.update_num_leds(4, value)
elif key == "pattern":
if not patterns.select(value):
return "Pattern doesn't exist", 400
elif key == "delay":
delay = int(data["delay"])
patterns.set_delay(delay)
elif key == "brightness":
brightness = int(data["brightness"])
patterns.set_brightness(brightness)
elif key == "name":
settings[key] = value
settings.save()
machine.reset()
else:
return "Invalid key", 400
settings[key] = value
settings.save()
return "OK", 200
except (KeyError, ValueError):
return "Bad request", 400
# Run the example # Run the example
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -4,12 +4,12 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>LED Control</title> <title>{{settings['name']}}</title>
<script src="static/main.js"></script> <script src="static/main.js"></script>
<link rel="stylesheet" href="static/main.css" /> <link rel="stylesheet" href="static/main.css" />
</head> </head>
<body> <body>
<h1>Control LEDs</h1> <h1>{{settings['name']}}</h1>
<button onclick="selectControls()">Controls</button> <button onclick="selectControls()">Controls</button>
<button onclick="selectSettings()">Settings</button> <button onclick="selectSettings()">Settings</button>

View File

@@ -2,7 +2,6 @@ from microdot import Microdot, send_file, Response
from microdot.utemplate import Template from microdot.utemplate import Template
from microdot.websocket import with_websocket from microdot.websocket import with_websocket
import machine import machine
from settings import set_settings
import wifi import wifi
import json import json
@@ -26,7 +25,7 @@ def web(settings, patterns):
def settings_handler(request): def settings_handler(request):
# Keep the POST handler for compatibility or alternative usage if needed # Keep the POST handler for compatibility or alternative usage if needed
# For WebSocket updates, the /ws handler is now primary # For WebSocket updates, the /ws handler is now primary
return set_settings(request.body.decode('utf-8'), settings, patterns) return settings.set_settings(request.body.decode('utf-8'), patterns)
@app.route("/ws") @app.route("/ws")
@with_websocket @with_websocket
@@ -35,7 +34,7 @@ def web(settings, patterns):
data = await ws.receive() data = await ws.receive()
if data: if data:
# Process the received data # Process the received data
_, status_code = set_settings(data, settings, patterns) _, status_code = settings.set_settings(data, patterns)
#await ws.send(status_code) #await ws.send(status_code)
else: else:
break break

View File

@@ -2,14 +2,15 @@ import network
from time import sleep from time import sleep
def connect(ssid, password, ip, gateway): def connect(ssid, password, ip, gateway):
if ssid is None or password is None:
print("Missing ssid or password")
return None
try: try:
sta_if = network.WLAN(network.STA_IF) sta_if = network.WLAN(network.STA_IF)
if ip is not None and gateway is not None:
sta_if.ifconfig((ip, '255.255.255.0', gateway, '1.1.1.1'))
if not sta_if.isconnected(): if not sta_if.isconnected():
if ssid == "" or password == "":
print("Missing ssid or password")
return None
if ip != "" and gateway != "":
sta_if.ifconfig((ip, '255.255.255.0', gateway, '1.1.1.1'))
print('connecting to network...') print('connecting to network...')
sta_if.active(True) sta_if.active(True)
sta_if.connect(ssid, password) sta_if.connect(ssid, password)