Add Here travel time arrival departure (#29909)

* here_travel_time: Add modes arrival and departure

* convert arrival/departure from datetime to time

* Default departure is set by external lib on None

* Use cv.key_value_schemas
This commit is contained in:
Kevin Eifinger 2020-03-17 05:16:49 +01:00 committed by GitHub
parent 7ac014744c
commit 2cda7bf1e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 207 additions and 40 deletions

View File

@ -1,5 +1,5 @@
"""Support for HERE travel time sensors.""" """Support for HERE travel time sensors."""
from datetime import timedelta from datetime import datetime, timedelta
import logging import logging
from typing import Callable, Dict, Optional, Union from typing import Callable, Dict, Optional, Union
@ -24,6 +24,7 @@ from homeassistant.core import HomeAssistant, State, callback
from homeassistant.helpers import location from homeassistant.helpers import location
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
import homeassistant.util.dt as dt
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -36,6 +37,8 @@ CONF_ORIGIN_ENTITY_ID = "origin_entity_id"
CONF_API_KEY = "api_key" CONF_API_KEY = "api_key"
CONF_TRAFFIC_MODE = "traffic_mode" CONF_TRAFFIC_MODE = "traffic_mode"
CONF_ROUTE_MODE = "route_mode" CONF_ROUTE_MODE = "route_mode"
CONF_ARRIVAL = "arrival"
CONF_DEPARTURE = "departure"
DEFAULT_NAME = "HERE Travel Time" DEFAULT_NAME = "HERE Travel Time"
@ -90,10 +93,7 @@ SCAN_INTERVAL = timedelta(minutes=5)
NO_ROUTE_ERROR_MESSAGE = "HERE could not find a route based on the input" NO_ROUTE_ERROR_MESSAGE = "HERE could not find a route based on the input"
PLATFORM_SCHEMA = vol.All( PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
cv.has_at_least_one_key(CONF_DESTINATION_LATITUDE, CONF_DESTINATION_ENTITY_ID),
cv.has_at_least_one_key(CONF_ORIGIN_LATITUDE, CONF_ORIGIN_ENTITY_ID),
PLATFORM_SCHEMA.extend(
{ {
vol.Required(CONF_API_KEY): cv.string, vol.Required(CONF_API_KEY): cv.string,
vol.Inclusive( vol.Inclusive(
@ -108,14 +108,34 @@ PLATFORM_SCHEMA = vol.All(
vol.Inclusive(CONF_ORIGIN_LONGITUDE, "origin_coordinates"): cv.longitude, vol.Inclusive(CONF_ORIGIN_LONGITUDE, "origin_coordinates"): cv.longitude,
vol.Exclusive(CONF_ORIGIN_LATITUDE, "origin"): cv.latitude, vol.Exclusive(CONF_ORIGIN_LATITUDE, "origin"): cv.latitude,
vol.Exclusive(CONF_ORIGIN_ENTITY_ID, "origin"): cv.entity_id, vol.Exclusive(CONF_ORIGIN_ENTITY_ID, "origin"): cv.entity_id,
vol.Optional(CONF_DEPARTURE): cv.time,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_MODE, default=TRAVEL_MODE_CAR): vol.In(TRAVEL_MODE), vol.Optional(CONF_MODE, default=TRAVEL_MODE_CAR): vol.In(TRAVEL_MODE),
vol.Optional(CONF_ROUTE_MODE, default=ROUTE_MODE_FASTEST): vol.In( vol.Optional(CONF_ROUTE_MODE, default=ROUTE_MODE_FASTEST): vol.In(ROUTE_MODE),
ROUTE_MODE
),
vol.Optional(CONF_TRAFFIC_MODE, default=False): cv.boolean, vol.Optional(CONF_TRAFFIC_MODE, default=False): cv.boolean,
vol.Optional(CONF_UNIT_SYSTEM): vol.In(UNITS), vol.Optional(CONF_UNIT_SYSTEM): vol.In(UNITS),
} }
)
PLATFORM_SCHEMA = vol.All(
cv.has_at_least_one_key(CONF_DESTINATION_LATITUDE, CONF_DESTINATION_ENTITY_ID),
cv.has_at_least_one_key(CONF_ORIGIN_LATITUDE, CONF_ORIGIN_ENTITY_ID),
cv.key_value_schemas(
CONF_MODE,
{
None: PLATFORM_SCHEMA,
TRAVEL_MODE_BICYCLE: PLATFORM_SCHEMA,
TRAVEL_MODE_CAR: PLATFORM_SCHEMA,
TRAVEL_MODE_PEDESTRIAN: PLATFORM_SCHEMA,
TRAVEL_MODE_PUBLIC: PLATFORM_SCHEMA,
TRAVEL_MODE_TRUCK: PLATFORM_SCHEMA,
TRAVEL_MODE_PUBLIC_TIME_TABLE: PLATFORM_SCHEMA.extend(
{
vol.Exclusive(CONF_ARRIVAL, "arrival_departure"): cv.time,
vol.Exclusive(CONF_DEPARTURE, "arrival_departure"): cv.time,
}
),
},
), ),
) )
@ -160,9 +180,11 @@ async def async_setup_platform(
route_mode = config[CONF_ROUTE_MODE] route_mode = config[CONF_ROUTE_MODE]
name = config[CONF_NAME] name = config[CONF_NAME]
units = config.get(CONF_UNIT_SYSTEM, hass.config.units.name) units = config.get(CONF_UNIT_SYSTEM, hass.config.units.name)
arrival = config.get(CONF_ARRIVAL)
departure = config.get(CONF_DEPARTURE)
here_data = HERETravelTimeData( here_data = HERETravelTimeData(
here_client, travel_mode, traffic_mode, route_mode, units here_client, travel_mode, traffic_mode, route_mode, units, arrival, departure
) )
sensor = HERETravelTimeSensor( sensor = HERETravelTimeSensor(
@ -361,6 +383,8 @@ class HERETravelTimeData:
traffic_mode: bool, traffic_mode: bool,
route_mode: str, route_mode: str,
units: str, units: str,
arrival: datetime,
departure: datetime,
) -> None: ) -> None:
"""Initialize herepy.""" """Initialize herepy."""
self.origin = None self.origin = None
@ -368,6 +392,8 @@ class HERETravelTimeData:
self.travel_mode = travel_mode self.travel_mode = travel_mode
self.traffic_mode = traffic_mode self.traffic_mode = traffic_mode
self.route_mode = route_mode self.route_mode = route_mode
self.arrival = arrival
self.departure = departure
self.attribution = None self.attribution = None
self.traffic_time = None self.traffic_time = None
self.distance = None self.distance = None
@ -377,6 +403,7 @@ class HERETravelTimeData:
self.destination_name = None self.destination_name = None
self.units = units self.units = units
self._client = here_client self._client = here_client
self.combine_change = True
def update(self) -> None: def update(self) -> None:
"""Get the latest data from HERE.""" """Get the latest data from HERE."""
@ -389,24 +416,36 @@ class HERETravelTimeData:
# Convert location to HERE friendly location # Convert location to HERE friendly location
destination = self.destination.split(",") destination = self.destination.split(",")
origin = self.origin.split(",") origin = self.origin.split(",")
arrival = self.arrival
if arrival is not None:
arrival = convert_time_to_isodate(arrival)
departure = self.departure
if departure is not None:
departure = convert_time_to_isodate(departure)
_LOGGER.debug( _LOGGER.debug(
"Requesting route for origin: %s, destination: %s, route_mode: %s, mode: %s, traffic_mode: %s", "Requesting route for origin: %s, destination: %s, route_mode: %s, mode: %s, traffic_mode: %s, arrival: %s, departure: %s",
origin, origin,
destination, destination,
herepy.RouteMode[self.route_mode], herepy.RouteMode[self.route_mode],
herepy.RouteMode[self.travel_mode], herepy.RouteMode[self.travel_mode],
herepy.RouteMode[traffic_mode], herepy.RouteMode[traffic_mode],
arrival,
departure,
) )
try: try:
response = self._client.car_route( response = self._client.public_transport_timetable(
origin, origin,
destination, destination,
self.combine_change,
[ [
herepy.RouteMode[self.route_mode], herepy.RouteMode[self.route_mode],
herepy.RouteMode[self.travel_mode], herepy.RouteMode[self.travel_mode],
herepy.RouteMode[traffic_mode], herepy.RouteMode[traffic_mode],
], ],
arrival=arrival,
departure=departure,
) )
except herepy.NoRouteFoundError: except herepy.NoRouteFoundError:
# Better error message for cryptic no route error codes # Better error message for cryptic no route error codes
@ -453,3 +492,11 @@ class HERETravelTimeData:
joined_supplier_titles = ",".join(supplier_titles) joined_supplier_titles = ",".join(supplier_titles)
attribution = f"With the support of {joined_supplier_titles}. All information is provided without warranty of any kind." attribution = f"With the support of {joined_supplier_titles}. All information is provided without warranty of any kind."
return attribution return attribution
def convert_time_to_isodate(timestr: str) -> str:
"""Take a string like 08:00:00 and combine it with the current date."""
combined = datetime.combine(dt.start_of_local_day(), dt.parse_time(timestr))
if combined < datetime.now():
combined = combined + timedelta(days=1)
return combined.isoformat()

View File

@ -37,6 +37,7 @@ from homeassistant.components.here_travel_time.sensor import (
TRAVEL_MODE_PUBLIC, TRAVEL_MODE_PUBLIC,
TRAVEL_MODE_PUBLIC_TIME_TABLE, TRAVEL_MODE_PUBLIC_TIME_TABLE,
TRAVEL_MODE_TRUCK, TRAVEL_MODE_TRUCK,
convert_time_to_isodate,
) )
from homeassistant.const import ATTR_ICON, EVENT_HOMEASSISTANT_START from homeassistant.const import ATTR_ICON, EVENT_HOMEASSISTANT_START
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
@ -66,7 +67,7 @@ CAR_DESTINATION_LATITUDE = "39.0"
CAR_DESTINATION_LONGITUDE = "-77.1" CAR_DESTINATION_LONGITUDE = "-77.1"
def _build_mock_url(origin, destination, modes, api_key, departure): def _build_mock_url(origin, destination, modes, api_key, departure=None, arrival=None):
"""Construct a url for HERE.""" """Construct a url for HERE."""
base_url = "https://route.ls.hereapi.com/routing/7.2/calculateroute.json?" base_url = "https://route.ls.hereapi.com/routing/7.2/calculateroute.json?"
parameters = { parameters = {
@ -74,9 +75,13 @@ def _build_mock_url(origin, destination, modes, api_key, departure):
"waypoint1": f"geo!{destination}", "waypoint1": f"geo!{destination}",
"mode": ";".join(str(herepy.RouteMode[mode]) for mode in modes), "mode": ";".join(str(herepy.RouteMode[mode]) for mode in modes),
"apikey": api_key, "apikey": api_key,
"departure": departure,
} }
if arrival is not None:
parameters["arrival"] = arrival
if departure is not None:
parameters["departure"] = departure
url = base_url + urllib.parse.urlencode(parameters) url = base_url + urllib.parse.urlencode(parameters)
print(url)
return url return url
@ -117,7 +122,6 @@ def requests_mock_credentials_check(requests_mock):
",".join([CAR_DESTINATION_LATITUDE, CAR_DESTINATION_LONGITUDE]), ",".join([CAR_DESTINATION_LATITUDE, CAR_DESTINATION_LONGITUDE]),
modes, modes,
API_KEY, API_KEY,
"now",
) )
requests_mock.get( requests_mock.get(
response_url, text=load_fixture("here_travel_time/car_response.json") response_url, text=load_fixture("here_travel_time/car_response.json")
@ -134,7 +138,6 @@ def requests_mock_truck_response(requests_mock_credentials_check):
",".join([TRUCK_DESTINATION_LATITUDE, TRUCK_DESTINATION_LONGITUDE]), ",".join([TRUCK_DESTINATION_LATITUDE, TRUCK_DESTINATION_LONGITUDE]),
modes, modes,
API_KEY, API_KEY,
"now",
) )
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, text=load_fixture("here_travel_time/truck_response.json") response_url, text=load_fixture("here_travel_time/truck_response.json")
@ -150,7 +153,6 @@ def requests_mock_car_disabled_response(requests_mock_credentials_check):
",".join([CAR_DESTINATION_LATITUDE, CAR_DESTINATION_LONGITUDE]), ",".join([CAR_DESTINATION_LATITUDE, CAR_DESTINATION_LONGITUDE]),
modes, modes,
API_KEY, API_KEY,
"now",
) )
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, text=load_fixture("here_travel_time/car_response.json") response_url, text=load_fixture("here_travel_time/car_response.json")
@ -214,7 +216,6 @@ async def test_traffic_mode_enabled(hass, requests_mock_credentials_check):
",".join([CAR_DESTINATION_LATITUDE, CAR_DESTINATION_LONGITUDE]), ",".join([CAR_DESTINATION_LATITUDE, CAR_DESTINATION_LONGITUDE]),
modes, modes,
API_KEY, API_KEY,
"now",
) )
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, text=load_fixture("here_travel_time/car_enabled_response.json") response_url, text=load_fixture("here_travel_time/car_enabled_response.json")
@ -272,7 +273,7 @@ async def test_route_mode_shortest(hass, requests_mock_credentials_check):
origin = "38.902981,-77.048338" origin = "38.902981,-77.048338"
destination = "39.042158,-77.119116" destination = "39.042158,-77.119116"
modes = [ROUTE_MODE_SHORTEST, TRAVEL_MODE_CAR, TRAFFIC_MODE_DISABLED] modes = [ROUTE_MODE_SHORTEST, TRAVEL_MODE_CAR, TRAFFIC_MODE_DISABLED]
response_url = _build_mock_url(origin, destination, modes, API_KEY, "now") response_url = _build_mock_url(origin, destination, modes, API_KEY)
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, text=load_fixture("here_travel_time/car_shortest_response.json") response_url, text=load_fixture("here_travel_time/car_shortest_response.json")
) )
@ -303,7 +304,7 @@ async def test_route_mode_fastest(hass, requests_mock_credentials_check):
origin = "38.902981,-77.048338" origin = "38.902981,-77.048338"
destination = "39.042158,-77.119116" destination = "39.042158,-77.119116"
modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_CAR, TRAFFIC_MODE_ENABLED] modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_CAR, TRAFFIC_MODE_ENABLED]
response_url = _build_mock_url(origin, destination, modes, API_KEY, "now") response_url = _build_mock_url(origin, destination, modes, API_KEY)
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, text=load_fixture("here_travel_time/car_enabled_response.json") response_url, text=load_fixture("here_travel_time/car_enabled_response.json")
) )
@ -357,7 +358,7 @@ async def test_public_transport(hass, requests_mock_credentials_check):
origin = "41.9798,-87.8801" origin = "41.9798,-87.8801"
destination = "41.9043,-87.9216" destination = "41.9043,-87.9216"
modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_PUBLIC, TRAFFIC_MODE_DISABLED] modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_PUBLIC, TRAFFIC_MODE_DISABLED]
response_url = _build_mock_url(origin, destination, modes, API_KEY, "now") response_url = _build_mock_url(origin, destination, modes, API_KEY)
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, text=load_fixture("here_travel_time/public_response.json") response_url, text=load_fixture("here_travel_time/public_response.json")
) )
@ -406,7 +407,7 @@ async def test_public_transport_time_table(hass, requests_mock_credentials_check
origin = "41.9798,-87.8801" origin = "41.9798,-87.8801"
destination = "41.9043,-87.9216" destination = "41.9043,-87.9216"
modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_PUBLIC_TIME_TABLE, TRAFFIC_MODE_DISABLED] modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_PUBLIC_TIME_TABLE, TRAFFIC_MODE_DISABLED]
response_url = _build_mock_url(origin, destination, modes, API_KEY, "now") response_url = _build_mock_url(origin, destination, modes, API_KEY)
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, response_url,
text=load_fixture("here_travel_time/public_time_table_response.json"), text=load_fixture("here_travel_time/public_time_table_response.json"),
@ -456,7 +457,7 @@ async def test_pedestrian(hass, requests_mock_credentials_check):
origin = "41.9798,-87.8801" origin = "41.9798,-87.8801"
destination = "41.9043,-87.9216" destination = "41.9043,-87.9216"
modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_PEDESTRIAN, TRAFFIC_MODE_DISABLED] modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_PEDESTRIAN, TRAFFIC_MODE_DISABLED]
response_url = _build_mock_url(origin, destination, modes, API_KEY, "now") response_url = _build_mock_url(origin, destination, modes, API_KEY)
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, text=load_fixture("here_travel_time/pedestrian_response.json") response_url, text=load_fixture("here_travel_time/pedestrian_response.json")
) )
@ -508,7 +509,7 @@ async def test_bicycle(hass, requests_mock_credentials_check):
origin = "41.9798,-87.8801" origin = "41.9798,-87.8801"
destination = "41.9043,-87.9216" destination = "41.9043,-87.9216"
modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_BICYCLE, TRAFFIC_MODE_DISABLED] modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_BICYCLE, TRAFFIC_MODE_DISABLED]
response_url = _build_mock_url(origin, destination, modes, API_KEY, "now") response_url = _build_mock_url(origin, destination, modes, API_KEY)
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, text=load_fixture("here_travel_time/bike_response.json") response_url, text=load_fixture("here_travel_time/bike_response.json")
) )
@ -841,7 +842,7 @@ async def test_route_not_found(hass, requests_mock_credentials_check, caplog):
origin = "52.516,13.3779" origin = "52.516,13.3779"
destination = "47.013399,-10.171986" destination = "47.013399,-10.171986"
modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_CAR, TRAFFIC_MODE_DISABLED] modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_CAR, TRAFFIC_MODE_DISABLED]
response_url = _build_mock_url(origin, destination, modes, API_KEY, "now") response_url = _build_mock_url(origin, destination, modes, API_KEY)
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, response_url,
text=load_fixture("here_travel_time/routing_error_no_route_found.json"), text=load_fixture("here_travel_time/routing_error_no_route_found.json"),
@ -914,7 +915,6 @@ async def test_invalid_credentials(hass, requests_mock, caplog):
",".join([CAR_DESTINATION_LATITUDE, CAR_DESTINATION_LONGITUDE]), ",".join([CAR_DESTINATION_LATITUDE, CAR_DESTINATION_LONGITUDE]),
modes, modes,
API_KEY, API_KEY,
"now",
) )
requests_mock.get( requests_mock.get(
response_url, response_url,
@ -942,7 +942,7 @@ async def test_attribution(hass, requests_mock_credentials_check):
origin = "50.037751372637686,14.39233448220898" origin = "50.037751372637686,14.39233448220898"
destination = "50.07993838201255,14.42582157361062" destination = "50.07993838201255,14.42582157361062"
modes = [ROUTE_MODE_SHORTEST, TRAVEL_MODE_PUBLIC_TIME_TABLE, TRAFFIC_MODE_ENABLED] modes = [ROUTE_MODE_SHORTEST, TRAVEL_MODE_PUBLIC_TIME_TABLE, TRAFFIC_MODE_ENABLED]
response_url = _build_mock_url(origin, destination, modes, API_KEY, "now") response_url = _build_mock_url(origin, destination, modes, API_KEY)
requests_mock_credentials_check.get( requests_mock_credentials_check.get(
response_url, text=load_fixture("here_travel_time/attribution_response.json") response_url, text=load_fixture("here_travel_time/attribution_response.json")
) )
@ -1051,3 +1051,123 @@ async def test_delayed_update(hass, requests_mock_truck_response, caplog):
await hass.async_block_till_done() await hass.async_block_till_done()
assert "Unable to find entity" not in caplog.text assert "Unable to find entity" not in caplog.text
async def test_arrival(hass, requests_mock_credentials_check):
"""Test that arrival works."""
origin = "41.9798,-87.8801"
destination = "41.9043,-87.9216"
arrival = "01:00:00"
arrival_isodate = convert_time_to_isodate(arrival)
modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_PUBLIC_TIME_TABLE, TRAFFIC_MODE_DISABLED]
response_url = _build_mock_url(
origin, destination, modes, API_KEY, arrival=arrival_isodate
)
requests_mock_credentials_check.get(
response_url,
text=load_fixture("here_travel_time/public_time_table_response.json"),
)
config = {
DOMAIN: {
"platform": PLATFORM,
"name": "test",
"origin_latitude": origin.split(",")[0],
"origin_longitude": origin.split(",")[1],
"destination_latitude": destination.split(",")[0],
"destination_longitude": destination.split(",")[1],
"api_key": API_KEY,
"mode": TRAVEL_MODE_PUBLIC_TIME_TABLE,
"arrival": arrival,
}
}
assert await async_setup_component(hass, DOMAIN, config)
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
await hass.async_block_till_done()
sensor = hass.states.get("sensor.test")
assert sensor.state == "80"
async def test_departure(hass, requests_mock_credentials_check):
"""Test that arrival works."""
origin = "41.9798,-87.8801"
destination = "41.9043,-87.9216"
departure = "23:00:00"
departure_isodate = convert_time_to_isodate(departure)
modes = [ROUTE_MODE_FASTEST, TRAVEL_MODE_PUBLIC_TIME_TABLE, TRAFFIC_MODE_DISABLED]
response_url = _build_mock_url(
origin, destination, modes, API_KEY, departure=departure_isodate
)
requests_mock_credentials_check.get(
response_url,
text=load_fixture("here_travel_time/public_time_table_response.json"),
)
config = {
DOMAIN: {
"platform": PLATFORM,
"name": "test",
"origin_latitude": origin.split(",")[0],
"origin_longitude": origin.split(",")[1],
"destination_latitude": destination.split(",")[0],
"destination_longitude": destination.split(",")[1],
"api_key": API_KEY,
"mode": TRAVEL_MODE_PUBLIC_TIME_TABLE,
"departure": departure,
}
}
assert await async_setup_component(hass, DOMAIN, config)
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
await hass.async_block_till_done()
sensor = hass.states.get("sensor.test")
assert sensor.state == "80"
async def test_arrival_only_allowed_for_timetable(hass, caplog):
"""Test that arrival is only allowed when mode is publicTransportTimeTable."""
caplog.set_level(logging.ERROR)
origin = "41.9798,-87.8801"
destination = "41.9043,-87.9216"
config = {
DOMAIN: {
"platform": PLATFORM,
"name": "test",
"origin_latitude": origin.split(",")[0],
"origin_longitude": origin.split(",")[1],
"destination_latitude": destination.split(",")[0],
"destination_longitude": destination.split(",")[1],
"api_key": API_KEY,
"arrival": "01:00:00",
}
}
assert await async_setup_component(hass, DOMAIN, config)
assert len(caplog.records) == 1
assert "[arrival] is an invalid option" in caplog.text
async def test_exclusive_arrival_and_departure(hass, caplog):
"""Test that arrival and departure are exclusive."""
caplog.set_level(logging.ERROR)
origin = "41.9798,-87.8801"
destination = "41.9043,-87.9216"
config = {
DOMAIN: {
"platform": PLATFORM,
"name": "test",
"origin_latitude": origin.split(",")[0],
"origin_longitude": origin.split(",")[1],
"destination_latitude": destination.split(",")[0],
"destination_longitude": destination.split(",")[1],
"api_key": API_KEY,
"arrival": "01:00:00",
"mode": TRAVEL_MODE_PUBLIC_TIME_TABLE,
"departure": "01:00:00",
}
}
assert await async_setup_component(hass, DOMAIN, config)
assert len(caplog.records) == 1
assert "two or more values in the same group of exclusion" in caplog.text