Support configuring the mode of MQTT number entities (#77478)

* Support configuring the mode of MQTT number entities

* Use modern schema for tests

Co-authored-by: jbouwh <jan@jbsoft.nl>
This commit is contained in:
Erik Montnemery 2022-08-30 12:47:35 +02:00 committed by GitHub
parent cf5a11a1e7
commit 14717951c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 1 deletions

View File

@ -99,6 +99,7 @@ ABBREVIATIONS = {
"min_mirs": "min_mireds",
"max_temp": "max_temp",
"min_temp": "min_temp",
"mode": "mode",
"mode_cmd_tpl": "mode_command_template",
"mode_cmd_t": "mode_command_topic",
"mode_stat_t": "mode_state_topic",

View File

@ -13,11 +13,13 @@ from homeassistant.components.number import (
DEFAULT_STEP,
DEVICE_CLASSES_SCHEMA,
NumberDeviceClass,
NumberMode,
RestoreNumber,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_DEVICE_CLASS,
CONF_MODE,
CONF_NAME,
CONF_OPTIMISTIC,
CONF_UNIT_OF_MEASUREMENT,
@ -83,6 +85,7 @@ _PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_MAX, default=DEFAULT_MAX_VALUE): vol.Coerce(float),
vol.Optional(CONF_MIN, default=DEFAULT_MIN_VALUE): vol.Coerce(float),
vol.Optional(CONF_MODE, default=NumberMode.AUTO): vol.Coerce(NumberMode),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_PAYLOAD_RESET, default=DEFAULT_PAYLOAD_RESET): cv.string,
@ -276,6 +279,11 @@ class MqttNumber(MqttEntity, RestoreNumber):
"""Return the current value."""
return self._current_number
@property
def mode(self) -> NumberMode:
"""Return the mode of the entity."""
return self._config[CONF_MODE]
async def async_set_native_value(self, value: float) -> None:
"""Update the current value."""
current_number = value

View File

@ -5,7 +5,7 @@ from unittest.mock import patch
import pytest
from homeassistant.components import number
from homeassistant.components import mqtt, number
from homeassistant.components.mqtt.number import (
CONF_MAX,
CONF_MIN,
@ -24,6 +24,7 @@ from homeassistant.const import (
ATTR_ASSUMED_STATE,
ATTR_DEVICE_CLASS,
ATTR_ENTITY_ID,
ATTR_MODE,
ATTR_UNIT_OF_MEASUREMENT,
TEMP_FAHRENHEIT,
Platform,
@ -702,6 +703,77 @@ async def test_invalid_min_max_attributes(hass, caplog, mqtt_mock_entry_no_yaml_
assert f"'{CONF_MAX}' must be > '{CONF_MIN}'" in caplog.text
async def test_default_mode(hass, mqtt_mock_entry_with_yaml_config):
"""Test default mode."""
topic = "test/number"
await async_setup_component(
hass,
mqtt.DOMAIN,
{
mqtt.DOMAIN: {
number.DOMAIN: {
"state_topic": topic,
"command_topic": topic,
"name": "Test Number",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
state = hass.states.get("number.test_number")
assert state.attributes.get(ATTR_MODE) == "auto"
@pytest.mark.parametrize("mode", ("auto", "box", "slider"))
async def test_mode(hass, mqtt_mock_entry_with_yaml_config, mode):
"""Test mode."""
topic = "test/number"
await async_setup_component(
hass,
mqtt.DOMAIN,
{
mqtt.DOMAIN: {
number.DOMAIN: {
"state_topic": topic,
"command_topic": topic,
"name": "Test Number",
"mode": mode,
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
state = hass.states.get("number.test_number")
assert state.attributes.get(ATTR_MODE) == mode
@pytest.mark.parametrize("mode,valid", [("bleh", False), ("auto", True)])
async def test_invalid_mode(hass, mode, valid):
"""Test invalid mode."""
topic = "test/number"
assert (
await async_setup_component(
hass,
mqtt.DOMAIN,
{
mqtt.DOMAIN: {
number.DOMAIN: {
"state_topic": topic,
"command_topic": topic,
"name": "Test Number",
"mode": mode,
}
}
},
)
is valid
)
async def test_mqtt_payload_not_a_number_warning(
hass, caplog, mqtt_mock_entry_with_yaml_config
):