started stages logic

This commit is contained in:
John Lancaster
2025-11-21 07:54:49 -06:00
parent 19d1f9bdfe
commit 98d9ad0556
3 changed files with 124 additions and 3 deletions

55
apps/motion.py Normal file
View File

@@ -0,0 +1,55 @@
import json
from collections.abc import Generator
from datetime import datetime
from itertools import count, cycle, pairwise
from pathlib import Path
from appdaemon.adapi import ADAPI
from pydantic import BaseModel, TypeAdapter
from stages import Stage
adapter = TypeAdapter(list[Stage])
class StagedMotionLight(ADAPI):
def initialize(self):
self.set_log_level("DEBUG")
self._stages = adapter.validate_python(self.args["stages"])
self.log(f"Initialized Motion Sensor with {len(self._stages)} stages")
self.activate()
def _stage_starts(self) -> Generator[datetime]:
for offset in count(start=-1):
for stage in self._stages:
dt = self.parse_datetime(
stage.start,
days_offset=offset,
aware=True,
today=True,
)
dt = dt.replace(microsecond=0)
yield dt
def start_pairs(self):
yield from pairwise(self._stage_starts())
def current_stage(self) -> Stage:
for stage, (t1, t2) in zip(cycle(self._stages), self.start_pairs()):
start, end = sorted([t1, t2])
if self.now_is_between(start, end):
self.log(f"Current stage start time: {stage.start}")
return stage
else:
raise ValueError
def current_scene(self):
return self.current_stage().model_dump(mode="json")["scene"]
def activate(self, **kwargs):
return self.call_service("scene/apply", entities=self.current_scene())
# @property
# def stages(self) -> GeneratorExit:
# yield from pairwise(self._stage_starts)