From 56b6f4792bf814812e63876f38b3da51d6b87c65 Mon Sep 17 00:00:00 2001 From: frozenwizard <172203+frozenwizard@users.noreply.github.com> Date: Sat, 1 Feb 2025 19:13:45 -0600 Subject: [PATCH 1/3] Upgrading micropython release to 1.27.0 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 05c1c3d..43b9e95 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ setup-python-env: ## Setups python dev environment .PHONY: setup setup: ## Downloads and setups required dependencies mkdir micropython - wget -P micropython https://micropython.org/resources/firmware/rp2-pico-w-20230426-v1.20.0.uf2 + wget -P micropython https://micropython.org/resources/firmware/RPI_PICO2-20241129-v1.24.1.uf2 mkdir temp cp src/config.py.template src/settings.py From 0291554ac961cb6efe721149bdc7073e6f880f3d Mon Sep 17 00:00:00 2001 From: frozenwizard <172203+frozenwizard@users.noreply.github.com> Date: Sat, 3 Jan 2026 00:12:38 -0600 Subject: [PATCH 2/3] uasyncio -> asyncio and tweaks --- Makefile | 2 +- main.py | 4 ++-- src/gunpla/nu_gundam.py | 8 ++++---- src/gunpla/unicorn_banshee.py | 4 ++-- src/hardware/Hardware.py | 1 - src/hardware/Networking.py | 4 ++-- src/hardware/PicoHardwre.py | 12 ++++++------ src/hardware/VirtualHardware.py | 3 +-- src/pi/led_effect.py | 16 ++++++++-------- src/server/RouteDecorator.py | 6 +++--- src/server/microdot/Microdot.py | 20 ++++++++++---------- src/server/webserver.py | 10 +++++----- tests/LocalServerTest.py | 4 ++-- 13 files changed, 46 insertions(+), 48 deletions(-) diff --git a/Makefile b/Makefile index 43b9e95..6110bc7 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ setup-python-env: ## Setups python dev environment .PHONY: setup setup: ## Downloads and setups required dependencies mkdir micropython - wget -P micropython https://micropython.org/resources/firmware/RPI_PICO2-20241129-v1.24.1.uf2 + wget -P micropython https://micropython.org/resources/firmware/RPI_PICO_W-20251209-v1.27.0.uf2 mkdir temp cp src/config.py.template src/settings.py diff --git a/main.py b/main.py index 0e5dafd..713fb7f 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -import uasyncio +import asyncio import src from src import settings @@ -9,7 +9,7 @@ def main(): hardware: Hardware = src.hardware.get_hardware() webserver = WebServer(settings.webserver, hardware) - uasyncio.run( webserver.run()) + asyncio.run( webserver.run()) if __name__ == "__main__": diff --git a/src/gunpla/nu_gundam.py b/src/gunpla/nu_gundam.py index 1ac995b..165527a 100644 --- a/src/gunpla/nu_gundam.py +++ b/src/gunpla/nu_gundam.py @@ -1,6 +1,6 @@ import random -import uasyncio +import asyncio from src.gunpla.base_gundam import BaseGundam from src.pi.led_effect import LEDEffects @@ -24,9 +24,9 @@ async def activation(self) -> None: """ head_led = self._get_led_from_name("head") head_led.on() - await uasyncio.sleep(0.1) + await asyncio.sleep(0.1) head_led.off() - await uasyncio.sleep(0.5) + await asyncio.sleep(0.5) await LEDEffects.brighten(head_led) async def fire_funnels(self) -> None: @@ -52,4 +52,4 @@ async def random_funnels(self) -> None: while True: funnel = random.choice(funnels) await LEDEffects.charge_fire(funnel) - await uasyncio.sleep(random.uniform(0, 3)) + await asyncio.sleep(random.uniform(0, 3)) diff --git a/src/gunpla/unicorn_banshee.py b/src/gunpla/unicorn_banshee.py index 31879bc..e4ee1cc 100644 --- a/src/gunpla/unicorn_banshee.py +++ b/src/gunpla/unicorn_banshee.py @@ -1,4 +1,4 @@ -import uasyncio +import asyncio from src.gunpla.base_gundam import BaseGundam from src.pi.led_effect import LEDEffects @@ -20,5 +20,5 @@ async def glow(self) -> None: Runs the glow lightshow """ await LEDEffects.brighten_all(self.get_all_leds()) - await uasyncio.sleep(3) + await asyncio.sleep(3) self._all_leds_off() diff --git a/src/hardware/Hardware.py b/src/hardware/Hardware.py index 2163619..42a62c6 100644 --- a/src/hardware/Hardware.py +++ b/src/hardware/Hardware.py @@ -17,7 +17,6 @@ def get_pwm(self, pin_obj): def reset_pin(self, pin_num): raise NotImplementedError - @property def networking(self) -> Networking: raise NotImplementedError diff --git a/src/hardware/Networking.py b/src/hardware/Networking.py index 6798760..5cfc6e5 100644 --- a/src/hardware/Networking.py +++ b/src/hardware/Networking.py @@ -1,4 +1,4 @@ -import uasyncio +import asyncio class Networking: @@ -38,7 +38,7 @@ async def connect_to_wifi(self, ssid: str, password: str, attempts=10) -> str: print(f"Connected to {ssid}") return wlan.ifconfig()[0] # Wait to retry - await uasyncio.sleep(1) + await asyncio.sleep(1) print("WiFi failed") raise Exception("WiFi connection failed") diff --git a/src/hardware/PicoHardwre.py b/src/hardware/PicoHardwre.py index 8db8fb0..7b5a45e 100644 --- a/src/hardware/PicoHardwre.py +++ b/src/hardware/PicoHardwre.py @@ -12,17 +12,17 @@ def __init__(self): from machine import PWM, Pin self.Pin = Pin self.PWM = PWM - self.networking = Networking() - self.board_led = BoardLED() + self._networking = Networking() + self._board_led = BoardLED() - def networking(self): + def networking(self) -> Networking: """ :return: networking """ - return self.networking + return self._networking - def board_led(self): - return self.board_led + def board_led(self) -> BoardLED: + return self._board_led def get_pin(self, pin_num, mode="OUT"): # machine.Pin.OUT is an integer constant diff --git a/src/hardware/VirtualHardware.py b/src/hardware/VirtualHardware.py index 541103a..ca8c031 100644 --- a/src/hardware/VirtualHardware.py +++ b/src/hardware/VirtualHardware.py @@ -48,7 +48,7 @@ class NoOpNetworking(Networking): def __init__(self): pass - async def connect_to_wifi(self, ssid: str, password: str, attempts=10) -> str or None: + async def connect_to_wifi(self, ssid: str, password: str, attempts=10) -> str: return "123.123.123.123" def configure_host(self, host_name: str): @@ -76,7 +76,6 @@ def get_pwm(self, pin_obj): def board_led(self) -> BoardLED: return self.MockBoardLED() - @property def networking(self) -> Networking: return self.NoOpNetworking() diff --git a/src/pi/led_effect.py b/src/pi/led_effect.py index 59e1f63..4acaee6 100644 --- a/src/pi/led_effect.py +++ b/src/pi/led_effect.py @@ -1,6 +1,6 @@ import time -import uasyncio +import asyncio import src.hardware from src.pi import LED @@ -19,9 +19,9 @@ async def blink(led: LED) -> None: led.on() time.sleep(0.5) led.off() - await uasyncio.sleep(0.5) + await asyncio.sleep(0.5) led.on() - await uasyncio.sleep(0.5) + await asyncio.sleep(0.5) led.off() @staticmethod @@ -32,7 +32,7 @@ async def fire(led: LED) -> None: :return: """ led.on() - await uasyncio.sleep(.5) + await asyncio.sleep(.5) led.off() @staticmethod @@ -42,10 +42,10 @@ async def charge_fire(led: LED, charge_speed: int = 1) -> None: """ await LEDEffects.brighten(led, start_percent=0, end_percent=75, speed=charge_speed) led.off() - await uasyncio.sleep(0.5) + await asyncio.sleep(0.5) # LEDEffects.brighten(led, start_percent=75, end_percent=100, speed=1) led.on() - await uasyncio.sleep(2) + await asyncio.sleep(2) led.off() @staticmethod @@ -70,7 +70,7 @@ async def brighten(led: LED, start_percent: int = 0, end_percent: int = 100, spe for percent in range(start_percent, end_percent, step_rate): duty = int((percent / 100) * 65_535) pwm.duty_u16(duty) - await uasyncio.sleep(sleep_time) + await asyncio.sleep(sleep_time) pwm.deinit() @staticmethod @@ -97,7 +97,7 @@ async def brighten_all(leds: list[LED], start_percent: int = 0, end_percent: int duty = int((percent / 100) * 65_535) for pwm in pwms: pwm.duty_u16(duty) - await uasyncio.sleep(sleep_time) + await asyncio.sleep(sleep_time) for pwm in pwms: pwm.deinit() diff --git a/src/server/RouteDecorator.py b/src/server/RouteDecorator.py index 18c5f80..e9f2a19 100644 --- a/src/server/RouteDecorator.py +++ b/src/server/RouteDecorator.py @@ -1,4 +1,4 @@ -import uasyncio +import asyncio def lightshow_route(gunpla, manager_attr="current_task"): @@ -15,11 +15,11 @@ async def wrapper(request, *args, **kwargs): try: gunpla.all_off() await existing_task # Wait for cleanup - except uasyncio.CancelledError: + except asyncio.CancelledError: pass # Start the new show and track it - task = uasyncio.create_task(func()) + task = asyncio.create_task(func()) setattr(gunpla, manager_attr, task) # Return common HTTP response that the show started. diff --git a/src/server/microdot/Microdot.py b/src/server/microdot/Microdot.py index 33e402b..da55b37 100644 --- a/src/server/microdot/Microdot.py +++ b/src/server/microdot/Microdot.py @@ -9,7 +9,7 @@ import re import time -import uasyncio +import asyncio try: import orjson as json @@ -28,7 +28,7 @@ async def invoke_handler(handler, *args, **kwargs): if iscoroutinefunction(handler): ret = await handler(*args, **kwargs) else: - ret = await uasyncio.get_running_loop().run_in_executor( + ret = await asyncio.get_running_loop().run_in_executor( None, partial(handler, *args, **kwargs)) return ret except ImportError: # pragma: no cover @@ -38,7 +38,7 @@ def iscoroutine(coro): async def invoke_handler(handler, *args, **kwargs): """Invoke a handler and return the result. - This method runs sync handlers in the uasyncio thread, which can + This method runs sync handlers in the asyncio thread, which can potentially cause blocking and performance issues. """ ret = handler(*args, **kwargs) @@ -1240,7 +1240,7 @@ async def start_server(self, host='0.0.0.0', port=5000, debug=False, Example:: - import uasyncio + import asyncio from microdot import Microdot app = Microdot() @@ -1252,7 +1252,7 @@ async def index(request): async def main(): await app.start_server(debug=True) - uasyncio.run(main()) + asyncio.run(main()) """ self.ssl = ssl self.debug = debug @@ -1279,24 +1279,24 @@ async def aclose(self): host=host, port=port)) try: - self.server = await uasyncio.start_server(serve, host, port, + self.server = await asyncio.start_server(serve, host, port, ssl=ssl) except TypeError: # pragma: no cover - self.server = await uasyncio.start_server(serve, host, port) + self.server = await asyncio.start_server(serve, host, port) while True: try: if hasattr(self.server, 'serve_forever'): # pragma: no cover try: await self.server.serve_forever() - except uasyncio.CancelledError: + except asyncio.CancelledError: pass await self.server.wait_closed() break except AttributeError: # pragma: no cover # the task hasn't been initialized in the server object yet # wait a bit and try again - await uasyncio.sleep(0.1) + await asyncio.sleep(0.1) def run(self, host='0.0.0.0', port=5000, debug=False, ssl=None): """Start the web server. This function does not normally return, as @@ -1329,7 +1329,7 @@ async def index(request): app.run(debug=True) """ - uasyncio.run(self.start_server(host=host, port=port, debug=debug, + asyncio.run(self.start_server(host=host, port=port, debug=debug, ssl=ssl)) # pragma: no cover def shutdown(self): diff --git a/src/server/webserver.py b/src/server/webserver.py index f763de9..a48762d 100644 --- a/src/server/webserver.py +++ b/src/server/webserver.py @@ -1,6 +1,6 @@ import sys -import uasyncio +import asyncio from src.gunpla.generic_gundam import GenericGundam from src.hardware.Hardware import Hardware @@ -33,14 +33,14 @@ async def canary(self, request: Request): """ Sanity check to make sure webserver is running. """ - uasyncio.create_task(LEDEffects.blink(self.hardware.board_led)) + asyncio.create_task(LEDEffects.blink(self.hardware.board_led)) return "chirp", 202 async def _connect_to_wifi(self): - ipaddress: str = await self.hardware.networking.connect_to_wifi(self.settings['ssid'], self.settings['password']) + ipaddress: str = await self.hardware.networking().connect_to_wifi(self.settings['ssid'], self.settings['password']) if ipaddress: print(f"Server started on {ipaddress}") - await LEDEffects.blink(self.hardware.board_led) + await LEDEffects.blink(self.hardware.board_led()) else: print("Server failed to connect") sys.exit("Cannot start server") @@ -50,7 +50,7 @@ async def run(self): Main runner of the webserver. Loads configurations, paths, connects to wifi and runs the server """ - self.hardware.networking.configure_host(self.settings['hostname']) + self.hardware.networking().configure_host(self.settings['hostname']) await self._connect_to_wifi() self._add_routes() diff --git a/tests/LocalServerTest.py b/tests/LocalServerTest.py index 011c137..27377b6 100644 --- a/tests/LocalServerTest.py +++ b/tests/LocalServerTest.py @@ -1,7 +1,7 @@ import json -import uasyncio +import asyncio from src.gunpla.generic_gundam import GenericGundam from src.hardware.VirtualHardware import VirtualHardware @@ -55,7 +55,7 @@ def main(): } webserver = WebServer(test_settings, VirtualHardware()) - uasyncio.run(webserver.run()) + asyncio.run(webserver.run()) if __name__ == "__main__": From 9951b9294189a24db23f0d4e80798763bfde2fd2 Mon Sep 17 00:00:00 2001 From: frozenwizard <172203+frozenwizard@users.noreply.github.com> Date: Sat, 3 Jan 2026 00:15:11 -0600 Subject: [PATCH 3/3] import order --- src/gunpla/nu_gundam.py | 3 +-- src/pi/led_effect.py | 3 +-- src/server/microdot/Microdot.py | 7 +++---- src/server/webserver.py | 3 +-- tests/LocalServerTest.py | 3 +-- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/gunpla/nu_gundam.py b/src/gunpla/nu_gundam.py index 165527a..165129c 100644 --- a/src/gunpla/nu_gundam.py +++ b/src/gunpla/nu_gundam.py @@ -1,6 +1,5 @@ -import random - import asyncio +import random from src.gunpla.base_gundam import BaseGundam from src.pi.led_effect import LEDEffects diff --git a/src/pi/led_effect.py b/src/pi/led_effect.py index 4acaee6..0a7ac92 100644 --- a/src/pi/led_effect.py +++ b/src/pi/led_effect.py @@ -1,6 +1,5 @@ -import time - import asyncio +import time import src.hardware from src.pi import LED diff --git a/src/server/microdot/Microdot.py b/src/server/microdot/Microdot.py index da55b37..04da2ec 100644 --- a/src/server/microdot/Microdot.py +++ b/src/server/microdot/Microdot.py @@ -5,12 +5,11 @@ The ``microdot`` module defines a few classes that help implement HTTP-based servers for MicroPython and standard Python. """ +import asyncio import io import re import time -import asyncio - try: import orjson as json except ImportError: @@ -1280,7 +1279,7 @@ async def aclose(self): try: self.server = await asyncio.start_server(serve, host, port, - ssl=ssl) + ssl=ssl) except TypeError: # pragma: no cover self.server = await asyncio.start_server(serve, host, port) @@ -1330,7 +1329,7 @@ async def index(request): app.run(debug=True) """ asyncio.run(self.start_server(host=host, port=port, debug=debug, - ssl=ssl)) # pragma: no cover + ssl=ssl)) # pragma: no cover def shutdown(self): """Request a server shutdown. The server will then exit its request diff --git a/src/server/webserver.py b/src/server/webserver.py index a48762d..025cd63 100644 --- a/src/server/webserver.py +++ b/src/server/webserver.py @@ -1,6 +1,5 @@ -import sys - import asyncio +import sys from src.gunpla.generic_gundam import GenericGundam from src.hardware.Hardware import Hardware diff --git a/tests/LocalServerTest.py b/tests/LocalServerTest.py index 27377b6..9d74f6d 100644 --- a/tests/LocalServerTest.py +++ b/tests/LocalServerTest.py @@ -1,7 +1,6 @@ -import json - import asyncio +import json from src.gunpla.generic_gundam import GenericGundam from src.hardware.VirtualHardware import VirtualHardware