mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 16:57:10 +00:00
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:
parent
ba427a1054
commit
f5fd49d8cb
@ -68,6 +68,7 @@ def get_device_class(node: HomeeNode) -> CoverDeviceClass | None:
|
|||||||
"""Determine the device class a homee node based on the node profile."""
|
"""Determine the device class a homee node based on the node profile."""
|
||||||
COVER_DEVICE_PROFILES = {
|
COVER_DEVICE_PROFILES = {
|
||||||
NodeProfile.GARAGE_DOOR_OPERATOR: CoverDeviceClass.GARAGE,
|
NodeProfile.GARAGE_DOOR_OPERATOR: CoverDeviceClass.GARAGE,
|
||||||
|
NodeProfile.ENTRANCE_GATE_OPERATOR: CoverDeviceClass.GATE,
|
||||||
NodeProfile.SHUTTER_POSITION_SWITCH: CoverDeviceClass.SHUTTER,
|
NodeProfile.SHUTTER_POSITION_SWITCH: CoverDeviceClass.SHUTTER,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +94,7 @@ def is_cover_node(node: HomeeNode) -> bool:
|
|||||||
return node.profile in [
|
return node.profile in [
|
||||||
NodeProfile.ELECTRIC_MOTOR_METERING_SWITCH,
|
NodeProfile.ELECTRIC_MOTOR_METERING_SWITCH,
|
||||||
NodeProfile.ELECTRIC_MOTOR_METERING_SWITCH_WITHOUT_SLAT_POSITION,
|
NodeProfile.ELECTRIC_MOTOR_METERING_SWITCH_WITHOUT_SLAT_POSITION,
|
||||||
|
NodeProfile.ENTRANCE_GATE_OPERATOR,
|
||||||
NodeProfile.GARAGE_DOOR_OPERATOR,
|
NodeProfile.GARAGE_DOOR_OPERATOR,
|
||||||
NodeProfile.SHUTTER_POSITION_SWITCH,
|
NodeProfile.SHUTTER_POSITION_SWITCH,
|
||||||
]
|
]
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
from pyHomee.const import AttributeState, AttributeType, NodeProfile, NodeState
|
from pyHomee.const import AttributeState, AttributeType, NodeProfile, NodeState
|
||||||
from pyHomee.model import HomeeAttribute, HomeeNode
|
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.device_registry import DeviceInfo
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
@ -137,7 +139,13 @@ class HomeeNodeEntity(Entity):
|
|||||||
async def async_set_value(self, attribute: HomeeAttribute, value: float) -> None:
|
async def async_set_value(self, attribute: HomeeAttribute, value: float) -> None:
|
||||||
"""Set an attribute value on the homee node."""
|
"""Set an attribute value on the homee node."""
|
||||||
homee = self._entry.runtime_data
|
homee = self._entry.runtime_data
|
||||||
|
try:
|
||||||
await homee.set_value(attribute.node_id, attribute.id, value)
|
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:
|
def _on_node_updated(self, node: HomeeNode) -> None:
|
||||||
self.schedule_update_ha_state()
|
self.schedule_update_ha_state()
|
||||||
|
@ -177,6 +177,7 @@ SENSOR_DESCRIPTIONS: dict[AttributeType, HomeeSensorEntityDescription] = {
|
|||||||
AttributeType.TOTAL_CURRENT: HomeeSensorEntityDescription(
|
AttributeType.TOTAL_CURRENT: HomeeSensorEntityDescription(
|
||||||
key="total_current",
|
key="total_current",
|
||||||
device_class=SensorDeviceClass.CURRENT,
|
device_class=SensorDeviceClass.CURRENT,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AttributeType.TOTAL_CURRENT_ENERGY_USE: HomeeSensorEntityDescription(
|
AttributeType.TOTAL_CURRENT_ENERGY_USE: HomeeSensorEntityDescription(
|
||||||
key="total_power",
|
key="total_power",
|
||||||
@ -252,7 +253,7 @@ NODE_SENSOR_DESCRIPTIONS: tuple[HomeeNodeSensorEntityDescription, ...] = (
|
|||||||
],
|
],
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
entity_registry_enabled_default=False,
|
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),
|
value_fn=lambda node: get_name_for_enum(NodeState, node.state),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -67,7 +67,23 @@
|
|||||||
"name": "Link quality"
|
"name": "Link quality"
|
||||||
},
|
},
|
||||||
"node_state": {
|
"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": {
|
"operating_hours": {
|
||||||
"name": "Operating hours"
|
"name": "Operating hours"
|
||||||
@ -136,5 +152,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"exceptions": {
|
||||||
|
"connection_closed": {
|
||||||
|
"message": "Could not connect to Homee while setting attribute"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from websockets import frames
|
||||||
|
from websockets.exceptions import ConnectionClosed
|
||||||
|
|
||||||
from homeassistant.components.cover import (
|
from homeassistant.components.cover import (
|
||||||
ATTR_POSITION,
|
ATTR_POSITION,
|
||||||
ATTR_TILT_POSITION,
|
ATTR_TILT_POSITION,
|
||||||
@ -9,6 +13,7 @@ from homeassistant.components.cover import (
|
|||||||
CoverEntityFeature,
|
CoverEntityFeature,
|
||||||
CoverState,
|
CoverState,
|
||||||
)
|
)
|
||||||
|
from homeassistant.components.homee.const import DOMAIN
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
SERVICE_CLOSE_COVER,
|
SERVICE_CLOSE_COVER,
|
||||||
@ -20,6 +25,7 @@ from homeassistant.const import (
|
|||||||
SERVICE_STOP_COVER,
|
SERVICE_STOP_COVER,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
|
||||||
from . import build_mock_node, setup_integration
|
from . import build_mock_node, setup_integration
|
||||||
|
|
||||||
@ -253,3 +259,28 @@ async def test_reversed_cover(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert hass.states.get("cover.test_cover").state == CoverState.CLOSED
|
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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user