mirror of
https://github.com/home-assistant/core.git
synced 2025-07-20 11:47:06 +00:00
Add energy sensor to adax (#145995)
* 2nd attempt to add energysensors to Adax component * Ruff format changes * I did not reuse the first call for information.. Now i do.. * Fixed some tests after the last change * Remove extra attributes * Dont use info logger * aggregate if not rooms * Raise error if no rooms are discovered * Move code out of try catch * Catch more specific errors * removed platforms from manifest.json * remove attribute translation key * Getting rid of the summation of energy used.. * Fixed errorness in test * set roomproperty in Init * concatenated the two functions * use raw Wh values and suggest a konversion for HomeAssistant * Use snapshot testing * Update homeassistant/components/adax/coordinator.py Co-authored-by: Josef Zweck <josef@zweck.dev> * Update homeassistant/components/adax/strings.json Co-authored-by: Josef Zweck <josef@zweck.dev> * Update homeassistant/components/adax/sensor.py Co-authored-by: Josef Zweck <josef@zweck.dev> * Update homeassistant/components/adax/sensor.py Co-authored-by: Josef Zweck <josef@zweck.dev> * Update homeassistant/components/adax/sensor.py Co-authored-by: Josef Zweck <josef@zweck.dev> * Update homeassistant/components/adax/sensor.py Co-authored-by: Josef Zweck <josef@zweck.dev> * Removing un needed logg * Removing initial value * Changing tests to snapshot_platform * Removing available property from sensor.py and doing a ruff formating.. * Fix a broken indent * Add fix for coordinator updates in Adax energisensor and namesetting * Update homeassistant/components/adax/sensor.py Co-authored-by: Josef Zweck <josef@zweck.dev> * Update homeassistant/components/adax/coordinator.py Co-authored-by: Josef Zweck <josef@zweck.dev> * Update homeassistant/components/adax/coordinator.py Co-authored-by: Josef Zweck <josef@zweck.dev> * Update homeassistant/components/adax/sensor.py Co-authored-by: Josef Zweck <josef@zweck.dev> * generated snapshots * Ruff changes * Even more ruff changes, that did not appear on ruff command locally * Trying to fix CI updates * Update homeassistant/components/adax/sensor.py Co-authored-by: Josef Zweck <josef@zweck.dev> * Improve AdaxEnergySensor by simplifying code and ensuring correct handling of energy values. Adjust how room and device information is retrieved to avoid duplication and improve readability. * Removed a test för device_id as per request.. * Make supersure that value is int and not "Any" * removing executable status * Update tests/components/adax/test_sensor.py Co-authored-by: Josef Zweck <josef@zweck.dev> --------- Co-authored-by: Josef Zweck <josef@zweck.dev>
This commit is contained in:
parent
987753dd1c
commit
85b608912b
@ -8,7 +8,7 @@ from homeassistant.core import HomeAssistant
|
|||||||
from .const import CONNECTION_TYPE, LOCAL
|
from .const import CONNECTION_TYPE, LOCAL
|
||||||
from .coordinator import AdaxCloudCoordinator, AdaxConfigEntry, AdaxLocalCoordinator
|
from .coordinator import AdaxCloudCoordinator, AdaxConfigEntry, AdaxLocalCoordinator
|
||||||
|
|
||||||
PLATFORMS = [Platform.CLIMATE]
|
PLATFORMS = [Platform.CLIMATE, Platform.SENSOR]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: AdaxConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: AdaxConfigEntry) -> bool:
|
||||||
|
@ -41,7 +41,30 @@ class AdaxCloudCoordinator(DataUpdateCoordinator[dict[str, dict[str, Any]]]):
|
|||||||
|
|
||||||
async def _async_update_data(self) -> dict[str, dict[str, Any]]:
|
async def _async_update_data(self) -> dict[str, dict[str, Any]]:
|
||||||
"""Fetch data from the Adax."""
|
"""Fetch data from the Adax."""
|
||||||
rooms = await self.adax_data_handler.get_rooms() or []
|
try:
|
||||||
|
if hasattr(self.adax_data_handler, "fetch_rooms_info"):
|
||||||
|
rooms = await self.adax_data_handler.fetch_rooms_info() or []
|
||||||
|
_LOGGER.debug("fetch_rooms_info returned: %s", rooms)
|
||||||
|
else:
|
||||||
|
_LOGGER.debug("fetch_rooms_info method not available, using get_rooms")
|
||||||
|
rooms = []
|
||||||
|
|
||||||
|
if not rooms:
|
||||||
|
_LOGGER.debug(
|
||||||
|
"No rooms from fetch_rooms_info, trying get_rooms as fallback"
|
||||||
|
)
|
||||||
|
rooms = await self.adax_data_handler.get_rooms() or []
|
||||||
|
_LOGGER.debug("get_rooms fallback returned: %s", rooms)
|
||||||
|
|
||||||
|
if not rooms:
|
||||||
|
raise UpdateFailed("No rooms available from Adax API")
|
||||||
|
|
||||||
|
except OSError as e:
|
||||||
|
raise UpdateFailed(f"Error communicating with API: {e}") from e
|
||||||
|
|
||||||
|
for room in rooms:
|
||||||
|
room["energyWh"] = int(room.get("energyWh", 0))
|
||||||
|
|
||||||
return {r["id"]: r for r in rooms}
|
return {r["id"]: r for r in rooms}
|
||||||
|
|
||||||
|
|
||||||
|
77
homeassistant/components/adax/sensor.py
Normal file
77
homeassistant/components/adax/sensor.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
"""Support for Adax energy sensors."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
|
from homeassistant.components.sensor import (
|
||||||
|
SensorDeviceClass,
|
||||||
|
SensorEntity,
|
||||||
|
SensorStateClass,
|
||||||
|
)
|
||||||
|
from homeassistant.const import UnitOfEnergy
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
|
from . import AdaxConfigEntry
|
||||||
|
from .const import CONNECTION_TYPE, DOMAIN, LOCAL
|
||||||
|
from .coordinator import AdaxCloudCoordinator
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entry: AdaxConfigEntry,
|
||||||
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up the Adax energy sensors with config flow."""
|
||||||
|
if entry.data.get(CONNECTION_TYPE) != LOCAL:
|
||||||
|
cloud_coordinator = cast(AdaxCloudCoordinator, entry.runtime_data)
|
||||||
|
|
||||||
|
# Create individual energy sensors for each device
|
||||||
|
async_add_entities(
|
||||||
|
AdaxEnergySensor(cloud_coordinator, device_id)
|
||||||
|
for device_id in cloud_coordinator.data
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AdaxEnergySensor(CoordinatorEntity[AdaxCloudCoordinator], SensorEntity):
|
||||||
|
"""Representation of an Adax energy sensor."""
|
||||||
|
|
||||||
|
_attr_has_entity_name = True
|
||||||
|
_attr_translation_key = "energy"
|
||||||
|
_attr_device_class = SensorDeviceClass.ENERGY
|
||||||
|
_attr_native_unit_of_measurement = UnitOfEnergy.WATT_HOUR
|
||||||
|
_attr_suggested_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
|
||||||
|
_attr_state_class = SensorStateClass.TOTAL_INCREASING
|
||||||
|
_attr_suggested_display_precision = 3
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
coordinator: AdaxCloudCoordinator,
|
||||||
|
device_id: str,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the energy sensor."""
|
||||||
|
super().__init__(coordinator)
|
||||||
|
self._device_id = device_id
|
||||||
|
room = coordinator.data[device_id]
|
||||||
|
|
||||||
|
self._attr_unique_id = f"{room['homeId']}_{device_id}_energy"
|
||||||
|
self._attr_device_info = DeviceInfo(
|
||||||
|
identifiers={(DOMAIN, device_id)},
|
||||||
|
name=room["name"],
|
||||||
|
manufacturer="Adax",
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Return True if entity is available."""
|
||||||
|
return (
|
||||||
|
super().available and "energyWh" in self.coordinator.data[self._device_id]
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def native_value(self) -> int:
|
||||||
|
"""Return the native value of the sensor."""
|
||||||
|
return int(self.coordinator.data[self._device_id]["energyWh"])
|
@ -43,6 +43,7 @@ CLOUD_DEVICE_DATA: dict[str, Any] = [
|
|||||||
"temperature": 15,
|
"temperature": 15,
|
||||||
"targetTemperature": 20,
|
"targetTemperature": 20,
|
||||||
"heatingEnabled": True,
|
"heatingEnabled": True,
|
||||||
|
"energyWh": 1500,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -70,9 +71,17 @@ def mock_adax_cloud():
|
|||||||
with patch("homeassistant.components.adax.coordinator.Adax") as mock_adax:
|
with patch("homeassistant.components.adax.coordinator.Adax") as mock_adax:
|
||||||
mock_adax_class = mock_adax.return_value
|
mock_adax_class = mock_adax.return_value
|
||||||
|
|
||||||
|
mock_adax_class.fetch_rooms_info = AsyncMock()
|
||||||
|
mock_adax_class.fetch_rooms_info.return_value = CLOUD_DEVICE_DATA
|
||||||
|
|
||||||
mock_adax_class.get_rooms = AsyncMock()
|
mock_adax_class.get_rooms = AsyncMock()
|
||||||
mock_adax_class.get_rooms.return_value = CLOUD_DEVICE_DATA
|
mock_adax_class.get_rooms.return_value = CLOUD_DEVICE_DATA
|
||||||
|
|
||||||
|
mock_adax_class.fetch_energy_info = AsyncMock()
|
||||||
|
mock_adax_class.fetch_energy_info.return_value = [
|
||||||
|
{"deviceId": "1", "energyWh": 1500}
|
||||||
|
]
|
||||||
|
|
||||||
mock_adax_class.update = AsyncMock()
|
mock_adax_class.update = AsyncMock()
|
||||||
mock_adax_class.update.return_value = None
|
mock_adax_class.update.return_value = None
|
||||||
yield mock_adax_class
|
yield mock_adax_class
|
||||||
|
237
tests/components/adax/snapshots/test_sensor.ambr
Normal file
237
tests/components/adax/snapshots/test_sensor.ambr
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_fallback_to_get_rooms[sensor.room_1_energy-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.room_1_energy',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
'sensor': dict({
|
||||||
|
'suggested_display_precision': 3,
|
||||||
|
}),
|
||||||
|
'sensor.private': dict({
|
||||||
|
'suggested_unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Energy',
|
||||||
|
'platform': 'adax',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'suggested_object_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'energy',
|
||||||
|
'unique_id': '1_1_energy',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_fallback_to_get_rooms[sensor.room_1_energy-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'energy',
|
||||||
|
'friendly_name': 'Room 1 Energy',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.room_1_energy',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '0.0',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_multiple_devices_create_individual_sensors[sensor.room_1_energy-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.room_1_energy',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
'sensor': dict({
|
||||||
|
'suggested_display_precision': 3,
|
||||||
|
}),
|
||||||
|
'sensor.private': dict({
|
||||||
|
'suggested_unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Energy',
|
||||||
|
'platform': 'adax',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'suggested_object_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'energy',
|
||||||
|
'unique_id': '1_1_energy',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_multiple_devices_create_individual_sensors[sensor.room_1_energy-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'energy',
|
||||||
|
'friendly_name': 'Room 1 Energy',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.room_1_energy',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '1.5',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_multiple_devices_create_individual_sensors[sensor.room_2_energy-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.room_2_energy',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
'sensor': dict({
|
||||||
|
'suggested_display_precision': 3,
|
||||||
|
}),
|
||||||
|
'sensor.private': dict({
|
||||||
|
'suggested_unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Energy',
|
||||||
|
'platform': 'adax',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'suggested_object_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'energy',
|
||||||
|
'unique_id': '1_2_energy',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_multiple_devices_create_individual_sensors[sensor.room_2_energy-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'energy',
|
||||||
|
'friendly_name': 'Room 2 Energy',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.room_2_energy',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '2.5',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_sensor_cloud[sensor.room_1_energy-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.room_1_energy',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
'sensor': dict({
|
||||||
|
'suggested_display_precision': 3,
|
||||||
|
}),
|
||||||
|
'sensor.private': dict({
|
||||||
|
'suggested_unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Energy',
|
||||||
|
'platform': 'adax',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'suggested_object_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'energy',
|
||||||
|
'unique_id': '1_1_energy',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_sensor_cloud[sensor.room_1_energy-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'energy',
|
||||||
|
'friendly_name': 'Room 1 Energy',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.room_1_energy',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '1.5',
|
||||||
|
})
|
||||||
|
# ---
|
@ -20,7 +20,7 @@ async def test_climate_cloud(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test states of the (cloud) Climate entity."""
|
"""Test states of the (cloud) Climate entity."""
|
||||||
await setup_integration(hass, mock_cloud_config_entry)
|
await setup_integration(hass, mock_cloud_config_entry)
|
||||||
mock_adax_cloud.get_rooms.assert_called_once()
|
mock_adax_cloud.fetch_rooms_info.assert_called_once()
|
||||||
|
|
||||||
assert len(hass.states.async_entity_ids(Platform.CLIMATE)) == 1
|
assert len(hass.states.async_entity_ids(Platform.CLIMATE)) == 1
|
||||||
entity_id = hass.states.async_entity_ids(Platform.CLIMATE)[0]
|
entity_id = hass.states.async_entity_ids(Platform.CLIMATE)[0]
|
||||||
@ -37,7 +37,7 @@ async def test_climate_cloud(
|
|||||||
== CLOUD_DEVICE_DATA[0]["temperature"]
|
== CLOUD_DEVICE_DATA[0]["temperature"]
|
||||||
)
|
)
|
||||||
|
|
||||||
mock_adax_cloud.get_rooms.side_effect = Exception()
|
mock_adax_cloud.fetch_rooms_info.side_effect = Exception()
|
||||||
freezer.tick(SCAN_INTERVAL)
|
freezer.tick(SCAN_INTERVAL)
|
||||||
async_fire_time_changed(hass)
|
async_fire_time_changed(hass)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
121
tests/components/adax/test_sensor.py
Normal file
121
tests/components/adax/test_sensor.py
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
"""Test Adax sensor entity."""
|
||||||
|
|
||||||
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.const import Platform
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
|
from . import setup_integration
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry, snapshot_platform
|
||||||
|
|
||||||
|
|
||||||
|
async def test_sensor_cloud(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_adax_cloud: AsyncMock,
|
||||||
|
mock_cloud_config_entry: MockConfigEntry,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test sensor setup for cloud connection."""
|
||||||
|
with patch("homeassistant.components.adax.PLATFORMS", [Platform.SENSOR]):
|
||||||
|
await setup_integration(hass, mock_cloud_config_entry)
|
||||||
|
# Now we use fetch_rooms_info as primary method
|
||||||
|
mock_adax_cloud.fetch_rooms_info.assert_called_once()
|
||||||
|
|
||||||
|
await snapshot_platform(
|
||||||
|
hass, entity_registry, snapshot, mock_cloud_config_entry.entry_id
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_sensor_local_not_created(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_adax_local: AsyncMock,
|
||||||
|
mock_local_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test that sensors are not created for local connection."""
|
||||||
|
with patch("homeassistant.components.adax.PLATFORMS", [Platform.SENSOR]):
|
||||||
|
await setup_integration(hass, mock_local_config_entry)
|
||||||
|
|
||||||
|
# No sensor entities should be created for local connection
|
||||||
|
sensor_entities = hass.states.async_entity_ids("sensor")
|
||||||
|
adax_sensors = [e for e in sensor_entities if "adax" in e or "room" in e]
|
||||||
|
assert len(adax_sensors) == 0
|
||||||
|
|
||||||
|
|
||||||
|
async def test_multiple_devices_create_individual_sensors(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_adax_cloud: AsyncMock,
|
||||||
|
mock_cloud_config_entry: MockConfigEntry,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test that multiple devices create individual sensors."""
|
||||||
|
# Mock multiple devices for both fetch_rooms_info and get_rooms (fallback)
|
||||||
|
multiple_devices_data = [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"homeId": "1",
|
||||||
|
"name": "Room 1",
|
||||||
|
"temperature": 15,
|
||||||
|
"targetTemperature": 20,
|
||||||
|
"heatingEnabled": True,
|
||||||
|
"energyWh": 1500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"homeId": "1",
|
||||||
|
"name": "Room 2",
|
||||||
|
"temperature": 18,
|
||||||
|
"targetTemperature": 22,
|
||||||
|
"heatingEnabled": True,
|
||||||
|
"energyWh": 2500,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
mock_adax_cloud.fetch_rooms_info.return_value = multiple_devices_data
|
||||||
|
mock_adax_cloud.get_rooms.return_value = multiple_devices_data
|
||||||
|
|
||||||
|
with patch("homeassistant.components.adax.PLATFORMS", [Platform.SENSOR]):
|
||||||
|
await setup_integration(hass, mock_cloud_config_entry)
|
||||||
|
|
||||||
|
await snapshot_platform(
|
||||||
|
hass, entity_registry, snapshot, mock_cloud_config_entry.entry_id
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_fallback_to_get_rooms(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_adax_cloud: AsyncMock,
|
||||||
|
mock_cloud_config_entry: MockConfigEntry,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test fallback to get_rooms when fetch_rooms_info returns empty list."""
|
||||||
|
# Mock fetch_rooms_info to return empty list, get_rooms to return data
|
||||||
|
mock_adax_cloud.fetch_rooms_info.return_value = []
|
||||||
|
mock_adax_cloud.get_rooms.return_value = [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"homeId": "1",
|
||||||
|
"name": "Room 1",
|
||||||
|
"temperature": 15,
|
||||||
|
"targetTemperature": 20,
|
||||||
|
"heatingEnabled": True,
|
||||||
|
"energyWh": 0, # No energy data from get_rooms
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
with patch("homeassistant.components.adax.PLATFORMS", [Platform.SENSOR]):
|
||||||
|
await setup_integration(hass, mock_cloud_config_entry)
|
||||||
|
|
||||||
|
# Should call both methods
|
||||||
|
mock_adax_cloud.fetch_rooms_info.assert_called_once()
|
||||||
|
mock_adax_cloud.get_rooms.assert_called_once()
|
||||||
|
|
||||||
|
await snapshot_platform(
|
||||||
|
hass, entity_registry, snapshot, mock_cloud_config_entry.entry_id
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user