Calculate data using all sections for here_travel_time (#86576)
Calculate data using all sections
This commit is contained in:
parent
7bd56ad7d6
commit
781a4267cf
4 changed files with 309 additions and 13 deletions
|
@ -117,25 +117,43 @@ class HERERoutingDataUpdateCoordinator(DataUpdateCoordinator[HERETravelTimeData]
|
|||
|
||||
def _parse_routing_response(self, response: dict[str, Any]) -> HERETravelTimeData:
|
||||
"""Parse the routing response dict to a HERETravelTimeData."""
|
||||
section: dict[str, Any] = response["routes"][0]["sections"][0]
|
||||
summary: dict[str, int] = section["summary"]
|
||||
mapped_origin_lat: float = section["departure"]["place"]["location"]["lat"]
|
||||
mapped_origin_lon: float = section["departure"]["place"]["location"]["lng"]
|
||||
mapped_destination_lat: float = section["arrival"]["place"]["location"]["lat"]
|
||||
mapped_destination_lon: float = section["arrival"]["place"]["location"]["lng"]
|
||||
distance: float = DistanceConverter.convert(
|
||||
summary["length"], UnitOfLength.METERS, UnitOfLength.KILOMETERS
|
||||
)
|
||||
distance: float = 0.0
|
||||
duration: float = 0.0
|
||||
duration_in_traffic: float = 0.0
|
||||
|
||||
for section in response["routes"][0]["sections"]:
|
||||
distance += DistanceConverter.convert(
|
||||
section["summary"]["length"],
|
||||
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
|
||||
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"]
|
||||
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"]
|
||||
return HERETravelTimeData(
|
||||
attribution=None,
|
||||
duration=round(summary["baseDuration"] / 60),
|
||||
duration_in_traffic=round(summary["duration"] / 60),
|
||||
duration=round(duration / 60),
|
||||
duration_in_traffic=round(duration_in_traffic / 60),
|
||||
distance=distance,
|
||||
origin=f"{mapped_origin_lat},{mapped_origin_lon}",
|
||||
destination=f"{mapped_destination_lat},{mapped_destination_lon}",
|
||||
|
|
|
@ -13,6 +13,7 @@ TRANSIT_RESPONSE = json.loads(
|
|||
NO_ATTRIBUTION_TRANSIT_RESPONSE = json.loads(
|
||||
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")
|
||||
|
@ -27,6 +28,18 @@ def valid_response_fixture():
|
|||
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")
|
||||
def no_attribution_response_fixture():
|
||||
"""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()
|
||||
assert hass.states.get("sensor.test_distance").state == "1.883"
|
||||
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…
Add table
Reference in a new issue