Skip to content

Commit

Permalink
Add input_datetime implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
pnbruckner committed Oct 25, 2023
1 parent 4003b63 commit 3800511
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 16 deletions.
8 changes: 5 additions & 3 deletions custom_components/sun2/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ async def async_added_to_hass(self) -> None:

async def async_will_remove_from_hass(self) -> None:
"""Run when entity will be removed from hass."""
self._cancel_update()

def _cancel_update(self) -> None:
"""Cancel update."""
if self._unsub_update:
self._unsub_update()
self._unsub_update = None
Expand Down Expand Up @@ -187,9 +191,7 @@ async def loc_updated(loc_data: LocData) -> None:

async def _async_loc_updated(self, loc_data: LocData) -> None:
"""Location updated."""
if self._unsub_update:
self._unsub_update()
self._unsub_update = None
self._cancel_update()
self._loc_data = loc_data
self._setup_fixed_updating()
self.async_schedule_update_ha_state(True)
Expand Down
84 changes: 71 additions & 13 deletions custom_components/sun2/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@
DEGREE,
UnitOfTime,
)
from homeassistant.core import CALLBACK_TYPE, CoreState, HomeAssistant, callback
from homeassistant.core import CALLBACK_TYPE, CoreState, HomeAssistant, callback, Event
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_call_later, async_track_point_in_utc_time
from homeassistant.helpers.event import (
async_call_later,
async_track_point_in_utc_time,
async_track_state_change_event,
)
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util, slugify

Expand Down Expand Up @@ -217,6 +221,10 @@ def _update(self, cur_dttm: datetime) -> None:
class Sun2ElevationAtTimeSensor(Sun2SensorEntity[float]):
"""Sun2 Elevation at Time Sensor."""

_at_time: time | None = None
_input_datetime: str | None = None
_unsub_track: CALLBACK_TYPE | None = None

def __init__(
self,
loc_params: LocParams | None,
Expand All @@ -225,8 +233,10 @@ def __init__(
name: str,
) -> None:
"""Initialize sensor."""
assert isinstance(at_time, time)
self._at_time = at_time
if isinstance(at_time, str):
self._input_datetime = at_time
else:
self._at_time = at_time
entity_description = SensorEntityDescription(
key=CONF_ELEVATION_AT_TIME,
icon="mdi:weather-sunny",
Expand All @@ -236,8 +246,51 @@ def __init__(
super().__init__(loc_params, namespace, entity_description, name=name)
self._event = "solar_elevation"

def _setup_fixed_updating(self) -> None:
"""Set up fixed updating."""
super()._setup_fixed_updating()
if not self._input_datetime:
return

@callback
def update_at_time(event: Event | None = None) -> None:
"""Update time from input_datetime entity."""
if event:
state = event.data["new_state"]
else:
state = self.hass.states.get(self._input_datetime)
if not state:
self._at_time = None
LOGGER.debug("%s: %s state not found", self.name, self._input_datetime)
else:
self._at_time = time(
state.attributes["hour"],
state.attributes["minute"],
state.attributes["second"],
)
self.async_schedule_update_ha_state(True)

self._unsub_track = async_track_state_change_event(
self.hass,
self._input_datetime,
update_at_time,
)
update_at_time()

def _cancel_update(self) -> None:
"""Cancel update."""
super()._cancel_update()
if self._unsub_track:
self._unsub_track()
self._unsub_track = None

def _update(self, cur_dttm: datetime) -> None:
"""Update state."""
if not self._at_time:
self._yesterday = None
self._attr_native_value = self._today = None
self._tomorrow = None
return
cur_dttm = datetime.combine(cur_dttm.date(), self._at_time)
self._yesterday = cast(Optional[_T], self._astral_event(cur_dttm - ONE_DAY))
self._attr_native_value = self._today = cast(
Expand Down Expand Up @@ -837,6 +890,12 @@ def _setup_updates(self, cur_dttm: datetime, cur_elev: Num) -> None:
if cur_elev > elev > self._cp.tR_elev:
self._setup_update_at_elev(elev)

def _cancel_update(self) -> None:
"""Cancel pending updates."""
for update in self._updates:
update.remove()
self._updates = []

def _update(self, cur_dttm: datetime) -> None:
"""Update state."""
# Updates are determined only once per section of elevation curve (between a
Expand Down Expand Up @@ -869,14 +928,6 @@ def _update(self, cur_dttm: datetime) -> None:
self._attr_native_value = self._state_at_elev(cur_elev)
self._set_attrs(self._attrs_at_elev(cur_elev), self._updates[0].when)

def cancel_updates() -> None:
"""Cancel pending updates."""
for update in self._updates:
update.remove()
self._updates = []

self._unsub_update = cancel_updates

LOGGER.debug("%s: _update time: %s", self.name, dt_util.now() - start_update)


Expand Down Expand Up @@ -1123,7 +1174,14 @@ def _eat_defaults(config: ConfigType) -> ConfigType:
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_MONITORED_CONDITIONS): vol.All(
cv.ensure_list, [vol.Any(TIME_AT_ELEVATION_SCHEMA, ELEVATION_AT_TIME_SCHEMA, vol.In(_SENSOR_TYPES))]
cv.ensure_list,
[
vol.Any(
TIME_AT_ELEVATION_SCHEMA,
ELEVATION_AT_TIME_SCHEMA,
vol.In(_SENSOR_TYPES),
)
],
),
**LOC_PARAMS,
}
Expand Down

0 comments on commit 3800511

Please sign in to comment.