2022-06-29 09:02:58 +00:00
|
|
|
import sys
|
|
|
|
|
|
2022-10-05 13:39:47 +00:00
|
|
|
from PyQt5.QtCore import QThread, pyqtSignal
|
2022-08-01 11:29:12 +00:00
|
|
|
|
2022-07-18 10:32:05 +00:00
|
|
|
if "--sim-serial" in sys.argv:
|
2022-06-29 11:04:31 +00:00
|
|
|
from components.dummies.serial import serial
|
2022-06-29 09:02:58 +00:00
|
|
|
else:
|
|
|
|
|
import serial
|
|
|
|
|
|
|
|
|
|
from ctypes import c_uint32
|
|
|
|
|
|
|
|
|
|
from .component import Component
|
|
|
|
|
|
|
|
|
|
C_UINT32_MAX = c_uint32(-1).value
|
|
|
|
|
|
|
|
|
|
|
2022-06-29 10:09:48 +00:00
|
|
|
class NeoPixels(Component):
|
2022-10-05 13:39:47 +00:00
|
|
|
request = pyqtSignal(object)
|
|
|
|
|
|
2022-06-29 09:02:58 +00:00
|
|
|
def __init__(self, config=None, name=None):
|
2022-08-01 11:29:12 +00:00
|
|
|
self.conn = None
|
2022-06-29 09:02:58 +00:00
|
|
|
super().__init__(config=config, name=name, threaded=False)
|
2022-10-05 13:39:47 +00:00
|
|
|
self.set_requestors({"self": self.request})
|
2022-06-29 09:02:58 +00:00
|
|
|
|
|
|
|
|
def config_changed(self):
|
2022-07-12 09:54:05 +00:00
|
|
|
self.port = self.config[self.name]["port"]
|
2022-06-29 09:02:58 +00:00
|
|
|
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())
|
2022-09-13 11:36:22 +00:00
|
|
|
self.read_timeout = float(self.config[self.name].get("read_timeout", 1))
|
|
|
|
|
self.write_timeout = float(self.config[self.name].get("write_timeout", 1))
|
|
|
|
|
self.inter_byte_timeout = self.config[self.name].get("inter_byte_timeout", None)
|
|
|
|
|
if self.inter_byte_timeout is not None:
|
|
|
|
|
self.inter_byte_timeout = float(self.inter_byte_timeout)
|
2022-08-01 11:29:12 +00:00
|
|
|
if self.conn is not None:
|
|
|
|
|
self.conn.close()
|
|
|
|
|
self.conn = serial.Serial(
|
|
|
|
|
self.port,
|
|
|
|
|
baudrate=self.baudrate,
|
|
|
|
|
stopbits=self.stopbits,
|
|
|
|
|
parity=self.parity,
|
|
|
|
|
bytesize=self.bytesize,
|
2022-09-13 11:36:22 +00:00
|
|
|
timeout=self.read_timeout,
|
|
|
|
|
write_timeout=self.write_timeout,
|
|
|
|
|
inter_byte_timeout=self.inter_byte_timeout,
|
2022-08-01 11:29:12 +00:00
|
|
|
)
|
|
|
|
|
QThread.msleep(5000)
|
|
|
|
|
self.set_all_pixel_color("#000000")
|
2022-06-29 09:02:58 +00:00
|
|
|
|
2022-09-06 10:06:43 +00:00
|
|
|
@Component.reconfig_on_error
|
2022-10-05 13:39:47 +00:00
|
|
|
def _set(self, data=None):
|
|
|
|
|
if not isinstance(data, dict):
|
|
|
|
|
raise ValueError(f"bad call data: {data!r}")
|
|
|
|
|
pixel = data.get("pixel", None)
|
|
|
|
|
color = data.get("color", None)
|
|
|
|
|
if not isinstance(pixel, int) or pixel < 0 or pixel > C_UINT32_MAX:
|
2022-06-29 09:02:58 +00:00
|
|
|
raise ValueError(f"the pixel parameter must be a int between 0 and {C_UINT32_MAX} (broadcast)")
|
2022-10-05 13:39:47 +00:00
|
|
|
if not isinstance(color, str) or not color.startswith("#") or len(color) != 7:
|
2022-06-29 09:02:58 +00:00
|
|
|
raise ValueError("the color parameter must be in the html hex format: '#RRGGBB'")
|
2022-10-05 14:00:43 +00:00
|
|
|
self.conn.write(int.to_bytes(pixel, length=4, byteorder="big") + bytes.fromhex(color[1:7]) + b"\n")
|
|
|
|
|
response = self.conn.readline()
|
|
|
|
|
if response != b"ok\n":
|
|
|
|
|
self.log.error(response.strip())
|
2022-06-29 09:02:58 +00:00
|
|
|
|
2022-10-05 13:39:47 +00:00
|
|
|
def set(self, pixel, color):
|
|
|
|
|
self.request.emit({"pixel": pixel, "color": color})
|
|
|
|
|
|
2022-06-29 09:02:58 +00:00
|
|
|
def set_pixel_color(self, pixel, color):
|
|
|
|
|
self.set(pixel, color)
|
|
|
|
|
|
|
|
|
|
def set_all_pixel_color(self, color):
|
|
|
|
|
self.set(C_UINT32_MAX, color)
|