159 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Python
		
	
	
"""Support for Västtrafik public transport."""
 | 
						|
from datetime import timedelta
 | 
						|
import logging
 | 
						|
 | 
						|
import vasttrafik
 | 
						|
import voluptuous as vol
 | 
						|
 | 
						|
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
 | 
						|
from homeassistant.const import ATTR_ATTRIBUTION, CONF_DELAY, CONF_NAME
 | 
						|
import homeassistant.helpers.config_validation as cv
 | 
						|
from homeassistant.util import Throttle
 | 
						|
from homeassistant.util.dt import now
 | 
						|
 | 
						|
_LOGGER = logging.getLogger(__name__)
 | 
						|
 | 
						|
ATTR_ACCESSIBILITY = "accessibility"
 | 
						|
ATTR_DIRECTION = "direction"
 | 
						|
ATTR_LINE = "line"
 | 
						|
ATTR_TRACK = "track"
 | 
						|
ATTRIBUTION = "Data provided by Västtrafik"
 | 
						|
 | 
						|
CONF_DEPARTURES = "departures"
 | 
						|
CONF_FROM = "from"
 | 
						|
CONF_HEADING = "heading"
 | 
						|
CONF_LINES = "lines"
 | 
						|
CONF_KEY = "key"
 | 
						|
CONF_SECRET = "secret"
 | 
						|
 | 
						|
DEFAULT_DELAY = 0
 | 
						|
 | 
						|
ICON = "mdi:train"
 | 
						|
 | 
						|
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120)
 | 
						|
 | 
						|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
 | 
						|
    {
 | 
						|
        vol.Required(CONF_KEY): cv.string,
 | 
						|
        vol.Required(CONF_SECRET): cv.string,
 | 
						|
        vol.Optional(CONF_DEPARTURES): [
 | 
						|
            {
 | 
						|
                vol.Required(CONF_FROM): cv.string,
 | 
						|
                vol.Optional(CONF_DELAY, default=DEFAULT_DELAY): cv.positive_int,
 | 
						|
                vol.Optional(CONF_HEADING): cv.string,
 | 
						|
                vol.Optional(CONF_LINES, default=[]): vol.All(
 | 
						|
                    cv.ensure_list, [cv.string]
 | 
						|
                ),
 | 
						|
                vol.Optional(CONF_NAME): cv.string,
 | 
						|
            }
 | 
						|
        ],
 | 
						|
    }
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def setup_platform(hass, config, add_entities, discovery_info=None):
 | 
						|
    """Set up the departure sensor."""
 | 
						|
    planner = vasttrafik.JournyPlanner(config.get(CONF_KEY), config.get(CONF_SECRET))
 | 
						|
    sensors = []
 | 
						|
 | 
						|
    for departure in config.get(CONF_DEPARTURES):
 | 
						|
        sensors.append(
 | 
						|
            VasttrafikDepartureSensor(
 | 
						|
                planner,
 | 
						|
                departure.get(CONF_NAME),
 | 
						|
                departure.get(CONF_FROM),
 | 
						|
                departure.get(CONF_HEADING),
 | 
						|
                departure.get(CONF_LINES),
 | 
						|
                departure.get(CONF_DELAY),
 | 
						|
            )
 | 
						|
        )
 | 
						|
    add_entities(sensors, True)
 | 
						|
 | 
						|
 | 
						|
class VasttrafikDepartureSensor(SensorEntity):
 | 
						|
    """Implementation of a Vasttrafik Departure Sensor."""
 | 
						|
 | 
						|
    def __init__(self, planner, name, departure, heading, lines, delay):
 | 
						|
        """Initialize the sensor."""
 | 
						|
        self._planner = planner
 | 
						|
        self._name = name or departure
 | 
						|
        self._departure = self.get_station_id(departure)
 | 
						|
        self._heading = self.get_station_id(heading) if heading else None
 | 
						|
        self._lines = lines if lines else None
 | 
						|
        self._delay = timedelta(minutes=delay)
 | 
						|
        self._departureboard = None
 | 
						|
        self._state = None
 | 
						|
        self._attributes = None
 | 
						|
 | 
						|
    def get_station_id(self, location):
 | 
						|
        """Get the station ID."""
 | 
						|
        if location.isdecimal():
 | 
						|
            station_info = {"station_name": location, "station_id": location}
 | 
						|
        else:
 | 
						|
            station_id = self._planner.location_name(location)[0]["id"]
 | 
						|
            station_info = {"station_name": location, "station_id": station_id}
 | 
						|
        return station_info
 | 
						|
 | 
						|
    @property
 | 
						|
    def name(self):
 | 
						|
        """Return the name of the sensor."""
 | 
						|
        return self._name
 | 
						|
 | 
						|
    @property
 | 
						|
    def icon(self):
 | 
						|
        """Return the icon for the frontend."""
 | 
						|
        return ICON
 | 
						|
 | 
						|
    @property
 | 
						|
    def extra_state_attributes(self):
 | 
						|
        """Return the state attributes."""
 | 
						|
        return self._attributes
 | 
						|
 | 
						|
    @property
 | 
						|
    def state(self):
 | 
						|
        """Return the next departure time."""
 | 
						|
        return self._state
 | 
						|
 | 
						|
    @Throttle(MIN_TIME_BETWEEN_UPDATES)
 | 
						|
    def update(self):
 | 
						|
        """Get the departure board."""
 | 
						|
        try:
 | 
						|
            self._departureboard = self._planner.departureboard(
 | 
						|
                self._departure["station_id"],
 | 
						|
                direction=self._heading["station_id"] if self._heading else None,
 | 
						|
                date=now() + self._delay,
 | 
						|
            )
 | 
						|
        except vasttrafik.Error:
 | 
						|
            _LOGGER.debug("Unable to read departure board, updating token")
 | 
						|
            self._planner.update_token()
 | 
						|
 | 
						|
        if not self._departureboard:
 | 
						|
            _LOGGER.debug(
 | 
						|
                "No departures from departure station %s " "to destination station %s",
 | 
						|
                self._departure["station_name"],
 | 
						|
                self._heading["station_name"] if self._heading else "ANY",
 | 
						|
            )
 | 
						|
            self._state = None
 | 
						|
            self._attributes = {}
 | 
						|
        else:
 | 
						|
            for departure in self._departureboard:
 | 
						|
                line = departure.get("sname")
 | 
						|
                if "cancelled" in departure:
 | 
						|
                    continue
 | 
						|
                if not self._lines or line in self._lines:
 | 
						|
                    if "rtTime" in departure:
 | 
						|
                        self._state = departure["rtTime"]
 | 
						|
                    else:
 | 
						|
                        self._state = departure["time"]
 | 
						|
 | 
						|
                    params = {
 | 
						|
                        ATTR_ACCESSIBILITY: departure.get("accessibility"),
 | 
						|
                        ATTR_ATTRIBUTION: ATTRIBUTION,
 | 
						|
                        ATTR_DIRECTION: departure.get("direction"),
 | 
						|
                        ATTR_LINE: departure.get("sname"),
 | 
						|
                        ATTR_TRACK: departure.get("track"),
 | 
						|
                    }
 | 
						|
 | 
						|
                    self._attributes = {k: v for k, v in params.items() if v}
 | 
						|
                    break
 |