Refactor bond integration to be completely async (#38066)
This commit is contained in:
parent
15fe727f2c
commit
3480fb6996
16 changed files with 251 additions and 259 deletions
|
@ -1,7 +1,7 @@
|
||||||
"""The Bond integration."""
|
"""The Bond integration."""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from bond import Bond
|
from bond_api import Bond
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST
|
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST
|
||||||
|
@ -25,9 +25,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
host = entry.data[CONF_HOST]
|
host = entry.data[CONF_HOST]
|
||||||
token = entry.data[CONF_ACCESS_TOKEN]
|
token = entry.data[CONF_ACCESS_TOKEN]
|
||||||
|
|
||||||
bond = Bond(bondIp=host, bondToken=token)
|
bond = Bond(host=host, token=token)
|
||||||
hub = BondHub(bond)
|
hub = BondHub(bond)
|
||||||
await hass.async_add_executor_job(hub.setup)
|
await hub.setup()
|
||||||
hass.data[DOMAIN][entry.entry_id] = hub
|
hass.data[DOMAIN][entry.entry_id] = hub
|
||||||
|
|
||||||
device_registry = await dr.async_get_registry(hass)
|
device_registry = await dr.async_get_registry(hass)
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
"""Config flow for Bond integration."""
|
"""Config flow for Bond integration."""
|
||||||
from json import JSONDecodeError
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from bond import Bond
|
from aiohttp import ClientConnectionError, ClientResponseError
|
||||||
from requests.exceptions import ConnectionError as RequestConnectionError
|
from bond_api import Bond
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries, core, exceptions
|
from homeassistant import config_entries, exceptions
|
||||||
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST
|
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST
|
||||||
|
|
||||||
from .const import DOMAIN # pylint:disable=unused-import
|
from .const import DOMAIN # pylint:disable=unused-import
|
||||||
|
@ -18,24 +17,20 @@ DATA_SCHEMA = vol.Schema(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def validate_input(hass: core.HomeAssistant, data):
|
async def validate_input(data):
|
||||||
"""Validate the user input allows us to connect."""
|
"""Validate the user input allows us to connect."""
|
||||||
|
|
||||||
def authenticate(bond_hub: Bond) -> bool:
|
try:
|
||||||
try:
|
bond = Bond(data[CONF_HOST], data[CONF_ACCESS_TOKEN])
|
||||||
bond_hub.getDeviceIds()
|
await bond.devices()
|
||||||
return True
|
except ClientConnectionError:
|
||||||
except RequestConnectionError:
|
raise CannotConnect
|
||||||
raise CannotConnect
|
except ClientResponseError as error:
|
||||||
except JSONDecodeError:
|
if error.status == 401:
|
||||||
return False
|
raise InvalidAuth
|
||||||
|
raise
|
||||||
|
|
||||||
bond = Bond(data[CONF_HOST], data[CONF_ACCESS_TOKEN])
|
# Return info to be stored in the config entry.
|
||||||
|
|
||||||
if not await hass.async_add_executor_job(authenticate, bond):
|
|
||||||
raise InvalidAuth
|
|
||||||
|
|
||||||
# Return info that you want to store in the config entry.
|
|
||||||
return {"title": data[CONF_HOST]}
|
return {"title": data[CONF_HOST]}
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,7 +45,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
errors = {}
|
errors = {}
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
try:
|
try:
|
||||||
info = await validate_input(self.hass, user_input)
|
info = await validate_input(user_input)
|
||||||
except CannotConnect:
|
except CannotConnect:
|
||||||
errors["base"] = "cannot_connect"
|
errors["base"] = "cannot_connect"
|
||||||
except InvalidAuth:
|
except InvalidAuth:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""Support for Bond covers."""
|
"""Support for Bond covers."""
|
||||||
from typing import Any, Callable, List, Optional
|
from typing import Any, Callable, List, Optional
|
||||||
|
|
||||||
from bond import DeviceTypes
|
from bond_api import Action, DeviceType
|
||||||
|
|
||||||
from homeassistant.components.cover import DEVICE_CLASS_SHADE, CoverEntity
|
from homeassistant.components.cover import DEVICE_CLASS_SHADE, CoverEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
@ -24,7 +24,7 @@ async def async_setup_entry(
|
||||||
covers = [
|
covers = [
|
||||||
BondCover(hub, device)
|
BondCover(hub, device)
|
||||||
for device in hub.devices
|
for device in hub.devices
|
||||||
if device.type == DeviceTypes.MOTORIZED_SHADES
|
if device.type == DeviceType.MOTORIZED_SHADES
|
||||||
]
|
]
|
||||||
|
|
||||||
async_add_entities(covers, True)
|
async_add_entities(covers, True)
|
||||||
|
@ -44,9 +44,9 @@ class BondCover(BondEntity, CoverEntity):
|
||||||
"""Get device class."""
|
"""Get device class."""
|
||||||
return DEVICE_CLASS_SHADE
|
return DEVICE_CLASS_SHADE
|
||||||
|
|
||||||
def update(self):
|
async def async_update(self):
|
||||||
"""Fetch assumed state of the cover from the hub using API."""
|
"""Fetch assumed state of the cover from the hub using API."""
|
||||||
state: dict = self._hub.bond.getDeviceState(self._device.device_id)
|
state: dict = await self._hub.bond.device_state(self._device.device_id)
|
||||||
cover_open = state.get("open")
|
cover_open = state.get("open")
|
||||||
self._closed = True if cover_open == 0 else False if cover_open == 1 else None
|
self._closed = True if cover_open == 0 else False if cover_open == 1 else None
|
||||||
|
|
||||||
|
@ -55,14 +55,14 @@ class BondCover(BondEntity, CoverEntity):
|
||||||
"""Return if the cover is closed or not."""
|
"""Return if the cover is closed or not."""
|
||||||
return self._closed
|
return self._closed
|
||||||
|
|
||||||
def open_cover(self, **kwargs: Any) -> None:
|
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||||
"""Open the cover."""
|
"""Open the cover."""
|
||||||
self._hub.bond.open(self._device.device_id)
|
await self._hub.bond.action(self._device.device_id, Action.open())
|
||||||
|
|
||||||
def close_cover(self, **kwargs: Any) -> None:
|
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||||
"""Close cover."""
|
"""Close cover."""
|
||||||
self._hub.bond.close(self._device.device_id)
|
await self._hub.bond.action(self._device.device_id, Action.close())
|
||||||
|
|
||||||
def stop_cover(self, **kwargs):
|
async def async_stop_cover(self, **kwargs):
|
||||||
"""Hold cover."""
|
"""Hold cover."""
|
||||||
self._hub.bond.hold(self._device.device_id)
|
await self._hub.bond.action(self._device.device_id, Action.hold())
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import math
|
import math
|
||||||
from typing import Any, Callable, List, Optional
|
from typing import Any, Callable, List, Optional
|
||||||
|
|
||||||
from bond import DeviceTypes, Directions
|
from bond_api import Action, DeviceType, Direction
|
||||||
|
|
||||||
from homeassistant.components.fan import (
|
from homeassistant.components.fan import (
|
||||||
DIRECTION_FORWARD,
|
DIRECTION_FORWARD,
|
||||||
|
@ -33,9 +33,7 @@ async def async_setup_entry(
|
||||||
hub: BondHub = hass.data[DOMAIN][entry.entry_id]
|
hub: BondHub = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
fans = [
|
fans = [
|
||||||
BondFan(hub, device)
|
BondFan(hub, device) for device in hub.devices if DeviceType.is_fan(device.type)
|
||||||
for device in hub.devices
|
|
||||||
if device.type == DeviceTypes.CEILING_FAN
|
|
||||||
]
|
]
|
||||||
|
|
||||||
async_add_entities(fans, True)
|
async_add_entities(fans, True)
|
||||||
|
@ -85,21 +83,21 @@ class BondFan(BondEntity, FanEntity):
|
||||||
def current_direction(self) -> Optional[str]:
|
def current_direction(self) -> Optional[str]:
|
||||||
"""Return fan rotation direction."""
|
"""Return fan rotation direction."""
|
||||||
direction = None
|
direction = None
|
||||||
if self._direction == Directions.FORWARD:
|
if self._direction == Direction.FORWARD:
|
||||||
direction = DIRECTION_FORWARD
|
direction = DIRECTION_FORWARD
|
||||||
elif self._direction == Directions.REVERSE:
|
elif self._direction == Direction.REVERSE:
|
||||||
direction = DIRECTION_REVERSE
|
direction = DIRECTION_REVERSE
|
||||||
|
|
||||||
return direction
|
return direction
|
||||||
|
|
||||||
def update(self):
|
async def async_update(self):
|
||||||
"""Fetch assumed state of the fan from the hub using API."""
|
"""Fetch assumed state of the fan from the hub using API."""
|
||||||
state: dict = self._hub.bond.getDeviceState(self._device.device_id)
|
state: dict = await self._hub.bond.device_state(self._device.device_id)
|
||||||
self._power = state.get("power")
|
self._power = state.get("power")
|
||||||
self._speed = state.get("speed")
|
self._speed = state.get("speed")
|
||||||
self._direction = state.get("direction")
|
self._direction = state.get("direction")
|
||||||
|
|
||||||
def set_speed(self, speed: str) -> None:
|
async def async_set_speed(self, speed: str) -> None:
|
||||||
"""Set the desired speed for the fan."""
|
"""Set the desired speed for the fan."""
|
||||||
max_speed = self._device.props.get("max_speed", 3)
|
max_speed = self._device.props.get("max_speed", 3)
|
||||||
if speed == SPEED_LOW:
|
if speed == SPEED_LOW:
|
||||||
|
@ -108,21 +106,27 @@ class BondFan(BondEntity, FanEntity):
|
||||||
bond_speed = max_speed
|
bond_speed = max_speed
|
||||||
else:
|
else:
|
||||||
bond_speed = math.ceil(max_speed / 2)
|
bond_speed = math.ceil(max_speed / 2)
|
||||||
self._hub.bond.setSpeed(self._device.device_id, speed=bond_speed)
|
|
||||||
|
|
||||||
def turn_on(self, speed: Optional[str] = None, **kwargs) -> None:
|
await self._hub.bond.action(
|
||||||
|
self._device.device_id, Action.set_speed(bond_speed)
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_turn_on(self, speed: Optional[str] = None, **kwargs) -> None:
|
||||||
"""Turn on the fan."""
|
"""Turn on the fan."""
|
||||||
if speed is not None:
|
if speed is not None:
|
||||||
self.set_speed(speed)
|
await self.async_set_speed(speed)
|
||||||
self._hub.bond.turnOn(self._device.device_id)
|
else:
|
||||||
|
await self._hub.bond.action(self._device.device_id, Action.turn_on())
|
||||||
|
|
||||||
def turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the fan off."""
|
"""Turn the fan off."""
|
||||||
self._hub.bond.turnOff(self._device.device_id)
|
await self._hub.bond.action(self._device.device_id, Action.turn_off())
|
||||||
|
|
||||||
def set_direction(self, direction: str) -> None:
|
async def async_set_direction(self, direction: str):
|
||||||
"""Set fan rotation direction."""
|
"""Set fan rotation direction."""
|
||||||
bond_direction = (
|
bond_direction = (
|
||||||
Directions.REVERSE if direction == DIRECTION_REVERSE else Directions.FORWARD
|
Direction.REVERSE if direction == DIRECTION_REVERSE else Direction.FORWARD
|
||||||
|
)
|
||||||
|
await self._hub.bond.action(
|
||||||
|
self._device.device_id, Action.set_direction(bond_direction)
|
||||||
)
|
)
|
||||||
self._hub.bond.setDirection(self._device.device_id, bond_direction)
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""Support for Bond lights."""
|
"""Support for Bond lights."""
|
||||||
from typing import Any, Callable, List, Optional
|
from typing import Any, Callable, List, Optional
|
||||||
|
|
||||||
from bond import DeviceTypes
|
from bond_api import Action, DeviceType
|
||||||
|
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS,
|
ATTR_BRIGHTNESS,
|
||||||
|
@ -29,13 +29,13 @@ async def async_setup_entry(
|
||||||
lights: List[Entity] = [
|
lights: List[Entity] = [
|
||||||
BondLight(hub, device)
|
BondLight(hub, device)
|
||||||
for device in hub.devices
|
for device in hub.devices
|
||||||
if device.type == DeviceTypes.CEILING_FAN and device.supports_light()
|
if DeviceType.is_fan(device.type) and device.supports_light()
|
||||||
]
|
]
|
||||||
|
|
||||||
fireplaces: List[Entity] = [
|
fireplaces: List[Entity] = [
|
||||||
BondFireplace(hub, device)
|
BondFireplace(hub, device)
|
||||||
for device in hub.devices
|
for device in hub.devices
|
||||||
if device.type == DeviceTypes.FIREPLACE
|
if DeviceType.is_fireplace(device.type)
|
||||||
]
|
]
|
||||||
|
|
||||||
async_add_entities(lights + fireplaces, True)
|
async_add_entities(lights + fireplaces, True)
|
||||||
|
@ -55,18 +55,18 @@ class BondLight(BondEntity, LightEntity):
|
||||||
"""Return if light is currently on."""
|
"""Return if light is currently on."""
|
||||||
return self._light == 1
|
return self._light == 1
|
||||||
|
|
||||||
def update(self):
|
async def async_update(self):
|
||||||
"""Fetch assumed state of the light from the hub using API."""
|
"""Fetch assumed state of the light from the hub using API."""
|
||||||
state: dict = self._hub.bond.getDeviceState(self._device.device_id)
|
state: dict = await self._hub.bond.device_state(self._device.device_id)
|
||||||
self._light = state.get("light")
|
self._light = state.get("light")
|
||||||
|
|
||||||
def turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn on the light."""
|
"""Turn on the light."""
|
||||||
self._hub.bond.turnLightOn(self._device.device_id)
|
await self._hub.bond.action(self._device.device_id, Action.turn_light_on())
|
||||||
|
|
||||||
def turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn off the light."""
|
"""Turn off the light."""
|
||||||
self._hub.bond.turnLightOff(self._device.device_id)
|
await self._hub.bond.action(self._device.device_id, Action.turn_light_off())
|
||||||
|
|
||||||
|
|
||||||
class BondFireplace(BondEntity, LightEntity):
|
class BondFireplace(BondEntity, LightEntity):
|
||||||
|
@ -90,18 +90,18 @@ class BondFireplace(BondEntity, LightEntity):
|
||||||
"""Return True if power is on."""
|
"""Return True if power is on."""
|
||||||
return self._power == 1
|
return self._power == 1
|
||||||
|
|
||||||
def turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the fireplace on."""
|
"""Turn the fireplace on."""
|
||||||
self._hub.bond.turnOn(self._device.device_id)
|
|
||||||
|
|
||||||
brightness = kwargs.get(ATTR_BRIGHTNESS)
|
brightness = kwargs.get(ATTR_BRIGHTNESS)
|
||||||
if brightness:
|
if brightness:
|
||||||
flame = round((brightness * 100) / 255)
|
flame = round((brightness * 100) / 255)
|
||||||
self._hub.bond.setFlame(self._device.device_id, flame)
|
await self._hub.bond.action(self._device.device_id, Action.set_flame(flame))
|
||||||
|
else:
|
||||||
|
await self._hub.bond.action(self._device.device_id, Action.turn_on())
|
||||||
|
|
||||||
def turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the fireplace off."""
|
"""Turn the fireplace off."""
|
||||||
self._hub.bond.turnOff(self._device.device_id)
|
await self._hub.bond.action(self._device.device_id, Action.turn_off())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def brightness(self):
|
def brightness(self):
|
||||||
|
@ -113,8 +113,8 @@ class BondFireplace(BondEntity, LightEntity):
|
||||||
"""Show fireplace icon for the entity."""
|
"""Show fireplace icon for the entity."""
|
||||||
return "mdi:fireplace" if self._power == 1 else "mdi:fireplace-off"
|
return "mdi:fireplace" if self._power == 1 else "mdi:fireplace-off"
|
||||||
|
|
||||||
def update(self):
|
async def async_update(self):
|
||||||
"""Fetch assumed state of the device from the hub using API."""
|
"""Fetch assumed state of the device from the hub using API."""
|
||||||
state: dict = self._hub.bond.getDeviceState(self._device.device_id)
|
state: dict = await self._hub.bond.device_state(self._device.device_id)
|
||||||
self._power = state.get("power")
|
self._power = state.get("power")
|
||||||
self._flame = state.get("flame")
|
self._flame = state.get("flame")
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/bond",
|
"documentation": "https://www.home-assistant.io/integrations/bond",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"bond-home==0.0.9"
|
"bond-api==0.1.4"
|
||||||
],
|
],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
"@prystupa"
|
"@prystupa"
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
"""Support for Bond generic devices."""
|
"""Support for Bond generic devices."""
|
||||||
from typing import Any, Callable, List, Optional
|
from typing import Any, Callable, List, Optional
|
||||||
|
|
||||||
from bond import DeviceTypes
|
from bond_api import Action, DeviceType
|
||||||
|
|
||||||
|
from homeassistant.components.switch import SwitchEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
from ..switch import SwitchEntity
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .entity import BondEntity
|
from .entity import BondEntity
|
||||||
from .utils import BondDevice, BondHub
|
from .utils import BondDevice, BondHub
|
||||||
|
@ -24,7 +24,7 @@ async def async_setup_entry(
|
||||||
switches = [
|
switches = [
|
||||||
BondSwitch(hub, device)
|
BondSwitch(hub, device)
|
||||||
for device in hub.devices
|
for device in hub.devices
|
||||||
if device.type == DeviceTypes.GENERIC_DEVICE
|
if DeviceType.is_generic(device.type)
|
||||||
]
|
]
|
||||||
|
|
||||||
async_add_entities(switches, True)
|
async_add_entities(switches, True)
|
||||||
|
@ -44,15 +44,15 @@ class BondSwitch(BondEntity, SwitchEntity):
|
||||||
"""Return True if power is on."""
|
"""Return True if power is on."""
|
||||||
return self._power == 1
|
return self._power == 1
|
||||||
|
|
||||||
def turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device on."""
|
"""Turn the device on."""
|
||||||
self._hub.bond.turnOn(self._device.device_id)
|
await self._hub.bond.action(self._device.device_id, Action.turn_on())
|
||||||
|
|
||||||
def turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device off."""
|
"""Turn the device off."""
|
||||||
self._hub.bond.turnOff(self._device.device_id)
|
await self._hub.bond.action(self._device.device_id, Action.turn_off())
|
||||||
|
|
||||||
def update(self):
|
async def async_update(self):
|
||||||
"""Fetch assumed state of the device from the hub using API."""
|
"""Fetch assumed state of the device from the hub using API."""
|
||||||
state: dict = self._hub.bond.getDeviceState(self._device.device_id)
|
state: dict = await self._hub.bond.device_state(self._device.device_id)
|
||||||
self._power = state.get("power")
|
self._power = state.get("power")
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from bond import Actions, Bond
|
from bond_api import Action, Bond
|
||||||
|
|
||||||
|
|
||||||
class BondDevice:
|
class BondDevice:
|
||||||
|
@ -27,18 +27,12 @@ class BondDevice:
|
||||||
def supports_speed(self) -> bool:
|
def supports_speed(self) -> bool:
|
||||||
"""Return True if this device supports any of the speed related commands."""
|
"""Return True if this device supports any of the speed related commands."""
|
||||||
actions: List[str] = self._attrs["actions"]
|
actions: List[str] = self._attrs["actions"]
|
||||||
return bool([action for action in actions if action in [Actions.SET_SPEED]])
|
return bool([action for action in actions if action in [Action.SET_SPEED]])
|
||||||
|
|
||||||
def supports_direction(self) -> bool:
|
def supports_direction(self) -> bool:
|
||||||
"""Return True if this device supports any of the direction related commands."""
|
"""Return True if this device supports any of the direction related commands."""
|
||||||
actions: List[str] = self._attrs["actions"]
|
actions: List[str] = self._attrs["actions"]
|
||||||
return bool(
|
return bool([action for action in actions if action in [Action.SET_DIRECTION]])
|
||||||
[
|
|
||||||
action
|
|
||||||
for action in actions
|
|
||||||
if action in [Actions.SET_DIRECTION, Actions.TOGGLE_DIRECTION]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
def supports_light(self) -> bool:
|
def supports_light(self) -> bool:
|
||||||
"""Return True if this device supports any of the light related commands."""
|
"""Return True if this device supports any of the light related commands."""
|
||||||
|
@ -47,7 +41,7 @@ class BondDevice:
|
||||||
[
|
[
|
||||||
action
|
action
|
||||||
for action in actions
|
for action in actions
|
||||||
if action in [Actions.TURN_LIGHT_ON, Actions.TOGGLE_LIGHT]
|
if action in [Action.TURN_LIGHT_ON, Action.TURN_LIGHT_OFF]
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -61,17 +55,17 @@ class BondHub:
|
||||||
self._version: Optional[dict] = None
|
self._version: Optional[dict] = None
|
||||||
self._devices: Optional[List[BondDevice]] = None
|
self._devices: Optional[List[BondDevice]] = None
|
||||||
|
|
||||||
def setup(self):
|
async def setup(self):
|
||||||
"""Read hub version information."""
|
"""Read hub version information."""
|
||||||
self._version = self.bond.getVersion()
|
self._version = await self.bond.version()
|
||||||
|
|
||||||
# Fetch all available devices using Bond API.
|
# Fetch all available devices using Bond API.
|
||||||
device_ids = self.bond.getDeviceIds()
|
device_ids = await self.bond.devices()
|
||||||
self._devices = [
|
self._devices = [
|
||||||
BondDevice(
|
BondDevice(
|
||||||
device_id,
|
device_id,
|
||||||
self.bond.getDevice(device_id),
|
await self.bond.device(device_id),
|
||||||
self.bond.getProperties(device_id),
|
await self.bond.device_properties(device_id),
|
||||||
)
|
)
|
||||||
for device_id in device_ids
|
for device_id in device_ids
|
||||||
]
|
]
|
||||||
|
|
|
@ -356,7 +356,7 @@ blockchain==1.4.4
|
||||||
bomradarloop==0.1.4
|
bomradarloop==0.1.4
|
||||||
|
|
||||||
# homeassistant.components.bond
|
# homeassistant.components.bond
|
||||||
bond-home==0.0.9
|
bond-api==0.1.4
|
||||||
|
|
||||||
# homeassistant.components.amazon_polly
|
# homeassistant.components.amazon_polly
|
||||||
# homeassistant.components.route53
|
# homeassistant.components.route53
|
||||||
|
|
|
@ -181,7 +181,7 @@ blinkpy==0.15.1
|
||||||
bomradarloop==0.1.4
|
bomradarloop==0.1.4
|
||||||
|
|
||||||
# homeassistant.components.bond
|
# homeassistant.components.bond
|
||||||
bond-home==0.0.9
|
bond-api==0.1.4
|
||||||
|
|
||||||
# homeassistant.components.braviatv
|
# homeassistant.components.braviatv
|
||||||
bravia-tv==1.0.6
|
bravia-tv==1.0.6
|
||||||
|
|
|
@ -21,9 +21,7 @@ async def setup_bond_entity(
|
||||||
|
|
||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
with patch(
|
with patch("homeassistant.components.bond.Bond.version", return_value=hub_version):
|
||||||
"homeassistant.components.bond.Bond.getVersion", return_value=hub_version
|
|
||||||
):
|
|
||||||
return await hass.config_entries.async_setup(config_entry.entry_id)
|
return await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,13 +43,15 @@ async def setup_platform(
|
||||||
mock_entry.add_to_hass(hass)
|
mock_entry.add_to_hass(hass)
|
||||||
|
|
||||||
with patch("homeassistant.components.bond.PLATFORMS", [platform]), patch(
|
with patch("homeassistant.components.bond.PLATFORMS", [platform]), patch(
|
||||||
"homeassistant.components.bond.Bond.getVersion", return_value=MOCK_HUB_VERSION
|
"homeassistant.components.bond.Bond.version", return_value=MOCK_HUB_VERSION
|
||||||
), patch_bond_device_ids(return_value=[bond_device_id],), patch(
|
), patch_bond_device_ids(return_value=[bond_device_id],), patch(
|
||||||
"homeassistant.components.bond.Bond.getDevice", return_value=discovered_device
|
"homeassistant.components.bond.Bond.device", return_value=discovered_device
|
||||||
), patch_bond_device_state(
|
), patch_bond_device_state(
|
||||||
return_value={}
|
return_value={}
|
||||||
), patch(
|
), patch(
|
||||||
"homeassistant.components.bond.Bond.getProperties", return_value=props
|
"homeassistant.components.bond.Bond.device_properties", return_value=props
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.bond.Bond.device_state", return_value={}
|
||||||
):
|
):
|
||||||
assert await async_setup_component(hass, BOND_DOMAIN, {})
|
assert await async_setup_component(hass, BOND_DOMAIN, {})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -60,70 +60,25 @@ async def setup_platform(
|
||||||
|
|
||||||
|
|
||||||
def patch_bond_device_ids(return_value=None):
|
def patch_bond_device_ids(return_value=None):
|
||||||
"""Patch Bond API getDeviceIds command."""
|
"""Patch Bond API devices command."""
|
||||||
if return_value is None:
|
if return_value is None:
|
||||||
return_value = []
|
return_value = []
|
||||||
|
|
||||||
return patch(
|
return patch(
|
||||||
"homeassistant.components.bond.Bond.getDeviceIds", return_value=return_value,
|
"homeassistant.components.bond.Bond.devices", return_value=return_value,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def patch_bond_turn_on():
|
def patch_bond_action():
|
||||||
"""Patch Bond API turnOn command."""
|
"""Patch Bond API action command."""
|
||||||
return patch("homeassistant.components.bond.Bond.turnOn")
|
return patch("homeassistant.components.bond.Bond.action")
|
||||||
|
|
||||||
|
|
||||||
def patch_bond_turn_off():
|
|
||||||
"""Patch Bond API turnOff command."""
|
|
||||||
return patch("homeassistant.components.bond.Bond.turnOff")
|
|
||||||
|
|
||||||
|
|
||||||
def patch_bond_set_speed():
|
|
||||||
"""Patch Bond API setSpeed command."""
|
|
||||||
return patch("homeassistant.components.bond.Bond.setSpeed")
|
|
||||||
|
|
||||||
|
|
||||||
def patch_bond_set_flame():
|
|
||||||
"""Patch Bond API setFlame command."""
|
|
||||||
return patch("homeassistant.components.bond.Bond.setFlame")
|
|
||||||
|
|
||||||
|
|
||||||
def patch_bond_open():
|
|
||||||
"""Patch Bond API open command."""
|
|
||||||
return patch("homeassistant.components.bond.Bond.open")
|
|
||||||
|
|
||||||
|
|
||||||
def patch_bond_close():
|
|
||||||
"""Patch Bond API close command."""
|
|
||||||
return patch("homeassistant.components.bond.Bond.close")
|
|
||||||
|
|
||||||
|
|
||||||
def patch_bond_hold():
|
|
||||||
"""Patch Bond API hold command."""
|
|
||||||
return patch("homeassistant.components.bond.Bond.hold")
|
|
||||||
|
|
||||||
|
|
||||||
def patch_bond_set_direction():
|
|
||||||
"""Patch Bond API setDirection command."""
|
|
||||||
return patch("homeassistant.components.bond.Bond.setDirection")
|
|
||||||
|
|
||||||
|
|
||||||
def patch_turn_light_on():
|
|
||||||
"""Patch Bond API turnLightOn command."""
|
|
||||||
return patch("homeassistant.components.bond.Bond.turnLightOn")
|
|
||||||
|
|
||||||
|
|
||||||
def patch_turn_light_off():
|
|
||||||
"""Patch Bond API turnLightOff command."""
|
|
||||||
return patch("homeassistant.components.bond.Bond.turnLightOff")
|
|
||||||
|
|
||||||
|
|
||||||
def patch_bond_device_state(return_value=None):
|
def patch_bond_device_state(return_value=None):
|
||||||
"""Patch Bond API getDeviceState command."""
|
"""Patch Bond API device state endpoint."""
|
||||||
if return_value is None:
|
if return_value is None:
|
||||||
return_value = {}
|
return_value = {}
|
||||||
|
|
||||||
return patch(
|
return patch(
|
||||||
"homeassistant.components.bond.Bond.getDeviceState", return_value=return_value
|
"homeassistant.components.bond.Bond.device_state", return_value=return_value
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
"""Test the Bond config flow."""
|
"""Test the Bond config flow."""
|
||||||
from json import JSONDecodeError
|
|
||||||
|
|
||||||
from requests.exceptions import ConnectionError
|
from aiohttp import ClientConnectionError, ClientResponseError
|
||||||
|
|
||||||
from homeassistant import config_entries, core, setup
|
from homeassistant import config_entries, core, setup
|
||||||
from homeassistant.components.bond.const import DOMAIN
|
from homeassistant.components.bond.const import DOMAIN
|
||||||
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST
|
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST
|
||||||
|
|
||||||
from tests.async_mock import patch
|
from tests.async_mock import Mock, patch
|
||||||
|
|
||||||
|
|
||||||
async def test_form(hass: core.HomeAssistant):
|
async def test_form(hass: core.HomeAssistant):
|
||||||
|
@ -20,7 +19,7 @@ async def test_form(hass: core.HomeAssistant):
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.bond.config_flow.Bond.getDeviceIds", return_value=[],
|
"homeassistant.components.bond.config_flow.Bond.devices", return_value=[],
|
||||||
), patch(
|
), patch(
|
||||||
"homeassistant.components.bond.async_setup", return_value=True
|
"homeassistant.components.bond.async_setup", return_value=True
|
||||||
) as mock_setup, patch(
|
) as mock_setup, patch(
|
||||||
|
@ -48,8 +47,8 @@ async def test_form_invalid_auth(hass: core.HomeAssistant):
|
||||||
)
|
)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.bond.config_flow.Bond.getDeviceIds",
|
"homeassistant.components.bond.config_flow.Bond.devices",
|
||||||
side_effect=JSONDecodeError("test-message", "test-doc", 0),
|
side_effect=ClientResponseError(Mock(), Mock(), status=401),
|
||||||
):
|
):
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], {CONF_HOST: "1.1.1.1", CONF_ACCESS_TOKEN: "test-token"},
|
result["flow_id"], {CONF_HOST: "1.1.1.1", CONF_ACCESS_TOKEN: "test-token"},
|
||||||
|
@ -66,8 +65,8 @@ async def test_form_cannot_connect(hass: core.HomeAssistant):
|
||||||
)
|
)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.bond.config_flow.Bond.getDeviceIds",
|
"homeassistant.components.bond.config_flow.Bond.devices",
|
||||||
side_effect=ConnectionError,
|
side_effect=ClientConnectionError(),
|
||||||
):
|
):
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], {CONF_HOST: "1.1.1.1", CONF_ACCESS_TOKEN: "test-token"},
|
result["flow_id"], {CONF_HOST: "1.1.1.1", CONF_ACCESS_TOKEN: "test-token"},
|
||||||
|
@ -84,8 +83,8 @@ async def test_form_unexpected_error(hass: core.HomeAssistant):
|
||||||
)
|
)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.bond.config_flow.Bond.getDeviceIds",
|
"homeassistant.components.bond.config_flow.Bond.devices",
|
||||||
side_effect=Exception,
|
side_effect=ClientResponseError(Mock(), Mock(), status=500),
|
||||||
):
|
):
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], {CONF_HOST: "1.1.1.1", CONF_ACCESS_TOKEN: "test-token"},
|
result["flow_id"], {CONF_HOST: "1.1.1.1", CONF_ACCESS_TOKEN: "test-token"},
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from bond import DeviceTypes
|
from bond_api import Action, DeviceType
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
from homeassistant.components.cover import DOMAIN as COVER_DOMAIN
|
from homeassistant.components.cover import DOMAIN as COVER_DOMAIN
|
||||||
|
@ -15,13 +15,7 @@ from homeassistant.const import (
|
||||||
from homeassistant.helpers.entity_registry import EntityRegistry
|
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||||
from homeassistant.util import utcnow
|
from homeassistant.util import utcnow
|
||||||
|
|
||||||
from .common import (
|
from .common import patch_bond_action, patch_bond_device_state, setup_platform
|
||||||
patch_bond_close,
|
|
||||||
patch_bond_device_state,
|
|
||||||
patch_bond_hold,
|
|
||||||
patch_bond_open,
|
|
||||||
setup_platform,
|
|
||||||
)
|
|
||||||
|
|
||||||
from tests.common import async_fire_time_changed
|
from tests.common import async_fire_time_changed
|
||||||
|
|
||||||
|
@ -30,7 +24,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
def shades(name: str):
|
def shades(name: str):
|
||||||
"""Create motorized shades with given name."""
|
"""Create motorized shades with given name."""
|
||||||
return {"name": name, "type": DeviceTypes.MOTORIZED_SHADES}
|
return {"name": name, "type": DeviceType.MOTORIZED_SHADES}
|
||||||
|
|
||||||
|
|
||||||
async def test_entity_registry(hass: core.HomeAssistant):
|
async def test_entity_registry(hass: core.HomeAssistant):
|
||||||
|
@ -43,9 +37,11 @@ async def test_entity_registry(hass: core.HomeAssistant):
|
||||||
|
|
||||||
async def test_open_cover(hass: core.HomeAssistant):
|
async def test_open_cover(hass: core.HomeAssistant):
|
||||||
"""Tests that open cover command delegates to API."""
|
"""Tests that open cover command delegates to API."""
|
||||||
await setup_platform(hass, COVER_DOMAIN, shades("name-1"))
|
await setup_platform(
|
||||||
|
hass, COVER_DOMAIN, shades("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_open() as mock_open, patch_bond_device_state():
|
with patch_bond_action() as mock_open, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
COVER_DOMAIN,
|
COVER_DOMAIN,
|
||||||
SERVICE_OPEN_COVER,
|
SERVICE_OPEN_COVER,
|
||||||
|
@ -53,14 +49,17 @@ async def test_open_cover(hass: core.HomeAssistant):
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_open.assert_called_once()
|
|
||||||
|
mock_open.assert_called_once_with("test-device-id", Action.open())
|
||||||
|
|
||||||
|
|
||||||
async def test_close_cover(hass: core.HomeAssistant):
|
async def test_close_cover(hass: core.HomeAssistant):
|
||||||
"""Tests that close cover command delegates to API."""
|
"""Tests that close cover command delegates to API."""
|
||||||
await setup_platform(hass, COVER_DOMAIN, shades("name-1"))
|
await setup_platform(
|
||||||
|
hass, COVER_DOMAIN, shades("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_close() as mock_close, patch_bond_device_state():
|
with patch_bond_action() as mock_close, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
COVER_DOMAIN,
|
COVER_DOMAIN,
|
||||||
SERVICE_CLOSE_COVER,
|
SERVICE_CLOSE_COVER,
|
||||||
|
@ -68,14 +67,17 @@ async def test_close_cover(hass: core.HomeAssistant):
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_close.assert_called_once()
|
|
||||||
|
mock_close.assert_called_once_with("test-device-id", Action.close())
|
||||||
|
|
||||||
|
|
||||||
async def test_stop_cover(hass: core.HomeAssistant):
|
async def test_stop_cover(hass: core.HomeAssistant):
|
||||||
"""Tests that stop cover command delegates to API."""
|
"""Tests that stop cover command delegates to API."""
|
||||||
await setup_platform(hass, COVER_DOMAIN, shades("name-1"))
|
await setup_platform(
|
||||||
|
hass, COVER_DOMAIN, shades("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_hold() as mock_hold, patch_bond_device_state():
|
with patch_bond_action() as mock_hold, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
COVER_DOMAIN,
|
COVER_DOMAIN,
|
||||||
SERVICE_STOP_COVER,
|
SERVICE_STOP_COVER,
|
||||||
|
@ -83,7 +85,8 @@ async def test_stop_cover(hass: core.HomeAssistant):
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_hold.assert_called_once()
|
|
||||||
|
mock_hold.assert_called_once_with("test-device-id", Action.hold())
|
||||||
|
|
||||||
|
|
||||||
async def test_update_reports_open_cover(hass: core.HomeAssistant):
|
async def test_update_reports_open_cover(hass: core.HomeAssistant):
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
"""Tests for the Bond fan device."""
|
"""Tests for the Bond fan device."""
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from bond import DeviceTypes, Directions
|
from bond_api import Action, DeviceType, Direction
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
from homeassistant.components import fan
|
from homeassistant.components import fan
|
||||||
|
@ -17,14 +18,7 @@ from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_O
|
||||||
from homeassistant.helpers.entity_registry import EntityRegistry
|
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||||
from homeassistant.util import utcnow
|
from homeassistant.util import utcnow
|
||||||
|
|
||||||
from .common import (
|
from .common import patch_bond_action, patch_bond_device_state, setup_platform
|
||||||
patch_bond_device_state,
|
|
||||||
patch_bond_set_direction,
|
|
||||||
patch_bond_set_speed,
|
|
||||||
patch_bond_turn_off,
|
|
||||||
patch_bond_turn_on,
|
|
||||||
setup_platform,
|
|
||||||
)
|
|
||||||
|
|
||||||
from tests.common import async_fire_time_changed
|
from tests.common import async_fire_time_changed
|
||||||
|
|
||||||
|
@ -33,18 +27,20 @@ def ceiling_fan(name: str):
|
||||||
"""Create a ceiling fan with given name."""
|
"""Create a ceiling fan with given name."""
|
||||||
return {
|
return {
|
||||||
"name": name,
|
"name": name,
|
||||||
"type": DeviceTypes.CEILING_FAN,
|
"type": DeviceType.CEILING_FAN,
|
||||||
"actions": ["SetSpeed", "SetDirection"],
|
"actions": ["SetSpeed", "SetDirection"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async def turn_fan_on(hass: core.HomeAssistant, fan_id: str, speed: str) -> None:
|
async def turn_fan_on(
|
||||||
|
hass: core.HomeAssistant, fan_id: str, speed: Optional[str] = None
|
||||||
|
) -> None:
|
||||||
"""Turn the fan on at the specified speed."""
|
"""Turn the fan on at the specified speed."""
|
||||||
|
service_data = {ATTR_ENTITY_ID: fan_id}
|
||||||
|
if speed:
|
||||||
|
service_data[fan.ATTR_SPEED] = speed
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
FAN_DOMAIN,
|
FAN_DOMAIN, SERVICE_TURN_ON, service_data=service_data, blocking=True,
|
||||||
SERVICE_TURN_ON,
|
|
||||||
{ATTR_ENTITY_ID: fan_id, fan.ATTR_SPEED: speed},
|
|
||||||
blocking=True,
|
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -57,7 +53,7 @@ async def test_entity_registry(hass: core.HomeAssistant):
|
||||||
assert [key for key in registry.entities] == ["fan.name_1"]
|
assert [key for key in registry.entities] == ["fan.name_1"]
|
||||||
|
|
||||||
|
|
||||||
async def test_entity_non_standard_speed_list(hass: core.HomeAssistant):
|
async def test_non_standard_speed_list(hass: core.HomeAssistant):
|
||||||
"""Tests that the device is registered with custom speed list if number of supported speeds differs form 3."""
|
"""Tests that the device is registered with custom speed list if number of supported speeds differs form 3."""
|
||||||
await setup_platform(
|
await setup_platform(
|
||||||
hass,
|
hass,
|
||||||
|
@ -76,41 +72,62 @@ async def test_entity_non_standard_speed_list(hass: core.HomeAssistant):
|
||||||
]
|
]
|
||||||
|
|
||||||
with patch_bond_device_state():
|
with patch_bond_device_state():
|
||||||
with patch_bond_turn_on(), patch_bond_set_speed() as mock_set_speed_low:
|
with patch_bond_action() as mock_set_speed_low:
|
||||||
await turn_fan_on(hass, "fan.name_1", fan.SPEED_LOW)
|
await turn_fan_on(hass, "fan.name_1", fan.SPEED_LOW)
|
||||||
mock_set_speed_low.assert_called_once_with("test-device-id", speed=1)
|
mock_set_speed_low.assert_called_once_with(
|
||||||
|
"test-device-id", Action.set_speed(1)
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_turn_on(), patch_bond_set_speed() as mock_set_speed_medium:
|
with patch_bond_action() as mock_set_speed_medium:
|
||||||
await turn_fan_on(hass, "fan.name_1", fan.SPEED_MEDIUM)
|
await turn_fan_on(hass, "fan.name_1", fan.SPEED_MEDIUM)
|
||||||
mock_set_speed_medium.assert_called_once_with("test-device-id", speed=3)
|
mock_set_speed_medium.assert_called_once_with(
|
||||||
|
"test-device-id", Action.set_speed(3)
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_turn_on(), patch_bond_set_speed() as mock_set_speed_high:
|
with patch_bond_action() as mock_set_speed_high:
|
||||||
await turn_fan_on(hass, "fan.name_1", fan.SPEED_HIGH)
|
await turn_fan_on(hass, "fan.name_1", fan.SPEED_HIGH)
|
||||||
mock_set_speed_high.assert_called_once_with("test-device-id", speed=6)
|
mock_set_speed_high.assert_called_once_with(
|
||||||
|
"test-device-id", Action.set_speed(6)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_turn_on_fan(hass: core.HomeAssistant):
|
async def test_turn_on_fan_with_speed(hass: core.HomeAssistant):
|
||||||
"""Tests that turn on command delegates to API."""
|
"""Tests that turn on command delegates to set speed API."""
|
||||||
await setup_platform(hass, FAN_DOMAIN, ceiling_fan("name-1"))
|
await setup_platform(
|
||||||
|
hass, FAN_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_turn_on() as mock_turn_on, patch_bond_set_speed() as mock_set_speed, patch_bond_device_state():
|
with patch_bond_action() as mock_set_speed, patch_bond_device_state():
|
||||||
await turn_fan_on(hass, "fan.name_1", fan.SPEED_LOW)
|
await turn_fan_on(hass, "fan.name_1", fan.SPEED_LOW)
|
||||||
|
|
||||||
mock_set_speed.assert_called_once()
|
mock_set_speed.assert_called_with("test-device-id", Action.set_speed(1))
|
||||||
mock_turn_on.assert_called_once()
|
|
||||||
|
|
||||||
|
async def test_turn_on_fan_without_speed(hass: core.HomeAssistant):
|
||||||
|
"""Tests that turn on command delegates to turn on API."""
|
||||||
|
await setup_platform(
|
||||||
|
hass, FAN_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch_bond_action() as mock_turn_on, patch_bond_device_state():
|
||||||
|
await turn_fan_on(hass, "fan.name_1")
|
||||||
|
|
||||||
|
mock_turn_on.assert_called_with("test-device-id", Action.turn_on())
|
||||||
|
|
||||||
|
|
||||||
async def test_turn_off_fan(hass: core.HomeAssistant):
|
async def test_turn_off_fan(hass: core.HomeAssistant):
|
||||||
"""Tests that turn off command delegates to API."""
|
"""Tests that turn off command delegates to API."""
|
||||||
await setup_platform(hass, FAN_DOMAIN, ceiling_fan("name-1"))
|
await setup_platform(
|
||||||
|
hass, FAN_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_turn_off() as mock_turn_off, patch_bond_device_state():
|
with patch_bond_action() as mock_turn_off, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
FAN_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: "fan.name_1"}, blocking=True,
|
FAN_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: "fan.name_1"}, blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
mock_turn_off.assert_called_once()
|
mock_turn_off.assert_called_once_with("test-device-id", Action.turn_off())
|
||||||
|
|
||||||
|
|
||||||
async def test_update_reports_fan_on(hass: core.HomeAssistant):
|
async def test_update_reports_fan_on(hass: core.HomeAssistant):
|
||||||
|
@ -139,7 +156,7 @@ async def test_update_reports_direction_forward(hass: core.HomeAssistant):
|
||||||
"""Tests that update command sets correct direction when Bond API reports fan direction is forward."""
|
"""Tests that update command sets correct direction when Bond API reports fan direction is forward."""
|
||||||
await setup_platform(hass, FAN_DOMAIN, ceiling_fan("name-1"))
|
await setup_platform(hass, FAN_DOMAIN, ceiling_fan("name-1"))
|
||||||
|
|
||||||
with patch_bond_device_state(return_value={"direction": Directions.FORWARD}):
|
with patch_bond_device_state(return_value={"direction": Direction.FORWARD}):
|
||||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=30))
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=30))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -150,7 +167,7 @@ async def test_update_reports_direction_reverse(hass: core.HomeAssistant):
|
||||||
"""Tests that update command sets correct direction when Bond API reports fan direction is reverse."""
|
"""Tests that update command sets correct direction when Bond API reports fan direction is reverse."""
|
||||||
await setup_platform(hass, FAN_DOMAIN, ceiling_fan("name-1"))
|
await setup_platform(hass, FAN_DOMAIN, ceiling_fan("name-1"))
|
||||||
|
|
||||||
with patch_bond_device_state(return_value={"direction": Directions.REVERSE}):
|
with patch_bond_device_state(return_value={"direction": Direction.REVERSE}):
|
||||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=30))
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=30))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -159,9 +176,11 @@ async def test_update_reports_direction_reverse(hass: core.HomeAssistant):
|
||||||
|
|
||||||
async def test_set_fan_direction(hass: core.HomeAssistant):
|
async def test_set_fan_direction(hass: core.HomeAssistant):
|
||||||
"""Tests that set direction command delegates to API."""
|
"""Tests that set direction command delegates to API."""
|
||||||
await setup_platform(hass, FAN_DOMAIN, ceiling_fan("name-1"))
|
await setup_platform(
|
||||||
|
hass, FAN_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_set_direction() as mock_set_direction, patch_bond_device_state():
|
with patch_bond_action() as mock_set_direction, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
FAN_DOMAIN,
|
FAN_DOMAIN,
|
||||||
SERVICE_SET_DIRECTION,
|
SERVICE_SET_DIRECTION,
|
||||||
|
@ -169,4 +188,7 @@ async def test_set_fan_direction(hass: core.HomeAssistant):
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_set_direction.assert_called_once()
|
|
||||||
|
mock_set_direction.assert_called_once_with(
|
||||||
|
"test-device-id", Action.set_direction(Direction.FORWARD)
|
||||||
|
)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from bond import Actions, DeviceTypes
|
from bond_api import Action, DeviceType
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
from homeassistant.components.light import ATTR_BRIGHTNESS, DOMAIN as LIGHT_DOMAIN
|
from homeassistant.components.light import ATTR_BRIGHTNESS, DOMAIN as LIGHT_DOMAIN
|
||||||
|
@ -10,15 +10,7 @@ from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_O
|
||||||
from homeassistant.helpers.entity_registry import EntityRegistry
|
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||||
from homeassistant.util import utcnow
|
from homeassistant.util import utcnow
|
||||||
|
|
||||||
from .common import (
|
from .common import patch_bond_action, patch_bond_device_state, setup_platform
|
||||||
patch_bond_device_state,
|
|
||||||
patch_bond_set_flame,
|
|
||||||
patch_bond_turn_off,
|
|
||||||
patch_bond_turn_on,
|
|
||||||
patch_turn_light_off,
|
|
||||||
patch_turn_light_on,
|
|
||||||
setup_platform,
|
|
||||||
)
|
|
||||||
|
|
||||||
from tests.common import async_fire_time_changed
|
from tests.common import async_fire_time_changed
|
||||||
|
|
||||||
|
@ -29,14 +21,14 @@ def ceiling_fan(name: str):
|
||||||
"""Create a ceiling fan (that has built-in light) with given name."""
|
"""Create a ceiling fan (that has built-in light) with given name."""
|
||||||
return {
|
return {
|
||||||
"name": name,
|
"name": name,
|
||||||
"type": DeviceTypes.CEILING_FAN,
|
"type": DeviceType.CEILING_FAN,
|
||||||
"actions": [Actions.TOGGLE_LIGHT],
|
"actions": [Action.TURN_LIGHT_ON, Action.TURN_LIGHT_OFF],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def fireplace(name: str):
|
def fireplace(name: str):
|
||||||
"""Create a fireplace with given name."""
|
"""Create a fireplace with given name."""
|
||||||
return {"name": name, "type": DeviceTypes.FIREPLACE}
|
return {"name": name, "type": DeviceType.FIREPLACE}
|
||||||
|
|
||||||
|
|
||||||
async def test_entity_registry(hass: core.HomeAssistant):
|
async def test_entity_registry(hass: core.HomeAssistant):
|
||||||
|
@ -49,9 +41,11 @@ async def test_entity_registry(hass: core.HomeAssistant):
|
||||||
|
|
||||||
async def test_turn_on_light(hass: core.HomeAssistant):
|
async def test_turn_on_light(hass: core.HomeAssistant):
|
||||||
"""Tests that turn on command delegates to API."""
|
"""Tests that turn on command delegates to API."""
|
||||||
await setup_platform(hass, LIGHT_DOMAIN, ceiling_fan("name-1"))
|
await setup_platform(
|
||||||
|
hass, LIGHT_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_turn_light_on() as mock_turn_light_on, patch_bond_device_state():
|
with patch_bond_action() as mock_turn_light_on, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
|
@ -59,14 +53,17 @@ async def test_turn_on_light(hass: core.HomeAssistant):
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_turn_light_on.assert_called_once()
|
|
||||||
|
mock_turn_light_on.assert_called_once_with("test-device-id", Action.turn_light_on())
|
||||||
|
|
||||||
|
|
||||||
async def test_turn_off_light(hass: core.HomeAssistant):
|
async def test_turn_off_light(hass: core.HomeAssistant):
|
||||||
"""Tests that turn off command delegates to API."""
|
"""Tests that turn off command delegates to API."""
|
||||||
await setup_platform(hass, LIGHT_DOMAIN, ceiling_fan("name-1"))
|
await setup_platform(
|
||||||
|
hass, LIGHT_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_turn_light_off() as mock_turn_light_off, patch_bond_device_state():
|
with patch_bond_action() as mock_turn_light_off, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
|
@ -74,7 +71,10 @@ async def test_turn_off_light(hass: core.HomeAssistant):
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_turn_light_off.assert_called_once()
|
|
||||||
|
mock_turn_light_off.assert_called_once_with(
|
||||||
|
"test-device-id", Action.turn_light_off()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_update_reports_light_is_on(hass: core.HomeAssistant):
|
async def test_update_reports_light_is_on(hass: core.HomeAssistant):
|
||||||
|
@ -99,13 +99,13 @@ async def test_update_reports_light_is_off(hass: core.HomeAssistant):
|
||||||
assert hass.states.get("light.name_1").state == "off"
|
assert hass.states.get("light.name_1").state == "off"
|
||||||
|
|
||||||
|
|
||||||
async def test_turn_on_fireplace(hass: core.HomeAssistant):
|
async def test_turn_on_fireplace_with_brightness(hass: core.HomeAssistant):
|
||||||
"""Tests that turn on command delegates to API."""
|
"""Tests that turn on command delegates to set flame API."""
|
||||||
await setup_platform(
|
await setup_platform(
|
||||||
hass, LIGHT_DOMAIN, fireplace("name-1"), bond_device_id="test-device-id"
|
hass, LIGHT_DOMAIN, fireplace("name-1"), bond_device_id="test-device-id"
|
||||||
)
|
)
|
||||||
|
|
||||||
with patch_bond_turn_on() as mock_turn_on, patch_bond_set_flame() as mock_set_flame, patch_bond_device_state():
|
with patch_bond_action() as mock_set_flame, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
|
@ -114,15 +114,34 @@ async def test_turn_on_fireplace(hass: core.HomeAssistant):
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
mock_turn_on.assert_called_once()
|
mock_set_flame.assert_called_once_with("test-device-id", Action.set_flame(50))
|
||||||
mock_set_flame.assert_called_once_with("test-device-id", 50)
|
|
||||||
|
|
||||||
|
async def test_turn_on_fireplace_without_brightness(hass: core.HomeAssistant):
|
||||||
|
"""Tests that turn on command delegates to turn on API."""
|
||||||
|
await setup_platform(
|
||||||
|
hass, LIGHT_DOMAIN, fireplace("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch_bond_action() as mock_turn_on, patch_bond_device_state():
|
||||||
|
await hass.services.async_call(
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{ATTR_ENTITY_ID: "light.name_1"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
mock_turn_on.assert_called_once_with("test-device-id", Action.turn_on())
|
||||||
|
|
||||||
|
|
||||||
async def test_turn_off_fireplace(hass: core.HomeAssistant):
|
async def test_turn_off_fireplace(hass: core.HomeAssistant):
|
||||||
"""Tests that turn off command delegates to API."""
|
"""Tests that turn off command delegates to API."""
|
||||||
await setup_platform(hass, LIGHT_DOMAIN, fireplace("name-1"))
|
await setup_platform(
|
||||||
|
hass, LIGHT_DOMAIN, fireplace("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_turn_off() as mock_turn_off, patch_bond_device_state():
|
with patch_bond_action() as mock_turn_off, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
|
@ -130,7 +149,8 @@ async def test_turn_off_fireplace(hass: core.HomeAssistant):
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_turn_off.assert_called_once()
|
|
||||||
|
mock_turn_off.assert_called_once_with("test-device-id", Action.turn_off())
|
||||||
|
|
||||||
|
|
||||||
async def test_flame_converted_to_brightness(hass: core.HomeAssistant):
|
async def test_flame_converted_to_brightness(hass: core.HomeAssistant):
|
||||||
|
@ -141,5 +161,4 @@ async def test_flame_converted_to_brightness(hass: core.HomeAssistant):
|
||||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=30))
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=30))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
_LOGGER.warning(hass.states.get("light.name_1").attributes)
|
|
||||||
assert hass.states.get("light.name_1").attributes[ATTR_BRIGHTNESS] == 128
|
assert hass.states.get("light.name_1").attributes[ATTR_BRIGHTNESS] == 128
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from bond import DeviceTypes
|
from bond_api import Action, DeviceType
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||||
|
@ -10,12 +10,7 @@ from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_O
|
||||||
from homeassistant.helpers.entity_registry import EntityRegistry
|
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||||
from homeassistant.util import utcnow
|
from homeassistant.util import utcnow
|
||||||
|
|
||||||
from .common import (
|
from .common import patch_bond_action, patch_bond_device_state, setup_platform
|
||||||
patch_bond_device_state,
|
|
||||||
patch_bond_turn_off,
|
|
||||||
patch_bond_turn_on,
|
|
||||||
setup_platform,
|
|
||||||
)
|
|
||||||
|
|
||||||
from tests.common import async_fire_time_changed
|
from tests.common import async_fire_time_changed
|
||||||
|
|
||||||
|
@ -24,7 +19,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
def generic_device(name: str):
|
def generic_device(name: str):
|
||||||
"""Create a generic device with given name."""
|
"""Create a generic device with given name."""
|
||||||
return {"name": name, "type": DeviceTypes.GENERIC_DEVICE}
|
return {"name": name, "type": DeviceType.GENERIC_DEVICE}
|
||||||
|
|
||||||
|
|
||||||
async def test_entity_registry(hass: core.HomeAssistant):
|
async def test_entity_registry(hass: core.HomeAssistant):
|
||||||
|
@ -37,9 +32,11 @@ async def test_entity_registry(hass: core.HomeAssistant):
|
||||||
|
|
||||||
async def test_turn_on_switch(hass: core.HomeAssistant):
|
async def test_turn_on_switch(hass: core.HomeAssistant):
|
||||||
"""Tests that turn on command delegates to API."""
|
"""Tests that turn on command delegates to API."""
|
||||||
await setup_platform(hass, SWITCH_DOMAIN, generic_device("name-1"))
|
await setup_platform(
|
||||||
|
hass, SWITCH_DOMAIN, generic_device("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_turn_on() as mock_turn_on, patch_bond_device_state():
|
with patch_bond_action() as mock_turn_on, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
SWITCH_DOMAIN,
|
SWITCH_DOMAIN,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
|
@ -47,14 +44,17 @@ async def test_turn_on_switch(hass: core.HomeAssistant):
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_turn_on.assert_called_once()
|
|
||||||
|
mock_turn_on.assert_called_once_with("test-device-id", Action.turn_on())
|
||||||
|
|
||||||
|
|
||||||
async def test_turn_off_switch(hass: core.HomeAssistant):
|
async def test_turn_off_switch(hass: core.HomeAssistant):
|
||||||
"""Tests that turn off command delegates to API."""
|
"""Tests that turn off command delegates to API."""
|
||||||
await setup_platform(hass, SWITCH_DOMAIN, generic_device("name-1"))
|
await setup_platform(
|
||||||
|
hass, SWITCH_DOMAIN, generic_device("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
with patch_bond_turn_off() as mock_turn_off, patch_bond_device_state():
|
with patch_bond_action() as mock_turn_off, patch_bond_device_state():
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
SWITCH_DOMAIN,
|
SWITCH_DOMAIN,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
|
@ -62,7 +62,8 @@ async def test_turn_off_switch(hass: core.HomeAssistant):
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_turn_off.assert_called_once()
|
|
||||||
|
mock_turn_off.assert_called_once_with("test-device-id", Action.turn_off())
|
||||||
|
|
||||||
|
|
||||||
async def test_update_reports_switch_is_on(hass: core.HomeAssistant):
|
async def test_update_reports_switch_is_on(hass: core.HomeAssistant):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue