mirror of
https://github.com/home-assistant/core.git
synced 2026-04-20 15:34:56 +00:00
@@ -8,5 +8,5 @@
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["homevolt==0.2.3"]
|
||||
"requirements": ["homevolt==0.2.4"]
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ rules:
|
||||
docs-installation-parameters: todo
|
||||
entity-unavailable: done
|
||||
integration-owner: done
|
||||
log-when-unavailable: done
|
||||
log-when-unavailable: todo
|
||||
parallel-updates: done
|
||||
reauthentication-flow: todo
|
||||
test-coverage: todo
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from homevolt.models import SensorType
|
||||
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
@@ -31,8 +29,6 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
from .const import DOMAIN, MANUFACTURER, HomevoltConfigEntry
|
||||
from .coordinator import HomevoltDataUpdateCoordinator
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PARALLEL_UPDATES = 0 # Coordinator-based updates
|
||||
|
||||
SENSORS: tuple[SensorEntityDescription, ...] = (
|
||||
@@ -115,14 +111,12 @@ async def async_setup_entry(
|
||||
sensors_by_key = {sensor.key: sensor for sensor in SENSORS}
|
||||
for sensor_key, sensor in coordinator.data.sensors.items():
|
||||
if (description := sensors_by_key.get(sensor.type)) is None:
|
||||
_LOGGER.error("Sensor %s not found", sensor.type.name)
|
||||
continue
|
||||
entities.append(
|
||||
HomevoltSensor(
|
||||
description,
|
||||
coordinator,
|
||||
sensor_key,
|
||||
|
||||
)
|
||||
)
|
||||
async_add_entities(entities)
|
||||
@@ -145,22 +139,25 @@ class HomevoltSensor(CoordinatorEntity[HomevoltDataUpdateCoordinator], SensorEnt
|
||||
device_id = coordinator.data.device_id
|
||||
self._attr_unique_id = f"{device_id}_{sensor_key}"
|
||||
sensor_data = coordinator.data.sensors[sensor_key]
|
||||
self._attr_translation_key = sensor_data.slug
|
||||
self._sensor_key = sensor_key
|
||||
device_metadata = coordinator.data.device_metadata.get(
|
||||
sensor_data.device_identifier
|
||||
)
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, f"{device_id}_{sensor_data.device_identifier}")},
|
||||
configuration_url=coordinator.client.hostname,
|
||||
configuration_url=coordinator.client.base_url,
|
||||
manufacturer=MANUFACTURER,
|
||||
model=device_metadata.model if device_metadata else None,
|
||||
name=device_metadata.name if device_metadata else None,
|
||||
)
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return if entity is available."""
|
||||
return super().available and self._sensor_key in self.coordinator.data.sensors
|
||||
|
||||
@property
|
||||
def native_value(self) -> StateType:
|
||||
"""Return the native value of the sensor."""
|
||||
sensor_data = self.coordinator.data.sensors[self._sensor_key]
|
||||
if sensor_data is None:
|
||||
return None
|
||||
return sensor_data.value
|
||||
return self.coordinator.data.sensors[self._sensor_key].value
|
||||
|
||||
@@ -151,6 +151,9 @@
|
||||
"l3_voltage_load": {
|
||||
"name": "Load L3 voltage"
|
||||
},
|
||||
"power": {
|
||||
"name": "Power"
|
||||
},
|
||||
"power_grid": {
|
||||
"name": "Grid power"
|
||||
},
|
||||
@@ -178,6 +181,9 @@
|
||||
"schedule_type": {
|
||||
"name": "Schedule type"
|
||||
},
|
||||
"state_of_charge": {
|
||||
"name": "State of charge"
|
||||
},
|
||||
"system_temperature": {
|
||||
"name": "System temperature"
|
||||
},
|
||||
|
||||
2
requirements_all.txt
generated
2
requirements_all.txt
generated
@@ -1225,7 +1225,7 @@ homelink-integration-api==0.0.1
|
||||
homematicip==2.4.0
|
||||
|
||||
# homeassistant.components.homevolt
|
||||
homevolt==0.2.3
|
||||
homevolt==0.2.4
|
||||
|
||||
# homeassistant.components.horizon
|
||||
horimote==0.4.1
|
||||
|
||||
2
requirements_test_all.txt
generated
2
requirements_test_all.txt
generated
@@ -1083,7 +1083,7 @@ homelink-integration-api==0.0.1
|
||||
homematicip==2.4.0
|
||||
|
||||
# homeassistant.components.homevolt
|
||||
homevolt==0.2.3
|
||||
homevolt==0.2.4
|
||||
|
||||
# homeassistant.components.remember_the_milk
|
||||
httplib2==0.20.4
|
||||
|
||||
@@ -51,7 +51,7 @@ def mock_homevolt_client() -> Generator[MagicMock]:
|
||||
),
|
||||
):
|
||||
client = homevolt_mock.return_value
|
||||
client.hostname = "http://127.0.0.1"
|
||||
client.base_url = "http://127.0.0.1"
|
||||
client.update_info = AsyncMock()
|
||||
client.close_connection = AsyncMock()
|
||||
|
||||
@@ -63,16 +63,19 @@ def mock_homevolt_client() -> Generator[MagicMock]:
|
||||
value=234.5,
|
||||
type=SensorType.VOLTAGE,
|
||||
device_identifier="ems_40580137858664",
|
||||
slug="l1_voltage",
|
||||
),
|
||||
"Battery State of Charge": Sensor(
|
||||
value=80.6,
|
||||
type=SensorType.PERCENTAGE,
|
||||
device_identifier="ems_40580137858664",
|
||||
slug="battery_state_of_charge",
|
||||
),
|
||||
"Power": Sensor(
|
||||
value=-12,
|
||||
type=SensorType.POWER,
|
||||
device_identifier="ems_40580137858664",
|
||||
slug="power",
|
||||
),
|
||||
}
|
||||
device.device_metadata = {
|
||||
|
||||
@@ -100,7 +100,6 @@ async def test_step_user_errors(
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {"base": expected_error}
|
||||
|
||||
# Clear the error and complete the flow successfully
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.homevolt.config_flow.Homevolt.update_info",
|
||||
@@ -169,48 +168,3 @@ async def test_duplicate_entry(
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_duplicate_entry_no_device_id(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: AsyncMock,
|
||||
) -> None:
|
||||
"""Test that a duplicate host aborts the flow when device_id is None."""
|
||||
existing_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={CONF_HOST: "192.168.1.100", CONF_PASSWORD: "test-password"},
|
||||
)
|
||||
existing_entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
user_input = {
|
||||
CONF_HOST: "192.168.1.100",
|
||||
CONF_PASSWORD: "test-password",
|
||||
}
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.homevolt.config_flow.Homevolt.update_info",
|
||||
new_callable=AsyncMock,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.homevolt.config_flow.Homevolt.get_device",
|
||||
) as mock_get_device,
|
||||
):
|
||||
mock_device = MagicMock()
|
||||
mock_device.device_id = None
|
||||
mock_get_device.return_value = mock_device
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
Reference in New Issue
Block a user