mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 04:37:06 +00:00
Map bond fan speeds to standard HA speeds (#37808)
This commit is contained in:
parent
9e8e5c37f4
commit
95e72b4c4b
@ -1,4 +1,5 @@
|
||||
"""Support for Bond fans."""
|
||||
import math
|
||||
from typing import Any, Callable, List, Optional
|
||||
|
||||
from bond import DeviceTypes, Directions
|
||||
@ -67,12 +68,15 @@ class BondFan(BondEntity, FanEntity):
|
||||
@property
|
||||
def speed(self) -> Optional[str]:
|
||||
"""Return the current speed."""
|
||||
if self._power is None:
|
||||
return None
|
||||
if self._power == 0:
|
||||
return SPEED_OFF
|
||||
if not self._power or not self._speed:
|
||||
return None
|
||||
|
||||
return self.speed_list[self._speed] if self._speed is not None else None
|
||||
# map 1..max_speed Bond speed to 1..3 HA speed
|
||||
max_speed = self._device.props.get("max_speed", 3)
|
||||
ha_speed = math.ceil(self._speed * (len(self.speed_list) - 1) / max_speed)
|
||||
return self.speed_list[ha_speed]
|
||||
|
||||
@property
|
||||
def speed_list(self) -> list:
|
||||
@ -99,8 +103,14 @@ class BondFan(BondEntity, FanEntity):
|
||||
|
||||
def set_speed(self, speed: str) -> None:
|
||||
"""Set the desired speed for the fan."""
|
||||
speed_index = self.speed_list.index(speed)
|
||||
self._hub.bond.setSpeed(self._device.device_id, speed=speed_index)
|
||||
max_speed = self._device.props.get("max_speed", 3)
|
||||
if speed == SPEED_LOW:
|
||||
bond_speed = 1
|
||||
elif speed == SPEED_HIGH:
|
||||
bond_speed = max_speed
|
||||
else:
|
||||
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:
|
||||
"""Turn on the fan."""
|
||||
|
@ -8,9 +8,10 @@ from bond import Actions, Bond
|
||||
class BondDevice:
|
||||
"""Helper device class to hold ID and attributes together."""
|
||||
|
||||
def __init__(self, device_id: str, attrs: dict):
|
||||
def __init__(self, device_id: str, attrs: dict, props: dict):
|
||||
"""Create a helper device from ID and attributes returned by API."""
|
||||
self.device_id = device_id
|
||||
self.props = props
|
||||
self._attrs = attrs
|
||||
|
||||
@property
|
||||
@ -67,7 +68,11 @@ class BondHub:
|
||||
"""Fetch all available devices using Bond API."""
|
||||
device_ids = self.bond.getDeviceIds()
|
||||
devices = [
|
||||
BondDevice(device_id, self.bond.getDevice(device_id))
|
||||
BondDevice(
|
||||
device_id,
|
||||
self.bond.getDevice(device_id),
|
||||
self.bond.getProperties(device_id),
|
||||
)
|
||||
for device_id in device_ids
|
||||
]
|
||||
return devices
|
||||
|
@ -28,9 +28,16 @@ async def setup_bond_entity(
|
||||
|
||||
|
||||
async def setup_platform(
|
||||
hass: core.HomeAssistant, platform: str, discovered_device: Dict[str, Any]
|
||||
hass: core.HomeAssistant,
|
||||
platform: str,
|
||||
discovered_device: Dict[str, Any],
|
||||
bond_device_id: str = "bond-device-id",
|
||||
props: Dict[str, Any] = None,
|
||||
):
|
||||
"""Set up the specified Bond platform."""
|
||||
if not props:
|
||||
props = {}
|
||||
|
||||
mock_entry = MockConfigEntry(
|
||||
domain=BOND_DOMAIN,
|
||||
data={CONF_HOST: "1.1.1.1", CONF_ACCESS_TOKEN: "test-token"},
|
||||
@ -41,11 +48,13 @@ async def setup_platform(
|
||||
"homeassistant.components.bond.Bond.getVersion", return_value=MOCK_HUB_VERSION
|
||||
), patch(
|
||||
"homeassistant.components.bond.Bond.getDeviceIds",
|
||||
return_value=["bond-device-id"],
|
||||
return_value=[bond_device_id],
|
||||
), patch(
|
||||
"homeassistant.components.bond.Bond.getDevice", return_value=discovered_device
|
||||
), patch(
|
||||
"homeassistant.components.bond.Bond.getDeviceState", return_value={}
|
||||
), patch(
|
||||
"homeassistant.components.bond.Bond.getProperties", return_value=props
|
||||
):
|
||||
assert await async_setup_component(hass, BOND_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
@ -7,6 +7,7 @@ from homeassistant import core
|
||||
from homeassistant.components import fan
|
||||
from homeassistant.components.fan import (
|
||||
ATTR_DIRECTION,
|
||||
ATTR_SPEED_LIST,
|
||||
DIRECTION_FORWARD,
|
||||
DIRECTION_REVERSE,
|
||||
DOMAIN as FAN_DOMAIN,
|
||||
@ -16,10 +17,10 @@ from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_O
|
||||
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||
from homeassistant.util import utcnow
|
||||
|
||||
from ...common import async_fire_time_changed
|
||||
from .common import setup_platform
|
||||
|
||||
from tests.async_mock import patch
|
||||
from tests.common import async_fire_time_changed
|
||||
|
||||
|
||||
def ceiling_fan(name: str):
|
||||
@ -31,6 +32,17 @@ def ceiling_fan(name: str):
|
||||
}
|
||||
|
||||
|
||||
async def turn_fan_on(hass: core.HomeAssistant, fan_id: str, speed: str) -> None:
|
||||
"""Turn the fan on at the specified speed."""
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: fan_id, fan.ATTR_SPEED: speed},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_entity_registry(hass: core.HomeAssistant):
|
||||
"""Tests that the devices are registered in the entity registry."""
|
||||
await setup_platform(hass, FAN_DOMAIN, ceiling_fan("name-1"))
|
||||
@ -39,6 +51,43 @@ async def test_entity_registry(hass: core.HomeAssistant):
|
||||
assert [key for key in registry.entities] == ["fan.name_1"]
|
||||
|
||||
|
||||
async def test_entity_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."""
|
||||
await setup_platform(
|
||||
hass,
|
||||
FAN_DOMAIN,
|
||||
ceiling_fan("name-1"),
|
||||
bond_device_id="test-device-id",
|
||||
props={"max_speed": 6},
|
||||
)
|
||||
|
||||
actual_speeds = hass.states.get("fan.name_1").attributes[ATTR_SPEED_LIST]
|
||||
assert actual_speeds == [
|
||||
fan.SPEED_OFF,
|
||||
fan.SPEED_LOW,
|
||||
fan.SPEED_MEDIUM,
|
||||
fan.SPEED_HIGH,
|
||||
]
|
||||
|
||||
with patch("homeassistant.components.bond.Bond.turnOn"), patch(
|
||||
"homeassistant.components.bond.Bond.setSpeed"
|
||||
) as mock_set_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)
|
||||
|
||||
with patch("homeassistant.components.bond.Bond.turnOn"), patch(
|
||||
"homeassistant.components.bond.Bond.setSpeed"
|
||||
) as mock_set_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)
|
||||
|
||||
with patch("homeassistant.components.bond.Bond.turnOn"), patch(
|
||||
"homeassistant.components.bond.Bond.setSpeed"
|
||||
) as mock_set_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)
|
||||
|
||||
|
||||
async def test_turn_on_fan(hass: core.HomeAssistant):
|
||||
"""Tests that turn on command delegates to API."""
|
||||
await setup_platform(hass, FAN_DOMAIN, ceiling_fan("name-1"))
|
||||
@ -46,16 +95,10 @@ async def test_turn_on_fan(hass: core.HomeAssistant):
|
||||
with patch("homeassistant.components.bond.Bond.turnOn") as mock_turn_on, patch(
|
||||
"homeassistant.components.bond.Bond.setSpeed"
|
||||
) as mock_set_speed:
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: "fan.name_1", fan.ATTR_SPEED: fan.SPEED_LOW},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await turn_fan_on(hass, "fan.name_1", fan.SPEED_LOW)
|
||||
|
||||
mock_set_speed.assert_called_once()
|
||||
mock_turn_on.assert_called_once()
|
||||
mock_set_speed.assert_called_once()
|
||||
mock_turn_on.assert_called_once()
|
||||
|
||||
|
||||
async def test_turn_off_fan(hass: core.HomeAssistant):
|
||||
@ -67,7 +110,8 @@ async def test_turn_off_fan(hass: core.HomeAssistant):
|
||||
FAN_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: "fan.name_1"}, blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
mock_turn_off.assert_called_once()
|
||||
|
||||
mock_turn_off.assert_called_once()
|
||||
|
||||
|
||||
async def test_update_reports_fan_on(hass: core.HomeAssistant):
|
||||
|
Loading…
x
Reference in New Issue
Block a user