Add starship event sensor (#64965)

This commit is contained in:
Simon Hansen 2022-01-26 15:37:15 +01:00 committed by GitHub
parent dfdbeba7be
commit 37225c36fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 15 deletions

View file

@ -3,6 +3,9 @@ from __future__ import annotations
from typing import Any from typing import Any
from pylaunches.objects.event import Event
from pylaunches.objects.launch import Launch
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
@ -16,12 +19,22 @@ async def async_get_config_entry_diagnostics(
entry: ConfigEntry, entry: ConfigEntry,
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Return diagnostics for a config entry.""" """Return diagnostics for a config entry."""
coordinator: DataUpdateCoordinator[LaunchLibraryData] = hass.data[DOMAIN] coordinator: DataUpdateCoordinator[LaunchLibraryData] = hass.data[DOMAIN]
if coordinator.data is None: if coordinator.data is None:
return {} return {}
next_launch = coordinator.data["upcoming_launches"][0]
starship_launch = coordinator.data["starship_events"].upcoming.launches[0] def _first_element(data: list[Launch | Event]) -> dict[str, Any] | None:
if not data:
return None
return data[0].raw_data_contents
return { return {
"next_launch": next_launch.raw_data_contents, "next_launch": _first_element(coordinator.data["upcoming_launches"]),
"starship": starship_launch.raw_data_contents, "starship_launch": _first_element(
coordinator.data["starship_events"].upcoming.launches
),
"starship_event": _first_element(
coordinator.data["starship_events"].upcoming.events
),
} }

View file

@ -7,6 +7,7 @@ from datetime import datetime
import logging import logging
from typing import Any from typing import Any
from pylaunches.objects.event import Event
from pylaunches.objects.launch import Launch from pylaunches.objects.launch import Launch
import voluptuous as vol import voluptuous as vol
@ -45,8 +46,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
class LaunchLibrarySensorEntityDescriptionMixin: class LaunchLibrarySensorEntityDescriptionMixin:
"""Mixin for required keys.""" """Mixin for required keys."""
value_fn: Callable[[Launch], datetime | int | str | None] value_fn: Callable[[Launch | Event], datetime | int | str | None]
attributes_fn: Callable[[Launch], dict[str, Any] | None] attributes_fn: Callable[[Launch | Event], dict[str, Any] | None]
@dataclass @dataclass
@ -120,6 +121,19 @@ SENSOR_DESCRIPTIONS: tuple[LaunchLibrarySensorEntityDescription, ...] = (
"description": sl.mission.description, "description": sl.mission.description,
}, },
), ),
LaunchLibrarySensorEntityDescription(
key="starship_event",
icon="mdi:calendar",
name="Next Starship event",
device_class=SensorDeviceClass.TIMESTAMP,
value_fn=lambda se: parse_datetime(se.date),
attributes_fn=lambda se: {
"title": se.name,
"location": se.location,
"stream": se.video_url,
"description": se.description,
},
),
) )
@ -169,7 +183,7 @@ class LaunchLibrarySensor(CoordinatorEntity, SensorEntity):
"""Representation of the next launch sensors.""" """Representation of the next launch sensors."""
_attr_attribution = "Data provided by Launch Library." _attr_attribution = "Data provided by Launch Library."
_next_launch: Launch | None = None _next_event: Launch | Event | None = None
entity_description: LaunchLibrarySensorEntityDescription entity_description: LaunchLibrarySensorEntityDescription
coordinator: DataUpdateCoordinator[LaunchLibraryData] coordinator: DataUpdateCoordinator[LaunchLibraryData]
@ -190,31 +204,33 @@ class LaunchLibrarySensor(CoordinatorEntity, SensorEntity):
@property @property
def native_value(self) -> datetime | str | int | None: def native_value(self) -> datetime | str | int | None:
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self._next_launch is None: if self._next_event is None:
return None return None
return self.entity_description.value_fn(self._next_launch) return self.entity_description.value_fn(self._next_event)
@property @property
def extra_state_attributes(self) -> dict[str, Any] | None: def extra_state_attributes(self) -> dict[str, Any] | None:
"""Return the attributes of the sensor.""" """Return the attributes of the sensor."""
if self._next_launch is None: if self._next_event is None:
return None return None
return self.entity_description.attributes_fn(self._next_launch) return self.entity_description.attributes_fn(self._next_event)
@property @property
def available(self) -> bool: def available(self) -> bool:
"""Return if the sensor is available.""" """Return if the sensor is available."""
return super().available and self._next_launch is not None return super().available and self._next_event is not None
@callback @callback
def _handle_coordinator_update(self) -> None: def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator.""" """Handle updated data from the coordinator."""
if self.entity_description.key == "starship_launch": if self.entity_description.key == "starship_launch":
launches = self.coordinator.data["starship_events"].upcoming.launches events = self.coordinator.data["starship_events"].upcoming.launches
elif self.entity_description.key == "starship_event":
events = self.coordinator.data["starship_events"].upcoming.events
else: else:
launches = self.coordinator.data["upcoming_launches"] events = self.coordinator.data["upcoming_launches"]
self._next_launch = next((launch for launch in (launches)), None) self._next_event = next((event for event in (events)), None)
super()._handle_coordinator_update() super()._handle_coordinator_update()
async def async_added_to_hass(self) -> None: async def async_added_to_hass(self) -> None: