Skip to content

Commit bced50f

Browse files
committed
Address PR comment with HTTP lib refactor
1 parent dc9f398 commit bced50f

File tree

1 file changed

+73
-16
lines changed

1 file changed

+73
-16
lines changed

badge/apps/wled/__init__.py

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,76 @@
99
import network
1010
import gc
1111

12+
# ---------------------------------------------------------------------------
13+
# Standardized HTTP helper
14+
# ---------------------------------------------------------------------------
15+
# A tiny wrapper (`rq`) mimics the minimal subset of the urequests interface
16+
# used here (get/post + status_code/text/close) while keeping memory usage low.
17+
18+
try: # MicroPython-provided lightweight HTTP client
19+
from urllib.urequest import urlopen # type: ignore
20+
except ImportError: # Extremely unlikely on badge firmware; handled gracefully
21+
urlopen = None # type: ignore
22+
23+
24+
class _HTTPResponse:
25+
"""Minimal response object exposing .status_code, .text, .close().
26+
27+
Text is lazily decoded to avoid allocating unless needed. If decoding fails,
28+
raw bytes are returned (repr-safe for small payloads)."""
29+
30+
def __init__(self, raw, status=200):
31+
self._raw = raw
32+
self.status_code = getattr(raw, "status", status)
33+
self._text = None
34+
35+
@property
36+
def text(self):
37+
if self._text is None:
38+
try:
39+
# Some MicroPython builds return bytes; decode defensively.
40+
data = self._raw.read()
41+
if isinstance(data, bytes):
42+
try:
43+
self._text = data.decode()
44+
except Exception:
45+
self._text = data.decode("utf-8", "ignore")
46+
else: # already str
47+
self._text = data
48+
except Exception:
49+
self._text = ""
50+
return self._text
51+
52+
def close(self):
53+
try:
54+
if hasattr(self._raw, "close"):
55+
self._raw.close()
56+
except Exception:
57+
pass
58+
59+
60+
class rq: # Mimic minimal urequests-like interface used by this app
61+
@staticmethod
62+
def get(url, timeout=2): # timeout retained for signature compatibility
63+
if urlopen is None:
64+
raise ImportError("urllib.urequest unavailable")
65+
# MicroPython's urlopen may ignore timeout; acceptable for short badge calls.
66+
raw = urlopen(url)
67+
return _HTTPResponse(raw)
68+
69+
@staticmethod
70+
def post(url, data=None, headers=None, timeout=2):
71+
if urlopen is None:
72+
raise ImportError("urllib.urequest unavailable")
73+
# Encode string payload to bytes when needed.
74+
if isinstance(data, str):
75+
data_bytes = data.encode()
76+
else:
77+
data_bytes = data
78+
# MicroPython's urlopen accepts headers as dict (not list of tuples)
79+
raw = urlopen(url, data=data_bytes, headers=headers)
80+
return _HTTPResponse(raw)
81+
1282
# Load fonts - use smaller, more compact fonts
1383
small_font = PixelFont.load("/system/assets/fonts/ark.ppf")
1484

@@ -224,20 +294,14 @@ def send_wled_command(data, timeout=2):
224294
try:
225295
import json
226296
url = f"http://{WLED_HOST}/json/state"
227-
try:
228-
import urequests as rq
229-
except ImportError:
230-
from urllib import urequest as rq # type: ignore
231297
payload = json.dumps(data)
232298
headers = {"Content-Type": "application/json"}
233299
resp = rq.post(url, data=payload, headers=headers, timeout=timeout)
234300
success = resp.status_code in (200, 201)
301+
# Ensure we release underlying resources early.
235302
resp.close()
236303
in_flight = False
237-
if success:
238-
status_message = "Command sent"
239-
else:
240-
status_message = f"HTTP {resp.status_code}"
304+
status_message = "Command sent" if success else f"HTTP {resp.status_code}"
241305
return success
242306
except Exception as e:
243307
in_flight = False
@@ -261,18 +325,11 @@ def http_request(path, timeout=1):
261325
return None
262326
try:
263327
url = f"http://{WLED_HOST}{path}"
264-
try:
265-
import urequests as rq
266-
except ImportError:
267-
from urllib import urequest as rq # type: ignore
268-
# Use a short timeout so we don't freeze the render loop for long
269328
resp = rq.get(url, timeout=timeout)
270329
if resp.status_code == 200:
271330
try:
272-
# Try to read raw text first to see what we got
273-
raw_text = resp.text
331+
raw_text = resp.text # Lazily decoded
274332
resp.close()
275-
# Now try to parse it
276333
import json
277334
data = json.loads(raw_text)
278335
wled_connected = True

0 commit comments

Comments
 (0)