Improve sun typing (#78298)

This commit is contained in:
epenet 2022-09-12 21:34:35 +02:00 committed by GitHub
parent 3be9bee61e
commit 19bee11a01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 33 deletions

View file

@ -1,6 +1,11 @@
"""Support for functionality to keep track of the sun.""" """Support for functionality to keep track of the sun."""
from datetime import timedelta from __future__ import annotations
from datetime import datetime, timedelta
import logging import logging
from typing import Any
from astral.location import Elevation, Location
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
@ -9,7 +14,7 @@ from homeassistant.const import (
SUN_EVENT_SUNRISE, SUN_EVENT_SUNRISE,
SUN_EVENT_SUNSET, SUN_EVENT_SUNSET,
) )
from homeassistant.core import HomeAssistant, callback from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant, callback
from homeassistant.helpers import event from homeassistant.helpers import event
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.helpers.integration_platform import ( from homeassistant.helpers.integration_platform import (
@ -24,8 +29,6 @@ from homeassistant.util import dt as dt_util
from .const import DOMAIN from .const import DOMAIN
# mypy: allow-untyped-calls, allow-untyped-defs, no-check-untyped-defs
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ENTITY_ID = "sun.sun" ENTITY_ID = "sun.sun"
@ -114,32 +117,40 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
class Sun(Entity): class Sun(Entity):
"""Representation of the Sun.""" """Representation of the Sun."""
_attr_name = "Sun"
entity_id = ENTITY_ID entity_id = ENTITY_ID
def __init__(self, hass): location: Location
elevation: Elevation
next_rising: datetime
next_setting: datetime
next_dawn: datetime
next_dusk: datetime
next_midnight: datetime
next_noon: datetime
solar_elevation: float
solar_azimuth: float
rising: bool
_next_change: datetime
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize the sun.""" """Initialize the sun."""
self.hass = hass self.hass = hass
self.location = None self.phase: str | None = None
self.elevation = 0.0
self._state = self.next_rising = self.next_setting = None self._config_listener: CALLBACK_TYPE | None = None
self.next_dawn = self.next_dusk = None self._update_events_listener: CALLBACK_TYPE | None = None
self.next_midnight = self.next_noon = None self._update_sun_position_listener: CALLBACK_TYPE | None = None
self.solar_elevation = self.solar_azimuth = None
self.rising = self.phase = None
self._next_change = None
self._config_listener = None
self._update_events_listener = None
self._update_sun_position_listener = None
self._config_listener = self.hass.bus.async_listen( self._config_listener = self.hass.bus.async_listen(
EVENT_CORE_CONFIG_UPDATE, self.update_location EVENT_CORE_CONFIG_UPDATE, self.update_location
) )
self.update_location() self.update_location(initial=True)
@callback @callback
def update_location(self, *_): def update_location(self, _: Event | None = None, initial: bool = False) -> None:
"""Update location.""" """Update location."""
location, elevation = get_astral_location(self.hass) location, elevation = get_astral_location(self.hass)
if location == self.location: if not initial and location == self.location:
return return
self.location = location self.location = location
self.elevation = elevation self.elevation = elevation
@ -148,7 +159,7 @@ class Sun(Entity):
self.update_events() self.update_events()
@callback @callback
def remove_listeners(self): def remove_listeners(self) -> None:
"""Remove listeners.""" """Remove listeners."""
if self._config_listener: if self._config_listener:
self._config_listener() self._config_listener()
@ -158,12 +169,7 @@ class Sun(Entity):
self._update_sun_position_listener() self._update_sun_position_listener()
@property @property
def name(self): def state(self) -> str:
"""Return the name."""
return "Sun"
@property
def state(self):
"""Return the state of the sun.""" """Return the state of the sun."""
# 0.8333 is the same value as astral uses # 0.8333 is the same value as astral uses
if self.solar_elevation > -0.833: if self.solar_elevation > -0.833:
@ -172,7 +178,7 @@ class Sun(Entity):
return STATE_BELOW_HORIZON return STATE_BELOW_HORIZON
@property @property
def extra_state_attributes(self): def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes of the sun.""" """Return the state attributes of the sun."""
return { return {
STATE_ATTR_NEXT_DAWN: self.next_dawn.isoformat(), STATE_ATTR_NEXT_DAWN: self.next_dawn.isoformat(),
@ -186,7 +192,9 @@ class Sun(Entity):
STATE_ATTR_RISING: self.rising, STATE_ATTR_RISING: self.rising,
} }
def _check_event(self, utc_point_in_time, sun_event, before): def _check_event(
self, utc_point_in_time: datetime, sun_event: str, before: str | None
) -> datetime:
next_utc = get_location_astral_event_next( next_utc = get_location_astral_event_next(
self.location, self.elevation, sun_event, utc_point_in_time self.location, self.elevation, sun_event, utc_point_in_time
) )
@ -196,7 +204,7 @@ class Sun(Entity):
return next_utc return next_utc
@callback @callback
def update_events(self, now=None): def update_events(self, now: datetime | None = None) -> None:
"""Update the attributes containing solar events.""" """Update the attributes containing solar events."""
# Grab current time in case system clock changed since last time we ran. # Grab current time in case system clock changed since last time we ran.
utc_point_in_time = dt_util.utcnow() utc_point_in_time = dt_util.utcnow()
@ -266,7 +274,7 @@ class Sun(Entity):
_LOGGER.debug("next time: %s", self._next_change.isoformat()) _LOGGER.debug("next time: %s", self._next_change.isoformat())
@callback @callback
def update_sun_position(self, now=None): def update_sun_position(self, now: datetime | None = None) -> None:
"""Calculate the position of the sun.""" """Calculate the position of the sun."""
# Grab current time in case system clock changed since last time we ran. # Grab current time in case system clock changed since last time we ran.
utc_point_in_time = dt_util.utcnow() utc_point_in_time = dt_util.utcnow()
@ -286,6 +294,7 @@ class Sun(Entity):
self.async_write_ha_state() self.async_write_ha_state()
# Next update as per the current phase # Next update as per the current phase
assert self.phase
delta = _PHASE_UPDATES[self.phase] delta = _PHASE_UPDATES[self.phase]
# if the next update is within 1.25 of the next # if the next update is within 1.25 of the next
# position update just drop it # position update just drop it

View file

@ -15,8 +15,6 @@ from homeassistant.helpers.event import async_track_sunrise, async_track_sunset
from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
# mypy: allow-untyped-defs, no-check-untyped-defs
TRIGGER_SCHEMA = cv.TRIGGER_BASE_SCHEMA.extend( TRIGGER_SCHEMA = cv.TRIGGER_BASE_SCHEMA.extend(
{ {
vol.Required(CONF_PLATFORM): "sun", vol.Required(CONF_PLATFORM): "sun",
@ -42,7 +40,7 @@ async def async_attach_trigger(
job = HassJob(action) job = HassJob(action)
@callback @callback
def call_action(): def call_action() -> None:
"""Call action with right context.""" """Call action with right context."""
hass.async_run_hass_job( hass.async_run_hass_job(
job, job,