mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add bond cover assumed state and local polling (#37666)
* Declare Bond covers as having assumed state, setup local polling for state updates * Declare Bond covers as having assumed state, setup local polling for state updates (apply feedback from PR review) * Declare Bond covers as having assumed state, setup local polling for state updates (apply feedback from PR review) * Declare Bond covers as having assumed state, setup local polling for state updates (apply feedback from PR review)
This commit is contained in:
parent
ef254a1c3d
commit
69a8ba2af8
@ -1,5 +1,4 @@
|
|||||||
"""Support for Bond covers."""
|
"""Support for Bond covers."""
|
||||||
import logging
|
|
||||||
from typing import Any, Callable, Dict, List, Optional
|
from typing import Any, Callable, Dict, List, Optional
|
||||||
|
|
||||||
from bond import BOND_DEVICE_TYPE_MOTORIZED_SHADES, Bond
|
from bond import BOND_DEVICE_TYPE_MOTORIZED_SHADES, Bond
|
||||||
@ -13,13 +12,11 @@ from homeassistant.helpers.entity import Entity
|
|||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .utils import BondDevice, get_bond_devices
|
from .utils import BondDevice, get_bond_devices
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: ConfigEntry,
|
||||||
async_add_entities: Callable[[List[Entity]], None],
|
async_add_entities: Callable[[List[Entity], bool], None],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up Bond cover devices."""
|
"""Set up Bond cover devices."""
|
||||||
bond: Bond = hass.data[DOMAIN][entry.entry_id]
|
bond: Bond = hass.data[DOMAIN][entry.entry_id]
|
||||||
@ -32,7 +29,7 @@ async def async_setup_entry(
|
|||||||
if device.type == BOND_DEVICE_TYPE_MOTORIZED_SHADES
|
if device.type == BOND_DEVICE_TYPE_MOTORIZED_SHADES
|
||||||
]
|
]
|
||||||
|
|
||||||
async_add_entities(covers)
|
async_add_entities(covers, True)
|
||||||
|
|
||||||
|
|
||||||
class BondCover(CoverEntity):
|
class BondCover(CoverEntity):
|
||||||
@ -42,6 +39,7 @@ class BondCover(CoverEntity):
|
|||||||
"""Create HA entity representing Bond cover."""
|
"""Create HA entity representing Bond cover."""
|
||||||
self._bond = bond
|
self._bond = bond
|
||||||
self._device = device
|
self._device = device
|
||||||
|
self._closed: Optional[bool] = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_class(self) -> Optional[str]:
|
def device_class(self) -> Optional[str]:
|
||||||
@ -63,10 +61,21 @@ class BondCover(CoverEntity):
|
|||||||
"""Get a an HA device representing this cover."""
|
"""Get a an HA device representing this cover."""
|
||||||
return {ATTR_NAME: self.name, "identifiers": {(DOMAIN, self._device.device_id)}}
|
return {ATTR_NAME: self.name, "identifiers": {(DOMAIN, self._device.device_id)}}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def assumed_state(self) -> bool:
|
||||||
|
"""Let HA know this entity relies on an assumed state tracked by Bond."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
"""Fetch assumed state of the cover from the hub using API."""
|
||||||
|
state: dict = self._bond.getDeviceState(self._device.device_id)
|
||||||
|
cover_open = state.get("open")
|
||||||
|
self._closed = True if cover_open == 0 else False if cover_open == 1 else None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self):
|
def is_closed(self):
|
||||||
"""Return if the cover is closed or not."""
|
"""Return if the cover is closed or not."""
|
||||||
return None
|
return self._closed
|
||||||
|
|
||||||
def open_cover(self, **kwargs: Any) -> None:
|
def open_cover(self, **kwargs: Any) -> None:
|
||||||
"""Open the cover."""
|
"""Open the cover."""
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
"""Tests for the Bond cover device."""
|
"""Tests for the Bond cover device."""
|
||||||
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from bond import BOND_DEVICE_TYPE_MOTORIZED_SHADES
|
from bond import BOND_DEVICE_TYPE_MOTORIZED_SHADES
|
||||||
|
|
||||||
|
from homeassistant import core
|
||||||
from homeassistant.components.cover import DOMAIN as COVER_DOMAIN
|
from homeassistant.components.cover import DOMAIN as COVER_DOMAIN
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
@ -11,35 +13,45 @@ from homeassistant.const import (
|
|||||||
SERVICE_STOP_COVER,
|
SERVICE_STOP_COVER,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.entity_registry import EntityRegistry
|
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||||
|
from homeassistant.util import utcnow
|
||||||
|
|
||||||
from .common import setup_platform
|
from .common import setup_platform
|
||||||
|
|
||||||
from tests.async_mock import patch
|
from tests.async_mock import patch
|
||||||
|
from tests.common import async_fire_time_changed
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
TEST_DEVICE_IDS = ["device-1"]
|
TEST_DEVICE_IDS = ["device-1"]
|
||||||
TEST_DEVICE = {"name": "name-1", "type": BOND_DEVICE_TYPE_MOTORIZED_SHADES}
|
TEST_COVER_DEVICE = {"name": "name-1", "type": BOND_DEVICE_TYPE_MOTORIZED_SHADES}
|
||||||
|
|
||||||
|
|
||||||
async def test_entity_registry(hass):
|
async def test_entity_registry(hass: core.HomeAssistant):
|
||||||
"""Tests that the devices are registered in the entity registry."""
|
"""Tests that the devices are registered in the entity registry."""
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.bond.Bond.getDeviceIds", return_value=TEST_DEVICE_IDS
|
"homeassistant.components.bond.Bond.getDeviceIds", return_value=TEST_DEVICE_IDS
|
||||||
), patch("homeassistant.components.bond.Bond.getDevice", return_value=TEST_DEVICE):
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDevice", return_value=TEST_COVER_DEVICE
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDeviceState", return_value={}
|
||||||
|
):
|
||||||
await setup_platform(hass, COVER_DOMAIN)
|
await setup_platform(hass, COVER_DOMAIN)
|
||||||
|
|
||||||
registry: EntityRegistry = await hass.helpers.entity_registry.async_get_registry()
|
registry: EntityRegistry = await hass.helpers.entity_registry.async_get_registry()
|
||||||
assert [key for key in registry.entities.keys()] == ["cover.name_1"]
|
assert [key for key in registry.entities.keys()] == ["cover.name_1"]
|
||||||
|
|
||||||
|
|
||||||
async def test_open_cover(hass):
|
async def test_open_cover(hass: core.HomeAssistant):
|
||||||
"""Tests that open cover command delegates to API."""
|
"""Tests that open cover command delegates to API."""
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.bond.Bond.getDeviceIds", return_value=TEST_DEVICE_IDS
|
"homeassistant.components.bond.Bond.getDeviceIds", return_value=TEST_DEVICE_IDS
|
||||||
), patch("homeassistant.components.bond.Bond.getDevice", return_value=TEST_DEVICE):
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDevice", return_value=TEST_COVER_DEVICE
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDeviceState", return_value={}
|
||||||
|
):
|
||||||
await setup_platform(hass, COVER_DOMAIN)
|
await setup_platform(hass, COVER_DOMAIN)
|
||||||
|
|
||||||
with patch("homeassistant.components.bond.Bond.open") as mock_open:
|
with patch("homeassistant.components.bond.Bond.open") as mock_open:
|
||||||
@ -53,12 +65,16 @@ async def test_open_cover(hass):
|
|||||||
mock_open.assert_called_once()
|
mock_open.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
async def test_close_cover(hass):
|
async def test_close_cover(hass: core.HomeAssistant):
|
||||||
"""Tests that close cover command delegates to API."""
|
"""Tests that close cover command delegates to API."""
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.bond.Bond.getDeviceIds", return_value=TEST_DEVICE_IDS
|
"homeassistant.components.bond.Bond.getDeviceIds", return_value=TEST_DEVICE_IDS
|
||||||
), patch("homeassistant.components.bond.Bond.getDevice", return_value=TEST_DEVICE):
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDevice", return_value=TEST_COVER_DEVICE
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDeviceState", return_value={}
|
||||||
|
):
|
||||||
await setup_platform(hass, COVER_DOMAIN)
|
await setup_platform(hass, COVER_DOMAIN)
|
||||||
|
|
||||||
with patch("homeassistant.components.bond.Bond.close") as mock_close:
|
with patch("homeassistant.components.bond.Bond.close") as mock_close:
|
||||||
@ -72,12 +88,16 @@ async def test_close_cover(hass):
|
|||||||
mock_close.assert_called_once()
|
mock_close.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
async def test_stop_cover(hass):
|
async def test_stop_cover(hass: core.HomeAssistant):
|
||||||
"""Tests that stop cover command delegates to API."""
|
"""Tests that stop cover command delegates to API."""
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.bond.Bond.getDeviceIds", return_value=TEST_DEVICE_IDS
|
"homeassistant.components.bond.Bond.getDeviceIds", return_value=TEST_DEVICE_IDS
|
||||||
), patch("homeassistant.components.bond.Bond.getDevice", return_value=TEST_DEVICE):
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDevice", return_value=TEST_COVER_DEVICE
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDeviceState", return_value={}
|
||||||
|
):
|
||||||
await setup_platform(hass, COVER_DOMAIN)
|
await setup_platform(hass, COVER_DOMAIN)
|
||||||
|
|
||||||
with patch("homeassistant.components.bond.Bond.hold") as mock_hold:
|
with patch("homeassistant.components.bond.Bond.hold") as mock_hold:
|
||||||
@ -89,3 +109,45 @@ async def test_stop_cover(hass):
|
|||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_hold.assert_called_once()
|
mock_hold.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_update_reports_open_cover(hass: core.HomeAssistant):
|
||||||
|
"""Tests that update command sets correct state when Bond API reports cover is open."""
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDeviceIds", return_value=TEST_DEVICE_IDS
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDevice", return_value=TEST_COVER_DEVICE
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDeviceState", return_value={}
|
||||||
|
):
|
||||||
|
await setup_platform(hass, COVER_DOMAIN)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDeviceState", return_value={"open": 1}
|
||||||
|
):
|
||||||
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=30))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert hass.states.get("cover.name_1").state == "open"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_update_reports_closed_cover(hass: core.HomeAssistant):
|
||||||
|
"""Tests that update command sets correct state when Bond API reports cover is closed."""
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDeviceIds", return_value=TEST_DEVICE_IDS
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDevice", return_value=TEST_COVER_DEVICE
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDeviceState", return_value={}
|
||||||
|
):
|
||||||
|
await setup_platform(hass, COVER_DOMAIN)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.bond.Bond.getDeviceState", return_value={"open": 0}
|
||||||
|
):
|
||||||
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=30))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert hass.states.get("cover.name_1").state == "closed"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user