"""NeoPixel mock for Pyodide/browser execution. Supports a useful subset of MicroPython's neopixel.NeoPixel API: - NeoPixel(pin, n, bpp=3, timing=1) - __setitem__, __getitem__, __len__ - fill(color) - write() # prints current pixel buffer snapshot """ import json def _normalize_color(value, bpp: int): if not hasattr(value, "__iter__"): raise TypeError("Color must be an iterable, e.g. (r, g, b)") parts = [int(v) for v in value] if len(parts) != bpp: raise ValueError(f"Expected {bpp} color channels, got {len(parts)}") out = [] for channel in parts: out.append(max(0, min(255, channel))) return tuple(out) class NeoPixel: def __init__(self, pin, n: int, bpp: int = 3, timing: int = 1): self.pin = pin self.n = int(n) self.bpp = int(bpp) self.timing = int(timing) self._buf = [tuple([0] * self.bpp) for _ in range(self.n)] def __len__(self): return self.n def __getitem__(self, index): return self._buf[int(index)] def __setitem__(self, index, color): idx = int(index) self._buf[idx] = _normalize_color(color, self.bpp) def fill(self, color): c = _normalize_color(color, self.bpp) for i in range(self.n): self._buf[i] = c def write(self): pin_id = getattr(self.pin, "id", self.pin) payload = { "type": "neopixel", "pin": pin_id, "pixels": [list(pixel) for pixel in self._buf], "bpp": self.bpp, } print("[neopixel-json]" + json.dumps(payload))