Add "station is open" sensor to Tankerkoenig (#68925)

This commit is contained in:
Michael 2022-03-31 22:45:58 +02:00 committed by GitHub
parent e69450f7ca
commit c6cd474312
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 131 additions and 82 deletions

View File

@ -1197,6 +1197,7 @@ omit =
homeassistant/components/tado/water_heater.py
homeassistant/components/tank_utility/sensor.py
homeassistant/components/tankerkoenig/__init__.py
homeassistant/components/tankerkoenig/binary_sensor.py
homeassistant/components/tankerkoenig/const.py
homeassistant/components/tankerkoenig/sensor.py
homeassistant/components/tapsaff/binary_sensor.py

View File

@ -75,7 +75,7 @@ CONFIG_SCHEMA = vol.Schema(
extra=vol.ALLOW_EXTRA,
)
PLATFORMS = [Platform.SENSOR]
PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR]
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
@ -170,14 +170,14 @@ class TankerkoenigDataUpdateCoordinator(DataUpdateCoordinator):
update_interval=timedelta(minutes=update_interval),
)
self._api_key = entry.data[CONF_API_KEY]
self._selected_stations = entry.data[CONF_STATIONS]
self._api_key: str = entry.data[CONF_API_KEY]
self._selected_stations: list[str] = entry.data[CONF_STATIONS]
self._hass = hass
self.stations: dict[str, dict] = {}
self.fuel_types = entry.data[CONF_FUEL_TYPES]
self.show_on_map = entry.options[CONF_SHOW_ON_MAP]
self.fuel_types: list[str] = entry.data[CONF_FUEL_TYPES]
self.show_on_map: bool = entry.options[CONF_SHOW_ON_MAP]
def setup(self):
def setup(self) -> bool:
"""Set up the tankerkoenig API."""
for station_id in self._selected_stations:
try:
@ -205,7 +205,7 @@ class TankerkoenigDataUpdateCoordinator(DataUpdateCoordinator):
)
return True
async def _async_update_data(self):
async def _async_update_data(self) -> dict:
"""Get the latest data from tankerkoenig.de."""
_LOGGER.debug("Fetching new data from tankerkoenig.de")
station_ids = list(self.stations)

View File

@ -0,0 +1,78 @@
"""Tankerkoenig binary sensor integration."""
from __future__ import annotations
import logging
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ID, ATTR_LATITUDE, ATTR_LONGITUDE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import TankerkoenigDataUpdateCoordinator
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the tankerkoenig binary sensors."""
coordinator: TankerkoenigDataUpdateCoordinator = hass.data[DOMAIN][entry.unique_id]
stations = coordinator.stations.values()
entities = []
for station in stations:
sensor = StationOpenBinarySensorEntity(
station,
coordinator,
coordinator.show_on_map,
)
entities.append(sensor)
_LOGGER.debug("Added sensors %s", entities)
async_add_entities(entities)
class StationOpenBinarySensorEntity(CoordinatorEntity, BinarySensorEntity):
"""Shows if a station is open or closed."""
_attr_device_class = BinarySensorDeviceClass.DOOR
def __init__(
self,
station: dict,
coordinator: TankerkoenigDataUpdateCoordinator,
show_on_map: bool,
) -> None:
"""Initialize the sensor."""
super().__init__(coordinator)
self._station_id = station["id"]
self._attr_name = (
f"{station['brand']} {station['street']} {station['houseNumber']} status"
)
self._attr_unique_id = f"{station['id']}_status"
self._attr_device_info = DeviceInfo(
identifiers={(ATTR_ID, station["id"])},
name=f"{station['brand']} {station['street']} {station['houseNumber']}",
model=station["brand"],
configuration_url="https://www.tankerkoenig.de",
)
if show_on_map:
self._attr_extra_state_attributes = {
ATTR_LATITUDE: station["lat"],
ATTR_LONGITUDE: station["lng"],
}
@property
def is_on(self) -> bool | None:
"""Return true if the station is open."""
data = self.coordinator.data[self._station_id]
return data is not None and "status" in data

View File

@ -10,3 +10,12 @@ DEFAULT_RADIUS = 2
DEFAULT_SCAN_INTERVAL = 30
FUEL_TYPES = {"e5": "Super", "e10": "Super E10", "diesel": "Diesel"}
ATTR_BRAND = "brand"
ATTR_CITY = "city"
ATTR_FUEL_TYPE = "fuel_type"
ATTR_HOUSE_NUMBER = "house_number"
ATTR_POSTCODE = "postcode"
ATTR_STATION_NAME = "station_name"
ATTR_STREET = "street"
ATTRIBUTION = "Data provided by https://www.tankerkoenig.de"

View File

@ -18,22 +18,21 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import TankerkoenigDataUpdateCoordinator
from .const import DOMAIN, FUEL_TYPES
from .const import (
ATTR_BRAND,
ATTR_CITY,
ATTR_FUEL_TYPE,
ATTR_HOUSE_NUMBER,
ATTR_POSTCODE,
ATTR_STATION_NAME,
ATTR_STREET,
ATTRIBUTION,
DOMAIN,
FUEL_TYPES,
)
_LOGGER = logging.getLogger(__name__)
ATTR_BRAND = "brand"
ATTR_CITY = "city"
ATTR_FUEL_TYPE = "fuel_type"
ATTR_HOUSE_NUMBER = "house_number"
ATTR_IS_OPEN = "is_open"
ATTR_POSTCODE = "postcode"
ATTR_STATION_NAME = "station_name"
ATTR_STREET = "street"
ATTRIBUTION = "Data provided by https://creativecommons.tankerkoenig.de"
ICON = "mdi:gas-station"
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
@ -67,79 +66,41 @@ class FuelPriceSensor(CoordinatorEntity, SensorEntity):
"""Contains prices for fuel in a given station."""
_attr_state_class = STATE_CLASS_MEASUREMENT
_attr_icon = "mdi:gas-station"
def __init__(self, fuel_type, station, coordinator, show_on_map):
"""Initialize the sensor."""
super().__init__(coordinator)
self._station = station
self._station_id = station["id"]
self._fuel_type = fuel_type
self._latitude = station["lat"]
self._longitude = station["lng"]
self._city = station["place"]
self._house_number = station["houseNumber"]
self._postcode = station["postCode"]
self._street = station["street"]
self._brand = self._station["brand"]
self._price = station[fuel_type]
self._show_on_map = show_on_map
self._attr_name = f"{station['brand']} {station['street']} {station['houseNumber']} {FUEL_TYPES[fuel_type]}"
self._attr_native_unit_of_measurement = CURRENCY_EURO
self._attr_unique_id = f"{station['id']}_{fuel_type}"
self._attr_device_info = DeviceInfo(
identifiers={(ATTR_ID, station["id"])},
name=f"{station['brand']} {station['street']} {station['houseNumber']}",
model=station["brand"],
configuration_url="https://www.tankerkoenig.de",
)
@property
def name(self):
"""Return the name of the sensor."""
return f"{self._brand} {self._street} {self._house_number} {FUEL_TYPES[self._fuel_type]}"
attrs = {
ATTR_ATTRIBUTION: ATTRIBUTION,
ATTR_BRAND: station["brand"],
ATTR_FUEL_TYPE: fuel_type,
ATTR_STATION_NAME: station["name"],
ATTR_STREET: station["street"],
ATTR_HOUSE_NUMBER: station["houseNumber"],
ATTR_POSTCODE: station["postCode"],
ATTR_CITY: station["place"],
}
@property
def icon(self):
"""Icon to use in the frontend."""
return ICON
@property
def native_unit_of_measurement(self):
"""Return unit of measurement."""
return CURRENCY_EURO
if show_on_map:
attrs[ATTR_LATITUDE] = station["lat"]
attrs[ATTR_LONGITUDE] = station["lng"]
self._attr_extra_state_attributes = attrs
@property
def native_value(self):
"""Return the state of the device."""
# key Fuel_type is not available when the fuel station is closed, use "get" instead of "[]" to avoid exceptions
return self.coordinator.data[self._station_id].get(self._fuel_type)
@property
def unique_id(self) -> str:
"""Return a unique identifier for this entity."""
return f"{self._station_id}_{self._fuel_type}"
@property
def device_info(self) -> DeviceInfo | None:
"""Return device info."""
return DeviceInfo(
identifiers={(ATTR_ID, self._station_id)},
name=f"{self._brand} {self._street} {self._house_number}",
model=self._brand,
configuration_url="https://www.tankerkoenig.de",
)
@property
def extra_state_attributes(self):
"""Return the attributes of the device."""
data = self.coordinator.data[self._station_id]
attrs = {
ATTR_ATTRIBUTION: ATTRIBUTION,
ATTR_BRAND: self._station["brand"],
ATTR_FUEL_TYPE: self._fuel_type,
ATTR_STATION_NAME: self._station["name"],
ATTR_STREET: self._street,
ATTR_HOUSE_NUMBER: self._house_number,
ATTR_POSTCODE: self._postcode,
ATTR_CITY: self._city,
}
if self._show_on_map:
attrs[ATTR_LATITUDE] = self._latitude
attrs[ATTR_LONGITUDE] = self._longitude
if data is not None and "status" in data:
attrs[ATTR_IS_OPEN] = data["status"] == "open"
return attrs