Compare commits

4 Commits

Author SHA1 Message Date
df808f4ffa Add wifi ip and gateway 2024-12-11 22:42:56 +13:00
f23d040236 Upload files individually 2024-12-11 22:41:16 +13:00
12be71ae47 Move to src folder 2024-12-07 21:47:43 +13:00
acba80b958 Add mpremote 2024-12-07 21:42:50 +13:00
12 changed files with 299 additions and 39 deletions

27
boot.py
View File

@@ -1,27 +0,0 @@
import network
from machine import Pin
from config import *
def do_connect():
led = Pin(8, Pin.OUT)
sta_if = network.WLAN(network.STA_IF)
sta_if.ifconfig((ip, '255.255.255.0', gateway, '1.1.1.1'))
if not sta_if.isconnected():
print('connecting to network...')
sta_if.active(True)
sta_if.connect(ssid, password)
led.on()
while not sta_if.isconnected():
pass
print('network config:', sta_if.ifconfig())
do_connect()
ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid="led", password="qwerty1234")
print(ap.ifconfig())

21
dev.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
# Reset the MicroPython device
mpremote reset || { echo "Failed to reset device"; exit 1; }
# Loop through all files in ./src recursively
find ./src -type f | while read -r file; do
filename=$(basename "$file") # Extract filename from full path
# Skip copying settings.json
if [ "$filename" == "settings.json" ]; then
echo "Skipping $filename"
continue
fi
echo "Copying $filename"
mpremote cp "$file" :$filename || { echo "Failed to copy $filename"; exit 1; }
done
# Run the main.py script on the MicroPython device
mpremote run src/main.py || { echo "Failed to run main.py"; exit 1; }

36
src/boot.py Normal file
View File

@@ -0,0 +1,36 @@
# import network
# from machine import Pin
# from config import *
# from time import sleep
# import ubinascii
# def do_connect():
# led = Pin(8, Pin.OUT)
# sta_if = network.WLAN(network.STA_IF)
# sta_if.ifconfig((ip, '255.255.255.0', gateway, '1.1.1.1'))
# if not sta_if.isconnected():
# print('connecting to network...')
# sta_if.active(True)
# sta_if.connect(ssid, password)
# led.on()
# for i in range(10):
# if sta_if.isconnected():
# print('network config:', sta_if.ifconfig())
# led.off()
# break
# sleep(1)
# do_connect()
# ap = network.WLAN(network.AP_IF)
# ap.active(True)
# ap_mac = ap.config('mac')
# ssid = f"led-{ubinascii.hexlify(ap_mac).decode()}"
# print(ssid)
# ap.config(essid=ssid, password="qwerty1234")
# print(ap.ifconfig())

27
src/esp_now.py Normal file
View File

@@ -0,0 +1,27 @@
import network
import espnow
import select
# A WLAN interface must be active to send()/recv()
ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.disconnect() # Because ESP8266 auto-connects to last Access Point
ap_mac = ap.config('mac')
print(ap_mac)
print(ubinascii.hexlify(ap_mac))
e = espnow.ESPNow()
e.active(True)
poll = select.poll()
poll.register(e, select.POLLIN)
poll.poll(0)
while True:
for event in poll.poll(0) :
if event[0] == e:
host, msg = e.recv()
if msg: # msg == None if timeout in recv()
print(host, msg)

View File

@@ -53,6 +53,12 @@
<label for="password">Wi-Fi Password:</label> <label for="password">Wi-Fi Password:</label>
<input type="password" id="password" name="password"> <input type="password" id="password" name="password">
<br> <br>
<label for="ip">Wi-Fi IP:</label>
<input type="ip" id="ip" name="ip" value="{ip}">
<br>
<label for="gateway">Wi-Fi Gateway:</label>
<input type="gateway" id="gateway" name="gateway" value="{gateway}">
<br>
<input type="submit" value="Save Wi-Fi Settings"> <input type="submit" value="Save Wi-Fi Settings">
</form> </form>
</div> </div>

View File

@@ -8,6 +8,7 @@ body {
h1 { h1 {
text-align: center; text-align: center;
} }
form { form {
margin-bottom: 20px; margin-bottom: 20px;
} }

View File

@@ -84,8 +84,17 @@ async function updateWifi(event) {
event.preventDefault(); event.preventDefault();
const ssid = document.getElementById('ssid').value; const ssid = document.getElementById('ssid').value;
const password = document.getElementById('password').value; const password = document.getElementById('password').value;
const ip = document.getElementById('ip').value;
const gateway = document.getElementById('gateway').value;
if(!ssid || !password) {
alert("Missing ssid or password");
return;
}
console.log(ssid, password); console.log(ssid, password);
//await post('/num_leds', numLeds); const response = await post('/wifi_settings', ssid+"\n"+password+"\n"+ip+"\n"+gateway);
if(response === 500) {
alert("Failed to connect to wifi");
}
} }
function createPatternButtons(patterns) { function createPatternButtons(patterns) {

View File

@@ -1,4 +1,4 @@
from machine import Pin from machine import Pin, reset
from patterns import Patterns from patterns import Patterns
from settings import Settings from settings import Settings
import socket import socket
@@ -6,6 +6,8 @@ import select
import json import json
import utime import utime
import sys import sys
import espnow
import wifi
class LEDServer: class LEDServer:
SETTINGS_FILE = "/settings.json" # Path should be adjusted for MicroPython's filesystem SETTINGS_FILE = "/settings.json" # Path should be adjusted for MicroPython's filesystem
@@ -15,10 +17,13 @@ class LEDServer:
self.settings = Settings() self.settings = Settings()
print(self.settings) print(self.settings)
self.patterns = Patterns(pin, num_leds) self.patterns = Patterns(pin, self.settings["num_leds"])
self.patterns.select(self.settings["selected_pattern"]) self.patterns.select(self.settings["selected_pattern"])
self.patterns.set_color1(tuple(int(self.settings["color1"][i:i+2], 16) for i in (1, 5, 3))) self.patterns.set_color1(tuple(int(self.settings["color1"][i:i+2], 16) for i in (1, 5, 3)))
self.patterns.set_color2(tuple(int(self.settings["color2"][i:i+2], 16) for i in (1, 5, 3))) self.patterns.set_color2(tuple(int(self.settings["color2"][i:i+2], 16) for i in (1, 5, 3)))
self.patterns.set_brightness(int(self.settings["brightness"]))
self.patterns.set_delay(int(self.settings["delay"]))
# Initialize single LED # Initialize single LED
self.led = Pin(led_pin, Pin.OUT) self.led = Pin(led_pin, Pin.OUT)
@@ -29,16 +34,32 @@ class LEDServer:
self.server_socket.listen(1) self.server_socket.listen(1)
self.server_socket.settimeout(1) # Adjust timeout as needed self.server_socket.settimeout(1) # Adjust timeout as needed
self.e = espnow.ESPNow()
self.e.active(True)
self.poll = select.poll() self.poll = select.poll()
self.poll.register(self.server_socket, select.POLLIN) self.poll.register(self.server_socket, select.POLLIN)
self.poll.register(self.e, select.POLLIN)
self.html = self.read_file("/index.html") self.html = self.read_file("/index.html")
self.js = self.read_file("/main.js").encode('utf-8') self.js = self.read_file("/main.js").encode('utf-8')
self.css = self.read_file("/main.css").encode('utf-8') self.css = self.read_file("/main.css").encode('utf-8')
self.patterns_json = json.dumps(list(self.patterns.patterns.keys())) self.patterns_json = json.dumps(list(self.patterns.patterns.keys()))
ssid = self.settings["wifi"]["ssid"]
password = self.settings["wifi"]["password"]
ip = self.settings.get("wifi", {}).get("ip", None)
gateway = self.settings.get("wifi", {}).get("gateway", None)
wifi.ap(password="qwerty")
config = wifi.do_connect(ssid, password, ip, gateway)
if config is not None:
print(config)
def read_file(self, file_path): def read_file(self, file_path):
try: try:
with open(file_path, 'r') as file: with open(file_path, 'r') as file:
@@ -55,7 +76,9 @@ class LEDServer:
"/delay": self.delay, "/delay": self.delay,
"/brightness": self.brightness, "/brightness": self.brightness,
"/color": self.color, "/color": self.color,
"/color2": self.color2 "/color2": self.color2,
"/wifi_settings": self.wifi_settings,
"set_leds": self.set_leds
} }
if path in paths: if path in paths:
@@ -103,7 +126,7 @@ class LEDServer:
def color(self, client_socket, post_data): def color(self, client_socket, post_data):
try: try:
self.patterns.set_color1(tuple(int(post_data[i:i+2], 16) for i in (1, 5, 3))) # Convert hex to RGB self.patterns.set_color1(tuple(int(post_data[i:i+2], 16) for i in (1, 3, 5))) # Convert hex to RGB
self.settings["color1"] = post_data self.settings["color1"] = post_data
self.settings.save() self.settings.save()
client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n') client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n')
@@ -112,15 +135,47 @@ class LEDServer:
def color2(self, client_socket, post_data): def color2(self, client_socket, post_data):
try: try:
self.patterns.set_color2(tuple(int(post_data[i:i+2], 16) for i in (1, 5, 3))) # Convert hex to RGB self.patterns.set_color2(tuple(int(post_data[i:i+2], 16) for i in (1, 3, 5))) # Convert hex to RGB
self.settings["color2"] = post_data self.settings["color2"] = post_data
self.settings.save() self.settings.save()
client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n') client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n')
except: except:
client_socket.send(b'HTTP/1.0 400 Bad request\r\n\r\n') client_socket.send(b'HTTP/1.0 400 Bad request\r\n\r\n')
def wifi_settings(self, client_socket, post_data):
try:
lines = post_data.split('\n')
ssid, password, ip, gateway = (lines + ["", "", None, None])[:4]
self.settings["wifi"]["ssid"] = ssid
self.settings["wifi"]["password"] = password
self.settings["wifi"]["ip"] = ip
self.settings["wifi"]["gateway"] = gateway
self.settings.save()
self.settings.load()
print(self.settings)
print(ssid, password)
config = wifi.do_connect(ssid, password, ip ,gateway)
if config is not None:
print(config)
client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n')
else:
client_socket.send(b'HTTP/1.0 500 Failed to connect to wifi\r\n\r\n')
except ValueError:
client_socket.send(b'HTTP/1.0 400 Bad request\r\n\r\n')
def set_leds(self, client_socket, post_data):
if len(post_data == self.settings["num_leds"]*3):
print(post_data)
self.patterns.set(0, (255,255,255))
else:
print("Wrong number of leds")
def handle_get(self, path, client_socket): def handle_get(self, path, client_socket):
if path == "/": if path == "/":
print(self.settings)
client_socket.send(b'HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') client_socket.send(b'HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
client_socket.send(self.html.format( client_socket.send(self.html.format(
num_leds=self.settings["num_leds"], num_leds=self.settings["num_leds"],
@@ -128,7 +183,12 @@ class LEDServer:
brightness=self.settings["brightness"], brightness=self.settings["brightness"],
color=self.settings["color1"], color=self.settings["color1"],
color2=self.settings["color2"], color2=self.settings["color2"],
ssid=self.settings["wifi"]["ssid"]).encode()) ssid=self.settings["wifi"]["ssid"],
password=self.settings["wifi"]["password"],
ip=self.settings.get("wifi", {}).get("ip", ""),
gateway=self.settings.get("wifi", {}).get("gateway", "").encode() # Only encode if it's a string
))
elif path == "/main.js": elif path == "/main.js":
client_socket.send(b'HTTP/1.0 200 OK\r\nContent-type: application/javascript\r\n\r\n') client_socket.send(b'HTTP/1.0 200 OK\r\nContent-type: application/javascript\r\n\r\n')
client_socket.send(self.js) client_socket.send(self.js)
@@ -148,7 +208,7 @@ class LEDServer:
try: try:
while True: while True:
count += 1 count += 1
events = self.poll.poll(1) events = self.poll.poll(0)
for file in events: for file in events:
if file[0] == self.server_socket: if file[0] == self.server_socket:
client_socket, addr = self.server_socket.accept() client_socket, addr = self.server_socket.accept()
@@ -161,6 +221,10 @@ class LEDServer:
elif method == "GET": elif method == "GET":
self.handle_get(path, client_socket) self.handle_get(path, client_socket)
client_socket.close() client_socket.close()
elif file[0] == self.e:
host, msg = self.e.recv()
if msg: # msg == None if timeout in recv()
print(host, msg)
if count > 50: if count > 50:
self.led.off() self.led.off()
@@ -176,8 +240,12 @@ class LEDServer:
sys.print_exception(e) sys.print_exception(e)
finally: finally:
self.server_socket.close() self.server_socket.close()
self.settings.save()
def main():
server = LEDServer()
server.start()
# Example of creating and starting the server # Example of creating and starting the server
if __name__ == "__main__": if __name__ == "__main__":
server = LEDServer() main()
server.start()

View File

@@ -60,6 +60,12 @@ class Patterns:
return True return True
return False return False
def set(self, i, color):
self.n[i] = color
def write(self):
self.n.write()
def fill(self): def fill(self):
for i in range(self.num_leds): for i in range(self.num_leds):
self.n[i] = self.color1 self.n[i] = self.color1

View File

@@ -34,7 +34,7 @@ class Settings(dict):
self.update(loaded_settings) self.update(loaded_settings)
print("Settings loaded successfully.") print("Settings loaded successfully.")
except Exception as e: except Exception as e:
print(f"Error loading settings: {e}") print(f"Error loading settings")
self.set_defaults() self.set_defaults()
# Example usage # Example usage

62
src/web.py Normal file
View File

@@ -0,0 +1,62 @@
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-w-asynchronous-web-server-micropython/
# Import necessary modules
import network
import asyncio
import socket
import time
import random
from machine import Pin
# Asynchronous functio to handle client's requests
async def handle_client(reader, writer):
global state
print("Client connected")
request_line = await reader.readline()
print('Request:', request_line)
# Skip HTTP request headers
while await reader.readline() != b"\r\n":
pass
request = str(request_line, 'utf-8').split()[1]
print('Request:', request)
# Generate HTML response
response = "Hello"
# Send the HTTP response and close the connection
writer.write('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
writer.write(response)
await writer.drain()
await writer.wait_closed()
print('Client Disconnected')
async def main():
# Start the server and run the event loop
print('Setting up server')
server = asyncio.start_server(handle_client, "0.0.0.0", 80)
asyncio.create_task(server)
while True:
# Add other tasks that you might need to do in the loop
await asyncio.sleep(5)
print('This message will be printed every 5 seconds')
# Create an Event Loop
loop = asyncio.get_event_loop()
# Create a task to run the main function
loop.create_task(main())
try:
# Run the event loop indefinitely
loop.run_forever()
except Exception as e:
print('Error occured: ', e)
except KeyboardInterrupt:
print('Program Interrupted by the user')

51
src/wifi.py Normal file
View File

@@ -0,0 +1,51 @@
import network
from machine import Pin
from config import *
from time import sleep
import ubinascii
def do_connect(ssid, password, ip=None, gateway=None):
led = Pin(8, Pin.OUT)
try:
sta_if = network.WLAN(network.STA_IF)
sta_if.disconnect()
print(ip, gateway)
if ip and gateway:
print(ip, gateway)
sta_if.ifconfig((ip, '255.255.255.0', gateway, '1.1.1.1'))
if not sta_if.isconnected():
print(f'connecting to network {ssid}')
sta_if.active(True)
sta_if.connect(ssid, password)
led.on()
for i in range(10):
print(f"Attempt {i}")
if sta_if.isconnected():
led.off()
return sta_if.ifconfig()
sleep(0.5)
return None
else:
return sta_if.ifconfig()
except Exception as e:
print(f"Failed to connect to wifi {e}")
return None
def ap(password):
pass
ap_if = network.WLAN(network.AP_IF)
ap_if.active(True)
ap_mac = ap_if.config('mac')
ssid = f"led-{ubinascii.hexlify(ap_mac).decode()}"
print(ssid)
ap_if.config(essid=ssid, password="qwerty1234")
print(ap_if.ifconfig())