1
0
mirror of https://github.com/home-assistant/core.git synced 2026-02-15 07:36:16 +00:00

Prevent duplicate entities for Volvo integration (#151779)

This commit is contained in:
Thomas D
2025-09-27 12:29:11 +02:00
committed by GitHub
parent fb93fed2e5
commit e3d707f0b4
9 changed files with 1533 additions and 6 deletions

View File

@@ -354,13 +354,19 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up sensors."""
entities: dict[str, VolvoSensor] = {}
coordinators = entry.runtime_data.interval_coordinators
async_add_entities(
VolvoSensor(coordinator, description)
for coordinator in coordinators
for description in _DESCRIPTIONS
if description.api_field in coordinator.data
)
for coordinator in coordinators:
for description in _DESCRIPTIONS:
if description.key in entities:
continue
if description.api_field in coordinator.data:
entities[description.key] = VolvoSensor(coordinator, description)
async_add_entities(entities.values())
class VolvoSensor(VolvoEntity, SensorEntity):

View File

@@ -27,6 +27,12 @@ _MODEL_SPECIFIC_RESPONSES = {
"vehicle",
],
"xc90_petrol_2019": ["commands", "statistics", "vehicle"],
"xc90_phev_2024": [
"energy_capabilities",
"energy_state",
"statistics",
"vehicle",
],
}

View File

@@ -0,0 +1,33 @@
{
"isSupported": true,
"batteryChargeLevel": {
"isSupported": true
},
"electricRange": {
"isSupported": true
},
"chargerConnectionStatus": {
"isSupported": true
},
"chargingSystemStatus": {
"isSupported": true
},
"chargingType": {
"isSupported": true
},
"chargerPowerStatus": {
"isSupported": true
},
"estimatedChargingTimeToTargetBatteryChargeLevel": {
"isSupported": true
},
"targetBatteryChargeLevel": {
"isSupported": true
},
"chargingCurrentLimit": {
"isSupported": false
},
"chargingPower": {
"isSupported": false
}
}

View File

@@ -0,0 +1,55 @@
{
"batteryChargeLevel": {
"status": "OK",
"value": 87.3,
"unit": "percentage",
"updatedAt": "2025-09-05T07:58:14Z"
},
"electricRange": {
"status": "OK",
"value": 26,
"unit": "miles",
"updatedAt": "2025-09-05T07:58:14Z"
},
"chargerConnectionStatus": {
"status": "OK",
"value": "DISCONNECTED",
"updatedAt": "2025-09-05T07:58:14Z"
},
"chargingStatus": {
"status": "OK",
"value": "IDLE",
"updatedAt": "2025-09-05T07:58:14Z"
},
"chargingType": {
"status": "OK",
"value": "NONE",
"updatedAt": "2025-09-05T07:58:14Z"
},
"chargerPowerStatus": {
"status": "OK",
"value": "NO_POWER_AVAILABLE",
"updatedAt": "2025-09-05T07:58:14Z"
},
"estimatedChargingTimeToTargetBatteryChargeLevel": {
"status": "OK",
"value": 0,
"unit": "minutes",
"updatedAt": "2025-09-05T07:58:14Z"
},
"chargingCurrentLimit": {
"status": "ERROR",
"code": "NOT_SUPPORTED",
"message": "Resource is not supported for this vehicle"
},
"targetBatteryChargeLevel": {
"status": "ERROR",
"code": "ERROR_READING_PROPERTY",
"message": "Failed to retrieve property."
},
"chargingPower": {
"status": "ERROR",
"code": "NOT_SUPPORTED",
"message": "Resource is not supported for this vehicle"
}
}

View File

@@ -0,0 +1,47 @@
{
"averageFuelConsumption": {
"value": 2.0,
"unit": "l/100km",
"timestamp": "2025-09-04T18:03:57.437Z"
},
"averageEnergyConsumption": {
"value": 19.9,
"unit": "kWh/100km",
"timestamp": "2025-09-04T18:03:57.437Z"
},
"averageFuelConsumptionAutomatic": {
"value": 0.0,
"unit": "l/100km",
"timestamp": "2025-09-04T18:03:57.437Z"
},
"averageSpeed": {
"value": 47,
"unit": "km/h",
"timestamp": "2025-09-04T18:03:57.437Z"
},
"averageSpeedAutomatic": {
"value": 37,
"unit": "km/h",
"timestamp": "2025-09-04T18:03:57.437Z"
},
"tripMeterManual": {
"value": 5935.8,
"unit": "km",
"timestamp": "2025-09-04T18:03:57.437Z"
},
"tripMeterAutomatic": {
"value": 23.7,
"unit": "km",
"timestamp": "2025-09-04T18:03:57.437Z"
},
"distanceToEmptyTank": {
"value": 804,
"unit": "km",
"timestamp": "2025-09-04T18:03:57.437Z"
},
"distanceToEmptyBattery": {
"value": 43,
"unit": "km",
"timestamp": "2025-09-05T07:58:14.760Z"
}
}

View File

@@ -0,0 +1,17 @@
{
"vin": "YV1ABCDEFG1234567",
"modelYear": 2024,
"gearbox": "AUTOMATIC",
"fuelType": "PETROL/ELECTRIC",
"externalColour": "Crystal White Pearl",
"batteryCapacityKWH": 18.819,
"images": {
"exteriorImageUrl": "https://cas.volvocars.com/image/dynamic/MY24_0000/123/_/default.png?market=se&client=public-api-engineering&angle=1&bg=00000000&w=1920",
"internalImageUrl": "https://cas.volvocars.com/image/dynamic/MY24_0000/123/_/default.jpg?market=se&client=public-api-engineering&angle=0&w=1920"
},
"descriptions": {
"model": "XC90",
"upholstery": "null",
"steering": "LEFT"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@ from unittest.mock import patch
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.volvo.const import DOMAIN
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
@@ -31,3 +32,28 @@ async def test_binary_sensor(
assert await setup_integration()
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
@pytest.mark.usefixtures("mock_api", "full_model")
@pytest.mark.parametrize(
"full_model",
[
"ex30_2024",
"s90_diesel_2018",
"xc40_electric_2024",
"xc60_phev_2020",
"xc90_petrol_2019",
"xc90_phev_2024",
],
)
async def test_unique_ids(
hass: HomeAssistant,
setup_integration: Callable[[], Awaitable[bool]],
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test binary sensor for unique id's."""
with patch("homeassistant.components.volvo.PLATFORMS", [Platform.BINARY_SENSOR]):
assert await setup_integration()
assert f"Platform {DOMAIN} does not generate unique IDs" not in caplog.text

View File

@@ -6,6 +6,7 @@ from unittest.mock import patch
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.volvo.const import DOMAIN
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
@@ -22,6 +23,7 @@ from tests.common import MockConfigEntry, snapshot_platform
"xc40_electric_2024",
"xc60_phev_2020",
"xc90_petrol_2019",
"xc90_phev_2024",
],
)
async def test_sensor(
@@ -89,3 +91,28 @@ async def test_charging_power_value(
assert await setup_integration()
assert hass.states.get("sensor.volvo_ex30_charging_power").state == "0"
@pytest.mark.usefixtures("mock_api", "full_model")
@pytest.mark.parametrize(
"full_model",
[
"ex30_2024",
"s90_diesel_2018",
"xc40_electric_2024",
"xc60_phev_2020",
"xc90_petrol_2019",
"xc90_phev_2024",
],
)
async def test_unique_ids(
hass: HomeAssistant,
setup_integration: Callable[[], Awaitable[bool]],
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test sensor for unique id's."""
with patch("homeassistant.components.volvo.PLATFORMS", [Platform.SENSOR]):
assert await setup_integration()
assert f"Platform {DOMAIN} does not generate unique IDs" not in caplog.text