Multiple views

This commit is contained in:
Edgar P. Burkhart 2024-11-11 16:49:43 +01:00
parent 8b4521a447
commit 9ad46a717a
Signed by: edpibu
GPG key ID: 9833D3C5A25BD227

View file

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