1 """Support for the Italian train system using ViaggiaTreno API."""
3 from __future__
import annotations
6 from http
import HTTPStatus
11 import voluptuous
as vol
14 PLATFORM_SCHEMA
as SENSOR_PLATFORM_SCHEMA,
24 _LOGGER = logging.getLogger(__name__)
26 VIAGGIATRENO_ENDPOINT = (
27 "http://www.viaggiatreno.it/infomobilita/"
28 "resteasy/viaggiatreno/andamentoTreno/"
29 "{station_id}/{train_id}/{timestamp}"
36 "compOrarioArrivoZeroEffettivo",
37 "compOrarioPartenzaZeroEffettivo",
46 DEFAULT_NAME =
"Train {}"
48 CONF_NAME =
"train_name"
49 CONF_STATION_ID =
"station_id"
50 CONF_STATION_NAME =
"station_name"
51 CONF_TRAIN_ID =
"train_id"
53 ARRIVED_STRING =
"Arrived"
54 CANCELLED_STRING =
"Cancelled"
55 NOT_DEPARTED_STRING =
"Not departed yet"
56 NO_INFORMATION_STRING =
"No information for this train now"
58 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
60 vol.Required(CONF_TRAIN_ID): cv.string,
61 vol.Required(CONF_STATION_ID): cv.string,
62 vol.Optional(CONF_NAME): cv.string,
70 async_add_entities: AddEntitiesCallback,
71 discovery_info: DiscoveryInfoType |
None =
None,
73 """Set up the ViaggiaTreno platform."""
74 train_id = config.get(CONF_TRAIN_ID)
75 station_id = config.get(CONF_STATION_ID)
76 if not (name := config.get(CONF_NAME)):
77 name = DEFAULT_NAME.format(train_id)
82 """Perform actual request."""
85 async
with asyncio.timeout(REQUEST_TIMEOUT):
86 req = await session.get(uri)
87 if req.status != HTTPStatus.OK:
88 return {
"error": req.status}
89 json_response = await req.json()
90 except (TimeoutError, aiohttp.ClientError)
as exc:
91 _LOGGER.error(
"Cannot connect to ViaggiaTreno API endpoint: %s", exc)
94 _LOGGER.error(
"Received non-JSON data from ViaggiaTreno API endpoint")
100 """Implementation of a ViaggiaTreno sensor."""
102 _attr_attribution =
"Powered by ViaggiaTreno Data"
105 """Initialize the sensor."""
113 self.
uriuri = VIAGGIATRENO_ENDPOINT.format(
114 station_id=station_id, train_id=train_id, timestamp=
int(time.time()) * 1000
119 """Return the name of the sensor."""
120 return self.
_name_name
124 """Return the state of the sensor."""
129 """Icon to use in the frontend, if any."""
130 return self.
_icon_icon
134 """Return the unit of measurement."""
135 return self.
_unit_unit
139 """Return extra attributes."""
144 """Check if the train has actually departed."""
146 first_station = data[
"fermate"][0]
147 if data[
"oraUltimoRilevamento"]
or first_station[
"effettiva"]:
150 _LOGGER.error(
"Cannot fetch first station: %s", data)
155 """Check if the train has already arrived."""
156 last_station = data[
"fermate"][-1]
157 if not last_station[
"effettiva"]:
163 """Check if the train is cancelled."""
164 if data[
"tipoTreno"] ==
"ST" and data[
"provvedimento"] == 1:
172 if res.get(
"error",
""):
173 if res[
"error"] == 204:
174 self.
_state_state = NO_INFORMATION_STRING
177 self.
_state_state = f
"Error: {res['error']}"
180 for i
in MONITORED_INFO:
184 self.
_state_state = CANCELLED_STRING
185 self.
_icon_icon =
"mdi:cancel"
188 self.
_state_state = NOT_DEPARTED_STRING
191 self.
_state_state = ARRIVED_STRING
194 self.
_state_state = res.get(
"ritardo")
195 self.
_unit_unit = UnitOfTime.MINUTES
196 self.
_icon_icon = ICON
def native_unit_of_measurement(self)
def extra_state_attributes(self)
def __init__(self, train_id, station_id, name)
def async_http_request(hass, uri)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)