Add starship event sensor (#64965)
This commit is contained in:
parent
dfdbeba7be
commit
37225c36fc
2 changed files with 44 additions and 15 deletions
|
@ -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
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue