mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Calculate data using all sections for here_travel_time (#86576)
Calculate data using all sections
This commit is contained in:
parent
7bd56ad7d6
commit
781a4267cf
@ -117,25 +117,43 @@ class HERERoutingDataUpdateCoordinator(DataUpdateCoordinator[HERETravelTimeData]
|
|||||||
|
|
||||||
def _parse_routing_response(self, response: dict[str, Any]) -> HERETravelTimeData:
|
def _parse_routing_response(self, response: dict[str, Any]) -> HERETravelTimeData:
|
||||||
"""Parse the routing response dict to a HERETravelTimeData."""
|
"""Parse the routing response dict to a HERETravelTimeData."""
|
||||||
section: dict[str, Any] = response["routes"][0]["sections"][0]
|
distance: float = 0.0
|
||||||
summary: dict[str, int] = section["summary"]
|
duration: float = 0.0
|
||||||
mapped_origin_lat: float = section["departure"]["place"]["location"]["lat"]
|
duration_in_traffic: float = 0.0
|
||||||
mapped_origin_lon: float = section["departure"]["place"]["location"]["lng"]
|
|
||||||
mapped_destination_lat: float = section["arrival"]["place"]["location"]["lat"]
|
for section in response["routes"][0]["sections"]:
|
||||||
mapped_destination_lon: float = section["arrival"]["place"]["location"]["lng"]
|
distance += DistanceConverter.convert(
|
||||||
distance: float = DistanceConverter.convert(
|
section["summary"]["length"],
|
||||||
summary["length"], UnitOfLength.METERS, UnitOfLength.KILOMETERS
|
UnitOfLength.METERS,
|
||||||
)
|
UnitOfLength.KILOMETERS,
|
||||||
|
)
|
||||||
|
duration += section["summary"]["baseDuration"]
|
||||||
|
duration_in_traffic += section["summary"]["duration"]
|
||||||
|
|
||||||
|
first_section = response["routes"][0]["sections"][0]
|
||||||
|
last_section = response["routes"][0]["sections"][-1]
|
||||||
|
mapped_origin_lat: float = first_section["departure"]["place"]["location"][
|
||||||
|
"lat"
|
||||||
|
]
|
||||||
|
mapped_origin_lon: float = first_section["departure"]["place"]["location"][
|
||||||
|
"lng"
|
||||||
|
]
|
||||||
|
mapped_destination_lat: float = last_section["arrival"]["place"]["location"][
|
||||||
|
"lat"
|
||||||
|
]
|
||||||
|
mapped_destination_lon: float = last_section["arrival"]["place"]["location"][
|
||||||
|
"lng"
|
||||||
|
]
|
||||||
origin_name: str | None = None
|
origin_name: str | None = None
|
||||||
if (names := section["spans"][0].get("names")) is not None:
|
if (names := first_section["spans"][0].get("names")) is not None:
|
||||||
origin_name = names[0]["value"]
|
origin_name = names[0]["value"]
|
||||||
destination_name: str | None = None
|
destination_name: str | None = None
|
||||||
if (names := section["spans"][-1].get("names")) is not None:
|
if (names := last_section["spans"][-1].get("names")) is not None:
|
||||||
destination_name = names[0]["value"]
|
destination_name = names[0]["value"]
|
||||||
return HERETravelTimeData(
|
return HERETravelTimeData(
|
||||||
attribution=None,
|
attribution=None,
|
||||||
duration=round(summary["baseDuration"] / 60),
|
duration=round(duration / 60),
|
||||||
duration_in_traffic=round(summary["duration"] / 60),
|
duration_in_traffic=round(duration_in_traffic / 60),
|
||||||
distance=distance,
|
distance=distance,
|
||||||
origin=f"{mapped_origin_lat},{mapped_origin_lon}",
|
origin=f"{mapped_origin_lat},{mapped_origin_lon}",
|
||||||
destination=f"{mapped_destination_lat},{mapped_destination_lon}",
|
destination=f"{mapped_destination_lat},{mapped_destination_lon}",
|
||||||
|
@ -13,6 +13,7 @@ TRANSIT_RESPONSE = json.loads(
|
|||||||
NO_ATTRIBUTION_TRANSIT_RESPONSE = json.loads(
|
NO_ATTRIBUTION_TRANSIT_RESPONSE = json.loads(
|
||||||
load_fixture("here_travel_time/no_attribution_transit_route_response.json")
|
load_fixture("here_travel_time/no_attribution_transit_route_response.json")
|
||||||
)
|
)
|
||||||
|
BIKE_RESPONSE = json.loads(load_fixture("here_travel_time/bike_response.json"))
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="valid_response")
|
@pytest.fixture(name="valid_response")
|
||||||
@ -27,6 +28,18 @@ def valid_response_fixture():
|
|||||||
yield mock
|
yield mock
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="bike_response")
|
||||||
|
def bike_response_fixture():
|
||||||
|
"""Return valid api response."""
|
||||||
|
with patch(
|
||||||
|
"here_transit.HERETransitApi.route", return_value=TRANSIT_RESPONSE
|
||||||
|
), patch(
|
||||||
|
"here_routing.HERERoutingApi.route",
|
||||||
|
return_value=BIKE_RESPONSE,
|
||||||
|
) as mock:
|
||||||
|
yield mock
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="no_attribution_response")
|
@pytest.fixture(name="no_attribution_response")
|
||||||
def no_attribution_response_fixture():
|
def no_attribution_response_fixture():
|
||||||
"""Return valid api response without attribution."""
|
"""Return valid api response without attribution."""
|
||||||
|
214
tests/components/here_travel_time/fixtures/bike_response.json
Normal file
214
tests/components/here_travel_time/fixtures/bike_response.json
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
{
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"id": "6d8ae729-3b30-4d81-adaf-6a485b15b70a",
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "c8d12b37-05e1-47f0-a5c2-43f5fb589768",
|
||||||
|
"type": "pedestrian",
|
||||||
|
"departure": {
|
||||||
|
"time": "2023-01-23T18:26:12+01:00",
|
||||||
|
"place": {
|
||||||
|
"type": "place",
|
||||||
|
"location": {
|
||||||
|
"lat": 49.1260894,
|
||||||
|
"lng": 6.1843356
|
||||||
|
},
|
||||||
|
"originalLocation": {
|
||||||
|
"lat": 49.1264093,
|
||||||
|
"lng": 6.1841419
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"arrival": {
|
||||||
|
"time": "2023-01-23T18:29:09+01:00",
|
||||||
|
"place": {
|
||||||
|
"type": "place",
|
||||||
|
"location": {
|
||||||
|
"lat": 49.12547,
|
||||||
|
"lng": 6.18242
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"duration": 177,
|
||||||
|
"length": 157,
|
||||||
|
"baseDuration": 177
|
||||||
|
},
|
||||||
|
"polyline": "BGyst29Cg5u5LpOj2BjIzZnQ_nB",
|
||||||
|
"spans": [
|
||||||
|
{
|
||||||
|
"offset": 0,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Chemin de Halage",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transport": {
|
||||||
|
"mode": "pedestrian"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d37123f4-034a-4c46-8678-596f999e8eae",
|
||||||
|
"type": "vehicle",
|
||||||
|
"departure": {
|
||||||
|
"time": "2023-01-23T18:29:09+01:00",
|
||||||
|
"place": {
|
||||||
|
"type": "place",
|
||||||
|
"location": {
|
||||||
|
"lat": 49.12547,
|
||||||
|
"lng": 6.18242
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"arrival": {
|
||||||
|
"time": "2023-01-23T18:44:41+01:00",
|
||||||
|
"place": {
|
||||||
|
"type": "place",
|
||||||
|
"location": {
|
||||||
|
"lat": 49.1025668,
|
||||||
|
"lng": 6.1768518
|
||||||
|
},
|
||||||
|
"originalLocation": {
|
||||||
|
"lat": 49.1025784,
|
||||||
|
"lng": 6.1770297
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"duration": 932,
|
||||||
|
"length": 3426,
|
||||||
|
"baseDuration": 932
|
||||||
|
},
|
||||||
|
"polyline": "BG8ls29Cohr5L0UjXgFvH4DnGgFrJ7G3IvHrJrJvMnB7B_JjN_JzPvH_JjDsJjD8G7B4DrEkIvHwMzF4I7GgKjDgF7BwC7G0KjN0U3I4D7GsEvHkDzK4D7a4I3IwCzesJvH8B7GoBjDU7LsEjIwC_JkDrJkD_JsEvH4DvH4DvHsE3IgFrEkD_E4DvH0F7G0FrJ4IzFsErE4DjDgFnGsE_EwCrEoB3DUzFUnGAvHT7GTjDTvHT7GU7BArJUjD4DvCwCzFgF_EsE_EgF_JoLzF0F_EsEzFsErEkD3DwC3D8B3D8BrE8B3DoBvH8BjI8BzFoBzFUjIUnGAjSAzFTnLvC_E7BzF7B_E7B_EjD7G3D7G7B_ETnpBvCnQTzUnB3DAvMT7B7BnGvCzFrErEvCzFjDzF3DnGzF_EzF3I7LnV3cnG3IzF0K7LsTrE8G3I4NvC4DvC4D7BwC7BwCvCwCjD4DvCkDjD4D3D4DjDkDzFsEvCA3DUjDUrEUrEUrEU_ETrEvCnGrErd_nB3DnGnLnQ_JzP7Q_Y7G_JvR7ajI7Lrd3rBvH7LzZrnBnL3SnLjSjI7Lna7pBjN_T_EjIvCrE7GnL7GjNrE3IjDrEjDrEvCjDzF3IvCrE_JzU3Nrd_J_TvCrEvC3DT7BnBvC7B3D3XvvB7kBjuCoB7BoB7BUnBU7BU7BU3DAvCTjDT7BnBjDnBvC7BvCnBnB7BT7BTnBA7BU7BoBnBoBnB8BnB8BnBkDTwC_vC0PzoBwMvb8GnB0jB7B4cUgP4D0oB7foGZE",
|
||||||
|
"spans": [
|
||||||
|
{
|
||||||
|
"offset": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 4,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Avenue de Blida",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 11,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Pont des Grilles",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 22,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Boulevard Paixhans",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 49,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Boulevard André Maginot",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 97,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Boulevard André Maginot",
|
||||||
|
"language": "fr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "Place Jean Cocteau",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 98,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Place Mazelle",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 110,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Passage de Plantières",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 119
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 127,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Avenue de lAmphithéâtre",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 146,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Rue aux Arènes",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 192,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Rue Saint-Pierre",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 195,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Rue Émile Boilvin",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"offset": 199,
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"value": "Rue Charles Sadoul",
|
||||||
|
"language": "fr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transport": {
|
||||||
|
"mode": "bicycle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -749,3 +749,54 @@ async def test_transit_rate_limit(hass: HomeAssistant, caplog):
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("sensor.test_distance").state == "1.883"
|
assert hass.states.get("sensor.test_distance").state == "1.883"
|
||||||
assert "Resetting update interval to" in caplog.text
|
assert "Resetting update interval to" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("bike_response")
|
||||||
|
async def test_multiple_sections(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
):
|
||||||
|
"""Test that multiple sections are handled correctly."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id="0123456789",
|
||||||
|
data={
|
||||||
|
CONF_ORIGIN_LATITUDE: float(ORIGIN_LATITUDE),
|
||||||
|
CONF_ORIGIN_LONGITUDE: float(ORIGIN_LONGITUDE),
|
||||||
|
CONF_DESTINATION_LATITUDE: float(DESTINATION_LATITUDE),
|
||||||
|
CONF_DESTINATION_LONGITUDE: float(DESTINATION_LONGITUDE),
|
||||||
|
CONF_API_KEY: API_KEY,
|
||||||
|
CONF_MODE: TRAVEL_MODE_BICYCLE,
|
||||||
|
CONF_NAME: "test",
|
||||||
|
},
|
||||||
|
options=DEFAULT_OPTIONS,
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
duration = hass.states.get("sensor.test_duration")
|
||||||
|
assert duration.state == "18"
|
||||||
|
|
||||||
|
assert float(hass.states.get("sensor.test_distance").state) == pytest.approx(3.583)
|
||||||
|
assert hass.states.get("sensor.test_duration_in_traffic").state == "18"
|
||||||
|
assert hass.states.get("sensor.test_origin").state == "Chemin de Halage"
|
||||||
|
assert (
|
||||||
|
hass.states.get("sensor.test_origin").attributes.get(ATTR_LATITUDE)
|
||||||
|
== "49.1260894"
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
hass.states.get("sensor.test_origin").attributes.get(ATTR_LONGITUDE)
|
||||||
|
== "6.1843356"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert hass.states.get("sensor.test_destination").state == "Rue Charles Sadoul"
|
||||||
|
assert (
|
||||||
|
hass.states.get("sensor.test_destination").attributes.get(ATTR_LATITUDE)
|
||||||
|
== "49.1025668"
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
hass.states.get("sensor.test_destination").attributes.get(ATTR_LONGITUDE)
|
||||||
|
== "6.1768518"
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user