diff --git a/oin_ha/display/__init__.py b/oin_ha/display/__init__.py index 829ed6a..58a5396 100644 --- a/oin_ha/display/__init__.py +++ b/oin_ha/display/__init__.py @@ -2,7 +2,7 @@ import json from threading import Timer import bdfparser -from sense_hat import SenseHat +from sense_hat import ACTION_RELEASED, SenseHat class Display: @@ -49,7 +49,7 @@ class Display: class Light: - def __init__(self, name, parent_uid, slug, sense, **kwargs): + def __init__(self, name, parent_uid, slug, sense, n=3, **kwargs): self.name = name self.parent_uid = parent_uid self.slug = slug @@ -57,60 +57,69 @@ class Light: self.options = kwargs self._switch = False - self._color = [255, 255, 255] - self._pre = "" - self._value = "" + self._color = [[255, 255, 255]] * n + self._pres = [""] * n + self._values = [""] * n + self._n = n + self._i = 0 self.font = bdfparser.Font("src/tom-thumb.bdf") self.timer = Timer(0, self.__init__) + self.sense.stick.direction_right = self.switch_screen + self.sense.stick.direction_left = self.switch_screen_rev + def publish_discovery(self, mqttc): - mqttc.publish( - self.discovery_topic, - json.dumps( - { - "command_topic": self.command_topic("command"), - "effect_command_topic": self.command_topic("effect"), - "effect_list": ["Low Light", "Normal"], - "effect_state_topie": self.state_topic, - "effect_value_template": "{{ value_json.effect }}", - "icon": "mdi:dots-grid", - "name": self.name, - "on_command_type": "brightness", - "rgb_command_topic": self.command_topic("rgb"), - "rgb_state_topic": self.state_topic, - "rgb_value_template": "{{ value_json.rgb }}", - "retain": True, - "unique_id": self.uid, - "state_topic": self.state_topic, - "state_value_template": "{{ value_json.state }}", - } - | self.options - ), - retain=True, - ) - self.publish_state(mqttc) + for i in range(self._n): + mqttc.publish( + self.get_discovery_topic(i), + json.dumps( + { + "command_topic": self.command_topic(i, "command"), + "effect_command_topic": self.command_topic(i, "effect"), + "effect_list": ["Low Light", "Normal"], + "effect_state_topie": self.state_topic, + "effect_value_template": "{{ value_json.effect }}", + "icon": "mdi:dots-grid", + "name": f"{self.name} {i}", + "on_command_type": "brightness", + "rgb_command_topic": self.command_topic(i, "command"), + "rgb_state_topic": self.state_topic, + "rgb_value_template": "{{" + f"value_json.rgb[{i}]" + "}}", + "retain": True, + "unique_id": f"{self.uid}_{i}", + "state_topic": self.state_topic, + "state_value_template": "{{ value_json.state }}", + } + | self.options + ), + retain=True, + ) + self.publish_state(mqttc) def subscribe(self, mqttc): - mqttc.subscribe(self.command_topic("command")) - mqttc.subscribe(self.command_topic("effect")) - mqttc.subscribe(self.command_topic("rgb")) - - mqttc.subscribe(self.command_topic("value")) + for i in range(self._n): + mqttc.subscribe(self.command_topic(i, "command")) + mqttc.subscribe(self.command_topic(i, "effect")) + mqttc.subscribe(self.command_topic(i, "rgb")) + mqttc.subscribe(self.command_topic(i, "value")) def on_message(self, client, userdata, message): data = message.payload.decode() + print(message.topic) print(data) - match message.topic.rsplit("/", maxsplit=1): - case [self.base_topic, "command"]: - self.switch = data == "ON" - case [self.base_topic, "rgb"]: - self.color = list(map(int, data.split(","))) - case [self.base_topic, "effect"]: + match message.topic.rsplit("/", maxsplit=2): + case [self.base_topic, i, "command"]: + match data.split(","): + case ["OFF"]: + self.switch = False + case [*rgb]: + self.set_color(int(i), list(map(int, rgb))) + case [self.base_topic, i, "effect"]: self.sense.low_light = data == "Low Light" - case [self.base_topic, "value"]: - self.value = data + case [self.base_topic, i, "value"]: + self.set_value(int(i), data) case _: return self.publish_state(client) @@ -132,16 +141,15 @@ class Light: def uid(self): return f"{self.parent_uid}_{self.slug}" - @property - def discovery_topic(self): - return f"homeassistant/light/{self.uid}/config" + def get_discovery_topic(self, i): + return f"homeassistant/light/{self.uid}_{i}/config" @property def base_topic(self): return f"{self.parent_uid}/display/{self.slug}" - def command_topic(self, cmd): - return f"{self.base_topic}/{cmd}" + def command_topic(self, i, cmd): + return f"{self.base_topic}/{i}/{cmd}" @property def state_topic(self): @@ -167,60 +175,73 @@ class Light: def color(self): return self._color - @color.setter - def color(self, value): - self._color = value + def set_color(self, i, value): + self._color[i] = value if not self.switch: self.switch = True - self.display_value() + if i == self._i: + self.display_value() @property def rgb(self): - return ",".join(map(str, self.color)) + return [",".join(map(str, self.color[i])) for i in range(self._n)] @property def value(self): - return f"{self._pre} {self._value}" + return f"{self._pres[self._i]} {self._values[self._i]}" - @value.setter - def value(self, value): + def set_value(self, i, value): match value.split(): case [val]: - self._pre = "" - self._value = val + self._pres[i] = "" + self._values[i] = val case [pre, val, *_]: - self._pre = pre - self._value = val - self.display_value() + self._pres[i] = pre + self._values[i] = val + if i == self._i: + self.display_value() def update_value(self): if not self.switch: return - if not self._pre: + if not self._pres[self._i]: self.display_value() return self.timer.cancel() - pixels = self.to_pixels(self._pre) + pixels = self.to_pixels(self._pres[self._i]) + print(pixels) self.sense.set_pixels(pixels) - self.timer = Timer(1, self.display_value, kwargs=dict(timer=True)) + self.timer = Timer(0.25, self.display_value, kwargs=dict(timer=True)) self.timer.start() def display_value(self, timer=False): if (not timer and self.timer.is_alive()) or not self.switch: return - pixels = self.to_pixels(self._value) + pixels = self.to_pixels(self._values[self._i]) self.sense.set_pixels(pixels) def to_pixels(self, text): if text: return [ - self.color if x else [0, 0, 0] + self.color[self._i] if x else [0, 0, 0] for x in self.font.draw(text).crop(8, 8, yoff=-2).todata(3) ] - return [self.color] * 64 + return [self.color[self._i]] * 64 + + def switch_screen(self, event): + if event.action == ACTION_RELEASED: + self._i = (self._i + 1) % self._n + self.update_value() + print(f"switch to {self._i}") + + def switch_screen_rev(self, event): + if event.action == ACTION_RELEASED: + self._i = (self._i - 1) % self._n + self.update_value() + print(f"switch to {self._i}")