forked from home-assistant/core
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Palazzetti power control (home-assistant#131833)
* Add number entity * Catch exceptions * Add test coverage * Add translation * Fix exception message * Simplify number.py * Remove dead code
- Loading branch information
Showing
6 changed files
with
206 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
"""Number platform for Palazzetti settings.""" | ||
|
||
from __future__ import annotations | ||
|
||
from pypalazzetti.exceptions import CommunicationError, ValidationError | ||
|
||
from homeassistant.components.number import NumberDeviceClass, NumberEntity | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError | ||
from homeassistant.helpers.entity_platform import AddEntitiesCallback | ||
|
||
from . import PalazzettiConfigEntry | ||
from .const import DOMAIN | ||
from .coordinator import PalazzettiDataUpdateCoordinator | ||
from .entity import PalazzettiEntity | ||
|
||
|
||
async def async_setup_entry( | ||
hass: HomeAssistant, | ||
config_entry: PalazzettiConfigEntry, | ||
async_add_entities: AddEntitiesCallback, | ||
) -> None: | ||
"""Set up Palazzetti number platform.""" | ||
async_add_entities([PalazzettiCombustionPowerEntity(config_entry.runtime_data)]) | ||
|
||
|
||
class PalazzettiCombustionPowerEntity(PalazzettiEntity, NumberEntity): | ||
"""Representation of Palazzetti number entity for Combustion power.""" | ||
|
||
_attr_translation_key = "combustion_power" | ||
_attr_device_class = NumberDeviceClass.POWER_FACTOR | ||
_attr_native_min_value = 1 | ||
_attr_native_max_value = 5 | ||
_attr_native_step = 1 | ||
|
||
def __init__( | ||
self, | ||
coordinator: PalazzettiDataUpdateCoordinator, | ||
) -> None: | ||
"""Initialize the Palazzetti number entity.""" | ||
super().__init__(coordinator) | ||
self._attr_unique_id = f"{coordinator.config_entry.unique_id}-combustion_power" | ||
|
||
@property | ||
def native_value(self) -> float: | ||
"""Return the state of the setting entity.""" | ||
return self.coordinator.client.power_mode | ||
|
||
async def async_set_native_value(self, value: float) -> None: | ||
"""Update the setting.""" | ||
try: | ||
await self.coordinator.client.set_power_mode(int(value)) | ||
except CommunicationError as err: | ||
raise HomeAssistantError( | ||
translation_domain=DOMAIN, translation_key="cannot_connect" | ||
) from err | ||
except ValidationError as err: | ||
raise ServiceValidationError( | ||
translation_domain=DOMAIN, | ||
translation_key="invalid_combustion_power", | ||
translation_placeholders={ | ||
"value": str(value), | ||
}, | ||
) from err | ||
|
||
await self.coordinator.async_request_refresh() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# serializer version: 1 | ||
# name: test_all_entities[number.stove_combustion_power-entry] | ||
EntityRegistryEntrySnapshot({ | ||
'aliases': set({ | ||
}), | ||
'area_id': None, | ||
'capabilities': dict({ | ||
'max': 5, | ||
'min': 1, | ||
'mode': <NumberMode.AUTO: 'auto'>, | ||
'step': 1, | ||
}), | ||
'config_entry_id': <ANY>, | ||
'device_class': None, | ||
'device_id': <ANY>, | ||
'disabled_by': None, | ||
'domain': 'number', | ||
'entity_category': None, | ||
'entity_id': 'number.stove_combustion_power', | ||
'has_entity_name': True, | ||
'hidden_by': None, | ||
'icon': None, | ||
'id': <ANY>, | ||
'labels': set({ | ||
}), | ||
'name': None, | ||
'options': dict({ | ||
}), | ||
'original_device_class': <NumberDeviceClass.POWER_FACTOR: 'power_factor'>, | ||
'original_icon': None, | ||
'original_name': 'Combustion power', | ||
'platform': 'palazzetti', | ||
'previous_unique_id': None, | ||
'supported_features': 0, | ||
'translation_key': 'combustion_power', | ||
'unique_id': '11:22:33:44:55:66-combustion_power', | ||
'unit_of_measurement': None, | ||
}) | ||
# --- | ||
# name: test_all_entities[number.stove_combustion_power-state] | ||
StateSnapshot({ | ||
'attributes': ReadOnlyDict({ | ||
'device_class': 'power_factor', | ||
'friendly_name': 'Stove Combustion power', | ||
'max': 5, | ||
'min': 1, | ||
'mode': <NumberMode.AUTO: 'auto'>, | ||
'step': 1, | ||
}), | ||
'context': <ANY>, | ||
'entity_id': 'number.stove_combustion_power', | ||
'last_changed': <ANY>, | ||
'last_reported': <ANY>, | ||
'last_updated': <ANY>, | ||
'state': '3', | ||
}) | ||
# --- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
"""Tests for the Palazzetti sensor platform.""" | ||
|
||
from unittest.mock import AsyncMock, patch | ||
|
||
from pypalazzetti.exceptions import CommunicationError, ValidationError | ||
import pytest | ||
from syrupy import SnapshotAssertion | ||
|
||
from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN, SERVICE_SET_VALUE | ||
from homeassistant.const import ATTR_ENTITY_ID, Platform | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError | ||
from homeassistant.helpers import entity_registry as er | ||
|
||
from . import setup_integration | ||
|
||
from tests.common import MockConfigEntry, snapshot_platform | ||
|
||
ENTITY_ID = "number.stove_combustion_power" | ||
|
||
|
||
async def test_all_entities( | ||
hass: HomeAssistant, | ||
snapshot: SnapshotAssertion, | ||
mock_palazzetti_client: AsyncMock, | ||
mock_config_entry: MockConfigEntry, | ||
entity_registry: er.EntityRegistry, | ||
) -> None: | ||
"""Test all entities.""" | ||
with patch("homeassistant.components.palazzetti.PLATFORMS", [Platform.NUMBER]): | ||
await setup_integration(hass, mock_config_entry) | ||
|
||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id) | ||
|
||
|
||
async def test_async_set_data( | ||
hass: HomeAssistant, | ||
mock_palazzetti_client: AsyncMock, | ||
mock_config_entry: MockConfigEntry, | ||
) -> None: | ||
"""Test setting number data via service call.""" | ||
await setup_integration(hass, mock_config_entry) | ||
|
||
# Set value: Success | ||
await hass.services.async_call( | ||
NUMBER_DOMAIN, | ||
SERVICE_SET_VALUE, | ||
{ATTR_ENTITY_ID: ENTITY_ID, "value": 1}, | ||
blocking=True, | ||
) | ||
mock_palazzetti_client.set_power_mode.assert_called_once_with(1) | ||
mock_palazzetti_client.set_on.reset_mock() | ||
|
||
# Set value: Error | ||
mock_palazzetti_client.set_power_mode.side_effect = CommunicationError() | ||
with pytest.raises(HomeAssistantError): | ||
await hass.services.async_call( | ||
NUMBER_DOMAIN, | ||
SERVICE_SET_VALUE, | ||
{ATTR_ENTITY_ID: ENTITY_ID, "value": 1}, | ||
blocking=True, | ||
) | ||
mock_palazzetti_client.set_on.reset_mock() | ||
|
||
mock_palazzetti_client.set_power_mode.side_effect = ValidationError() | ||
with pytest.raises(ServiceValidationError): | ||
await hass.services.async_call( | ||
NUMBER_DOMAIN, | ||
SERVICE_SET_VALUE, | ||
{ATTR_ENTITY_ID: ENTITY_ID, "value": 1}, | ||
blocking=True, | ||
) |