mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 01:38:02 +00:00
Add Fan Speed number entity to Nexia (#98642)
* Add Fan Speed support to Nexia integration Adds a new "set_fan_speed" service to the Nexia integration, to allow setting speed of the air-handler/blower fans. * Add Fan Speed to Nexia Tests * Remove mistakenly-added changes to Climate tests A previous version of this change made modifications to the base Climate entity, but that approach was later abandonded. These changes to Climate tests were left over from that, and should never have been included. * Add Fan Speed Number Entity * Remove Set Fan Speed Service * Remove fan_speed attribute The fan_speed attribute is not necessary with the new Number entity. * Address reviewer feedback Rename test function to reflect fact that fan speed entities are entities, and not sensors. Added missing typing to variables. Sorted list of platforms * Add test_set_fan_speed Also adds new test fixture for mock response to API call * Update homeassistant/components/nexia/number.py * Name change --------- Co-authored-by: G Johansson <goran.johansson@shiftit.se>
This commit is contained in:
parent
3094991236
commit
5965918c86
@ -2,10 +2,11 @@
|
||||
from homeassistant.const import Platform
|
||||
|
||||
PLATFORMS = [
|
||||
Platform.SENSOR,
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.CLIMATE,
|
||||
Platform.NUMBER,
|
||||
Platform.SCENE,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
]
|
||||
|
||||
|
72
homeassistant/components/nexia/number.py
Normal file
72
homeassistant/components/nexia/number.py
Normal file
@ -0,0 +1,72 @@
|
||||
"""Support for Nexia / Trane XL Thermostats."""
|
||||
from __future__ import annotations
|
||||
|
||||
from nexia.home import NexiaHome
|
||||
from nexia.thermostat import NexiaThermostat
|
||||
|
||||
from homeassistant.components.number import NumberEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import PERCENTAGE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import NexiaDataUpdateCoordinator
|
||||
from .entity import NexiaThermostatEntity
|
||||
from .util import percent_conv
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up sensors for a Nexia device."""
|
||||
coordinator: NexiaDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||
nexia_home: NexiaHome = coordinator.nexia_home
|
||||
|
||||
entities: list[NexiaThermostatEntity] = []
|
||||
for thermostat_id in nexia_home.get_thermostat_ids():
|
||||
thermostat = nexia_home.get_thermostat_by_id(thermostat_id)
|
||||
if thermostat.has_variable_fan_speed():
|
||||
entities.append(
|
||||
NexiaFanSpeedEntity(
|
||||
coordinator, thermostat, thermostat.get_variable_fan_speed_limits()
|
||||
)
|
||||
)
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class NexiaFanSpeedEntity(NexiaThermostatEntity, NumberEntity):
|
||||
"""Provides Nexia Fan Speed support."""
|
||||
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
_attr_icon = "mdi:fan"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: NexiaDataUpdateCoordinator,
|
||||
thermostat: NexiaThermostat,
|
||||
valid_range: tuple[float, float],
|
||||
) -> None:
|
||||
"""Initialize the entity."""
|
||||
super().__init__(
|
||||
coordinator,
|
||||
thermostat,
|
||||
name=f"{thermostat.get_name()} Fan speed",
|
||||
unique_id=f"{thermostat.thermostat_id}_fan_speed_setpoint",
|
||||
)
|
||||
min_value, max_value = valid_range
|
||||
self._attr_native_min_value = percent_conv(min_value)
|
||||
self._attr_native_max_value = percent_conv(max_value)
|
||||
|
||||
@property
|
||||
def native_value(self) -> float:
|
||||
"""Return the current value."""
|
||||
fan_speed = self._thermostat.get_fan_speed_setpoint()
|
||||
return percent_conv(fan_speed)
|
||||
|
||||
async def async_set_native_value(self, value: float) -> None:
|
||||
"""Set a new value."""
|
||||
await self._thermostat.set_fan_setpoint(value / 100)
|
||||
self._signal_thermostat_update()
|
3086
tests/components/nexia/fixtures/set_fan_speed_2293892.json
Normal file
3086
tests/components/nexia/fixtures/set_fan_speed_2293892.json
Normal file
File diff suppressed because it is too large
Load Diff
62
tests/components/nexia/test_number.py
Normal file
62
tests/components/nexia/test_number.py
Normal file
@ -0,0 +1,62 @@
|
||||
"""The number entity tests for the nexia platform."""
|
||||
|
||||
from homeassistant.components.number import (
|
||||
ATTR_VALUE,
|
||||
DOMAIN as NUMBER_DOMAIN,
|
||||
SERVICE_SET_VALUE,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .util import async_init_integration
|
||||
|
||||
|
||||
async def test_create_fan_speed_number_entities(hass: HomeAssistant) -> None:
|
||||
"""Test creation of fan speed number entities."""
|
||||
|
||||
await async_init_integration(hass)
|
||||
|
||||
state = hass.states.get("number.master_suite_fan_speed")
|
||||
assert state.state == "35.0"
|
||||
expected_attributes = {
|
||||
"attribution": "Data provided by Trane Technologies",
|
||||
"friendly_name": "Master Suite Fan speed",
|
||||
"min": 35,
|
||||
"max": 100,
|
||||
}
|
||||
# Only test for a subset of attributes in case
|
||||
# HA changes the implementation and a new one appears
|
||||
assert all(
|
||||
state.attributes[key] == expected_attributes[key] for key in expected_attributes
|
||||
)
|
||||
|
||||
state = hass.states.get("number.downstairs_east_wing_fan_speed")
|
||||
assert state.state == "35.0"
|
||||
expected_attributes = {
|
||||
"attribution": "Data provided by Trane Technologies",
|
||||
"friendly_name": "Downstairs East Wing Fan speed",
|
||||
"min": 35,
|
||||
"max": 100,
|
||||
}
|
||||
# Only test for a subset of attributes in case
|
||||
# HA changes the implementation and a new one appears
|
||||
assert all(
|
||||
state.attributes[key] == expected_attributes[key] for key in expected_attributes
|
||||
)
|
||||
|
||||
|
||||
async def test_set_fan_speed(hass: HomeAssistant) -> None:
|
||||
"""Test setting fan speed."""
|
||||
|
||||
await async_init_integration(hass)
|
||||
|
||||
state_before = hass.states.get("number.master_suite_fan_speed")
|
||||
assert state_before.state == "35.0"
|
||||
await hass.services.async_call(
|
||||
NUMBER_DOMAIN,
|
||||
SERVICE_SET_VALUE,
|
||||
service_data={ATTR_VALUE: 50},
|
||||
blocking=True,
|
||||
target={"entity_id": "number.master_suite_fan_speed"},
|
||||
)
|
||||
state = hass.states.get("number.master_suite_fan_speed")
|
||||
assert state.state == "50.0"
|
@ -22,6 +22,7 @@ async def async_init_integration(
|
||||
house_fixture = "nexia/mobile_houses_123456.json"
|
||||
session_fixture = "nexia/session_123456.json"
|
||||
sign_in_fixture = "nexia/sign_in.json"
|
||||
set_fan_speed_fixture = "nexia/set_fan_speed_2293892.json"
|
||||
with mock_aiohttp_client() as mock_session, patch(
|
||||
"nexia.home.load_or_create_uuid", return_value=uuid.uuid4()
|
||||
):
|
||||
@ -46,6 +47,10 @@ async def async_init_integration(
|
||||
nexia.API_MOBILE_ACCOUNTS_SIGN_IN_URL,
|
||||
text=load_fixture(sign_in_fixture),
|
||||
)
|
||||
mock_session.post(
|
||||
"https://www.mynexia.com/mobile/xxl_thermostats/2293892/fan_speed",
|
||||
text=load_fixture(set_fan_speed_fixture),
|
||||
)
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN, data={CONF_USERNAME: "mock", CONF_PASSWORD: "mock"}
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user