Add Modbus fan speed support (#104577)

Co-authored-by: jan iversen <jancasacondor@gmail.com>
This commit is contained in:
Cían Hughes 2023-12-07 07:19:03 +00:00 committed by GitHub
parent 22119a2fd8
commit e051244927
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 587 additions and 16 deletions

View file

@ -3,14 +3,34 @@ import pytest
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN
from homeassistant.components.climate.const import (
ATTR_FAN_MODE,
ATTR_FAN_MODES,
ATTR_HVAC_MODE,
ATTR_HVAC_MODES,
FAN_AUTO,
FAN_DIFFUSE,
FAN_FOCUS,
FAN_HIGH,
FAN_LOW,
FAN_MEDIUM,
FAN_MIDDLE,
FAN_OFF,
FAN_ON,
FAN_TOP,
HVACMode,
)
from homeassistant.components.modbus.const import (
CONF_CLIMATES,
CONF_DATA_TYPE,
CONF_DEVICE_ADDRESS,
CONF_FAN_MODE_AUTO,
CONF_FAN_MODE_HIGH,
CONF_FAN_MODE_LOW,
CONF_FAN_MODE_MEDIUM,
CONF_FAN_MODE_OFF,
CONF_FAN_MODE_ON,
CONF_FAN_MODE_REGISTER,
CONF_FAN_MODE_VALUES,
CONF_HVAC_MODE_AUTO,
CONF_HVAC_MODE_COOL,
CONF_HVAC_MODE_DRY,
@ -183,7 +203,7 @@ async def test_config_climate(hass: HomeAssistant, mock_modbus) -> None:
],
)
async def test_config_hvac_mode_register(hass: HomeAssistant, mock_modbus) -> None:
"""Run configuration test for mode register."""
"""Run configuration test for HVAC mode register."""
state = hass.states.get(ENTITY_ID)
assert HVACMode.OFF in state.attributes[ATTR_HVAC_MODES]
assert HVACMode.HEAT in state.attributes[ATTR_HVAC_MODES]
@ -193,6 +213,47 @@ async def test_config_hvac_mode_register(hass: HomeAssistant, mock_modbus) -> No
assert HVACMode.FAN_ONLY in state.attributes[ATTR_HVAC_MODES]
@pytest.mark.parametrize(
"do_config",
[
{
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_TARGET_TEMP: 117,
CONF_ADDRESS: 117,
CONF_SLAVE: 10,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 11,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_ON: 0,
CONF_FAN_MODE_OFF: 1,
CONF_FAN_MODE_AUTO: 2,
CONF_FAN_MODE_LOW: 3,
CONF_FAN_MODE_MEDIUM: 4,
CONF_FAN_MODE_HIGH: 5,
},
},
}
],
},
],
)
async def test_config_fan_mode_register(hass: HomeAssistant, mock_modbus) -> None:
"""Run configuration test for Fan mode register."""
state = hass.states.get(ENTITY_ID)
assert FAN_ON in state.attributes[ATTR_FAN_MODES]
assert FAN_OFF in state.attributes[ATTR_FAN_MODES]
assert FAN_AUTO in state.attributes[ATTR_FAN_MODES]
assert FAN_LOW in state.attributes[ATTR_FAN_MODES]
assert FAN_MEDIUM in state.attributes[ATTR_FAN_MODES]
assert FAN_HIGH in state.attributes[ATTR_FAN_MODES]
assert FAN_TOP not in state.attributes[ATTR_FAN_MODES]
assert FAN_MIDDLE not in state.attributes[ATTR_FAN_MODES]
assert FAN_DIFFUSE not in state.attributes[ATTR_FAN_MODES]
assert FAN_FOCUS not in state.attributes[ATTR_FAN_MODES]
@pytest.mark.parametrize(
"do_config",
[
@ -338,6 +399,96 @@ async def test_service_climate_update(
assert hass.states.get(ENTITY_ID).state == result
@pytest.mark.parametrize(
("do_config", "result", "register_words"),
[
(
{
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_TARGET_TEMP: 117,
CONF_ADDRESS: 117,
CONF_SLAVE: 10,
CONF_SCAN_INTERVAL: 0,
CONF_DATA_TYPE: DataType.INT32,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 118,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_LOW: 0,
CONF_FAN_MODE_MEDIUM: 1,
CONF_FAN_MODE_HIGH: 2,
},
},
},
]
},
FAN_LOW,
[0x00],
),
(
{
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_TARGET_TEMP: 117,
CONF_ADDRESS: 117,
CONF_SLAVE: 10,
CONF_SCAN_INTERVAL: 0,
CONF_DATA_TYPE: DataType.INT32,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 118,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_LOW: 0,
CONF_FAN_MODE_MEDIUM: 1,
CONF_FAN_MODE_HIGH: 2,
},
},
},
]
},
FAN_MEDIUM,
[0x01],
),
(
{
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_TARGET_TEMP: 117,
CONF_ADDRESS: 117,
CONF_SLAVE: 10,
CONF_SCAN_INTERVAL: 0,
CONF_DATA_TYPE: DataType.INT32,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 118,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_LOW: 0,
CONF_FAN_MODE_MEDIUM: 1,
CONF_FAN_MODE_HIGH: 2,
},
},
CONF_HVAC_ONOFF_REGISTER: 119,
},
]
},
FAN_HIGH,
[0x02],
),
],
)
async def test_service_climate_fan_update(
hass: HomeAssistant, mock_modbus, mock_ha, result, register_words
) -> None:
"""Run test for service homeassistant.update_entity."""
mock_modbus.read_holding_registers.return_value = ReadResult(register_words)
await hass.services.async_call(
"homeassistant", "update_entity", {"entity_id": ENTITY_ID}, blocking=True
)
await hass.async_block_till_done()
assert hass.states.get(ENTITY_ID).attributes[ATTR_FAN_MODE] == result
@pytest.mark.parametrize(
("temperature", "result", "do_config"),
[
@ -529,10 +680,10 @@ async def test_service_climate_set_temperature(
),
],
)
async def test_service_set_mode(
async def test_service_set_hvac_mode(
hass: HomeAssistant, hvac_mode, result, mock_modbus, mock_ha
) -> None:
"""Test set mode."""
"""Test set HVAC mode."""
mock_modbus.read_holding_registers.return_value = ReadResult(result)
await hass.services.async_call(
CLIMATE_DOMAIN,
@ -545,6 +696,69 @@ async def test_service_set_mode(
)
@pytest.mark.parametrize(
("fan_mode", "result", "do_config"),
[
(
FAN_OFF,
[0x02],
{
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_TARGET_TEMP: 117,
CONF_ADDRESS: 117,
CONF_SLAVE: 10,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 118,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_ON: 1,
CONF_FAN_MODE_OFF: 2,
},
},
}
]
},
),
(
FAN_ON,
[0x01],
{
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_TARGET_TEMP: 117,
CONF_ADDRESS: 117,
CONF_SLAVE: 10,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 118,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_ON: 1,
CONF_FAN_MODE_OFF: 2,
},
},
}
]
},
),
],
)
async def test_service_set_fan_mode(
hass: HomeAssistant, fan_mode, result, mock_modbus, mock_ha
) -> None:
"""Test set Fan mode."""
mock_modbus.read_holding_registers.return_value = ReadResult(result)
await hass.services.async_call(
CLIMATE_DOMAIN,
"set_fan_mode",
{
"entity_id": ENTITY_ID,
ATTR_FAN_MODE: fan_mode,
},
blocking=True,
)
test_value = State(ENTITY_ID, 35)
test_value.attributes = {ATTR_TEMPERATURE: 37}