import logging import math from collections.abc import Callable from typing import Any from sense_hat.sense_hat import SenseHat from sense_hat.stick import ACTION_HELD, ACTION_RELEASED, InputEvent logger = logging.getLogger(__name__) class Selector: default_data = {"temperature": None, "mode": None, "switch": None} def __init__(self, send_data: Callable[[dict[str, Any]], Any]): self.stick = SenseHat().stick self.temperature: float | None = None self.mode: str | None = None self.switch: bool | None = None self.preset_modes: list[str] = [] self.send_data = send_data self.switch_held = False self.stick.direction_middle = self.toggle self.stick.direction_up = self.increase_temperature self.stick.direction_down = self.decrease_temperature self.stick.direction_right = self.next_mode self.stick.direction_left = self.prev_mode @property def ha_options(self) -> dict[str, dict[str, str]]: return { "temperature": { "p": "sensor", "value_template": "{{ value_json.temperature }}", "unique_id": "oin_temp", "device_class": "temperature", "entity_category": "diagnostic", "icon": "mdi:thermostat", "unit_of_measurement": "°C", }, "mode": { "p": "sensor", "name": "Mode", "value_template": "{{ value_json.mode }}", "unique_id": "oin_mode", "entity_category": "diagnostic", "icon": "mdi:thermostat-auto", }, "switch": { "p": "sensor", "name": "Switch", "value_template": "{{ value_json.switch }}", "unique_id": "oin_switch", "entity_category": "diagnostic", "icon": "mdi:thermostat-auto", }, } def increase_temperature(self, event: InputEvent) -> None: if event.action != ACTION_RELEASED and self.temperature is not None: self.callback({"temperature": math.floor(self.temperature * 2) / 2 + 0.5}) def decrease_temperature(self, event: InputEvent) -> None: if event.action != ACTION_RELEASED and self.temperature is not None: self.callback({"temperature": math.ceil(self.temperature * 2) / 2 - 0.5}) def next_mode(self, event: InputEvent) -> None: if event.action != ACTION_RELEASED and self.mode is not None: self.callback( { "mode": self.preset_modes[ (self.preset_modes.index(self.mode) + 1) % len(self.preset_modes) ] } ) def prev_mode(self, event: InputEvent) -> None: if event.action != ACTION_RELEASED and self.mode is not None: self.callback( { "mode": self.preset_modes[ (self.preset_modes.index(self.mode) - 1) % len(self.preset_modes) ] } ) def toggle(self, event: InputEvent) -> None: if not self.switch_held and event.action == ACTION_HELD: self.switch_held = True self.callback({"switch": "off" if self.switch else "heat"}) elif self.switch_held and event.action == ACTION_RELEASED: self.switch_held = False def callback(self, data: dict[str, Any]) -> None: self.send_data(self.default_data | data)