bolster.data_sources.translink.vehicles ======================================= .. py:module:: bolster.data_sources.translink.vehicles .. autoapi-nested-parse:: Translink live vehicle positions from the VMI (Vehicle Monitoring Interface) feed. The VMI feed at ``vpos.translinkniplanner.co.uk/velocmap/vmi/VMI`` is an undocumented, unauthenticated JSON endpoint operated by Vix Technology on behalf of Translink. It returns a snapshot of all active vehicles across Ulsterbus, Metro, and Glider services, updated approximately every 66 seconds. Key notes on the feed: - ``X`` / ``Y`` are strings (longitude / latitude WGS84), not floats. - ``JourneyIdentifier`` contains ``#!ADD!#vixvm_new#`` suffixes — strip from ``#``. - ``IsAtStop`` only appears when ``True`` (sparse field). - ``Delay`` is in seconds (negative = early). - Operator code ``TM`` in ``VehicleIdentifier`` denotes Metro buses. - ``CurrentStop`` / ``NextStop`` are NaPTAN ATCOCodes (``700000xxxxxx``). .. rubric:: Example >>> vdf = get_live_vehicles() >>> {"vehicle_id", "line", "latitude", "longitude"}.issubset(vdf.columns) True >>> len(vdf) > 0 True Attributes ---------- .. autoapisummary:: bolster.data_sources.translink.vehicles.logger Functions --------- .. autoapisummary:: bolster.data_sources.translink.vehicles.get_live_vehicles bolster.data_sources.translink.vehicles.validate_vehicles Module Contents --------------- .. py:data:: logger .. py:function:: get_live_vehicles(line = None, operator = None, enrich_stops = False) Return a snapshot of live vehicle positions from the Translink VMI feed. :param line: Optional line filter, case-insensitive (e.g. ``"11E"`` or ``"G1"``). :param operator: Optional operator filter, case-insensitive. Accepts canonical codes (``"MET"``) or VMI codes (``"TM"``). Both map to Metro. :param enrich_stops: If True, resolve ``current_stop`` / ``next_stop`` ATCOCodes to human-readable names. Requires building the stop lookup table on first call (~1.3 MB download). :returns: ``id``, ``vehicle_id``, ``operator``, ``operator_raw``, ``line``, ``direction``, ``journey_id``, ``day_of_operation``, ``longitude``, ``latitude``, ``longitude_prev``, ``latitude_prev``, ``timestamp`` (tz-aware), ``timestamp_prev`` (tz-aware), ``delay_seconds`` (Int64, negative = early), ``current_stop``, ``next_stop``, ``is_at_stop`` (bool), ``realtime_available`` (bool), ``mot_code`` (Int64). :rtype: DataFrame with one row per active vehicle. Columns :raises TranslinkDataNotFoundError: If the VMI feed cannot be reached. :raises TranslinkValidationError: If the response is malformed. .. rubric:: Example >>> vdf = get_live_vehicles(line="11E") >>> all(vdf["line"].str.upper() == "11E") True .. py:function:: validate_vehicles(df) Validate a live vehicles DataFrame. :param df: DataFrame as returned by :func:`get_live_vehicles`. :returns: True if validation passes. :raises TranslinkValidationError: If required columns are missing or coordinates are invalid.