Add ESPNow preset send backend support
Implement ESPNow helper model, WebSocket forwarding, and /presets/send endpoint that chunks and broadcasts presets to devices.
This commit is contained in:
61
src/models/espnow.py
Normal file
61
src/models/espnow.py
Normal file
@@ -0,0 +1,61 @@
|
||||
import aioespnow
|
||||
|
||||
|
||||
class ESPNow:
|
||||
"""
|
||||
Singleton ESPNow helper:
|
||||
- Manages a single AIOESPNow instance
|
||||
- Adds a single broadcast-like peer
|
||||
- Exposes async send(data) to send to that peer.
|
||||
"""
|
||||
|
||||
_instance = None
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
if getattr(self, "_initialized", False):
|
||||
return
|
||||
|
||||
# Initialize ESPNow once (no disk persistence)
|
||||
self._esp = aioespnow.AIOESPNow()
|
||||
self._esp.active(True)
|
||||
|
||||
|
||||
try:
|
||||
self._esp.add_peer(b"\xff\xff\xff\xff\xff\xff")
|
||||
except Exception:
|
||||
# Ignore add_peer failures (e.g. duplicate)
|
||||
pass
|
||||
|
||||
self._initialized = True
|
||||
|
||||
|
||||
async def send(self, data):
|
||||
"""
|
||||
Async send to the broadcast peer.
|
||||
- data: bytes or str (JSON)
|
||||
"""
|
||||
if isinstance(data, str):
|
||||
payload = data.encode()
|
||||
else:
|
||||
payload = data
|
||||
|
||||
# Debug: show what we're sending and its size
|
||||
try:
|
||||
preview = payload.decode('utf-8')
|
||||
except Exception:
|
||||
preview = str(payload)
|
||||
if len(preview) > 200:
|
||||
preview = preview[:200] + "...(truncated)"
|
||||
print("ESPNow.send len=", len(payload), "payload=", preview)
|
||||
|
||||
try:
|
||||
await self._esp.asend(b"\xff\xff\xff\xff\xff\xff", payload)
|
||||
except Exception as e:
|
||||
# Log send failures but don't crash the app
|
||||
print("ESPNow.send error:", e)
|
||||
|
||||
Reference in New Issue
Block a user