Files
core/homeassistant/components/moon/trigger.py
T
2026-07-15 16:11:42 +02:00

89 lines
2.6 KiB
Python

"""Provides triggers for the moon."""
from datetime import datetime
from typing import cast, override
import voluptuous as vol
from homeassistant.const import CONF_OPTIONS
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.helpers.event import async_track_time_change
from homeassistant.helpers.trigger import (
Trigger,
TriggerActionRunner,
TriggerConfig,
TriggerNotTriggeredReporter,
)
from homeassistant.helpers.typing import ConfigType
from .const import CONF_PHASE
from .helpers import MOON_PHASES, moon_phase
PHASE_ANY = "any"
_PHASE_CHANGED_TRIGGER_SCHEMA = vol.Schema(
{
vol.Required(CONF_OPTIONS, default=dict): {
vol.Optional(CONF_PHASE, default=PHASE_ANY): vol.In(
[PHASE_ANY, *MOON_PHASES]
),
}
}
)
class MoonPhaseChangedTrigger(Trigger):
"""Trigger that fires when the moon enters a new phase."""
@override
@classmethod
async def async_validate_config(
cls, hass: HomeAssistant, config: ConfigType
) -> ConfigType:
"""Validate config."""
return cast(ConfigType, _PHASE_CHANGED_TRIGGER_SCHEMA(config))
def __init__(self, hass: HomeAssistant, config: TriggerConfig) -> None:
"""Initialize the trigger."""
super().__init__(hass, config)
options = config.options or {}
self._phase: str = options[CONF_PHASE]
@override
async def async_attach_runner(
self,
run_action: TriggerActionRunner,
did_not_trigger: TriggerNotTriggeredReporter | None = None,
) -> CALLBACK_TYPE:
"""Attach the trigger to an action runner."""
last_phase = moon_phase()
@callback
def check_phase(_now: datetime) -> None:
nonlocal last_phase
current_phase = moon_phase()
if current_phase == last_phase:
return
previous_phase = last_phase
last_phase = current_phase
if self._phase in (PHASE_ANY, current_phase):
run_action(
{"phase": current_phase, "previous_phase": previous_phase},
"moon phase changed",
)
# The binned phase can only change when the local date rolls over.
return async_track_time_change(
self._hass, check_phase, hour=0, minute=0, second=0
)
TRIGGERS: dict[str, type[Trigger]] = {
"phase_changed": MoonPhaseChangedTrigger,
}
async def async_get_triggers(hass: HomeAssistant) -> dict[str, type[Trigger]]:
"""Return the triggers for the moon."""
return TRIGGERS