mirror of
https://github.com/home-assistant/core.git
synced 2026-09-05 02:25:07 -05:00
Refactor Nederlandse Spoorwegen integration (#154616)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: G Johansson <goran.johansson@shiftit.se> Co-authored-by: Erwin Douna <e.douna@gmail.com> Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
co-authored by
Copilot
G Johansson
Erwin Douna
Joostlek
parent
b23134f4f1
commit
10c8ee417b
@@ -6,6 +6,7 @@ from datetime import datetime
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from ns_api import Trip
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
@@ -38,6 +39,33 @@ from .const import (
|
||||
)
|
||||
from .coordinator import NSConfigEntry, NSDataUpdateCoordinator
|
||||
|
||||
|
||||
def _get_departure_time(trip: Trip | None) -> datetime | None:
|
||||
"""Get next departure time from trip data."""
|
||||
return trip.departure_time_actual or trip.departure_time_planned if trip else None
|
||||
|
||||
|
||||
def _get_time_str(time: datetime | None) -> str | None:
|
||||
"""Get time as string."""
|
||||
return time.strftime("%H:%M") if time else None
|
||||
|
||||
|
||||
def _get_route(trip: Trip | None) -> list[str]:
|
||||
"""Get the route as a list of station names from trip data."""
|
||||
if not trip or not (trip_parts := trip.trip_parts):
|
||||
return []
|
||||
route = []
|
||||
if departure := trip.departure:
|
||||
route.append(departure)
|
||||
route.extend(part.destination for part in trip_parts)
|
||||
return route
|
||||
|
||||
|
||||
def _get_delay(planned: datetime | None, actual: datetime | None) -> bool:
|
||||
"""Return True if delay is present, False otherwise."""
|
||||
return bool(planned and actual and planned != actual)
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ROUTE_SCHEMA = vol.Schema(
|
||||
@@ -163,94 +191,38 @@ class NSDepartureSensor(CoordinatorEntity[NSDataUpdateCoordinator], SensorEntity
|
||||
return None
|
||||
|
||||
first_trip = route_data.first_trip
|
||||
if first_trip.departure_time_actual:
|
||||
return first_trip.departure_time_actual
|
||||
return first_trip.departure_time_planned
|
||||
return _get_departure_time(first_trip)
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any] | None:
|
||||
"""Return the state attributes."""
|
||||
route_data = self.coordinator.data
|
||||
if not route_data:
|
||||
return None
|
||||
|
||||
first_trip = route_data.first_trip
|
||||
next_trip = route_data.next_trip
|
||||
first_trip = self.coordinator.data.first_trip
|
||||
next_trip = self.coordinator.data.next_trip
|
||||
|
||||
if not first_trip:
|
||||
return None
|
||||
|
||||
route = []
|
||||
if first_trip.trip_parts:
|
||||
route = [first_trip.departure]
|
||||
route.extend(k.destination for k in first_trip.trip_parts)
|
||||
|
||||
# Static attributes
|
||||
attributes = {
|
||||
return {
|
||||
"going": first_trip.going,
|
||||
"departure_time_planned": None,
|
||||
"departure_time_actual": None,
|
||||
"departure_delay": False,
|
||||
"departure_time_planned": _get_time_str(first_trip.departure_time_planned),
|
||||
"departure_time_actual": _get_time_str(first_trip.departure_time_actual),
|
||||
"departure_delay": _get_delay(
|
||||
first_trip.departure_time_planned,
|
||||
first_trip.departure_time_actual,
|
||||
),
|
||||
"departure_platform_planned": first_trip.departure_platform_planned,
|
||||
"departure_platform_actual": first_trip.departure_platform_actual,
|
||||
"arrival_time_planned": None,
|
||||
"arrival_time_actual": None,
|
||||
"arrival_delay": False,
|
||||
"arrival_time_planned": _get_time_str(first_trip.arrival_time_planned),
|
||||
"arrival_time_actual": _get_time_str(first_trip.arrival_time_actual),
|
||||
"arrival_delay": _get_delay(
|
||||
first_trip.arrival_time_planned,
|
||||
first_trip.arrival_time_actual,
|
||||
),
|
||||
"arrival_platform_planned": first_trip.arrival_platform_planned,
|
||||
"arrival_platform_actual": first_trip.arrival_platform_actual,
|
||||
"next": None,
|
||||
"next": _get_time_str(_get_departure_time(next_trip)),
|
||||
"status": first_trip.status.lower() if first_trip.status else None,
|
||||
"transfers": first_trip.nr_transfers,
|
||||
"route": route,
|
||||
"route": _get_route(first_trip),
|
||||
"remarks": None,
|
||||
}
|
||||
|
||||
# Planned departure attributes
|
||||
if first_trip.departure_time_planned is not None:
|
||||
attributes["departure_time_planned"] = (
|
||||
first_trip.departure_time_planned.strftime("%H:%M")
|
||||
)
|
||||
|
||||
# Actual departure attributes
|
||||
if first_trip.departure_time_actual is not None:
|
||||
attributes["departure_time_actual"] = (
|
||||
first_trip.departure_time_actual.strftime("%H:%M")
|
||||
)
|
||||
|
||||
# Delay departure attributes
|
||||
if (
|
||||
attributes["departure_time_planned"]
|
||||
and attributes["departure_time_actual"]
|
||||
and attributes["departure_time_planned"]
|
||||
!= attributes["departure_time_actual"]
|
||||
):
|
||||
attributes["departure_delay"] = True
|
||||
|
||||
# Planned arrival attributes
|
||||
if first_trip.arrival_time_planned is not None:
|
||||
attributes["arrival_time_planned"] = (
|
||||
first_trip.arrival_time_planned.strftime("%H:%M")
|
||||
)
|
||||
|
||||
# Actual arrival attributes
|
||||
if first_trip.arrival_time_actual is not None:
|
||||
attributes["arrival_time_actual"] = first_trip.arrival_time_actual.strftime(
|
||||
"%H:%M"
|
||||
)
|
||||
|
||||
# Delay arrival attributes
|
||||
if (
|
||||
attributes["arrival_time_planned"]
|
||||
and attributes["arrival_time_actual"]
|
||||
and attributes["arrival_time_planned"] != attributes["arrival_time_actual"]
|
||||
):
|
||||
attributes["arrival_delay"] = True
|
||||
|
||||
# Next trip attributes
|
||||
if next_trip:
|
||||
if next_trip.departure_time_actual is not None:
|
||||
attributes["next"] = next_trip.departure_time_actual.strftime("%H:%M")
|
||||
elif next_trip.departure_time_planned is not None:
|
||||
attributes["next"] = next_trip.departure_time_planned.strftime("%H:%M")
|
||||
|
||||
return attributes
|
||||
|
||||
@@ -56,6 +56,21 @@ def mock_nsapi() -> Generator[AsyncMock]:
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_single_trip_nsapi(mock_nsapi: AsyncMock) -> Generator[AsyncMock]:
|
||||
"""Override async_setup_entry."""
|
||||
trips_data = load_json_object_fixture("trip_single.json", DOMAIN)
|
||||
mock_nsapi.get_trips.return_value = [Trip(trip) for trip in trips_data["trips"]]
|
||||
return mock_nsapi
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_no_trips_nsapi(mock_nsapi: AsyncMock) -> Generator[AsyncMock]:
|
||||
"""Override async_setup_entry."""
|
||||
mock_nsapi.get_trips.return_value = []
|
||||
return mock_nsapi
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry() -> MockConfigEntry:
|
||||
"""Mock config entry."""
|
||||
|
||||
@@ -0,0 +1,856 @@
|
||||
{
|
||||
"source": "HARP",
|
||||
"trips": [
|
||||
{
|
||||
"idx": 2,
|
||||
"uid": "arnu|fromStation=8400058|requestedFromStation=8400058|toStation=8400530|requestedToStation=8400530|viaStation=8400319|plannedFromTime=2025-09-15T16:34:00+02:00|plannedArrivalTime=2025-09-15T18:45:00+02:00|excludeHighSpeedTrains=false|searchForAccessibleTrip=false|localTrainsOnly=false|disabledTransportModalities=BUS,FERRY,TRAM,METRO|travelAssistance=false|tripSummaryHash=1596512355",
|
||||
"ctxRecon": "arnu|fromStation=8400058|requestedFromStation=8400058|toStation=8400530|requestedToStation=8400530|viaStation=8400319|plannedFromTime=2025-09-15T16:34:00+02:00|plannedArrivalTime=2025-09-15T18:45:00+02:00|excludeHighSpeedTrains=false|searchForAccessibleTrip=false|localTrainsOnly=false|disabledTransportModalities=BUS,FERRY,TRAM,METRO|travelAssistance=false|tripSummaryHash=1596512355",
|
||||
"sourceCtxRecon": "¶HKI¶T$A=1@O=Amsterdam Centraal@L=1100836@a=128@$A=1@O='s-Hertogenbosch@L=1100870@a=128@$202509151634$202509151731$IC 2761 $$1$$$$$$§W$A=1@O='s-Hertogenbosch@L=1100870@a=128@$A=1@O='s-Hertogenbosch@L=1101751@a=128@$202509151731$202509151733$$$1$$$$$$§T$A=1@O='s-Hertogenbosch@L=1101751@a=128@$A=1@O=Breda@L=1101034@a=128@$202509151741$202509151810$IC 3661 $$3$$$$$$§W$A=1@O=Breda@L=1101034@a=128@$A=1@O=Breda@L=1100942@a=128@$202509151810$202509151812$$$1$$$$$$§T$A=1@O=Breda@L=1100942@a=128@$A=1@O=Rotterdam Centraal@L=1100668@a=128@$202509151823$202509151845$IC 1162 $$1$$$$$$¶KC¶#VE#2#CF#100#CA#0#CM#0#SICT#0#AM#16465#AM2#0#RT#31#¶KCC¶#VE#0#ERG#45317#HIN#390#ECK#13954|13954|14077|14085|0|0|485|13938|3|0|8|0|0|-2147483648#¶KRCC¶#VE#1#MRTF#",
|
||||
"plannedDurationInMinutes": 131,
|
||||
"actualDurationInMinutes": 130,
|
||||
"transfers": 2,
|
||||
"status": "NORMAL",
|
||||
"messages": [],
|
||||
"legs": [
|
||||
{
|
||||
"idx": "0",
|
||||
"name": "IC 2761",
|
||||
"travelType": "PUBLIC_TRANSIT",
|
||||
"direction": "Maastricht",
|
||||
"partCancelled": false,
|
||||
"cancelled": false,
|
||||
"isAfterCancelledLeg": false,
|
||||
"isOnOrAfterCancelledLeg": false,
|
||||
"changePossible": true,
|
||||
"alternativeTransport": false,
|
||||
"journeyDetailRef": "HARP_MM-2|#VN#1#ST#1757498654#PI#0#ZI#1088#TA#0#DA#150925#1S#1101009#1T#1557#LS#1101011#LT#1903#PU#784#RT#1#CA#IC#ZE#2761#ZB#IC 2761 #PC#1#FR#1101009#FT#1557#TO#1101011#TT#1903#",
|
||||
"origin": {
|
||||
"name": "Amsterdam Centraal",
|
||||
"lng": 4.90027761459351,
|
||||
"lat": 52.3788871765137,
|
||||
"countryCode": "NL",
|
||||
"uicCode": "8400058",
|
||||
"uicCdCode": "118400058",
|
||||
"stationCode": "ASD",
|
||||
"type": "STATION",
|
||||
"plannedTimeZoneOffset": 120,
|
||||
"plannedDateTime": "2025-09-15T16:34:00+0200",
|
||||
"actualTimeZoneOffset": 120,
|
||||
"actualDateTime": "2025-09-15T16:35:00+0200",
|
||||
"plannedTrack": "4",
|
||||
"actualTrack": "4",
|
||||
"checkinStatus": "NOTHING",
|
||||
"notes": []
|
||||
},
|
||||
"destination": {
|
||||
"name": "'s-Hertogenbosch",
|
||||
"lng": 5.29362,
|
||||
"lat": 51.69048,
|
||||
"countryCode": "NL",
|
||||
"uicCode": "8400319",
|
||||
"uicCdCode": "118400319",
|
||||
"stationCode": "HT",
|
||||
"type": "STATION",
|
||||
"plannedTimeZoneOffset": 120,
|
||||
"plannedDateTime": "2025-09-15T17:31:00+0200",
|
||||
"actualTimeZoneOffset": 120,
|
||||
"actualDateTime": "2025-09-15T17:31:00+0200",
|
||||
"plannedTrack": "6",
|
||||
"actualTrack": "6",
|
||||
"exitSide": "RIGHT",
|
||||
"checkinStatus": "NOTHING",
|
||||
"notes": []
|
||||
},
|
||||
"product": {
|
||||
"productType": "Product",
|
||||
"number": "2761",
|
||||
"categoryCode": "IC",
|
||||
"shortCategoryName": "IC",
|
||||
"longCategoryName": "Intercity",
|
||||
"operatorCode": "NS",
|
||||
"operatorName": "NS",
|
||||
"operatorAdministrativeCode": 100,
|
||||
"type": "TRAIN",
|
||||
"displayName": "NS Intercity",
|
||||
"nameNesProperties": {
|
||||
"color": "text-body"
|
||||
},
|
||||
"iconNesProperties": {
|
||||
"color": "text-body",
|
||||
"icon": "train"
|
||||
},
|
||||
"notes": [
|
||||
[
|
||||
{
|
||||
"value": "NS Intercity",
|
||||
"shortValue": "NS Intercity",
|
||||
"accessibilityValue": "NS Intercity",
|
||||
"key": "PRODUCT_NAME",
|
||||
"noteType": "ATTRIBUTE",
|
||||
"isPresentationRequired": true,
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"value": "richting Maastricht",
|
||||
"shortValue": "richting Maastricht",
|
||||
"accessibilityValue": "richting Maastricht",
|
||||
"key": "PRODUCT_DIRECTION",
|
||||
"noteType": "ATTRIBUTE",
|
||||
"isPresentationRequired": true,
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"value": "2 tussenstops",
|
||||
"shortValue": "2 tussenstops",
|
||||
"accessibilityValue": "2 tussenstops",
|
||||
"key": "PRODUCT_INTERMEDIATE_STOPS",
|
||||
"noteType": "ATTRIBUTE",
|
||||
"isPresentationRequired": true,
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"stops": [
|
||||
{
|
||||
"uicCode": "8400058",
|
||||
"uicCdCode": "118400058",
|
||||
"name": "Amsterdam Centraal",
|
||||
"lat": 52.3788871765137,
|
||||
"lng": 4.90027761459351,
|
||||
"countryCode": "NL",
|
||||
"notes": [],
|
||||
"routeIdx": 0,
|
||||
"plannedDepartureDateTime": "2025-09-15T16:34:00+0200",
|
||||
"plannedDepartureTimeZoneOffset": 120,
|
||||
"actualDepartureDateTime": "2025-09-15T16:35:00+0200",
|
||||
"actualDepartureTimeZoneOffset": 120,
|
||||
"actualDepartureTrack": "4",
|
||||
"plannedDepartureTrack": "4",
|
||||
"plannedArrivalTrack": "4",
|
||||
"actualArrivalTrack": "4",
|
||||
"departureDelayInSeconds": 60,
|
||||
"cancelled": false,
|
||||
"borderStop": false,
|
||||
"passing": false
|
||||
},
|
||||
{
|
||||
"uicCode": "8400057",
|
||||
"uicCdCode": "118400057",
|
||||
"name": "Amsterdam Amstel",
|
||||
"lat": 52.3466682434082,
|
||||
"lng": 4.91777801513672,
|
||||
"countryCode": "NL",
|
||||
"notes": [],
|
||||
"routeIdx": 2,
|
||||
"plannedDepartureDateTime": "2025-09-15T16:42:00+0200",
|
||||
"plannedDepartureTimeZoneOffset": 120,
|
||||
"actualDepartureDateTime": "2025-09-15T16:43:00+0200",
|
||||
"actualDepartureTimeZoneOffset": 120,
|
||||
"plannedArrivalDateTime": "2025-09-15T16:42:00+0200",
|
||||
"plannedArrivalTimeZoneOffset": 120,
|
||||
"actualArrivalDateTime": "2025-09-15T16:43:00+0200",
|
||||
"actualArrivalTimeZoneOffset": 120,
|
||||
"actualDepartureTrack": "4",
|
||||
"plannedDepartureTrack": "4",
|
||||
"plannedArrivalTrack": "4",
|
||||
"actualArrivalTrack": "4",
|
||||
"departureDelayInSeconds": 60,
|
||||
"arrivalDelayInSeconds": 60,
|
||||
"cancelled": false,
|
||||
"borderStop": false,
|
||||
"passing": false
|
||||
},
|
||||
{
|
||||
"uicCode": "8400621",
|
||||
"uicCdCode": "118400621",
|
||||
"name": "Utrecht Centraal",
|
||||
"lat": 52.0888900756836,
|
||||
"lng": 5.11027765274048,
|
||||
"countryCode": "NL",
|
||||
"notes": [],
|
||||
"routeIdx": 10,
|
||||
"plannedDepartureDateTime": "2025-09-15T17:03:00+0200",
|
||||
"plannedDepartureTimeZoneOffset": 120,
|
||||
"actualDepartureDateTime": "2025-09-15T17:03:00+0200",
|
||||
"actualDepartureTimeZoneOffset": 120,
|
||||
"plannedArrivalDateTime": "2025-09-15T17:00:00+0200",
|
||||
"plannedArrivalTimeZoneOffset": 120,
|
||||
"actualArrivalDateTime": "2025-09-15T17:00:00+0200",
|
||||
"actualArrivalTimeZoneOffset": 120,
|
||||
"actualDepartureTrack": "15",
|
||||
"plannedDepartureTrack": "15",
|
||||
"plannedArrivalTrack": "15",
|
||||
"actualArrivalTrack": "15",
|
||||
"departureDelayInSeconds": 0,
|
||||
"arrivalDelayInSeconds": 0,
|
||||
"cancelled": false,
|
||||
"borderStop": false,
|
||||
"passing": false
|
||||
},
|
||||
{
|
||||
"uicCode": "8400319",
|
||||
"uicCdCode": "118400319",
|
||||
"name": "'s-Hertogenbosch",
|
||||
"lat": 51.69048,
|
||||
"lng": 5.29362,
|
||||
"countryCode": "NL",
|
||||
"notes": [],
|
||||
"routeIdx": 18,
|
||||
"plannedArrivalDateTime": "2025-09-15T17:31:00+0200",
|
||||
"plannedArrivalTimeZoneOffset": 120,
|
||||
"actualArrivalDateTime": "2025-09-15T17:31:00+0200",
|
||||
"actualArrivalTimeZoneOffset": 120,
|
||||
"actualDepartureTrack": "6",
|
||||
"plannedDepartureTrack": "6",
|
||||
"plannedArrivalTrack": "6",
|
||||
"actualArrivalTrack": "6",
|
||||
"arrivalDelayInSeconds": 0,
|
||||
"cancelled": false,
|
||||
"borderStop": false,
|
||||
"passing": false
|
||||
}
|
||||
],
|
||||
"crowdForecast": "MEDIUM",
|
||||
"bicycleSpotCount": 6,
|
||||
"crossPlatformTransfer": true,
|
||||
"shorterStock": false,
|
||||
"journeyDetail": [
|
||||
{
|
||||
"type": "TRAIN_XML",
|
||||
"link": {
|
||||
"uri": "/api/v2/journey?id=HARP_MM-2|#VN#1#ST#1757498654#PI#0#ZI#1088#TA#0#DA#150925#1S#1101009#1T#1557#LS#1101011#LT#1903#PU#784#RT#1#CA#IC#ZE#2761#ZB#IC 2761 #PC#1#FR#1101009#FT#1557#TO#1101011#TT#1903#&train=2761&datetime=2025-09-15T16:34:00+02:00"
|
||||
}
|
||||
}
|
||||
],
|
||||
"reachable": true,
|
||||
"plannedDurationInMinutes": 57,
|
||||
"nesProperties": {
|
||||
"color": "text-info",
|
||||
"scope": "LEG_LINE",
|
||||
"styles": {
|
||||
"type": "LineStyles",
|
||||
"dashed": false
|
||||
}
|
||||
},
|
||||
"duration": {
|
||||
"value": "56 min.",
|
||||
"accessibilityValue": "56 minuten",
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
},
|
||||
"preSteps": [],
|
||||
"postSteps": [],
|
||||
"transferTimeToNextLeg": 2,
|
||||
"distanceInMeters": 84795
|
||||
},
|
||||
{
|
||||
"idx": "1",
|
||||
"name": "IC 3661",
|
||||
"travelType": "PUBLIC_TRANSIT",
|
||||
"direction": "Roosendaal",
|
||||
"partCancelled": false,
|
||||
"cancelled": false,
|
||||
"isAfterCancelledLeg": false,
|
||||
"isOnOrAfterCancelledLeg": false,
|
||||
"changePossible": true,
|
||||
"alternativeTransport": false,
|
||||
"journeyDetailRef": "HARP_MM-2|#VN#1#ST#1757498654#PI#0#ZI#505945#TA#0#DA#150925#1S#1101167#1T#1550#LS#1101102#LT#1833#PU#784#RT#3#CA#IC#ZE#3661#ZB#IC 3661 #PC#1#FR#1101167#FT#1550#TO#1101102#TT#1833#",
|
||||
"origin": {
|
||||
"name": "'s-Hertogenbosch",
|
||||
"lng": 5.29362,
|
||||
"lat": 51.69048,
|
||||
"countryCode": "NL",
|
||||
"uicCode": "8400319",
|
||||
"uicCdCode": "118400319",
|
||||
"stationCode": "HT",
|
||||
"type": "STATION",
|
||||
"plannedTimeZoneOffset": 120,
|
||||
"plannedDateTime": "2025-09-15T17:41:00+0200",
|
||||
"actualTimeZoneOffset": 120,
|
||||
"actualDateTime": "2025-09-15T17:41:00+0200",
|
||||
"plannedTrack": "7",
|
||||
"actualTrack": "7",
|
||||
"checkinStatus": "NOTHING",
|
||||
"notes": []
|
||||
},
|
||||
"destination": {
|
||||
"name": "Breda",
|
||||
"lng": 4.78000020980835,
|
||||
"lat": 51.5955543518066,
|
||||
"countryCode": "NL",
|
||||
"uicCode": "8400131",
|
||||
"uicCdCode": "118400131",
|
||||
"stationCode": "BD",
|
||||
"type": "STATION",
|
||||
"plannedTimeZoneOffset": 120,
|
||||
"plannedDateTime": "2025-09-15T18:10:00+0200",
|
||||
"actualTimeZoneOffset": 120,
|
||||
"actualDateTime": "2025-09-15T18:10:00+0200",
|
||||
"plannedTrack": "8",
|
||||
"actualTrack": "8",
|
||||
"exitSide": "LEFT",
|
||||
"checkinStatus": "NOTHING",
|
||||
"notes": []
|
||||
},
|
||||
"product": {
|
||||
"productType": "Product",
|
||||
"number": "3661",
|
||||
"categoryCode": "IC",
|
||||
"shortCategoryName": "IC",
|
||||
"longCategoryName": "Intercity",
|
||||
"operatorCode": "NS",
|
||||
"operatorName": "NS",
|
||||
"operatorAdministrativeCode": 100,
|
||||
"type": "TRAIN",
|
||||
"displayName": "NS Intercity",
|
||||
"nameNesProperties": {
|
||||
"color": "text-body"
|
||||
},
|
||||
"iconNesProperties": {
|
||||
"color": "text-body",
|
||||
"icon": "train"
|
||||
},
|
||||
"notes": [
|
||||
[
|
||||
{
|
||||
"value": "NS Intercity",
|
||||
"shortValue": "NS Intercity",
|
||||
"accessibilityValue": "NS Intercity",
|
||||
"key": "PRODUCT_NAME",
|
||||
"noteType": "ATTRIBUTE",
|
||||
"isPresentationRequired": true,
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"value": "richting Roosendaal",
|
||||
"shortValue": "richting Roosendaal",
|
||||
"accessibilityValue": "richting Roosendaal",
|
||||
"key": "PRODUCT_DIRECTION",
|
||||
"noteType": "ATTRIBUTE",
|
||||
"isPresentationRequired": true,
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"value": "1 tussenstop",
|
||||
"shortValue": "1 tussenstop",
|
||||
"accessibilityValue": "1 tussenstop",
|
||||
"key": "PRODUCT_INTERMEDIATE_STOPS",
|
||||
"noteType": "ATTRIBUTE",
|
||||
"isPresentationRequired": true,
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"transferMessages": [
|
||||
{
|
||||
"message": "Overstap op zelfde perron",
|
||||
"accessibilityMessage": "Overstap op zelfde perron",
|
||||
"type": "CROSS_PLATFORM",
|
||||
"messageNesProperties": {
|
||||
"color": "text-default",
|
||||
"type": "informative"
|
||||
}
|
||||
}
|
||||
],
|
||||
"stops": [
|
||||
{
|
||||
"uicCode": "8400319",
|
||||
"uicCdCode": "118400319",
|
||||
"name": "'s-Hertogenbosch",
|
||||
"lat": 51.69048,
|
||||
"lng": 5.29362,
|
||||
"countryCode": "NL",
|
||||
"notes": [],
|
||||
"routeIdx": 0,
|
||||
"plannedDepartureDateTime": "2025-09-15T17:41:00+0200",
|
||||
"plannedDepartureTimeZoneOffset": 120,
|
||||
"actualDepartureDateTime": "2025-09-15T17:41:00+0200",
|
||||
"actualDepartureTimeZoneOffset": 120,
|
||||
"actualDepartureTrack": "7",
|
||||
"plannedDepartureTrack": "7",
|
||||
"plannedArrivalTrack": "7",
|
||||
"actualArrivalTrack": "7",
|
||||
"departureDelayInSeconds": 0,
|
||||
"cancelled": false,
|
||||
"borderStop": false,
|
||||
"passing": false
|
||||
},
|
||||
{
|
||||
"uicCode": "8400597",
|
||||
"uicCdCode": "118400597",
|
||||
"name": "Tilburg",
|
||||
"lat": 51.5605545043945,
|
||||
"lng": 5.08361101150513,
|
||||
"countryCode": "NL",
|
||||
"notes": [],
|
||||
"routeIdx": 1,
|
||||
"plannedDepartureDateTime": "2025-09-15T17:58:00+0200",
|
||||
"plannedDepartureTimeZoneOffset": 120,
|
||||
"actualDepartureDateTime": "2025-09-15T17:58:00+0200",
|
||||
"actualDepartureTimeZoneOffset": 120,
|
||||
"plannedArrivalDateTime": "2025-09-15T17:56:00+0200",
|
||||
"plannedArrivalTimeZoneOffset": 120,
|
||||
"actualArrivalDateTime": "2025-09-15T17:56:00+0200",
|
||||
"actualArrivalTimeZoneOffset": 120,
|
||||
"actualDepartureTrack": "3",
|
||||
"plannedDepartureTrack": "3",
|
||||
"plannedArrivalTrack": "3",
|
||||
"actualArrivalTrack": "3",
|
||||
"departureDelayInSeconds": 0,
|
||||
"arrivalDelayInSeconds": 0,
|
||||
"cancelled": false,
|
||||
"borderStop": false,
|
||||
"passing": false
|
||||
},
|
||||
{
|
||||
"uicCode": "8400131",
|
||||
"uicCdCode": "118400131",
|
||||
"name": "Breda",
|
||||
"lat": 51.5955543518066,
|
||||
"lng": 4.78000020980835,
|
||||
"countryCode": "NL",
|
||||
"notes": [],
|
||||
"routeIdx": 5,
|
||||
"plannedArrivalDateTime": "2025-09-15T18:10:00+0200",
|
||||
"plannedArrivalTimeZoneOffset": 120,
|
||||
"actualArrivalDateTime": "2025-09-15T18:10:00+0200",
|
||||
"actualArrivalTimeZoneOffset": 120,
|
||||
"actualDepartureTrack": "8",
|
||||
"plannedDepartureTrack": "8",
|
||||
"plannedArrivalTrack": "8",
|
||||
"actualArrivalTrack": "8",
|
||||
"arrivalDelayInSeconds": 0,
|
||||
"cancelled": false,
|
||||
"borderStop": false,
|
||||
"passing": false
|
||||
}
|
||||
],
|
||||
"crowdForecast": "MEDIUM",
|
||||
"punctuality": 58.3,
|
||||
"crossPlatformTransfer": true,
|
||||
"shorterStock": false,
|
||||
"journeyDetail": [
|
||||
{
|
||||
"type": "TRAIN_XML",
|
||||
"link": {
|
||||
"uri": "/api/v2/journey?id=HARP_MM-2|#VN#1#ST#1757498654#PI#0#ZI#505945#TA#0#DA#150925#1S#1101167#1T#1550#LS#1101102#LT#1833#PU#784#RT#3#CA#IC#ZE#3661#ZB#IC 3661 #PC#1#FR#1101167#FT#1550#TO#1101102#TT#1833#&train=3661&datetime=2025-09-15T17:41:00+02:00"
|
||||
}
|
||||
}
|
||||
],
|
||||
"reachable": true,
|
||||
"plannedDurationInMinutes": 29,
|
||||
"nesProperties": {
|
||||
"color": "text-info",
|
||||
"scope": "LEG_LINE",
|
||||
"styles": {
|
||||
"type": "LineStyles",
|
||||
"dashed": false
|
||||
}
|
||||
},
|
||||
"duration": {
|
||||
"value": "29 min.",
|
||||
"accessibilityValue": "29 minuten",
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
},
|
||||
"preSteps": [],
|
||||
"postSteps": [],
|
||||
"transferTimeToNextLeg": 2,
|
||||
"distanceInMeters": 41871
|
||||
},
|
||||
{
|
||||
"idx": "2",
|
||||
"name": "IC 1162",
|
||||
"travelType": "PUBLIC_TRANSIT",
|
||||
"direction": "Den Haag Centraal",
|
||||
"partCancelled": false,
|
||||
"cancelled": false,
|
||||
"isAfterCancelledLeg": false,
|
||||
"isOnOrAfterCancelledLeg": false,
|
||||
"changePossible": true,
|
||||
"alternativeTransport": false,
|
||||
"journeyDetailRef": "HARP_MM-2|#VN#1#ST#1757498654#PI#0#ZI#51#TA#9#DA#150925#1S#1100921#1T#1743#LS#1101078#LT#1911#PU#784#RT#1#CA#IC#ZE#1162#ZB#IC 1162 #PC#1#FR#1100921#FT#1743#TO#1101078#TT#1911#",
|
||||
"origin": {
|
||||
"name": "Breda",
|
||||
"lng": 4.78000020980835,
|
||||
"lat": 51.5955543518066,
|
||||
"countryCode": "NL",
|
||||
"uicCode": "8400131",
|
||||
"uicCdCode": "118400131",
|
||||
"stationCode": "BD",
|
||||
"type": "STATION",
|
||||
"plannedTimeZoneOffset": 120,
|
||||
"plannedDateTime": "2025-09-15T18:23:00+0200",
|
||||
"actualTimeZoneOffset": 120,
|
||||
"actualDateTime": "2025-09-15T18:23:00+0200",
|
||||
"plannedTrack": "7",
|
||||
"actualTrack": "7",
|
||||
"checkinStatus": "NOTHING",
|
||||
"notes": []
|
||||
},
|
||||
"destination": {
|
||||
"name": "Rotterdam Centraal",
|
||||
"lng": 4.46888875961304,
|
||||
"lat": 51.9249992370605,
|
||||
"countryCode": "NL",
|
||||
"uicCode": "8400530",
|
||||
"uicCdCode": "118400530",
|
||||
"stationCode": "RTD",
|
||||
"type": "STATION",
|
||||
"plannedTimeZoneOffset": 120,
|
||||
"plannedDateTime": "2025-09-15T18:45:00+0200",
|
||||
"actualTimeZoneOffset": 120,
|
||||
"actualDateTime": "2025-09-15T18:45:00+0200",
|
||||
"plannedTrack": "13",
|
||||
"actualTrack": "13",
|
||||
"exitSide": "RIGHT",
|
||||
"checkinStatus": "NOTHING",
|
||||
"notes": []
|
||||
},
|
||||
"product": {
|
||||
"productType": "Product",
|
||||
"number": "1162",
|
||||
"categoryCode": "IC",
|
||||
"shortCategoryName": "IC",
|
||||
"longCategoryName": "Intercity",
|
||||
"operatorCode": "NS",
|
||||
"operatorName": "NS",
|
||||
"operatorAdministrativeCode": 100,
|
||||
"type": "TRAIN",
|
||||
"displayName": "NS Intercity",
|
||||
"nameNesProperties": {
|
||||
"color": "text-body"
|
||||
},
|
||||
"iconNesProperties": {
|
||||
"color": "text-body",
|
||||
"icon": "train"
|
||||
},
|
||||
"notes": [
|
||||
[
|
||||
{
|
||||
"value": "NS Intercity",
|
||||
"shortValue": "NS Intercity",
|
||||
"accessibilityValue": "NS Intercity",
|
||||
"key": "PRODUCT_NAME",
|
||||
"noteType": "ATTRIBUTE",
|
||||
"isPresentationRequired": true,
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"value": "richting Den Haag Centraal",
|
||||
"shortValue": "richting Den Haag Centraal",
|
||||
"accessibilityValue": "richting Den Haag Centraal",
|
||||
"key": "PRODUCT_DIRECTION",
|
||||
"noteType": "ATTRIBUTE",
|
||||
"isPresentationRequired": true,
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"value": "Geen tussenstops",
|
||||
"shortValue": "Geen tussenstops",
|
||||
"accessibilityValue": "Geen tussenstops",
|
||||
"key": "PRODUCT_INTERMEDIATE_STOPS",
|
||||
"noteType": "ATTRIBUTE",
|
||||
"isPresentationRequired": true,
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"transferMessages": [
|
||||
{
|
||||
"message": "Overstap op zelfde perron",
|
||||
"accessibilityMessage": "Overstap op zelfde perron",
|
||||
"type": "CROSS_PLATFORM",
|
||||
"messageNesProperties": {
|
||||
"color": "text-default",
|
||||
"type": "informative"
|
||||
}
|
||||
}
|
||||
],
|
||||
"stops": [
|
||||
{
|
||||
"uicCode": "8400131",
|
||||
"uicCdCode": "118400131",
|
||||
"name": "Breda",
|
||||
"lat": 51.5955543518066,
|
||||
"lng": 4.78000020980835,
|
||||
"countryCode": "NL",
|
||||
"notes": [],
|
||||
"routeIdx": 0,
|
||||
"plannedDepartureDateTime": "2025-09-15T18:23:00+0200",
|
||||
"plannedDepartureTimeZoneOffset": 120,
|
||||
"actualDepartureDateTime": "2025-09-15T18:23:00+0200",
|
||||
"actualDepartureTimeZoneOffset": 120,
|
||||
"actualDepartureTrack": "7",
|
||||
"plannedDepartureTrack": "7",
|
||||
"plannedArrivalTrack": "7",
|
||||
"actualArrivalTrack": "7",
|
||||
"departureDelayInSeconds": 0,
|
||||
"cancelled": false,
|
||||
"borderStop": false,
|
||||
"passing": false
|
||||
},
|
||||
{
|
||||
"uicCode": "8400530",
|
||||
"uicCdCode": "118400530",
|
||||
"name": "Rotterdam Centraal",
|
||||
"lat": 51.9249992370605,
|
||||
"lng": 4.46888875961304,
|
||||
"countryCode": "NL",
|
||||
"notes": [],
|
||||
"routeIdx": 6,
|
||||
"plannedArrivalDateTime": "2025-09-15T18:45:00+0200",
|
||||
"plannedArrivalTimeZoneOffset": 120,
|
||||
"actualArrivalDateTime": "2025-09-15T18:45:00+0200",
|
||||
"actualArrivalTimeZoneOffset": 120,
|
||||
"actualDepartureTrack": "13",
|
||||
"plannedDepartureTrack": "13",
|
||||
"plannedArrivalTrack": "13",
|
||||
"actualArrivalTrack": "13",
|
||||
"arrivalDelayInSeconds": 0,
|
||||
"cancelled": false,
|
||||
"borderStop": false,
|
||||
"passing": false
|
||||
}
|
||||
],
|
||||
"crowdForecast": "LOW",
|
||||
"bicycleSpotCount": 16,
|
||||
"punctuality": 81.8,
|
||||
"shorterStock": false,
|
||||
"journeyDetail": [
|
||||
{
|
||||
"type": "TRAIN_XML",
|
||||
"link": {
|
||||
"uri": "/api/v2/journey?id=HARP_MM-2|#VN#1#ST#1757498654#PI#0#ZI#51#TA#9#DA#150925#1S#1100921#1T#1743#LS#1101078#LT#1911#PU#784#RT#1#CA#IC#ZE#1162#ZB#IC 1162 #PC#1#FR#1100921#FT#1743#TO#1101078#TT#1911#&train=1162&datetime=2025-09-15T18:23:00+02:00"
|
||||
}
|
||||
}
|
||||
],
|
||||
"reachable": true,
|
||||
"plannedDurationInMinutes": 22,
|
||||
"nesProperties": {
|
||||
"color": "text-info",
|
||||
"scope": "LEG_LINE",
|
||||
"styles": {
|
||||
"type": "LineStyles",
|
||||
"dashed": false
|
||||
}
|
||||
},
|
||||
"duration": {
|
||||
"value": "22 min.",
|
||||
"accessibilityValue": "22 minuten",
|
||||
"nesProperties": {
|
||||
"color": "text-body"
|
||||
}
|
||||
},
|
||||
"preSteps": [],
|
||||
"postSteps": [],
|
||||
"distanceInMeters": 44166
|
||||
}
|
||||
],
|
||||
"checksum": "fe950328_3",
|
||||
"crowdForecast": "MEDIUM",
|
||||
"punctuality": 58.3,
|
||||
"optimal": false,
|
||||
"fares": [],
|
||||
"fareLegs": [
|
||||
{
|
||||
"origin": {
|
||||
"name": "Amsterdam Centraal",
|
||||
"lng": 4.90027761459351,
|
||||
"lat": 52.3788871765137,
|
||||
"countryCode": "NL",
|
||||
"uicCode": "8400058",
|
||||
"uicCdCode": "118400058",
|
||||
"stationCode": "ASD",
|
||||
"type": "STATION"
|
||||
},
|
||||
"destination": {
|
||||
"name": "'s-Hertogenbosch",
|
||||
"lng": 5.29362,
|
||||
"lat": 51.69048,
|
||||
"countryCode": "NL",
|
||||
"uicCode": "8400319",
|
||||
"uicCdCode": "118400319",
|
||||
"stationCode": "HT",
|
||||
"type": "STATION"
|
||||
},
|
||||
"operator": "NS",
|
||||
"productTypes": ["TRAIN"],
|
||||
"fares": [
|
||||
{
|
||||
"priceInCents": 1910,
|
||||
"priceInCentsExcludingSupplement": 1910,
|
||||
"supplementInCents": 0,
|
||||
"buyableTicketSupplementPriceInCents": 0,
|
||||
"product": "OVCHIPKAART_ENKELE_REIS",
|
||||
"travelClass": "SECOND_CLASS",
|
||||
"discountType": "NO_DISCOUNT"
|
||||
}
|
||||
],
|
||||
"travelDate": "2025-09-15"
|
||||
},
|
||||
{
|
||||
"origin": {
|
||||
"name": "'s-Hertogenbosch",
|
||||
"lng": 5.29362,
|
||||
"lat": 51.69048,
|
||||
"countryCode": "NL",
|
||||
"uicCode": "8400319",
|
||||
"uicCdCode": "118400319",
|
||||
"stationCode": "HT",
|
||||
"type": "STATION"
|
||||
},
|
||||
"destination": {
|
||||
"name": "Rotterdam Centraal",
|
||||
"lng": 4.46888875961304,
|
||||
"lat": 51.9249992370605,
|
||||
"countryCode": "NL",
|
||||
"uicCode": "8400530",
|
||||
"uicCdCode": "118400530",
|
||||
"stationCode": "RTD",
|
||||
"type": "STATION"
|
||||
},
|
||||
"operator": "NS",
|
||||
"productTypes": ["TRAIN"],
|
||||
"fares": [
|
||||
{
|
||||
"priceInCents": 2010,
|
||||
"priceInCentsExcludingSupplement": 2010,
|
||||
"supplementInCents": 0,
|
||||
"buyableTicketSupplementPriceInCents": 0,
|
||||
"product": "OVCHIPKAART_ENKELE_REIS",
|
||||
"travelClass": "SECOND_CLASS",
|
||||
"discountType": "NO_DISCOUNT"
|
||||
}
|
||||
],
|
||||
"travelDate": "2025-09-15"
|
||||
}
|
||||
],
|
||||
"productFare": {
|
||||
"priceInCents": 3920,
|
||||
"priceInCentsExcludingSupplement": 3920,
|
||||
"buyableTicketPriceInCents": 3920,
|
||||
"buyableTicketPriceInCentsExcludingSupplement": 3920,
|
||||
"product": "OVCHIPKAART_ENKELE_REIS",
|
||||
"travelClass": "SECOND_CLASS",
|
||||
"discountType": "NO_DISCOUNT"
|
||||
},
|
||||
"fareOptions": {
|
||||
"isInternationalBookable": false,
|
||||
"isInternational": false,
|
||||
"isEticketBuyable": false,
|
||||
"isPossibleWithOvChipkaart": false,
|
||||
"isTotalPriceUnknown": false,
|
||||
"reasonEticketNotBuyable": {
|
||||
"reason": "VIA_STATION_REQUESTED",
|
||||
"description": "Je kunt voor deze reis geen kaartje kopen, omdat je je reis via een extra station hebt gepland. Uiteraard kun je voor deze reis betalen met het saldo op je OV-chipkaart."
|
||||
}
|
||||
},
|
||||
"nsiLink": {
|
||||
"url": "https://www.nsinternational.com/nl/treintickets-v3/#/search/ASD/RTD/20250915/1634/1845?stationType=domestic&cookieConsent=false",
|
||||
"showInternationalBanner": false
|
||||
},
|
||||
"type": "NS",
|
||||
"shareUrl": {
|
||||
"uri": "https://www.ns.nl/rpx?ctx=arnu%7CfromStation%3D8400058%7CrequestedFromStation%3D8400058%7CtoStation%3D8400530%7CrequestedToStation%3D8400530%7CviaStation%3D8400319%7CplannedFromTime%3D2025-09-15T16%3A34%3A00%2B02%3A00%7CplannedArrivalTime%3D2025-09-15T18%3A45%3A00%2B02%3A00%7CexcludeHighSpeedTrains%3Dfalse%7CsearchForAccessibleTrip%3Dfalse%7ClocalTrainsOnly%3Dfalse%7CdisabledTransportModalities%3DBUS%2CFERRY%2CTRAM%2CMETRO%7CtravelAssistance%3Dfalse%7CtripSummaryHash%3D1596512355"
|
||||
},
|
||||
"realtime": true,
|
||||
"registerJourney": {
|
||||
"url": "https://treinwijzer.ns.nl/idp/login?ctxRecon=arnu%7CfromStation%3D8400058%7CrequestedFromStation%3D8400058%7CtoStation%3D8400530%7CrequestedToStation%3D8400530%7CviaStation%3D8400319%7CplannedFromTime%3D2025-09-15T16%3A34%3A00%2B02%3A00%7CplannedArrivalTime%3D2025-09-15T18%3A45%3A00%2B02%3A00%7CexcludeHighSpeedTrains%3Dfalse%7CsearchForAccessibleTrip%3Dfalse%7ClocalTrainsOnly%3Dfalse%7CdisabledTransportModalities%3DBUS%2CFERRY%2CTRAM%2CMETRO%7CtravelAssistance%3Dfalse%7CtripSummaryHash%3D1596512355&originUicCode=8400058&destinationUicCode=8400530&dateTime=2025-09-15T16%3A28%3A00.051873%2B02%3A00&searchForArrival=false&viaUicCode=8400319&excludeHighSpeedTrains=false&localTrainsOnly=false&searchForAccessibleTrip=false&lang=nl&travelAssistance=false",
|
||||
"searchUrl": "https://treinwijzer.ns.nl/idp/login?search=true&originUicCode=8400058&destinationUicCode=8400530&dateTime=2025-09-15T16%3A28%3A00.051873%2B02%3A00&searchForArrival=false&viaUicCode=8400319&excludeHighSpeedTrains=false&localTrainsOnly=false&searchForAccessibleTrip=false&lang=nl&travelAssistance=false",
|
||||
"status": "REGISTRATION_POSSIBLE",
|
||||
"bicycleReservationRequired": false
|
||||
},
|
||||
"modalityListItems": [
|
||||
{
|
||||
"name": "Intercity",
|
||||
"nameNesProperties": {
|
||||
"color": "text-subtle",
|
||||
"styles": {
|
||||
"type": "TextStyles",
|
||||
"strikethrough": false,
|
||||
"bold": false
|
||||
}
|
||||
},
|
||||
"iconNesProperties": {
|
||||
"color": "text-body",
|
||||
"icon": "train"
|
||||
},
|
||||
"actualTrack": "4",
|
||||
"accessibilityName": "Intercity"
|
||||
},
|
||||
{
|
||||
"name": "Intercity",
|
||||
"nameNesProperties": {
|
||||
"color": "text-subtle",
|
||||
"styles": {
|
||||
"type": "TextStyles",
|
||||
"strikethrough": false,
|
||||
"bold": false
|
||||
}
|
||||
},
|
||||
"iconNesProperties": {
|
||||
"color": "text-body",
|
||||
"icon": "train"
|
||||
},
|
||||
"actualTrack": "7",
|
||||
"accessibilityName": "Intercity"
|
||||
},
|
||||
{
|
||||
"name": "Intercity",
|
||||
"nameNesProperties": {
|
||||
"color": "text-subtle",
|
||||
"styles": {
|
||||
"type": "TextStyles",
|
||||
"strikethrough": false,
|
||||
"bold": false
|
||||
}
|
||||
},
|
||||
"iconNesProperties": {
|
||||
"color": "text-body",
|
||||
"icon": "train"
|
||||
},
|
||||
"actualTrack": "7",
|
||||
"accessibilityName": "Intercity"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"scrollRequestBackwardContext": "3|OB|MTµ14µ13954µ13944µ14077µ14080µ0µ0µ485µ13938µ1µ0µ8µ0µ0µ-2147483648µ1µ2|PDHµ28839c70675e70c3d48018993723bca2|RDµ15092025|RTµ161800|USµ0|RSµINIT",
|
||||
"scrollRequestForwardContext": "3|OF|MTµ14µ13985µ13985µ14107µ14115µ0µ0µ485µ13955µ8µ0µ8µ0µ0µ-2147483648µ1µ2|PDHµ28839c70675e70c3d48018993723bca2|RDµ15092025|RTµ161800|USµ0|RSµINIT"
|
||||
}
|
||||
@@ -1,4 +1,106 @@
|
||||
# serializer version: 1
|
||||
# name: test_no_trips_sensor[sensor.to_home-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.to_home',
|
||||
'has_entity_name': False,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
|
||||
'original_icon': 'mdi:train',
|
||||
'original_name': 'To home',
|
||||
'platform': 'nederlandse_spoorwegen',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '01K721DZPMEN39R5DK0ATBMSY9-actual_departure',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_no_trips_sensor[sensor.to_home-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by NS',
|
||||
'device_class': 'timestamp',
|
||||
'friendly_name': 'To home',
|
||||
'icon': 'mdi:train',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.to_home',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_no_trips_sensor[sensor.to_work-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.to_work',
|
||||
'has_entity_name': False,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
|
||||
'original_icon': 'mdi:train',
|
||||
'original_name': 'To work',
|
||||
'platform': 'nederlandse_spoorwegen',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '01K721DZPMEN39R5DK0ATBMSY8-actual_departure',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_no_trips_sensor[sensor.to_work-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by NS',
|
||||
'device_class': 'timestamp',
|
||||
'friendly_name': 'To work',
|
||||
'icon': 'mdi:train',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.to_work',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.to_home-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
@@ -143,3 +245,147 @@
|
||||
'state': '2025-09-15T14:35:00+00:00',
|
||||
})
|
||||
# ---
|
||||
# name: test_single_trip_sensor[sensor.to_home-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.to_home',
|
||||
'has_entity_name': False,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
|
||||
'original_icon': 'mdi:train',
|
||||
'original_name': 'To home',
|
||||
'platform': 'nederlandse_spoorwegen',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '01K721DZPMEN39R5DK0ATBMSY9-actual_departure',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_single_trip_sensor[sensor.to_home-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'arrival_delay': False,
|
||||
'arrival_platform_actual': '13',
|
||||
'arrival_platform_planned': '13',
|
||||
'arrival_time_actual': '18:45',
|
||||
'arrival_time_planned': '18:45',
|
||||
'attribution': 'Data provided by NS',
|
||||
'departure_delay': True,
|
||||
'departure_platform_actual': '4',
|
||||
'departure_platform_planned': '4',
|
||||
'departure_time_actual': '16:35',
|
||||
'departure_time_planned': '16:34',
|
||||
'device_class': 'timestamp',
|
||||
'friendly_name': 'To home',
|
||||
'going': True,
|
||||
'icon': 'mdi:train',
|
||||
'next': None,
|
||||
'remarks': None,
|
||||
'route': list([
|
||||
'Amsterdam Centraal',
|
||||
"'s-Hertogenbosch",
|
||||
'Breda',
|
||||
'Rotterdam Centraal',
|
||||
]),
|
||||
'status': 'normal',
|
||||
'transfers': 2,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.to_home',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '2025-09-15T14:35:00+00:00',
|
||||
})
|
||||
# ---
|
||||
# name: test_single_trip_sensor[sensor.to_work-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.to_work',
|
||||
'has_entity_name': False,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
|
||||
'original_icon': 'mdi:train',
|
||||
'original_name': 'To work',
|
||||
'platform': 'nederlandse_spoorwegen',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '01K721DZPMEN39R5DK0ATBMSY8-actual_departure',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_single_trip_sensor[sensor.to_work-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'arrival_delay': False,
|
||||
'arrival_platform_actual': '13',
|
||||
'arrival_platform_planned': '13',
|
||||
'arrival_time_actual': '18:45',
|
||||
'arrival_time_planned': '18:45',
|
||||
'attribution': 'Data provided by NS',
|
||||
'departure_delay': True,
|
||||
'departure_platform_actual': '4',
|
||||
'departure_platform_planned': '4',
|
||||
'departure_time_actual': '16:35',
|
||||
'departure_time_planned': '16:34',
|
||||
'device_class': 'timestamp',
|
||||
'friendly_name': 'To work',
|
||||
'going': True,
|
||||
'icon': 'mdi:train',
|
||||
'next': None,
|
||||
'remarks': None,
|
||||
'route': list([
|
||||
'Amsterdam Centraal',
|
||||
"'s-Hertogenbosch",
|
||||
'Breda',
|
||||
'Rotterdam Centraal',
|
||||
]),
|
||||
'status': 'normal',
|
||||
'transfers': 2,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.to_work',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '2025-09-15T14:35:00+00:00',
|
||||
})
|
||||
# ---
|
||||
|
||||
@@ -68,7 +68,35 @@ async def test_config_import(
|
||||
@pytest.mark.freeze_time("2025-09-15 14:30:00+00:00")
|
||||
async def test_sensor(
|
||||
hass: HomeAssistant,
|
||||
mock_nsapi,
|
||||
mock_nsapi: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test sensor initialization."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
@pytest.mark.freeze_time("2025-09-15 14:30:00+00:00")
|
||||
async def test_single_trip_sensor(
|
||||
hass: HomeAssistant,
|
||||
mock_single_trip_nsapi: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test sensor initialization."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
@pytest.mark.freeze_time("2025-09-15 14:30:00+00:00")
|
||||
async def test_no_trips_sensor(
|
||||
hass: HomeAssistant,
|
||||
mock_no_trips_nsapi: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
entity_registry: er.EntityRegistry,
|
||||
|
||||
Reference in New Issue
Block a user