Small additions for Homee (#137000)

* fix entity set value error handling

* Translation for node_state sensor

* add entrance gate operator to covers

* fix review comments

* Update tests/components/homee/test_cover.py

* Delete Logging statement

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
Markus Adrario 2025-02-01 21:11:53 +01:00 committed by GitHub
parent ba427a1054
commit f5fd49d8cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 66 additions and 3 deletions

View File

@ -68,6 +68,7 @@ def get_device_class(node: HomeeNode) -> CoverDeviceClass | None:
"""Determine the device class a homee node based on the node profile."""
COVER_DEVICE_PROFILES = {
NodeProfile.GARAGE_DOOR_OPERATOR: CoverDeviceClass.GARAGE,
NodeProfile.ENTRANCE_GATE_OPERATOR: CoverDeviceClass.GATE,
NodeProfile.SHUTTER_POSITION_SWITCH: CoverDeviceClass.SHUTTER,
}
@ -93,6 +94,7 @@ def is_cover_node(node: HomeeNode) -> bool:
return node.profile in [
NodeProfile.ELECTRIC_MOTOR_METERING_SWITCH,
NodeProfile.ELECTRIC_MOTOR_METERING_SWITCH_WITHOUT_SLAT_POSITION,
NodeProfile.ENTRANCE_GATE_OPERATOR,
NodeProfile.GARAGE_DOOR_OPERATOR,
NodeProfile.SHUTTER_POSITION_SWITCH,
]

View File

@ -2,7 +2,9 @@
from pyHomee.const import AttributeState, AttributeType, NodeProfile, NodeState
from pyHomee.model import HomeeAttribute, HomeeNode
from websockets.exceptions import ConnectionClosed
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import Entity
@ -137,7 +139,13 @@ class HomeeNodeEntity(Entity):
async def async_set_value(self, attribute: HomeeAttribute, value: float) -> None:
"""Set an attribute value on the homee node."""
homee = self._entry.runtime_data
await homee.set_value(attribute.node_id, attribute.id, value)
try:
await homee.set_value(attribute.node_id, attribute.id, value)
except ConnectionClosed as exception:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="connection_closed",
) from exception
def _on_node_updated(self, node: HomeeNode) -> None:
self.schedule_update_ha_state()

View File

@ -177,6 +177,7 @@ SENSOR_DESCRIPTIONS: dict[AttributeType, HomeeSensorEntityDescription] = {
AttributeType.TOTAL_CURRENT: HomeeSensorEntityDescription(
key="total_current",
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
),
AttributeType.TOTAL_CURRENT_ENERGY_USE: HomeeSensorEntityDescription(
key="total_power",
@ -252,7 +253,7 @@ NODE_SENSOR_DESCRIPTIONS: tuple[HomeeNodeSensorEntityDescription, ...] = (
],
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
translation_key="node_sensor_state",
translation_key="node_state",
value_fn=lambda node: get_name_for_enum(NodeState, node.state),
),
)

View File

@ -67,7 +67,23 @@
"name": "Link quality"
},
"node_state": {
"name": "Node state"
"name": "Node state",
"state": {
"available": "Available",
"unavailable": "Unavailable",
"update_in_progress": "Update in progress",
"waiting_for_attributes": "Waiting for attributes",
"initializing": "Initializing",
"user_interaction_required": "User interaction required",
"password_required": "Password required",
"host_unavailable": "Host unavailable",
"delete_in_progress": "Delete in progress",
"cosi_connected": "Cosi connected",
"blocked": "Blocked",
"waiting_for_wakeup": "Waiting for wakeup",
"remote_node_deleted": "Remote node deleted",
"firmware_update_in_progress": "Firmware update in progress"
}
},
"operating_hours": {
"name": "Operating hours"
@ -136,5 +152,10 @@
}
}
}
},
"exceptions": {
"connection_closed": {
"message": "Could not connect to Homee while setting attribute"
}
}
}

View File

@ -2,6 +2,10 @@
from unittest.mock import MagicMock
import pytest
from websockets import frames
from websockets.exceptions import ConnectionClosed
from homeassistant.components.cover import (
ATTR_POSITION,
ATTR_TILT_POSITION,
@ -9,6 +13,7 @@ from homeassistant.components.cover import (
CoverEntityFeature,
CoverState,
)
from homeassistant.components.homee.const import DOMAIN
from homeassistant.const import (
ATTR_ENTITY_ID,
SERVICE_CLOSE_COVER,
@ -20,6 +25,7 @@ from homeassistant.const import (
SERVICE_STOP_COVER,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from . import build_mock_node, setup_integration
@ -253,3 +259,28 @@ async def test_reversed_cover(
await hass.async_block_till_done()
assert hass.states.get("cover.test_cover").state == CoverState.CLOSED
async def test_send_error(
hass: HomeAssistant,
mock_homee: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test failed set_value command."""
mock_homee.nodes = [build_mock_node("cover_without_position.json")]
await setup_integration(hass, mock_config_entry)
mock_homee.set_value.side_effect = ConnectionClosed(
rcvd=frames.Close(1002, "Protocol Error"), sent=None
)
with pytest.raises(HomeAssistantError) as exc_info:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_OPEN_COVER,
{ATTR_ENTITY_ID: "cover.test_cover"},
blocking=True,
)
assert exc_info.value.translation_domain == DOMAIN
assert exc_info.value.translation_key == "connection_closed"