1 """Support for departure information for public transport in Munich."""
4 from __future__
import annotations
6 from copy
import deepcopy
7 from datetime
import timedelta
11 import voluptuous
as vol
14 PLATFORM_SCHEMA
as SENSOR_PLATFORM_SCHEMA,
23 _LOGGER = logging.getLogger(__name__)
25 CONF_NEXT_DEPARTURE =
"nextdeparture"
27 CONF_STATION =
"station"
28 CONF_DESTINATIONS =
"destinations"
29 CONF_DIRECTIONS =
"directions"
31 CONF_PRODUCTS =
"products"
32 CONF_TIMEOFFSET =
"timeoffset"
33 CONF_NUMBER =
"number"
35 DEFAULT_PRODUCT = [
"U-Bahn",
"Tram",
"Bus",
"ExpressBus",
"S-Bahn",
"Nachteule"]
38 "U-Bahn":
"mdi:subway",
41 "ExpressBus":
"mdi:bus",
42 "S-Bahn":
"mdi:train",
43 "Nachteule":
"mdi:owl",
44 "SEV":
"mdi:checkbox-blank-circle-outline",
47 ATTRIBUTION =
"Data provided by MVG-live.de"
51 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
53 vol.Required(CONF_NEXT_DEPARTURE): [
55 vol.Required(CONF_STATION): cv.string,
56 vol.Optional(CONF_DESTINATIONS, default=[
""]): cv.ensure_list_csv,
57 vol.Optional(CONF_DIRECTIONS, default=[
""]): cv.ensure_list_csv,
58 vol.Optional(CONF_LINES, default=[
""]): cv.ensure_list_csv,
60 CONF_PRODUCTS, default=DEFAULT_PRODUCT
61 ): cv.ensure_list_csv,
62 vol.Optional(CONF_TIMEOFFSET, default=0): cv.positive_int,
63 vol.Optional(CONF_NUMBER, default=1): cv.positive_int,
64 vol.Optional(CONF_NAME): cv.string,
74 add_entities: AddEntitiesCallback,
75 discovery_info: DiscoveryInfoType |
None =
None,
77 """Set up the MVGLive sensor."""
81 nextdeparture.get(CONF_STATION),
82 nextdeparture.get(CONF_DESTINATIONS),
83 nextdeparture.get(CONF_DIRECTIONS),
84 nextdeparture.get(CONF_LINES),
85 nextdeparture.get(CONF_PRODUCTS),
86 nextdeparture.get(CONF_TIMEOFFSET),
87 nextdeparture.get(CONF_NUMBER),
88 nextdeparture.get(CONF_NAME),
90 for nextdeparture
in config[CONF_NEXT_DEPARTURE]
97 """Implementation of an MVG Live sensor."""
99 _attr_attribution = ATTRIBUTION
112 """Initialize the sensor."""
116 station, destinations, directions, lines, products, timeoffset, number
123 """Return the name of the sensor."""
125 return self.
_name_name
130 """Return the next departure time."""
135 """Return the state attributes."""
136 if not (dep := self.
datadata.departures):
139 attr[
"departures"] = deepcopy(dep)
144 """Icon to use in the frontend, if any."""
145 return self.
_icon_icon
149 """Return the unit this state is expressed in."""
150 return UnitOfTime.MINUTES
153 """Get the latest data and update the state."""
155 if not self.
datadata.departures:
157 self.
_icon_icon = ICONS[
"-"]
159 self.
_state_state = self.
datadata.departures[0].
get(
"time",
"-")
160 self.
_icon_icon = ICONS[self.
datadata.departures[0].
get(
"product",
"-")]
164 """Pull data from the mvg-live.de web page."""
167 self, station, destinations, directions, lines, products, timeoffset, number
169 """Initialize the sensor."""
181 self.
mvgmvg = MVGLive.MVGLive()
185 """Update the connection data."""
187 _departures = self.
mvgmvg.getlivedata(
197 _LOGGER.warning(
"Returned data not understood")
200 for i, _departure
in enumerate(_departures):
204 and _departure[
"destination"]
not in self.
_destinations_destinations
210 and _departure[
"direction"]
not in self.
_directions_directions
214 if "" not in self.
_lines_lines[:1]
and _departure[
"linename"]
not in self.
_lines_lines:
217 if _departure[
"time"] < self.
_timeoffset_timeoffset:
222 for k
in (
"destination",
"linename",
"time",
"direction",
"product"):
223 _nextdep[k] = _departure.get(k,
"")
224 _nextdep[
"time"] =
int(_nextdep[
"time"])
226 if i == self.
_number_number - 1:
def __init__(self, station, destinations, directions, lines, products, timeoffset, number)
def extra_state_attributes(self)
def __init__(self, station, destinations, directions, lines, products, timeoffset, number, name)
def native_unit_of_measurement(self)
web.Response get(self, web.Request request, str config_key)
def add_entities(account, async_add_entities, tracked)
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)