Added VT Thermometer to HACS
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
"""State container for Versatile Thermostat.
|
||||
|
||||
This lightweight data class is intended to group together the minimal
|
||||
public state we may want to persist, serialize, expose via services
|
||||
or exchange between managers (for example during algorithms decisions
|
||||
or for debug tooling).
|
||||
|
||||
Attributes:
|
||||
hvac_mode: Current HVAC mode of the thermostat (e.g. 'heat', 'off', 'cool', 'sleep').
|
||||
target_temperature: The active target temperature (can be None when mode does not use a temperature, e.g. 'off').
|
||||
preset: The current preset name (e.g. 'eco', 'comfort', 'boost', 'away') or None if not in a preset.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional, Any
|
||||
|
||||
from .vtherm_hvac_mode import VThermHvacMode
|
||||
from .vtherm_preset import VThermPreset
|
||||
|
||||
|
||||
class VThermState:
|
||||
"""Simple state snapshot for a VTherm.
|
||||
|
||||
The object is mutable; use set_state for a bulk update or assign
|
||||
attributes individually via properties. to_dict / from_dict help (de)serialization.
|
||||
"""
|
||||
|
||||
def __init__(self, hvac_mode: Any, target_temperature: Optional[float] = None, preset: Optional[VThermPreset] = None) -> None:
|
||||
if preset is not None and not isinstance(preset, str):
|
||||
raise ValueError(f"Invalid preset: {preset}. Should be an instance of VThermPreset.")
|
||||
|
||||
self._hvac_mode: VThermHvacMode = hvac_mode if isinstance(hvac_mode, VThermHvacMode) else VThermHvacMode(str(hvac_mode))
|
||||
self._target_temperature: Optional[float] = target_temperature
|
||||
self._preset: Optional[VThermPreset] = preset
|
||||
self._is_hvac_mode_changed: bool = True
|
||||
self._is_target_temperature_changed: bool = True
|
||||
self._is_preset_changed: bool = True
|
||||
|
||||
def set_state(
|
||||
self,
|
||||
hvac_mode: Optional[VThermHvacMode] = None,
|
||||
target_temperature: Optional[float] = None,
|
||||
preset: Optional[VThermPreset] = None,
|
||||
) -> None:
|
||||
"""Update only the attributes provided (not None).
|
||||
|
||||
Args:
|
||||
hvac_mode: New HVAC mode to set (if not None).
|
||||
target_temperature: New target temperature (if not None).
|
||||
preset: New preset (if not None).
|
||||
"""
|
||||
if hvac_mode is not None:
|
||||
self.set_hvac_mode(hvac_mode)
|
||||
if target_temperature is not None:
|
||||
self.set_target_temperature(target_temperature)
|
||||
if preset is not None:
|
||||
self.set_preset(preset)
|
||||
|
||||
def set_hvac_mode(self, hvac_mode: VThermHvacMode) -> None:
|
||||
"""Set the HVAC mode only.
|
||||
|
||||
Args:
|
||||
hvac_mode: New HVAC mode to set (e.g. 'heat', 'off', 'cool', 'sleep').
|
||||
"""
|
||||
if not isinstance(hvac_mode, VThermHvacMode):
|
||||
hvac_mode = VThermHvacMode(str(hvac_mode))
|
||||
|
||||
self._is_hvac_mode_changed = self._is_hvac_mode_changed or self._hvac_mode != hvac_mode
|
||||
self._hvac_mode = hvac_mode
|
||||
|
||||
def set_target_temperature(self, target_temperature: Optional[float]) -> None:
|
||||
"""Set the target temperature only.
|
||||
|
||||
Args:
|
||||
target_temperature: New target temperature to set, or None.
|
||||
"""
|
||||
self._is_target_temperature_changed = self._is_target_temperature_changed or self._target_temperature != target_temperature
|
||||
self._target_temperature = target_temperature
|
||||
|
||||
def set_preset(self, preset: Optional[VThermPreset]) -> None:
|
||||
"""Set the preset only.
|
||||
|
||||
Args:
|
||||
preset: New preset name to set, or None.
|
||||
"""
|
||||
if preset is not None and not isinstance(preset, str):
|
||||
raise ValueError(f"Invalid preset: {preset}. Should be an instance of VThermPreset.")
|
||||
|
||||
self._is_preset_changed = self._is_preset_changed or self._preset != preset
|
||||
self._preset = preset
|
||||
|
||||
def force_changed(self) -> None:
|
||||
"""Forcefully mark the state as changed."""
|
||||
self._is_hvac_mode_changed = True
|
||||
self._is_target_temperature_changed = True
|
||||
self._is_preset_changed = True
|
||||
|
||||
@property
|
||||
def hvac_mode(self) -> VThermHvacMode:
|
||||
"""Get or set the current HVAC mode."""
|
||||
return self._hvac_mode
|
||||
|
||||
@property
|
||||
def target_temperature(self) -> Optional[float]:
|
||||
"""Get or set the current target temperature."""
|
||||
return self._target_temperature
|
||||
|
||||
@property
|
||||
def preset(self) -> Optional[VThermPreset]:
|
||||
"""Get or set the current preset."""
|
||||
return self._preset
|
||||
|
||||
@property
|
||||
def is_changed(self) -> bool:
|
||||
"""Check if the state has changed."""
|
||||
return self._is_hvac_mode_changed or self._is_target_temperature_changed or self._is_preset_changed
|
||||
|
||||
@property
|
||||
def is_hvac_mode_changed(self) -> bool:
|
||||
"""Check if the HVAC mode has changed."""
|
||||
return self._is_hvac_mode_changed
|
||||
|
||||
@property
|
||||
def is_target_temperature_changed(self) -> bool:
|
||||
"""Check if the target temperature has changed."""
|
||||
return self._is_target_temperature_changed
|
||||
|
||||
@property
|
||||
def is_preset_changed(self) -> bool:
|
||||
"""Check if the preset has changed."""
|
||||
return self._is_preset_changed
|
||||
|
||||
def reset_changed(self) -> None:
|
||||
"""Reset the changed state."""
|
||||
self._is_hvac_mode_changed = False
|
||||
self._is_target_temperature_changed = False
|
||||
self._is_preset_changed = False
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
"""Convert the state to a dictionary."""
|
||||
return {
|
||||
"hvac_mode": str(self._hvac_mode),
|
||||
"target_temperature": self._target_temperature,
|
||||
"preset": str(self._preset),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict[str, Any]) -> "VThermState":
|
||||
"""Create a VThermState from a dictionary."""
|
||||
hvac_mode = VThermHvacMode(data["hvac_mode"])
|
||||
target_temperature = data["target_temperature"]
|
||||
preset = VThermPreset(data["preset"]) if data["preset"] else None
|
||||
state = cls(hvac_mode, target_temperature, preset)
|
||||
return state
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""Return a human readable representation of the state."""
|
||||
return f"VThermState(" f"hvac_mode={self._hvac_mode}, " f"target_temperature={self._target_temperature}, " f"preset={self._preset}, " f"is_changed={self.is_changed})"
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""Compare two VThermState instances for equality.
|
||||
|
||||
Args:
|
||||
other: Another object to compare with.
|
||||
|
||||
Returns:
|
||||
True if both states have the same hvac_mode, target_temperature, and preset.
|
||||
"""
|
||||
if not isinstance(other, VThermState):
|
||||
return False
|
||||
|
||||
return self._hvac_mode == other._hvac_mode and self._target_temperature == other._target_temperature and self._preset == other._preset
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
"""Compare two VThermState instances for inequality."""
|
||||
return not self.__eq__(other)
|
||||
Reference in New Issue
Block a user