From 90e34ab9cfa808c63cb5032a947ba3169256f838 Mon Sep 17 00:00:00 2001 From: Fabian Seitz Date: Thu, 29 Sep 2022 22:45:15 +0200 Subject: [PATCH 1/5] first partly working implementation of config flow --- README.md | 5 +- custom_components/deutschebahn/__init__.py | 85 +++++++- custom_components/deutschebahn/config_flow.py | 19 +- custom_components/deutschebahn/const.py | 5 +- custom_components/deutschebahn/manifest.json | 2 +- custom_components/deutschebahn/sensor.py | 205 ++++++++++-------- custom_components/deutschebahn/strings.json | 16 +- .../deutschebahn/translations/de.json | 22 -- .../deutschebahn/translations/en.json | 25 --- 9 files changed, 220 insertions(+), 164 deletions(-) delete mode 100644 custom_components/deutschebahn/translations/de.json delete mode 100644 custom_components/deutschebahn/translations/en.json diff --git a/README.md b/README.md index 192c545..f4ac613 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,9 @@ The `deutschebahn` sensor will give you the departure time of the next train for The official Deutsche Bahn Homeassistant integration got removed with release 2022.11 - therefore this custom integration exists. It got removed due to cloud scraping, but still was fully functional. -I will not give much support on this integration, only keeping the dependencys up to date! Use it as it is, this is the same part as of release 2022.09 from HA, see [here](https://github.com/home-assistant/core/tree/c741d9d0452970c39397deca1c65766c8cb917da/homeassistant/components/deutsche_bahn). +Please note that I will only give limited support on this integration + +This integration is based on the formerly officia HA DB integration, see [here](https://github.com/home-assistant/core/tree/c741d9d0452970c39397deca1c65766c8cb917da/homeassistant/components/deutsche_bahn). This sensor stores a lot of attributes which can be accessed by other sensors, e.g., a [template sensor](https://www.home-assistant.io/integrations/template/). @@ -75,5 +77,6 @@ logger: ## Thanks to Huge thanks to [@homeassistant](https://github.com/home-assistant/core/tree/c741d9d0452970c39397deca1c65766c8cb917da/homeassistant/components/deutsche_bahn) for the official old integration, where this one is based on! +Also to [@kennell](https://github.com/kennell/schiene) for the schiene python library that this integration is using. The data is coming from the [bahn.de](https://www.bahn.de/p/view/index.shtml) website. \ No newline at end of file diff --git a/custom_components/deutschebahn/__init__.py b/custom_components/deutschebahn/__init__.py index be59bab..b5557cb 100644 --- a/custom_components/deutschebahn/__init__.py +++ b/custom_components/deutschebahn/__init__.py @@ -1 +1,84 @@ -"""The deutschebahn component.""" +"""Bahn.de Custom Component.""" +import asyncio +import logging +from datetime import timedelta + +from homeassistant import config_entries, core + +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, + UpdateFailed, +) + +from .const import DOMAIN + +_LOGGER = logging.getLogger(__name__) +SCAN_INTERVAL = timedelta(minutes=2) + +async def async_setup_entry( + hass: core.HomeAssistant, entry: config_entries.ConfigEntry +) -> bool: + """Set up platform from a ConfigEntry.""" + hass.data.setdefault(DOMAIN, {}) + hass_data = dict(entry.data) + # Registers update listener to update config entry when options are updated. + unsub_options_update_listener = entry.add_update_listener(options_update_listener) + # Store a reference to the unsubscribe function to cleanup if an entry is unloaded. + hass_data["unsub_options_update_listener"] = unsub_options_update_listener + hass.data[DOMAIN][entry.entry_id] = hass_data + + # Forward the setup to the sensor platform. + hass.async_create_task( + hass.config_entries.async_forward_entry_setup(entry, "sensor") + ) + + config = hass.data[DOMAIN][entry.entry_id] + async def async_update_data(): + """Fetch data from Schiene.""" + update_interval=timedelta(minutes=config[CONF_SCAN_INTERVAL]) + async with async_timeout.timeout(update_interval - 1): + await hass.async_add_executor_job(lambda: data.update()) + + if not data.state: + raise UpdateFailed(f"Error fetching {entry.entry_id} Schiene state") + + return data.state + + coordinator = DataUpdateCoordinator( + hass, + _LOGGER, + name=f"{entry.entry_id} Schiene state", + update_method=async_update_data, + ) + + return True + + +async def options_update_listener( + hass: core.HomeAssistant, config_entry: config_entries.ConfigEntry +): + """Handle options update.""" + await hass.config_entries.async_reload(config_entry.entry_id) + +async def async_update(self): + """Async wrapper for update method.""" + return await self._hass.async_add_executor_job(self._update) + +async def async_unload_entry( + hass: core.HomeAssistant, entry: config_entries.ConfigEntry +) -> bool: + """Unload a config entry.""" + unload_ok = all( + await asyncio.gather( + *[hass.config_entries.async_forward_entry_unload(entry, "sensor")] + ) + ) + # Remove options_update_listener. + hass.data[DOMAIN][entry.entry_id]["unsub_options_update_listener"]() + + # Remove config entry from domain. + if unload_ok: + hass.data[DOMAIN].pop(entry.entry_id) + + return unload_ok \ No newline at end of file diff --git a/custom_components/deutschebahn/config_flow.py b/custom_components/deutschebahn/config_flow.py index 24b6ea0..d3d2fb0 100644 --- a/custom_components/deutschebahn/config_flow.py +++ b/custom_components/deutschebahn/config_flow.py @@ -4,7 +4,7 @@ import voluptuous as vol from homeassistant import config_entries -from homeassistant.const import CONF_NAME, CONF_LATITUDE, CONF_LONGITUDE +from homeassistant.const import CONF_NAME from homeassistant.core import callback import homeassistant.helpers.config_validation as cv @@ -13,9 +13,6 @@ CONF_START, CONF_OFFSET, CONF_ONLY_DIRECT, - - DEFAULT_OFFSET, - DEFAULT_ONLY_DIRECT, ) DOMAIN = "deutschebahn" @@ -33,20 +30,20 @@ async def async_step_user(self, user_input=None): errors = {} if user_input is not None: - await self.async_set_unique_id(user_input[CONF_LATITUDE_FS]) + await self.async_set_unique_id(user_input[CONF_START] + "-" + user_input[CONF_DESTINATION]) self._abort_if_unique_id_configured() - return self.async_create_entry(title=user_input[CONF_LATITUDE_FS], data=user_input) + return self.async_create_entry(title=user_input[CONF_START], data=user_input) _LOGGER.debug( - "Initialized new DeutscheBahn Sensor with id: {unique_id}" + "Initialized new deutschebahn with id: {unique_id}" ) data_schema = vol.Schema( { - vol.Required(CONF_DESTINATION): cv.string, - vol.Required(CONF_START): cv.string, - vol.Optional(CONF_OFFSET, default=DEFAULT_OFFSET): cv.time_period, - vol.Optional(CONF_ONLY_DIRECT, default=DEFAULT_ONLY_DIRECT): cv.boolean, + vol.Required(CONF_START): str, + vol.Required(CONF_DESTINATION): str, + vol.Required(CONF_OFFSET, default=0): cv.positive_int, + vol.Required(CONF_ONLY_DIRECT, default=False): cv.boolean, }, ) diff --git a/custom_components/deutschebahn/const.py b/custom_components/deutschebahn/const.py index d8d00b0..84abc41 100644 --- a/custom_components/deutschebahn/const.py +++ b/custom_components/deutschebahn/const.py @@ -1,6 +1,4 @@ """German Train System - Deutsche Bahn""" -from datetime import timedelta - DOMAIN = "deutschebahn" ATTRIBUTION = "Data provided by bahn.de api" @@ -9,5 +7,4 @@ CONF_OFFSET = "offset" CONF_ONLY_DIRECT = "only_direct" -DEFAULT_OFFSET = timedelta(minutes=0) -DEFAULT_ONLY_DIRECT = False \ No newline at end of file +ATTR_DATA = "data" \ No newline at end of file diff --git a/custom_components/deutschebahn/manifest.json b/custom_components/deutschebahn/manifest.json index e0b3c26..e73f2d3 100644 --- a/custom_components/deutschebahn/manifest.json +++ b/custom_components/deutschebahn/manifest.json @@ -4,7 +4,7 @@ "codeowners": [ "@faserf" ], - "config_flow": false, + "config_flow": true, "documentation": "https://github.com/faserf/ha-deutschebahn#readme", "issue_tracker": "https://github.com/faserf/ha-deutschebahn/issues", "requirements": [ diff --git a/custom_components/deutschebahn/sensor.py b/custom_components/deutschebahn/sensor.py index 6aa7fea..b79d717 100644 --- a/custom_components/deutschebahn/sensor.py +++ b/custom_components/deutschebahn/sensor.py @@ -1,64 +1,72 @@ -"""Support for information about the German train system.""" -from __future__ import annotations - -from datetime import timedelta +"""deutschebahn sensor platform.""" +from datetime import timedelta, datetime import logging import schiene -import voluptuous as vol +from typing import Any, Callable, Dict, Optional +import async_timeout +from homeassistant import config_entries, core from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity -from homeassistant.const import CONF_OFFSET -from homeassistant.core import HomeAssistant -import homeassistant.helpers.config_validation as cv +from homeassistant.const import ATTR_ATTRIBUTION from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.typing import ( + ConfigType, + HomeAssistantType, + DiscoveryInfoType, +) import homeassistant.util.dt as dt_util +import voluptuous as vol -CONF_DESTINATION = "to" -CONF_START = "from" -DEFAULT_OFFSET = timedelta(minutes=0) -CONF_ONLY_DIRECT = "only_direct" -DEFAULT_ONLY_DIRECT = False - -ICON = "mdi:train" - -SCAN_INTERVAL = timedelta(minutes=2) +from .const import ( + ATTRIBUTION, + CONF_DESTINATION, + CONF_START, + CONF_OFFSET, + CONF_ONLY_DIRECT, + ATTR_DATA, -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Required(CONF_DESTINATION): cv.string, - vol.Required(CONF_START): cv.string, - vol.Optional(CONF_OFFSET, default=DEFAULT_OFFSET): cv.time_period, - vol.Optional(CONF_ONLY_DIRECT, default=DEFAULT_ONLY_DIRECT): cv.boolean, - } + DOMAIN, ) _LOGGER = logging.getLogger(__name__) +SCAN_INTERVAL = timedelta(minutes=2) - -def setup_platform( - hass: HomeAssistant, - config: ConfigType, - add_entities: AddEntitiesCallback, - discovery_info: DiscoveryInfoType | None = None, -) -> None: - """Set up the Deutsche Bahn Sensor.""" - start = config.get(CONF_START) - destination = config[CONF_DESTINATION] - offset = config[CONF_OFFSET] - only_direct = config[CONF_ONLY_DIRECT] - add_entities([DeutscheBahnSensor(start, destination, offset, only_direct)], True) - +async def async_setup_entry( + hass: HomeAssistantType, entry: ConfigType, async_add_entities +): + """Setup sensors from a config entry created in the integrations UI.""" + config = hass.data[DOMAIN][entry.entry_id] + _LOGGER.debug("Sensor async_setup_entry") + if entry.options: + config.update(entry.options) + sensors = DeutscheBahnSensor(config, hass) + async_add_entities(sensors, update_before_add=True) + async_add_entities( + [ + DeutscheBahnSensor(config, hass) + ], + update_before_add=True + ) class DeutscheBahnSensor(SensorEntity): """Implementation of a Deutsche Bahn sensor.""" - def __init__(self, start, goal, offset, only_direct): - """Initialize the sensor.""" - self._name = f"{start} to {goal}" - self.data = SchieneData(start, goal, offset, only_direct) + def __init__(self, config, hass: HomeAssistantType): + super().__init__() + self._name = f"{config[CONF_START]} to {config[CONF_DESTINATION]}" self._state = None + self.data = None + self._available = True + self.hass = hass + self.updated = datetime.now() + self.start = config[CONF_START] + self.goal = config[CONF_DESTINATION] + self.offset = timedelta(seconds=config[CONF_OFFSET]) + self.only_direct = config[CONF_ONLY_DIRECT] + self.schiene = schiene.Schiene() + self.connections = [{}] @property def name(self): @@ -68,7 +76,14 @@ def name(self): @property def icon(self): """Return the icon for the frontend.""" - return ICON + return "mdi:train" + + @property + def state(self) -> Optional[str]: + if self._state is not None: + return self._state + else: + return "Error" @property def native_value(self): @@ -78,51 +93,61 @@ def native_value(self): @property def extra_state_attributes(self): """Return the state attributes.""" - connections = self.data.connections[0] - if len(self.data.connections) > 1: - connections["next"] = self.data.connections[1]["departure"] - if len(self.data.connections) > 2: - connections["next_on"] = self.data.connections[2]["departure"] + if len(self.connections) > 0: + connections = self.connections[0] + if len(self.connections) > 1: + connections["next"] = self.connections[1]["departure"] + if len(self.connections) > 2: + connections["next_on"] = self.connections[2]["departure"] + else: + connections = None return connections - def update(self) -> None: - """Get the latest delay from bahn.de and updates the state.""" - self.data.update() - self._state = self.data.connections[0].get("departure", "Unknown") - if self.data.connections[0].get("delay", 0) != 0: - self._state += f" + {self.data.connections[0]['delay']}" - - -class SchieneData: - """Pull data from the bahn.de web page.""" - - def __init__(self, start, goal, offset, only_direct): - """Initialize the sensor.""" - self.start = start - self.goal = goal - self.offset = offset - self.only_direct = only_direct - self.schiene = schiene.Schiene() - self.connections = [{}] - - def update(self): - """Update the connection data.""" - self.connections = self.schiene.connections( - self.start, - self.goal, - dt_util.as_local(dt_util.utcnow() + self.offset), - self.only_direct, - ) - - if not self.connections: - self.connections = [{}] - - for con in self.connections: - # Detail info is not useful. Having a more consistent interface - # simplifies usage of template sensors. - if "details" in con: - con.pop("details") - delay = con.get("delay", {"delay_departure": 0, "delay_arrival": 0}) - con["delay"] = delay["delay_departure"] - con["delay_arrival"] = delay["delay_arrival"] - con["ontime"] = con.get("ontime", False) \ No newline at end of file + async def async_update(self): + try: + with async_timeout.timeout(30): + hass = self.hass + """Pull data from the bahn.de web page.""" + _LOGGER.debug("Update the connection data") + self.connections = await hass.async_add_executor_job( + fetch_schiene_connections, hass, self + ) + + if not self.connections: + self.connections = [{}] + self._available = True + else: + _LOGGER.exception(f"Data from DB for direction: '{self.start}' '{self.goal}' was empty, retrying at next sync run. Maybe also check if you have spelled your start and destination correct?") + self._available = False + + for con in self.connections: + # Detail info is not useful. Having a more consistent interface + # simplifies usage of template sensors. + if "details" in con: + _LOGGER.debug("Got data from DB: {con}") + con.pop("details") + delay = con.get("delay", {"delay_departure": 0, "delay_arrival": 0}) + con["delay"] = delay["delay_departure"] + con["delay_arrival"] = delay["delay_arrival"] + con["ontime"] = con.get("ontime", False) + self.attrs[ATTR_DATA] = self.connections + self.attrs[ATTR_ATTRIBUTION] = f"last updated {datetime.now()} \n{ATTRIBUTION}" + + if self.connections[0].get("delay", 0) != 0: + self._state += f" + {self.connections[0]['delay']}" + else: + self._state = self.connections[0].get("departure", "Unknown") + + except: + self._available = False + _LOGGER.exception(f"Cannot retrieve data for direction: '{self.start}' '{self.goal}'") + +def fetch_schiene_connections(hass, self): + _LOGGER.debug("Fetching update from schiene python module") + data = self.schiene.connections( + self.start, + self.goal, + dt_util.as_local(dt_util.utcnow() + self.offset), + self.only_direct, + ) + return data \ No newline at end of file diff --git a/custom_components/deutschebahn/strings.json b/custom_components/deutschebahn/strings.json index fa29c70..ba8fff8 100644 --- a/custom_components/deutschebahn/strings.json +++ b/custom_components/deutschebahn/strings.json @@ -2,24 +2,22 @@ "config": { "step": { "user": { - "description": "The latitude and longitude coordinates will be used to search for baskets within your distance. Your username and password will be used to authentificate API.", + "description": "Submit your train station details for the search queries.", "data": { - "latitude": "Latitude", - "longitude": "Longitude", - "distance": "Distance in kilometers (km)", - "email": "E-Mail Adress from your foodsharing account", - "password": "Password from your foodsharing account", - "scan_interval": "Scan interval in minutes" + "start": "Start station", + "destination": "Destination station", + "offset": "Offset in minutes", + "only_direct": "Only show direct connections?" } } }, "error": { "cannot_connect": "Cannot connect", - "invalid_lat_long": "Invalid Langitude / Longitude coordinates", + "invalid_station": "Invalid Start / Destination station", "unknown": "Unknown Error" }, "abort": { - "already_configured": "This latitude & longitude combination is already configured" + "already_configured": "This start & Destination combination is already configured" } } } \ No newline at end of file diff --git a/custom_components/deutschebahn/translations/de.json b/custom_components/deutschebahn/translations/de.json deleted file mode 100644 index 11dc067..0000000 --- a/custom_components/deutschebahn/translations/de.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "config": { - "step": { - "user": { - "description": "Enter the DB station informations to set up the sensor", - "data": { - "start": "Latitude", - "destination": "Longitude", - "offset": "Distance in kilometers (km)", - "only_direct": "E-Mail Adress from your foodsharing account" - } - } - }, - "error": { - "cannot_connect": "Cannot connect", - "unknown": "Unknown Error" - }, - "abort": { - "already_configured": "This start & destination combination is already configured" - } - } -} \ No newline at end of file diff --git a/custom_components/deutschebahn/translations/en.json b/custom_components/deutschebahn/translations/en.json deleted file mode 100644 index fa29c70..0000000 --- a/custom_components/deutschebahn/translations/en.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "config": { - "step": { - "user": { - "description": "The latitude and longitude coordinates will be used to search for baskets within your distance. Your username and password will be used to authentificate API.", - "data": { - "latitude": "Latitude", - "longitude": "Longitude", - "distance": "Distance in kilometers (km)", - "email": "E-Mail Adress from your foodsharing account", - "password": "Password from your foodsharing account", - "scan_interval": "Scan interval in minutes" - } - } - }, - "error": { - "cannot_connect": "Cannot connect", - "invalid_lat_long": "Invalid Langitude / Longitude coordinates", - "unknown": "Unknown Error" - }, - "abort": { - "already_configured": "This latitude & longitude combination is already configured" - } - } -} \ No newline at end of file From 06d453d6e3305e8e5ccc4c94569fc2e99ce80a27 Mon Sep 17 00:00:00 2001 From: Fabian Seitz Date: Thu, 29 Sep 2022 23:08:52 +0200 Subject: [PATCH 2/5] fixed config flow and cleaned up the code --- README.md | 4 +++ custom_components/deutschebahn/sensor.py | 42 +++++++++++++----------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index f4ac613..f35b2b1 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ where `` is your Home Assistant configuration directory. >__NOTE__: Do not download the file by using the link above directly, the status in the "master" branch can be in development and therefore is maybe not working. ## Configuration +Go to Configuration -> Integrations and click on "add integration". Then search for Rewe. ### Configuration Variables - **from**: The name of the start station. @@ -44,6 +45,9 @@ where `` is your Home Assistant configuration directory. - **offset** (optional): Do not display departures leaving sooner than this number of seconds. Useful if you are a couple of minutes away from the stop. The formats "HH:MM" and "HH:MM:SS" are also supported. - **only_direct** (optional - default is false): Only show direct connections. +### YAML Config +DEPRECATED, use the GUI setup instead! + ```yaml # Example configuration.yaml entry sensor: diff --git a/custom_components/deutschebahn/sensor.py b/custom_components/deutschebahn/sensor.py index b79d717..a1e75f0 100644 --- a/custom_components/deutschebahn/sensor.py +++ b/custom_components/deutschebahn/sensor.py @@ -1,9 +1,9 @@ """deutschebahn sensor platform.""" from datetime import timedelta, datetime import logging +from typing import Any, Callable, Dict, Optional import schiene -from typing import Any, Callable, Dict, Optional import async_timeout from homeassistant import config_entries, core @@ -57,7 +57,6 @@ def __init__(self, config, hass: HomeAssistantType): super().__init__() self._name = f"{config[CONF_START]} to {config[CONF_DESTINATION]}" self._state = None - self.data = None self._available = True self.hass = hass self.updated = datetime.now() @@ -116,27 +115,29 @@ async def async_update(self): if not self.connections: self.connections = [{}] self._available = True + connections_count = len(self.connections) + + if connections_count > 0: + for con in self.connections: + # Detail info is not useful. Having a more consistent interface + # simplifies usage of template sensors. + if "details" in con: + #_LOGGER.debug(f"Processing connection: {con}") + con.pop("details") + delay = con.get("delay", {"delay_departure": 0, "delay_arrival": 0}) + con["delay"] = delay["delay_departure"] + con["delay_arrival"] = delay["delay_arrival"] + con["ontime"] = con.get("ontime", False) + #self.attrs[ATTR_DATA] = self.connections + #self.attrs[ATTR_ATTRIBUTION] = f"last updated {datetime.now()} \n{ATTRIBUTION}" + + if self.connections[0].get("delay", 0) != 0: + self._state += f"{self.connections[0]['delay']}" + else: + self._state = self.connections[0].get("departure", "Unknown") else: _LOGGER.exception(f"Data from DB for direction: '{self.start}' '{self.goal}' was empty, retrying at next sync run. Maybe also check if you have spelled your start and destination correct?") self._available = False - - for con in self.connections: - # Detail info is not useful. Having a more consistent interface - # simplifies usage of template sensors. - if "details" in con: - _LOGGER.debug("Got data from DB: {con}") - con.pop("details") - delay = con.get("delay", {"delay_departure": 0, "delay_arrival": 0}) - con["delay"] = delay["delay_departure"] - con["delay_arrival"] = delay["delay_arrival"] - con["ontime"] = con.get("ontime", False) - self.attrs[ATTR_DATA] = self.connections - self.attrs[ATTR_ATTRIBUTION] = f"last updated {datetime.now()} \n{ATTRIBUTION}" - - if self.connections[0].get("delay", 0) != 0: - self._state += f" + {self.connections[0]['delay']}" - else: - self._state = self.connections[0].get("departure", "Unknown") except: self._available = False @@ -150,4 +151,5 @@ def fetch_schiene_connections(hass, self): dt_util.as_local(dt_util.utcnow() + self.offset), self.only_direct, ) + _LOGGER.debug(f"Fetched data: {data}") return data \ No newline at end of file From 1e4dae9bd6a77007429024bf1d7bdb807d55b0e6 Mon Sep 17 00:00:00 2001 From: Fabian Seitz Date: Fri, 30 Sep 2022 09:21:39 +0200 Subject: [PATCH 3/5] Small improvements to configflow --- custom_components/deutschebahn/config_flow.py | 4 ++-- custom_components/deutschebahn/sensor.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/custom_components/deutschebahn/config_flow.py b/custom_components/deutschebahn/config_flow.py index d3d2fb0..0325c37 100644 --- a/custom_components/deutschebahn/config_flow.py +++ b/custom_components/deutschebahn/config_flow.py @@ -30,9 +30,9 @@ async def async_step_user(self, user_input=None): errors = {} if user_input is not None: - await self.async_set_unique_id(user_input[CONF_START] + "-" + user_input[CONF_DESTINATION]) + await self.async_set_unique_id(user_input[CONF_START]) self._abort_if_unique_id_configured() - return self.async_create_entry(title=user_input[CONF_START], data=user_input) + return self.async_create_entry(title=user_input[CONF_START] + "-" + user_input[CONF_DESTINATION], data=user_input) _LOGGER.debug( "Initialized new deutschebahn with id: {unique_id}" diff --git a/custom_components/deutschebahn/sensor.py b/custom_components/deutschebahn/sensor.py index a1e75f0..2785146 100644 --- a/custom_components/deutschebahn/sensor.py +++ b/custom_components/deutschebahn/sensor.py @@ -132,7 +132,7 @@ async def async_update(self): #self.attrs[ATTR_ATTRIBUTION] = f"last updated {datetime.now()} \n{ATTRIBUTION}" if self.connections[0].get("delay", 0) != 0: - self._state += f"{self.connections[0]['delay']}" + self._state = f"{self.connections[0]['delay']}" else: self._state = self.connections[0].get("departure", "Unknown") else: From 47f0c4673908102bae7bb90071fb1e4f2d4026f3 Mon Sep 17 00:00:00 2001 From: Fabian Seitz Date: Fri, 30 Sep 2022 11:03:20 +0200 Subject: [PATCH 4/5] fix state value --- custom_components/deutschebahn/sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/deutschebahn/sensor.py b/custom_components/deutschebahn/sensor.py index 2785146..ee0f00c 100644 --- a/custom_components/deutschebahn/sensor.py +++ b/custom_components/deutschebahn/sensor.py @@ -82,7 +82,7 @@ def state(self) -> Optional[str]: if self._state is not None: return self._state else: - return "Error" + return "Unknown" @property def native_value(self): @@ -132,7 +132,7 @@ async def async_update(self): #self.attrs[ATTR_ATTRIBUTION] = f"last updated {datetime.now()} \n{ATTRIBUTION}" if self.connections[0].get("delay", 0) != 0: - self._state = f"{self.connections[0]['delay']}" + self._state = f"{self.connections[0]['departure']} + {self.connections[0]['delay']}" else: self._state = self.connections[0].get("departure", "Unknown") else: From cb96d296cdb93d920fb712e58916c52cb90264a4 Mon Sep 17 00:00:00 2001 From: Fabian Seitz Date: Fri, 30 Sep 2022 11:11:50 +0200 Subject: [PATCH 5/5] Bump version to V2.0.0 --- custom_components/deutschebahn/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/deutschebahn/manifest.json b/custom_components/deutschebahn/manifest.json index b854784..6dac5f8 100644 --- a/custom_components/deutschebahn/manifest.json +++ b/custom_components/deutschebahn/manifest.json @@ -10,7 +10,7 @@ "requirements": [ "schiene==0.26" ], - "version": "1.0.2", + "version": "2.0.0", "iot_class": "cloud_polling", "loggers": [ "schiene"