oin/oin_thermostat/screen.py

141 lines
3.3 KiB
Python
Raw Normal View History

2024-12-07 15:22:08 +01:00
import logging
import math
from threading import Timer
import bdfparser
from sense_hat import SenseHat
logger = logging.getLogger(__name__)
COLORS = {
"Bleu": [0, 0, 255],
"Blanc": [0, 0, 0],
"Rouge": [255, 0, 0],
"Verte": [0, 127, 31],
"Jaune": [255, 255, 0],
"heat": [255, 0, 0],
"heating": [255, 0, 0],
"idle": [127, 0, 255],
"off": [127, 127, 127],
"on_setting": [255, 255, 0],
"off_setting": [255, 255, 255],
None: [0, 0, 0],
}
class Screen:
def __init__(self):
self.sense = SenseHat()
self._value = ""
self._tmp = False
self._tmp_value = None
self._mode = None
self.font = bdfparser.Font("src/tom-thumb.bdf")
self._secondary = dict()
self._secondary_pixels = [[0, 0, 0]] * 8
self.timer = Timer(0, self.set_pixels)
self._held = False
self.sense.stick.direction_middle = self.stick_click
@property
def value(self):
return self._value
@value.setter
def value(self, value):
logger.debug(f"Updated value: <{value}>")
self._value = format_value(value)
if not self._tmp:
self.set_pixels()
@property
def color(self):
return COLORS.get(self.mode, [0, 0, 0])
@property
def mode(self):
return self._mode
@mode.setter
def mode(self, value):
self._mode = value
if not self._tmp:
self.set_pixels()
@property
def tmp_value(self):
return self._tmp_value
@tmp_value.setter
def tmp_value(self, value):
logger.debug(f"Show value: <{value}>")
self.timer.cancel()
self._tmp_value = format_value(value)
self.show_tmp()
def show_tmp(self):
self._tmp = True
self.set_pixels(
self.tmp_value,
color=COLORS.get("off_setting" if self.mode == "off" else "on_setting"),
)
self.timer = Timer(3, self.set_pixels)
self.timer.start()
def set_pixels(self, value=None, color=None, bg_color=[0, 0, 0]):
if value is None:
value = self.value
self._tmp = False
if color is None:
color = self.color
if value:
pixels = [
color if x else bg_color
for x in self.font.draw(value, mode=0).crop(8, 7).todata(3)
]
else:
pixels = 48 * [[0, 0, 0]]
pixels += self.secondary_pixels
self.sense.set_pixels(pixels)
@property
def secondary(self):
return self._secondary
@property
def secondary_pixels(self):
return self._secondary_pixels
@secondary.setter
def secondary(self, value):
self._secondary = value
for idx in range(2):
self._secondary_pixels[4 * idx : 4 * (idx + 1)] = [
COLORS.get(value.get(idx, None), [0, 0, 0])
] * 4
if not self._tmp:
self.set_pixels()
def stick_click(self, event):
match (event.action, self._held):
case ("held", False):
self._held = True
case ("released", True):
self._held = False
case ("released", False):
self.show_tmp()
def format_value(value):
v = math.trunc(value)
d = "." if (value - v) >= 0.5 else ""
return f"{v}{d}"