import network
import socket
import neopixel
from machine import Pin, I2C, reset
from time import sleep
import ujson
import ssd1306
# === LED + OLED Setup ===
NUM_LEDS = 1
np = neopixel.NeoPixel(Pin(2), NUM_LEDS)
# I2C OLED
i2c = I2C(0, scl=Pin(1), sda=Pin(3))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# === Variables ===
current_color = (255, 0, 0)
brightness = 100
rainbow_mode = False
# === Functions ===
def set_led_color(color, bright):
try:
if len(color) != 3:
print("Invalid color:", color)
return
r, g, b = [int(c * (bright / 100)) for c in color]
np[0] = (r, g, b)
np.write()
except Exception as e:
print("LED color error:", e)
def save_state():
try:
with open("state.json", "w") as f:
ujson.dump({"color": current_color, "brightness": brightness, "rainbow": rainbow_mode}, f)
except Exception as e:
print("Save error:", e)
def load_state():
global current_color, brightness, rainbow_mode
try:
with open("state.json") as f:
state = ujson.load(f)
color = state.get("color", [255, 0, 0])
if isinstance(color, list):
current_color = tuple(color)
brightness = state.get("brightness", 100)
rainbow_mode = state.get("rainbow", False)
except Exception as e:
print("Load error:", e)
def update_display(status="Ready"):
oled.fill(0)
oled.text("Color: {}".format(current_color), 0, 0)
oled.text("Brightness: {}".format(brightness), 0, 10)
oled.text("Rainbow: {}".format("ON" if rainbow_mode else "OFF"), 0, 20)
oled.text(status, 0, 50)
oled.show()
# === Access Point Setup ===
ssid = "ESP32_LED"
password = "12345678"
ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid=ssid, password=password)
while not ap.active():
pass
print("AP active:", ap.ifconfig())
# === HTML Page ===
def web_page():
r, g, b = current_color
hex_color = "%02x%02x%02x" % (r, g, b)
return f"""
<html><head><title>ESP32 LED</title></head>
<body style='background:#111;color:white;text-align:center;font-family:sans-serif;'>
<h2>ESP32 LED Controller</h2>
<div style='background:#{hex_color};width:100px;height:100px;margin:auto;border:2px solid #fff;'></div>
<br><input type='color' id='colorPicker' value='#{hex_color}'><br><br>
<input type='range' id='brightness' min='0' max='100' value='{brightness}'><br>
Brightness: <span id='bval'>{brightness}</span>%<br><br>
<button onclick="fetch('/rainbow')">Toggle Rainbow</button>
<script>
const cp = document.getElementById('colorPicker');
const b = document.getElementById('brightness');
const bv = document.getElementById('bval');
cp.oninput = () => fetch('/color?hex=' + cp.value.substring(1));
b.oninput = () => {{
bv.innerText = b.value;
fetch('/brightness?val=' + b.value);
}};
</script>
</body></html>
"""
# === Web Server ===
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)
# === Initial State ===
load_state()
set_led_color(current_color, brightness)
update_display("Booted")
# === Main Loop ===
while True:
conn, addr = s.accept()
print("Client connected:", addr)
try:
request = conn.recv(1024).decode()
request = request.replace("\r", "").replace("\n", "")
if "/rainbow" in request:
rainbow_mode = not rainbow_mode
save_state()
if not rainbow_mode:
set_led_color(current_color, brightness)
update_display("Rainbow {}".format("ON" if rainbow_mode else "OFF"))
elif "/brightness?val=" in request:
try:
val = int(request.split("/brightness?val=")[1].split(" ")[0])
brightness = max(0, min(100, val))
if not rainbow_mode:
set_led_color(current_color, brightness)
save_state()
update_display("Brightness {}".format(brightness))
except Exception as e:
print("Brightness error:", e)
elif "/color?hex=" in request:
try:
hex_str = request.split("/color?hex=")[1].split(" ")[0].strip()
if len(hex_str) == 6:
color = int(hex_str, 16)
r = (color >> 16) & 0xFF
g = (color >> 8) & 0xFF
b = color & 0xFF
current_color = (r, g, b)
rainbow_mode = False
set_led_color(current_color, brightness)
save_state()
update_display("Color Set")
else:
print("Invalid hex string:", hex_str)
except Exception as e:
print("Color error:", e)
response = web_page()
conn.send("HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n")
conn.sendall(response.encode())
except Exception as e:
print("Request error:", e)
finally:
conn.close()