import sys import traceback if "--sim-serial-neo-pixels" in sys.argv: from components.dummies.serial import serial else: import serial from ctypes import c_uint32 from .component import Component C_UINT32_MAX = c_uint32(-1).value class NeoPixels(Component): def __init__(self, config=None, name=None): super().__init__(config=config, name=name, threaded=False) def config_changed(self): self.port = self.config[self.name]["port"] self.baudrate = int(self.config[self.name]["baudrate"]) self.stopbits = getattr(serial, self.config[self.name].get("stopbits", "stopbits_one").upper()) self.parity = getattr(serial, self.config[self.name].get("parity", "parity_none").upper()) self.bytesize = getattr(serial, self.config[self.name].get("bytesize", "eightbits").upper()) def set(self, pixel, color): if type(pixel) is not int or pixel < 0 or pixel > C_UINT32_MAX: raise ValueError(f"the pixel parameter must be a int between 0 and {C_UINT32_MAX} (broadcast)") if not color.startswith("#") or len(color) != 7: raise ValueError("the color parameter must be in the html hex format: '#RRGGBB'") try: conn = serial.Serial( self.port, baudrate=self.baudrate, stopbits=self.stopbits, parity=self.parity, bytesize=self.bytesize, ) conn.write(int.to_bytes(pixel, length=4, byteorder="big") + bytes.fromhex(color[1:7]) + b"\n") response = conn.readline() if response != "ok\n": self.log.error(response.strip()) conn.close() except serial.serialutil.SerialException: self.log.exception(traceback.format_exc()) def set_pixel_color(self, pixel, color): self.set(pixel, color) def set_all_pixel_color(self, color): self.set(C_UINT32_MAX, color)