121 lines
2.6 KiB
Python
121 lines
2.6 KiB
Python
from dataclasses import dataclass, field, fields
|
|
from datetime import datetime, time
|
|
from enum import StrEnum
|
|
from typing import Any
|
|
|
|
|
|
class ScheduleActionType(StrEnum):
|
|
SET = "set"
|
|
AUTO = "auto"
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class ScheduledSettings:
|
|
power: bool | None = None
|
|
speed: int | None = None
|
|
heater: bool | None = None
|
|
target_temp: int | None = None
|
|
mode: str | None = None
|
|
sound: bool | None = None
|
|
light: bool | None = None
|
|
|
|
def merged(self, newer: "ScheduledSettings") -> "ScheduledSettings":
|
|
"""
|
|
Наложить более новые настройки поверх старых.
|
|
|
|
None означает:
|
|
параметр в данной точке расписания не менялся.
|
|
"""
|
|
|
|
values: dict[str, Any] = {}
|
|
|
|
for item in fields(self):
|
|
old_value = getattr(self, item.name)
|
|
new_value = getattr(newer, item.name)
|
|
|
|
values[item.name] = (
|
|
old_value
|
|
if new_value is None
|
|
else new_value
|
|
)
|
|
|
|
return ScheduledSettings(**values)
|
|
|
|
@property
|
|
def empty(self) -> bool:
|
|
return all(
|
|
getattr(self, item.name) is None
|
|
for item in fields(self)
|
|
)
|
|
|
|
def to_dict(
|
|
self,
|
|
*,
|
|
skip_none: bool = True,
|
|
) -> dict:
|
|
result = {}
|
|
|
|
for item in fields(self):
|
|
value = getattr(self, item.name)
|
|
|
|
if skip_none and value is None:
|
|
continue
|
|
|
|
result[item.name] = value
|
|
|
|
return result
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class ScheduleAction:
|
|
type: ScheduleActionType
|
|
|
|
settings: ScheduledSettings = field(
|
|
default_factory=ScheduledSettings
|
|
)
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class SchedulePoint:
|
|
at: time
|
|
action: ScheduleAction
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class ScheduleConfig:
|
|
version: int
|
|
enabled: bool
|
|
timezone: str
|
|
|
|
templates: dict[
|
|
str,
|
|
tuple[SchedulePoint, ...]
|
|
]
|
|
|
|
days: dict[str, str]
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class ScheduleOccurrence:
|
|
"""
|
|
Конкретная точка расписания уже с датой.
|
|
"""
|
|
|
|
when: datetime
|
|
weekday: str
|
|
template: str
|
|
point: SchedulePoint
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class ScheduleResolution:
|
|
enabled: bool
|
|
|
|
current: ScheduleOccurrence | None
|
|
next: ScheduleOccurrence | None
|
|
|
|
scheduled_settings: ScheduledSettings
|
|
|
|
auto_active: bool
|
|
auto_fallback_speed: int | None
|
|
auto_target_temp: int | None = None |