Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for Transport NSW (AU) to query next leave event."""
2 
3 from __future__ import annotations
4 
5 from datetime import timedelta
6 from typing import Any
7 
8 from TransportNSW import TransportNSW
9 import voluptuous as vol
10 
12  PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
13  SensorDeviceClass,
14  SensorEntity,
15  SensorStateClass,
16 )
17 from homeassistant.const import ATTR_MODE, CONF_API_KEY, CONF_NAME, UnitOfTime
18 from homeassistant.core import HomeAssistant
20 from homeassistant.helpers.entity_platform import AddEntitiesCallback
21 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
22 
23 ATTR_STOP_ID = "stop_id"
24 ATTR_ROUTE = "route"
25 ATTR_DUE_IN = "due"
26 ATTR_DELAY = "delay"
27 ATTR_REAL_TIME = "real_time"
28 ATTR_DESTINATION = "destination"
29 
30 CONF_STOP_ID = "stop_id"
31 CONF_ROUTE = "route"
32 CONF_DESTINATION = "destination"
33 
34 DEFAULT_NAME = "Next Bus"
35 ICONS = {
36  "Train": "mdi:train",
37  "Lightrail": "mdi:tram",
38  "Bus": "mdi:bus",
39  "Coach": "mdi:bus",
40  "Ferry": "mdi:ferry",
41  "Schoolbus": "mdi:bus",
42  "n/a": "mdi:clock",
43  None: "mdi:clock",
44 }
45 
46 SCAN_INTERVAL = timedelta(seconds=60)
47 
48 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
49  {
50  vol.Required(CONF_STOP_ID): cv.string,
51  vol.Required(CONF_API_KEY): cv.string,
52  vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
53  vol.Optional(CONF_ROUTE, default=""): cv.string,
54  vol.Optional(CONF_DESTINATION, default=""): cv.string,
55  }
56 )
57 
58 
60  hass: HomeAssistant,
61  config: ConfigType,
62  add_entities: AddEntitiesCallback,
63  discovery_info: DiscoveryInfoType | None = None,
64 ) -> None:
65  """Set up the Transport NSW sensor."""
66  stop_id = config[CONF_STOP_ID]
67  api_key = config[CONF_API_KEY]
68  route = config.get(CONF_ROUTE)
69  destination = config.get(CONF_DESTINATION)
70  name = config.get(CONF_NAME)
71 
72  data = PublicTransportData(stop_id, route, destination, api_key)
73  add_entities([TransportNSWSensor(data, stop_id, name)], True)
74 
75 
77  """Implementation of an Transport NSW sensor."""
78 
79  _attr_attribution = "Data provided by Transport NSW"
80  _attr_device_class = SensorDeviceClass.DURATION
81  _attr_state_class = SensorStateClass.MEASUREMENT
82 
83  def __init__(self, data, stop_id, name):
84  """Initialize the sensor."""
85  self.datadata = data
86  self._name_name = name
87  self._stop_id_stop_id = stop_id
88  self._times_times = self._state_state = None
89  self._icon_icon = ICONS[None]
90 
91  @property
92  def name(self):
93  """Return the name of the sensor."""
94  return self._name_name
95 
96  @property
97  def native_value(self):
98  """Return the state of the sensor."""
99  return self._state_state
100 
101  @property
102  def extra_state_attributes(self) -> dict[str, Any] | None:
103  """Return the state attributes."""
104  if self._times_times is not None:
105  return {
106  ATTR_DUE_IN: self._times_times[ATTR_DUE_IN],
107  ATTR_STOP_ID: self._stop_id_stop_id,
108  ATTR_ROUTE: self._times_times[ATTR_ROUTE],
109  ATTR_DELAY: self._times_times[ATTR_DELAY],
110  ATTR_REAL_TIME: self._times_times[ATTR_REAL_TIME],
111  ATTR_DESTINATION: self._times_times[ATTR_DESTINATION],
112  ATTR_MODE: self._times_times[ATTR_MODE],
113  }
114  return None
115 
116  @property
118  """Return the unit this state is expressed in."""
119  return UnitOfTime.MINUTES
120 
121  @property
122  def icon(self):
123  """Icon to use in the frontend, if any."""
124  return self._icon_icon
125 
126  def update(self) -> None:
127  """Get the latest data from Transport NSW and update the states."""
128  self.datadata.update()
129  self._times_times = self.datadata.info
130  self._state_state = self._times_times[ATTR_DUE_IN]
131  self._icon_icon = ICONS[self._times_times[ATTR_MODE]]
132 
133 
134 def _get_value(value):
135  """Replace the API response 'n/a' value with None."""
136  return None if (value is None or value == "n/a") else value
137 
138 
140  """The Class for handling the data retrieval."""
141 
142  def __init__(self, stop_id, route, destination, api_key):
143  """Initialize the data object."""
144  self._stop_id_stop_id = stop_id
145  self._route_route = route
146  self._destination_destination = destination
147  self._api_key_api_key = api_key
148  self.infoinfo = {
149  ATTR_ROUTE: self._route_route,
150  ATTR_DUE_IN: None,
151  ATTR_DELAY: None,
152  ATTR_REAL_TIME: None,
153  ATTR_DESTINATION: None,
154  ATTR_MODE: None,
155  }
156  self.tnswtnsw = TransportNSW()
157 
158  def update(self):
159  """Get the next leave time."""
160  _data = self.tnswtnsw.get_departures(
161  self._stop_id_stop_id, self._route_route, self._destination_destination, self._api_key_api_key
162  )
163  self.infoinfo = {
164  ATTR_ROUTE: _get_value(_data["route"]),
165  ATTR_DUE_IN: _get_value(_data["due"]),
166  ATTR_DELAY: _get_value(_data["delay"]),
167  ATTR_REAL_TIME: _get_value(_data["real_time"]),
168  ATTR_DESTINATION: _get_value(_data["destination"]),
169  ATTR_MODE: _get_value(_data["mode"]),
170  }
def __init__(self, stop_id, route, destination, api_key)
Definition: sensor.py:142
def add_entities(account, async_add_entities, tracked)
Definition: sensor.py:40
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: sensor.py:64