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_schemaspull/32897/head
parent
7ac014744c
commit
2cda7bf1e7
|
@ -1,5 +1,5 @@
|
|||
"""Support for HERE travel time sensors."""
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
from typing import Callable, Dict, Optional, Union
|
||||
|
||||
|
@ -24,6 +24,7 @@ from homeassistant.core import HomeAssistant, State, callback
|
|||
from homeassistant.helpers import location
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity import Entity
|
||||
import homeassistant.util.dt as dt
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -36,6 +37,8 @@ CONF_ORIGIN_ENTITY_ID = "origin_entity_id"
|
|||
CONF_API_KEY = "api_key"
|
||||
CONF_TRAFFIC_MODE = "traffic_mode"
|
||||
CONF_ROUTE_MODE = "route_mode"
|
||||
CONF_ARRIVAL = "arrival"
|
||||
CONF_DEPARTURE = "departure"
|
||||
|
||||
DEFAULT_NAME = "HERE Travel Time"
|
||||
|
||||
|
@ -90,32 +93,49 @@ SCAN_INTERVAL = timedelta(minutes=5)
|
|||
|
||||
NO_ROUTE_ERROR_MESSAGE = "HERE could not find a route based on the input"
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Inclusive(
|
||||
CONF_DESTINATION_LATITUDE, "destination_coordinates"
|
||||
): cv.latitude,
|
||||
vol.Inclusive(
|
||||
CONF_DESTINATION_LONGITUDE, "destination_coordinates"
|
||||
): cv.longitude,
|
||||
vol.Exclusive(CONF_DESTINATION_LATITUDE, "destination"): cv.latitude,
|
||||
vol.Exclusive(CONF_DESTINATION_ENTITY_ID, "destination"): cv.entity_id,
|
||||
vol.Inclusive(CONF_ORIGIN_LATITUDE, "origin_coordinates"): cv.latitude,
|
||||
vol.Inclusive(CONF_ORIGIN_LONGITUDE, "origin_coordinates"): cv.longitude,
|
||||
vol.Exclusive(CONF_ORIGIN_LATITUDE, "origin"): cv.latitude,
|
||||
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_MODE, default=TRAVEL_MODE_CAR): vol.In(TRAVEL_MODE),
|
||||
vol.Optional(CONF_ROUTE_MODE, default=ROUTE_MODE_FASTEST): vol.In(ROUTE_MODE),
|
||||
vol.Optional(CONF_TRAFFIC_MODE, default=False): cv.boolean,
|
||||
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),
|
||||
PLATFORM_SCHEMA.extend(
|
||||
cv.key_value_schemas(
|
||||
CONF_MODE,
|
||||
{
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Inclusive(
|
||||
CONF_DESTINATION_LATITUDE, "destination_coordinates"
|
||||
): cv.latitude,
|
||||
vol.Inclusive(
|
||||
CONF_DESTINATION_LONGITUDE, "destination_coordinates"
|
||||
): cv.longitude,
|
||||
vol.Exclusive(CONF_DESTINATION_LATITUDE, "destination"): cv.latitude,
|
||||
vol.Exclusive(CONF_DESTINATION_ENTITY_ID, "destination"): cv.entity_id,
|
||||
vol.Inclusive(CONF_ORIGIN_LATITUDE, "origin_coordinates"): cv.latitude,
|
||||
vol.Inclusive(CONF_ORIGIN_LONGITUDE, "origin_coordinates"): cv.longitude,
|
||||
vol.Exclusive(CONF_ORIGIN_LATITUDE, "origin"): cv.latitude,
|
||||
vol.Exclusive(CONF_ORIGIN_ENTITY_ID, "origin"): cv.entity_id,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_MODE, default=TRAVEL_MODE_CAR): vol.In(TRAVEL_MODE),
|
||||
vol.Optional(CONF_ROUTE_MODE, default=ROUTE_MODE_FASTEST): vol.In(
|
||||
ROUTE_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,
|
||||
}
|
||||
),
|
||||
vol.Optional(CONF_TRAFFIC_MODE, default=False): cv.boolean,
|
||||
vol.Optional(CONF_UNIT_SYSTEM): vol.In(UNITS),
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -160,9 +180,11 @@ async def async_setup_platform(
|
|||
route_mode = config[CONF_ROUTE_MODE]
|
||||
name = config[CONF_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_client, travel_mode, traffic_mode, route_mode, units
|
||||
here_client, travel_mode, traffic_mode, route_mode, units, arrival, departure
|
||||
)
|
||||
|
||||
sensor = HERETravelTimeSensor(
|
||||
|
@ -361,6 +383,8 @@ class HERETravelTimeData:
|
|||
traffic_mode: bool,
|
||||
route_mode: str,
|
||||
units: str,
|
||||
arrival: datetime,
|
||||
departure: datetime,
|
||||
) -> None:
|
||||
"""Initialize herepy."""
|
||||
self.origin = None
|
||||
|
@ -368,6 +392,8 @@ class HERETravelTimeData:
|
|||
self.travel_mode = travel_mode
|
||||
self.traffic_mode = traffic_mode
|
||||
self.route_mode = route_mode
|
||||
self.arrival = arrival
|
||||
self.departure = departure
|
||||
self.attribution = None
|
||||
self.traffic_time = None
|
||||
self.distance = None
|
||||
|
@ -377,6 +403,7 @@ class HERETravelTimeData:
|
|||
self.destination_name = None
|
||||
self.units = units
|
||||
self._client = here_client
|
||||
self.combine_change = True
|
||||
|
||||
def update(self) -> None:
|
||||
"""Get the latest data from HERE."""
|
||||
|
@ -389,24 +416,36 @@ class HERETravelTimeData:
|
|||
# Convert location to HERE friendly location
|
||||
destination = self.destination.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(
|
||||
"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,
|
||||
destination,
|
||||
herepy.RouteMode[self.route_mode],
|
||||
herepy.RouteMode[self.travel_mode],
|
||||
herepy.RouteMode[traffic_mode],
|
||||
arrival,
|
||||
departure,
|
||||
)
|
||||
|
||||
try:
|
||||
response = self._client.car_route(
|
||||
response = self._client.public_transport_timetable(
|
||||
origin,
|
||||
destination,
|
||||
self.combine_change,
|
||||
[
|
||||
herepy.RouteMode[self.route_mode],
|
||||
herepy.RouteMode[self.travel_mode],
|
||||
herepy.RouteMode[traffic_mode],
|
||||
],
|
||||
arrival=arrival,
|
||||
departure=departure,
|
||||
)
|
||||
except herepy.NoRouteFoundError:
|
||||
# Better error message for cryptic no route error codes
|
||||
|
@ -453,3 +492,11 @@ class HERETravelTimeData:
|
|||
joined_supplier_titles = ",".join(supplier_titles)
|
||||
attribution = f"With the support of {joined_supplier_titles}. All information is provided without warranty of any kind."
|
||||
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()
|
||||
|
|
|
@ -37,6 +37,7 @@ from homeassistant.components.here_travel_time.sensor import (
|
|||
TRAVEL_MODE_PUBLIC,
|
||||
TRAVEL_MODE_PUBLIC_TIME_TABLE,
|
||||
TRAVEL_MODE_TRUCK,
|
||||
convert_time_to_isodate,
|
||||
)
|
||||
from homeassistant.const import ATTR_ICON, EVENT_HOMEASSISTANT_START
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
@ -66,7 +67,7 @@ CAR_DESTINATION_LATITUDE = "39.0"
|
|||
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."""
|
||||
base_url = "https://route.ls.hereapi.com/routing/7.2/calculateroute.json?"
|
||||
parameters = {
|
||||
|
@ -74,9 +75,13 @@ def _build_mock_url(origin, destination, modes, api_key, departure):
|
|||
"waypoint1": f"geo!{destination}",
|
||||
"mode": ";".join(str(herepy.RouteMode[mode]) for mode in modes),
|
||||
"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)
|
||||
print(url)
|
||||
return url
|
||||
|
||||
|
||||
|
@ -117,7 +122,6 @@ def requests_mock_credentials_check(requests_mock):
|
|||
",".join([CAR_DESTINATION_LATITUDE, CAR_DESTINATION_LONGITUDE]),
|
||||
modes,
|
||||
API_KEY,
|
||||
"now",
|
||||
)
|
||||
requests_mock.get(
|
||||
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]),
|
||||
modes,
|
||||
API_KEY,
|
||||
"now",
|
||||
)
|
||||
requests_mock_credentials_check.get(
|
||||
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]),
|
||||
modes,
|
||||
API_KEY,
|
||||
"now",
|
||||
)
|
||||
requests_mock_credentials_check.get(
|
||||
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]),
|
||||
modes,
|
||||
API_KEY,
|
||||
"now",
|
||||
)
|
||||
requests_mock_credentials_check.get(
|
||||
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"
|
||||
destination = "39.042158,-77.119116"
|
||||
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(
|
||||
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"
|
||||
destination = "39.042158,-77.119116"
|
||||
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(
|
||||
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"
|
||||
destination = "41.9043,-87.9216"
|
||||
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(
|
||||
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"
|
||||
destination = "41.9043,-87.9216"
|
||||
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(
|
||||
response_url,
|
||||
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"
|
||||
destination = "41.9043,-87.9216"
|
||||
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(
|
||||
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"
|
||||
destination = "41.9043,-87.9216"
|
||||
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(
|
||||
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"
|
||||
destination = "47.013399,-10.171986"
|
||||
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(
|
||||
response_url,
|
||||
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]),
|
||||
modes,
|
||||
API_KEY,
|
||||
"now",
|
||||
)
|
||||
requests_mock.get(
|
||||
response_url,
|
||||
|
@ -942,7 +942,7 @@ async def test_attribution(hass, requests_mock_credentials_check):
|
|||
origin = "50.037751372637686,14.39233448220898"
|
||||
destination = "50.07993838201255,14.42582157361062"
|
||||
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(
|
||||
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()
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue