Add value_template support to MQTT number (#52155)

pull/52245/head
Erik Montnemery 2021-06-28 10:23:34 +02:00 committed by GitHub
parent 3d556f14a5
commit e14480599b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 9 deletions

View File

@ -11,7 +11,7 @@ from homeassistant.components.number import (
DEFAULT_STEP,
NumberEntity,
)
from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC
from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, CONF_VALUE_TEMPLATE
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.reload import async_setup_reload_service
@ -59,6 +59,7 @@ PLATFORM_SCHEMA = vol.All(
vol.Optional(CONF_STEP, default=DEFAULT_STEP): vol.All(
vol.Coerce(float), vol.Range(min=1e-3)
),
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
},
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema),
validate_config,
@ -70,28 +71,28 @@ async def async_setup_platform(
):
"""Set up MQTT number through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(async_add_entities, config)
await _async_setup_entity(hass, async_add_entities, config)
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up MQTT number dynamically through MQTT discovery."""
setup = functools.partial(
_async_setup_entity, async_add_entities, config_entry=config_entry
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, number.DOMAIN, setup, PLATFORM_SCHEMA)
async def _async_setup_entity(
async_add_entities, config, config_entry=None, discovery_data=None
hass, async_add_entities, config, config_entry=None, discovery_data=None
):
"""Set up the MQTT number."""
async_add_entities([MqttNumber(config, config_entry, discovery_data)])
async_add_entities([MqttNumber(hass, config, config_entry, discovery_data)])
class MqttNumber(MqttEntity, NumberEntity, RestoreEntity):
"""representation of an MQTT number."""
def __init__(self, config, config_entry, discovery_data):
def __init__(self, hass, config, config_entry, discovery_data):
"""Initialize the MQTT Number."""
self._config = config
self._optimistic = False
@ -100,7 +101,7 @@ class MqttNumber(MqttEntity, NumberEntity, RestoreEntity):
self._current_number = None
NumberEntity.__init__(self)
MqttEntity.__init__(self, None, config, config_entry, discovery_data)
MqttEntity.__init__(self, hass, config, config_entry, discovery_data)
@staticmethod
def config_schema():
@ -111,6 +112,10 @@ class MqttNumber(MqttEntity, NumberEntity, RestoreEntity):
"""(Re)Setup the entity."""
self._optimistic = config[CONF_OPTIMISTIC]
value_template = self._config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template.hass = self.hass
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
@ -119,11 +124,14 @@ class MqttNumber(MqttEntity, NumberEntity, RestoreEntity):
def message_received(msg):
"""Handle new MQTT messages."""
payload = msg.payload
value_template = self._config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
payload = value_template.async_render_with_possible_json_value(payload)
try:
if payload.isnumeric():
num_value = int(msg.payload)
num_value = int(payload)
else:
num_value = float(msg.payload)
num_value = float(payload)
except ValueError:
_LOGGER.warning("Payload '%s' is not a Number", msg.payload)
return

View File

@ -81,6 +81,39 @@ async def test_run_number_setup(hass, mqtt_mock):
assert state.state == "20.5"
async def test_value_template(hass, mqtt_mock):
"""Test that it fetches the given payload with a template."""
topic = "test/number"
await async_setup_component(
hass,
"number",
{
"number": {
"platform": "mqtt",
"state_topic": topic,
"command_topic": topic,
"name": "Test Number",
"value_template": "{{ value_json.val }}",
}
},
)
await hass.async_block_till_done()
async_fire_mqtt_message(hass, topic, '{"val":10}')
await hass.async_block_till_done()
state = hass.states.get("number.test_number")
assert state.state == "10"
async_fire_mqtt_message(hass, topic, '{"val":20.5}')
await hass.async_block_till_done()
state = hass.states.get("number.test_number")
assert state.state == "20.5"
async def test_run_number_service_optimistic(hass, mqtt_mock):
"""Test that set_value service works in optimistic mode."""
topic = "test/number"