mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Mqtt rework on value templates (#62105)
* add MqttValueTemplate class * support variables at initiation * pass MqttEntity instead of hass * Use MqttValueTemplace class for value templates * make hass en enitity parameters conditional * remove unused property and remove None assignment * rename self._attr_value_template
This commit is contained in:
parent
bf78ddcadb
commit
3ca18922e6
@ -99,6 +99,8 @@ from .util import _VALID_QOS_SCHEMA, valid_publish_topic, valid_subscribe_topic
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
_SENTINEL = object()
|
||||||
|
|
||||||
DATA_MQTT = "mqtt"
|
DATA_MQTT = "mqtt"
|
||||||
|
|
||||||
SERVICE_PUBLISH = "publish"
|
SERVICE_PUBLISH = "publish"
|
||||||
@ -317,6 +319,62 @@ class MqttCommandTemplate:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MqttValueTemplate:
|
||||||
|
"""Class for rendering MQTT value template with possible json values."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
value_template: template.Template | None,
|
||||||
|
*,
|
||||||
|
hass: HomeAssistant | None = None,
|
||||||
|
entity: Entity | None = None,
|
||||||
|
config_attributes: template.TemplateVarsType = None,
|
||||||
|
) -> None:
|
||||||
|
"""Instantiate a value template."""
|
||||||
|
self._value_template = value_template
|
||||||
|
self._config_attributes = config_attributes
|
||||||
|
if value_template is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
value_template.hass = hass
|
||||||
|
self._entity = entity
|
||||||
|
|
||||||
|
if entity:
|
||||||
|
value_template.hass = entity.hass
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_render_with_possible_json_value(
|
||||||
|
self,
|
||||||
|
payload: ReceivePayloadType,
|
||||||
|
default: ReceivePayloadType | object = _SENTINEL,
|
||||||
|
variables: template.TemplateVarsType = None,
|
||||||
|
) -> ReceivePayloadType:
|
||||||
|
"""Render with possible json value or pass-though a received MQTT value."""
|
||||||
|
if self._value_template is None:
|
||||||
|
return payload
|
||||||
|
|
||||||
|
values: dict[str, Any] = {}
|
||||||
|
|
||||||
|
if variables is not None:
|
||||||
|
values.update(variables)
|
||||||
|
|
||||||
|
if self._config_attributes is not None:
|
||||||
|
values.update(self._config_attributes)
|
||||||
|
|
||||||
|
if self._entity:
|
||||||
|
values[ATTR_ENTITY_ID] = self._entity.entity_id
|
||||||
|
values[ATTR_NAME] = self._entity.name
|
||||||
|
|
||||||
|
if default == _SENTINEL:
|
||||||
|
return self._value_template.async_render_with_possible_json_value(
|
||||||
|
payload, variables=values
|
||||||
|
)
|
||||||
|
|
||||||
|
return self._value_template.async_render_with_possible_json_value(
|
||||||
|
payload, default, variables=values
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class MqttServiceInfo(BaseServiceInfo):
|
class MqttServiceInfo(BaseServiceInfo):
|
||||||
"""Prepared info from mqtt entries."""
|
"""Prepared info from mqtt entries."""
|
||||||
|
@ -38,7 +38,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
from homeassistant.helpers.reload import async_setup_reload_service
|
from homeassistant.helpers.reload import async_setup_reload_service
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from . import PLATFORMS, MqttCommandTemplate, subscription
|
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
@ -165,9 +165,10 @@ class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity):
|
|||||||
return DISCOVERY_SCHEMA
|
return DISCOVERY_SCHEMA
|
||||||
|
|
||||||
def _setup_from_config(self, config):
|
def _setup_from_config(self, config):
|
||||||
value_template = self._config.get(CONF_VALUE_TEMPLATE)
|
self._value_template = MqttValueTemplate(
|
||||||
if value_template is not None:
|
self._config.get(CONF_VALUE_TEMPLATE),
|
||||||
value_template.hass = self.hass
|
entity=self,
|
||||||
|
).async_render_with_possible_json_value
|
||||||
self._command_template = MqttCommandTemplate(
|
self._command_template = MqttCommandTemplate(
|
||||||
self._config[CONF_COMMAND_TEMPLATE], entity=self
|
self._config[CONF_COMMAND_TEMPLATE], entity=self
|
||||||
).async_render
|
).async_render
|
||||||
@ -179,12 +180,7 @@ class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity):
|
|||||||
@log_messages(self.hass, self.entity_id)
|
@log_messages(self.hass, self.entity_id)
|
||||||
def message_received(msg):
|
def message_received(msg):
|
||||||
"""Run when new MQTT message has been received."""
|
"""Run when new MQTT message has been received."""
|
||||||
payload = msg.payload
|
payload = self._value_template(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(
|
|
||||||
msg.payload, self._state
|
|
||||||
)
|
|
||||||
if payload not in (
|
if payload not in (
|
||||||
STATE_ALARM_DISARMED,
|
STATE_ALARM_DISARMED,
|
||||||
STATE_ALARM_ARMED_HOME,
|
STATE_ALARM_ARMED_HOME,
|
||||||
|
@ -30,7 +30,7 @@ from homeassistant.helpers.reload import async_setup_reload_service
|
|||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from . import PLATFORMS, subscription
|
from . import PLATFORMS, MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import CONF_ENCODING, CONF_QOS, CONF_STATE_TOPIC, DOMAIN
|
from .const import CONF_ENCODING, CONF_QOS, CONF_STATE_TOPIC, DOMAIN
|
||||||
from .debug_info import log_messages
|
from .debug_info import log_messages
|
||||||
@ -119,9 +119,10 @@ class MqttBinarySensor(MqttEntity, BinarySensorEntity):
|
|||||||
return DISCOVERY_SCHEMA
|
return DISCOVERY_SCHEMA
|
||||||
|
|
||||||
def _setup_from_config(self, config):
|
def _setup_from_config(self, config):
|
||||||
value_template = self._config.get(CONF_VALUE_TEMPLATE)
|
self._value_template = MqttValueTemplate(
|
||||||
if value_template is not None:
|
self._config.get(CONF_VALUE_TEMPLATE),
|
||||||
value_template.hass = self.hass
|
entity=self,
|
||||||
|
).async_render_with_possible_json_value
|
||||||
|
|
||||||
async def _subscribe_topics(self):
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
@ -137,7 +138,6 @@ class MqttBinarySensor(MqttEntity, BinarySensorEntity):
|
|||||||
@log_messages(self.hass, self.entity_id)
|
@log_messages(self.hass, self.entity_id)
|
||||||
def state_message_received(msg):
|
def state_message_received(msg):
|
||||||
"""Handle a new received MQTT state message."""
|
"""Handle a new received MQTT state message."""
|
||||||
payload = msg.payload
|
|
||||||
# auto-expire enabled?
|
# auto-expire enabled?
|
||||||
expire_after = self._config.get(CONF_EXPIRE_AFTER)
|
expire_after = self._config.get(CONF_EXPIRE_AFTER)
|
||||||
|
|
||||||
@ -159,18 +159,14 @@ class MqttBinarySensor(MqttEntity, BinarySensorEntity):
|
|||||||
self.hass, self._value_is_expired, expiration_at
|
self.hass, self._value_is_expired, expiration_at
|
||||||
)
|
)
|
||||||
|
|
||||||
value_template = self._config.get(CONF_VALUE_TEMPLATE)
|
payload = self._value_template(msg.payload)
|
||||||
if value_template is not None:
|
|
||||||
payload = value_template.async_render_with_possible_json_value(
|
|
||||||
payload, variables={"entity_id": self.entity_id}
|
|
||||||
)
|
|
||||||
if not payload.strip(): # No output from template, ignore
|
if not payload.strip(): # No output from template, ignore
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Empty template output for entity: %s with state topic: %s. Payload: '%s', with value template '%s'",
|
"Empty template output for entity: %s with state topic: %s. Payload: '%s', with value template '%s'",
|
||||||
self._config[CONF_NAME],
|
self._config[CONF_NAME],
|
||||||
self._config[CONF_STATE_TOPIC],
|
self._config[CONF_STATE_TOPIC],
|
||||||
msg.payload,
|
msg.payload,
|
||||||
value_template,
|
self._config.get(CONF_VALUE_TEMPLATE),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -180,8 +176,8 @@ class MqttBinarySensor(MqttEntity, BinarySensorEntity):
|
|||||||
self._state = False
|
self._state = False
|
||||||
else: # Payload is not for this entity
|
else: # Payload is not for this entity
|
||||||
template_info = ""
|
template_info = ""
|
||||||
if value_template is not None:
|
if self._config.get(CONF_VALUE_TEMPLATE) is not None:
|
||||||
template_info = f", template output: '{payload}', with value template '{str(value_template)}'"
|
template_info = f", template output: '{payload}', with value template '{str(self._config.get(CONF_VALUE_TEMPLATE))}'"
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"No matching payload found for entity: %s with state topic: %s. Payload: '%s'%s",
|
"No matching payload found for entity: %s with state topic: %s. Payload: '%s'%s",
|
||||||
self._config[CONF_NAME],
|
self._config[CONF_NAME],
|
||||||
|
@ -56,7 +56,13 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
from homeassistant.helpers.reload import async_setup_reload_service
|
from homeassistant.helpers.reload import async_setup_reload_service
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from . import MQTT_BASE_PLATFORM_SCHEMA, PLATFORMS, MqttCommandTemplate, subscription
|
from . import (
|
||||||
|
MQTT_BASE_PLATFORM_SCHEMA,
|
||||||
|
PLATFORMS,
|
||||||
|
MqttCommandTemplate,
|
||||||
|
MqttValueTemplate,
|
||||||
|
subscription,
|
||||||
|
)
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import CONF_ENCODING, CONF_QOS, CONF_RETAIN, DOMAIN
|
from .const import CONF_ENCODING, CONF_QOS, CONF_RETAIN, DOMAIN
|
||||||
from .debug_info import log_messages
|
from .debug_info import log_messages
|
||||||
@ -372,19 +378,20 @@ class MqttClimate(MqttEntity, ClimateEntity):
|
|||||||
|
|
||||||
value_templates = {}
|
value_templates = {}
|
||||||
for key in VALUE_TEMPLATE_KEYS:
|
for key in VALUE_TEMPLATE_KEYS:
|
||||||
value_templates[key] = lambda value: value
|
value_templates[key] = None
|
||||||
if CONF_VALUE_TEMPLATE in config:
|
if CONF_VALUE_TEMPLATE in config:
|
||||||
value_template = config.get(CONF_VALUE_TEMPLATE)
|
|
||||||
value_template.hass = self.hass
|
|
||||||
value_templates = {
|
value_templates = {
|
||||||
key: value_template.async_render_with_possible_json_value
|
key: config.get(CONF_VALUE_TEMPLATE) for key in VALUE_TEMPLATE_KEYS
|
||||||
for key in VALUE_TEMPLATE_KEYS
|
|
||||||
}
|
}
|
||||||
for key in VALUE_TEMPLATE_KEYS & config.keys():
|
for key in VALUE_TEMPLATE_KEYS & config.keys():
|
||||||
tpl = config[key]
|
value_templates[key] = config[key]
|
||||||
value_templates[key] = tpl.async_render_with_possible_json_value
|
self._value_templates = {
|
||||||
tpl.hass = self.hass
|
key: MqttValueTemplate(
|
||||||
self._value_templates = value_templates
|
template,
|
||||||
|
entity=self,
|
||||||
|
).async_render_with_possible_json_value
|
||||||
|
for key, template in value_templates.items()
|
||||||
|
}
|
||||||
|
|
||||||
command_templates = {}
|
command_templates = {}
|
||||||
for key in COMMAND_TEMPLATE_KEYS:
|
for key in COMMAND_TEMPLATE_KEYS:
|
||||||
|
@ -40,7 +40,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
from homeassistant.helpers.reload import async_setup_reload_service
|
from homeassistant.helpers.reload import async_setup_reload_service
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from . import PLATFORMS, MqttCommandTemplate, subscription
|
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
@ -303,27 +303,39 @@ class MqttCover(MqttEntity, CoverEntity):
|
|||||||
# Force into optimistic tilt mode.
|
# Force into optimistic tilt mode.
|
||||||
self._tilt_optimistic = True
|
self._tilt_optimistic = True
|
||||||
|
|
||||||
value_template = self._config.get(CONF_VALUE_TEMPLATE)
|
template_config_attributes = {
|
||||||
if value_template is not None:
|
"position_open": self._config[CONF_POSITION_OPEN],
|
||||||
value_template.hass = self.hass
|
"position_closed": self._config[CONF_POSITION_CLOSED],
|
||||||
|
"tilt_min": self._config[CONF_TILT_MIN],
|
||||||
|
"tilt_max": self._config[CONF_TILT_MAX],
|
||||||
|
}
|
||||||
|
|
||||||
|
self._value_template = MqttValueTemplate(
|
||||||
|
self._config.get(CONF_VALUE_TEMPLATE),
|
||||||
|
entity=self,
|
||||||
|
).async_render_with_possible_json_value
|
||||||
|
|
||||||
self._set_position_template = MqttCommandTemplate(
|
self._set_position_template = MqttCommandTemplate(
|
||||||
self._config.get(CONF_SET_POSITION_TEMPLATE), entity=self
|
self._config.get(CONF_SET_POSITION_TEMPLATE), entity=self
|
||||||
).async_render
|
).async_render
|
||||||
|
|
||||||
get_position_template = self._config.get(CONF_GET_POSITION_TEMPLATE)
|
self._get_position_template = MqttValueTemplate(
|
||||||
if get_position_template is not None:
|
self._config.get(CONF_GET_POSITION_TEMPLATE),
|
||||||
get_position_template.hass = self.hass
|
entity=self,
|
||||||
|
config_attributes=template_config_attributes,
|
||||||
|
).async_render_with_possible_json_value
|
||||||
|
|
||||||
self._set_tilt_template = MqttCommandTemplate(
|
self._set_tilt_template = MqttCommandTemplate(
|
||||||
self._config.get(CONF_TILT_COMMAND_TEMPLATE), entity=self
|
self._config.get(CONF_TILT_COMMAND_TEMPLATE), entity=self
|
||||||
).async_render
|
).async_render
|
||||||
|
|
||||||
tilt_status_template = self._config.get(CONF_TILT_STATUS_TEMPLATE)
|
self._tilt_status_template = MqttValueTemplate(
|
||||||
if tilt_status_template is not None:
|
self._config.get(CONF_TILT_STATUS_TEMPLATE),
|
||||||
tilt_status_template.hass = self.hass
|
entity=self,
|
||||||
|
config_attributes=template_config_attributes,
|
||||||
|
).async_render_with_possible_json_value
|
||||||
|
|
||||||
async def _subscribe_topics(self): # noqa: C901
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
topics = {}
|
topics = {}
|
||||||
|
|
||||||
@ -331,19 +343,7 @@ class MqttCover(MqttEntity, CoverEntity):
|
|||||||
@log_messages(self.hass, self.entity_id)
|
@log_messages(self.hass, self.entity_id)
|
||||||
def tilt_message_received(msg):
|
def tilt_message_received(msg):
|
||||||
"""Handle tilt updates."""
|
"""Handle tilt updates."""
|
||||||
payload = msg.payload
|
payload = self._tilt_status_template(msg.payload)
|
||||||
template = self._config.get(CONF_TILT_STATUS_TEMPLATE)
|
|
||||||
if template is not None:
|
|
||||||
variables = {
|
|
||||||
"entity_id": self.entity_id,
|
|
||||||
"position_open": self._config[CONF_POSITION_OPEN],
|
|
||||||
"position_closed": self._config[CONF_POSITION_CLOSED],
|
|
||||||
"tilt_min": self._config[CONF_TILT_MIN],
|
|
||||||
"tilt_max": self._config[CONF_TILT_MAX],
|
|
||||||
}
|
|
||||||
payload = template.async_render_with_possible_json_value(
|
|
||||||
payload, variables=variables
|
|
||||||
)
|
|
||||||
|
|
||||||
if not payload:
|
if not payload:
|
||||||
_LOGGER.debug("Ignoring empty tilt message from '%s'", msg.topic)
|
_LOGGER.debug("Ignoring empty tilt message from '%s'", msg.topic)
|
||||||
@ -355,13 +355,7 @@ class MqttCover(MqttEntity, CoverEntity):
|
|||||||
@log_messages(self.hass, self.entity_id)
|
@log_messages(self.hass, self.entity_id)
|
||||||
def state_message_received(msg):
|
def state_message_received(msg):
|
||||||
"""Handle new MQTT state messages."""
|
"""Handle new MQTT state messages."""
|
||||||
payload = msg.payload
|
payload = self._value_template(msg.payload)
|
||||||
template = self._config.get(CONF_VALUE_TEMPLATE)
|
|
||||||
if template is not None:
|
|
||||||
variables = {"entity_id": self.entity_id}
|
|
||||||
payload = template.async_render_with_possible_json_value(
|
|
||||||
payload, variables=variables
|
|
||||||
)
|
|
||||||
|
|
||||||
if not payload:
|
if not payload:
|
||||||
_LOGGER.debug("Ignoring empty state message from '%s'", msg.topic)
|
_LOGGER.debug("Ignoring empty state message from '%s'", msg.topic)
|
||||||
@ -399,25 +393,10 @@ class MqttCover(MqttEntity, CoverEntity):
|
|||||||
@log_messages(self.hass, self.entity_id)
|
@log_messages(self.hass, self.entity_id)
|
||||||
def position_message_received(msg):
|
def position_message_received(msg):
|
||||||
"""Handle new MQTT position messages."""
|
"""Handle new MQTT position messages."""
|
||||||
payload = msg.payload
|
payload = self._get_position_template(msg.payload)
|
||||||
|
|
||||||
template = self._config.get(CONF_GET_POSITION_TEMPLATE)
|
|
||||||
if template is not None:
|
|
||||||
variables = {
|
|
||||||
"entity_id": self.entity_id,
|
|
||||||
"position_open": self._config[CONF_POSITION_OPEN],
|
|
||||||
"position_closed": self._config[CONF_POSITION_CLOSED],
|
|
||||||
"tilt_min": self._config[CONF_TILT_MIN],
|
|
||||||
"tilt_max": self._config[CONF_TILT_MAX],
|
|
||||||
}
|
|
||||||
payload = template.async_render_with_possible_json_value(
|
|
||||||
payload, variables=variables
|
|
||||||
)
|
|
||||||
|
|
||||||
if not payload:
|
if not payload:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug("Ignoring empty position message from '%s'", msg.topic)
|
||||||
"Ignoring empty position message from '%s'", msg.topic
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -18,7 +18,7 @@ from homeassistant.const import (
|
|||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
from .. import subscription
|
from .. import MqttValueTemplate, subscription
|
||||||
from ... import mqtt
|
from ... import mqtt
|
||||||
from ..const import CONF_QOS, CONF_STATE_TOPIC
|
from ..const import CONF_QOS, CONF_STATE_TOPIC
|
||||||
from ..debug_info import log_messages
|
from ..debug_info import log_messages
|
||||||
@ -73,9 +73,9 @@ class MqttDeviceTracker(MqttEntity, TrackerEntity):
|
|||||||
|
|
||||||
def _setup_from_config(self, config):
|
def _setup_from_config(self, config):
|
||||||
"""(Re)Setup the entity."""
|
"""(Re)Setup the entity."""
|
||||||
value_template = self._config.get(CONF_VALUE_TEMPLATE)
|
self._value_template = MqttValueTemplate(
|
||||||
if value_template is not None:
|
self._config.get(CONF_VALUE_TEMPLATE), entity=self
|
||||||
value_template.hass = self.hass
|
).async_render_with_possible_json_value
|
||||||
|
|
||||||
async def _subscribe_topics(self):
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
@ -84,10 +84,7 @@ class MqttDeviceTracker(MqttEntity, TrackerEntity):
|
|||||||
@log_messages(self.hass, self.entity_id)
|
@log_messages(self.hass, self.entity_id)
|
||||||
def message_received(msg):
|
def message_received(msg):
|
||||||
"""Handle new MQTT messages."""
|
"""Handle new MQTT messages."""
|
||||||
payload = msg.payload
|
payload = self._value_template(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)
|
|
||||||
if payload == self._config[CONF_PAYLOAD_HOME]:
|
if payload == self._config[CONF_PAYLOAD_HOME]:
|
||||||
self._location_name = STATE_HOME
|
self._location_name = STATE_HOME
|
||||||
elif payload == self._config[CONF_PAYLOAD_NOT_HOME]:
|
elif payload == self._config[CONF_PAYLOAD_NOT_HOME]:
|
||||||
|
@ -40,7 +40,7 @@ from homeassistant.util.percentage import (
|
|||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import PLATFORMS, MqttCommandTemplate, subscription
|
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
@ -356,11 +356,10 @@ class MqttFan(MqttEntity, FanEntity):
|
|||||||
).async_render
|
).async_render
|
||||||
|
|
||||||
for key, tpl in self._value_templates.items():
|
for key, tpl in self._value_templates.items():
|
||||||
if tpl is None:
|
self._value_templates[key] = MqttValueTemplate(
|
||||||
self._value_templates[key] = lambda value: value
|
tpl,
|
||||||
else:
|
entity=self,
|
||||||
tpl.hass = self.hass
|
).async_render_with_possible_json_value
|
||||||
self._value_templates[key] = tpl.async_render_with_possible_json_value
|
|
||||||
|
|
||||||
async def _subscribe_topics(self):
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
|
@ -30,7 +30,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
from homeassistant.helpers.reload import async_setup_reload_service
|
from homeassistant.helpers.reload import async_setup_reload_service
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from . import PLATFORMS, MqttCommandTemplate, subscription
|
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
@ -262,11 +262,10 @@ class MqttHumidifier(MqttEntity, HumidifierEntity):
|
|||||||
).async_render
|
).async_render
|
||||||
|
|
||||||
for key, tpl in self._value_templates.items():
|
for key, tpl in self._value_templates.items():
|
||||||
if tpl is None:
|
self._value_templates[key] = MqttValueTemplate(
|
||||||
self._value_templates[key] = lambda value: value
|
tpl,
|
||||||
else:
|
entity=self,
|
||||||
tpl.hass = self.hass
|
).async_render_with_possible_json_value
|
||||||
self._value_templates[key] = tpl.async_render_with_possible_json_value
|
|
||||||
|
|
||||||
async def _subscribe_topics(self):
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
|
@ -51,7 +51,7 @@ import homeassistant.helpers.config_validation as cv
|
|||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
import homeassistant.util.color as color_util
|
import homeassistant.util.color as color_util
|
||||||
|
|
||||||
from .. import MqttCommandTemplate, subscription
|
from .. import MqttCommandTemplate, MqttValueTemplate, subscription
|
||||||
from ... import mqtt
|
from ... import mqtt
|
||||||
from ..const import (
|
from ..const import (
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
@ -325,12 +325,19 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||||||
|
|
||||||
value_templates = {}
|
value_templates = {}
|
||||||
for key in VALUE_TEMPLATE_KEYS:
|
for key in VALUE_TEMPLATE_KEYS:
|
||||||
value_templates[key] = lambda value, _: value
|
value_templates[key] = None
|
||||||
|
if CONF_VALUE_TEMPLATE in config:
|
||||||
|
value_templates = {
|
||||||
|
key: config.get(CONF_VALUE_TEMPLATE) for key in VALUE_TEMPLATE_KEYS
|
||||||
|
}
|
||||||
for key in VALUE_TEMPLATE_KEYS & config.keys():
|
for key in VALUE_TEMPLATE_KEYS & config.keys():
|
||||||
tpl = config[key]
|
value_templates[key] = config[key]
|
||||||
value_templates[key] = tpl.async_render_with_possible_json_value
|
self._value_templates = {
|
||||||
tpl.hass = self.hass
|
key: MqttValueTemplate(
|
||||||
self._value_templates = value_templates
|
template, entity=self
|
||||||
|
).async_render_with_possible_json_value
|
||||||
|
for key, template in value_templates.items()
|
||||||
|
}
|
||||||
|
|
||||||
command_templates = {}
|
command_templates = {}
|
||||||
for key in COMMAND_TEMPLATE_KEYS:
|
for key in COMMAND_TEMPLATE_KEYS:
|
||||||
|
@ -33,7 +33,7 @@ import homeassistant.helpers.config_validation as cv
|
|||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
import homeassistant.util.color as color_util
|
import homeassistant.util.color as color_util
|
||||||
|
|
||||||
from .. import subscription
|
from .. import MqttValueTemplate, subscription
|
||||||
from ... import mqtt
|
from ... import mqtt
|
||||||
from ..const import (
|
from ..const import (
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
@ -160,7 +160,7 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
for tpl in self._templates.values():
|
for tpl in self._templates.values():
|
||||||
if tpl is not None:
|
if tpl is not None:
|
||||||
tpl.hass = self.hass
|
tpl = MqttValueTemplate(tpl, entity=self)
|
||||||
|
|
||||||
last_state = await self.async_get_last_state()
|
last_state = await self.async_get_last_state()
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
from homeassistant.helpers.reload import async_setup_reload_service
|
from homeassistant.helpers.reload import async_setup_reload_service
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from . import PLATFORMS, subscription
|
from . import PLATFORMS, MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
@ -118,9 +118,10 @@ class MqttLock(MqttEntity, LockEntity):
|
|||||||
"""(Re)Setup the entity."""
|
"""(Re)Setup the entity."""
|
||||||
self._optimistic = config[CONF_OPTIMISTIC]
|
self._optimistic = config[CONF_OPTIMISTIC]
|
||||||
|
|
||||||
value_template = self._config.get(CONF_VALUE_TEMPLATE)
|
self._value_template = MqttValueTemplate(
|
||||||
if value_template is not None:
|
self._config.get(CONF_VALUE_TEMPLATE),
|
||||||
value_template.hass = self.hass
|
entity=self,
|
||||||
|
).async_render_with_possible_json_value
|
||||||
|
|
||||||
async def _subscribe_topics(self):
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
@ -129,10 +130,7 @@ class MqttLock(MqttEntity, LockEntity):
|
|||||||
@log_messages(self.hass, self.entity_id)
|
@log_messages(self.hass, self.entity_id)
|
||||||
def message_received(msg):
|
def message_received(msg):
|
||||||
"""Handle new MQTT messages."""
|
"""Handle new MQTT messages."""
|
||||||
payload = msg.payload
|
payload = self._value_template(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)
|
|
||||||
if payload == self._config[CONF_STATE_LOCKED]:
|
if payload == self._config[CONF_STATE_LOCKED]:
|
||||||
self._state = True
|
self._state = True
|
||||||
elif payload == self._config[CONF_STATE_UNLOCKED]:
|
elif payload == self._config[CONF_STATE_UNLOCKED]:
|
||||||
|
@ -38,7 +38,7 @@ from homeassistant.helpers.entity import (
|
|||||||
)
|
)
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
from . import DATA_MQTT, debug_info, publish, subscription
|
from . import DATA_MQTT, MqttValueTemplate, debug_info, publish, subscription
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_DISCOVERY_HASH,
|
ATTR_DISCOVERY_HASH,
|
||||||
ATTR_DISCOVERY_PAYLOAD,
|
ATTR_DISCOVERY_PAYLOAD,
|
||||||
@ -254,17 +254,15 @@ class MqttAttributes(Entity):
|
|||||||
|
|
||||||
async def _attributes_subscribe_topics(self):
|
async def _attributes_subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
attr_tpl = self._attributes_config.get(CONF_JSON_ATTRS_TEMPLATE)
|
attr_tpl = MqttValueTemplate(
|
||||||
if attr_tpl is not None:
|
self._attributes_config.get(CONF_JSON_ATTRS_TEMPLATE), entity=self
|
||||||
attr_tpl.hass = self.hass
|
).async_render_with_possible_json_value
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@log_messages(self.hass, self.entity_id)
|
@log_messages(self.hass, self.entity_id)
|
||||||
def attributes_message_received(msg: ReceiveMessage) -> None:
|
def attributes_message_received(msg: ReceiveMessage) -> None:
|
||||||
try:
|
try:
|
||||||
payload = msg.payload
|
payload = attr_tpl(msg.payload)
|
||||||
if attr_tpl is not None:
|
|
||||||
payload = attr_tpl.async_render_with_possible_json_value(payload)
|
|
||||||
json_dict = json.loads(payload) if isinstance(payload, str) else None
|
json_dict = json.loads(payload) if isinstance(payload, str) else None
|
||||||
if isinstance(json_dict, dict):
|
if isinstance(json_dict, dict):
|
||||||
filtered_dict = {
|
filtered_dict = {
|
||||||
@ -356,14 +354,10 @@ class MqttAvailability(Entity):
|
|||||||
topic, # pylint: disable=unused-variable
|
topic, # pylint: disable=unused-variable
|
||||||
avail_topic_conf,
|
avail_topic_conf,
|
||||||
) in self._avail_topics.items():
|
) in self._avail_topics.items():
|
||||||
tpl = avail_topic_conf[CONF_AVAILABILITY_TEMPLATE]
|
avail_topic_conf[CONF_AVAILABILITY_TEMPLATE] = MqttValueTemplate(
|
||||||
if tpl is None:
|
avail_topic_conf[CONF_AVAILABILITY_TEMPLATE],
|
||||||
avail_topic_conf[CONF_AVAILABILITY_TEMPLATE] = lambda value: value
|
entity=self,
|
||||||
else:
|
).async_render_with_possible_json_value
|
||||||
tpl.hass = self.hass
|
|
||||||
avail_topic_conf[
|
|
||||||
CONF_AVAILABILITY_TEMPLATE
|
|
||||||
] = tpl.async_render_with_possible_json_value
|
|
||||||
|
|
||||||
self._avail_config = config
|
self._avail_config = config
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ from homeassistant.helpers.reload import async_setup_reload_service
|
|||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from . import PLATFORMS, MqttCommandTemplate, subscription
|
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
@ -157,18 +157,12 @@ class MqttNumber(MqttEntity, NumberEntity, RestoreEntity):
|
|||||||
CONF_COMMAND_TEMPLATE: MqttCommandTemplate(
|
CONF_COMMAND_TEMPLATE: MqttCommandTemplate(
|
||||||
config.get(CONF_COMMAND_TEMPLATE), entity=self
|
config.get(CONF_COMMAND_TEMPLATE), entity=self
|
||||||
).async_render,
|
).async_render,
|
||||||
CONF_VALUE_TEMPLATE: config.get(CONF_VALUE_TEMPLATE),
|
CONF_VALUE_TEMPLATE: MqttValueTemplate(
|
||||||
|
config.get(CONF_VALUE_TEMPLATE),
|
||||||
|
entity=self,
|
||||||
|
).async_render_with_possible_json_value,
|
||||||
}
|
}
|
||||||
|
|
||||||
value_template = self._templates[CONF_VALUE_TEMPLATE]
|
|
||||||
if value_template is None:
|
|
||||||
self._templates[CONF_VALUE_TEMPLATE] = lambda value: value
|
|
||||||
else:
|
|
||||||
value_template.hass = self.hass
|
|
||||||
self._templates[
|
|
||||||
CONF_VALUE_TEMPLATE
|
|
||||||
] = value_template.async_render_with_possible_json_value
|
|
||||||
|
|
||||||
async def _subscribe_topics(self):
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ from homeassistant.helpers.reload import async_setup_reload_service
|
|||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from . import PLATFORMS, MqttCommandTemplate, subscription
|
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
@ -123,18 +123,12 @@ class MqttSelect(MqttEntity, SelectEntity, RestoreEntity):
|
|||||||
CONF_COMMAND_TEMPLATE: MqttCommandTemplate(
|
CONF_COMMAND_TEMPLATE: MqttCommandTemplate(
|
||||||
config.get(CONF_COMMAND_TEMPLATE), entity=self
|
config.get(CONF_COMMAND_TEMPLATE), entity=self
|
||||||
).async_render,
|
).async_render,
|
||||||
CONF_VALUE_TEMPLATE: config.get(CONF_VALUE_TEMPLATE),
|
CONF_VALUE_TEMPLATE: MqttValueTemplate(
|
||||||
|
config.get(CONF_VALUE_TEMPLATE),
|
||||||
|
entity=self,
|
||||||
|
).async_render_with_possible_json_value,
|
||||||
}
|
}
|
||||||
|
|
||||||
value_template = self._templates[CONF_VALUE_TEMPLATE]
|
|
||||||
if value_template is None:
|
|
||||||
self._templates[CONF_VALUE_TEMPLATE] = lambda value: value
|
|
||||||
else:
|
|
||||||
value_template.hass = self.hass
|
|
||||||
self._templates[
|
|
||||||
CONF_VALUE_TEMPLATE
|
|
||||||
] = value_template.async_render_with_possible_json_value
|
|
||||||
|
|
||||||
async def _subscribe_topics(self):
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ from homeassistant.helpers.reload import async_setup_reload_service
|
|||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from . import PLATFORMS, subscription
|
from . import PLATFORMS, MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import CONF_ENCODING, CONF_QOS, CONF_STATE_TOPIC, DOMAIN
|
from .const import CONF_ENCODING, CONF_QOS, CONF_STATE_TOPIC, DOMAIN
|
||||||
from .debug_info import log_messages
|
from .debug_info import log_messages
|
||||||
@ -167,19 +167,18 @@ class MqttSensor(MqttEntity, SensorEntity):
|
|||||||
|
|
||||||
def _setup_from_config(self, config):
|
def _setup_from_config(self, config):
|
||||||
"""(Re)Setup the entity."""
|
"""(Re)Setup the entity."""
|
||||||
template = self._config.get(CONF_VALUE_TEMPLATE)
|
self._template = MqttValueTemplate(
|
||||||
if template is not None:
|
self._config.get(CONF_VALUE_TEMPLATE), entity=self
|
||||||
template.hass = self.hass
|
).async_render_with_possible_json_value
|
||||||
last_reset_template = self._config.get(CONF_LAST_RESET_VALUE_TEMPLATE)
|
self._last_reset_template = MqttValueTemplate(
|
||||||
if last_reset_template is not None:
|
self._config.get(CONF_LAST_RESET_VALUE_TEMPLATE), entity=self
|
||||||
last_reset_template.hass = self.hass
|
).async_render_with_possible_json_value
|
||||||
|
|
||||||
async def _subscribe_topics(self):
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
topics = {}
|
topics = {}
|
||||||
|
|
||||||
def _update_state(msg):
|
def _update_state(msg):
|
||||||
payload = msg.payload
|
|
||||||
# auto-expire enabled?
|
# auto-expire enabled?
|
||||||
expire_after = self._config.get(CONF_EXPIRE_AFTER)
|
expire_after = self._config.get(CONF_EXPIRE_AFTER)
|
||||||
if expire_after is not None and expire_after > 0:
|
if expire_after is not None and expire_after > 0:
|
||||||
@ -198,14 +197,7 @@ class MqttSensor(MqttEntity, SensorEntity):
|
|||||||
self.hass, self._value_is_expired, expiration_at
|
self.hass, self._value_is_expired, expiration_at
|
||||||
)
|
)
|
||||||
|
|
||||||
template = self._config.get(CONF_VALUE_TEMPLATE)
|
payload = self._template(msg.payload)
|
||||||
if template is not None:
|
|
||||||
variables = {"entity_id": self.entity_id}
|
|
||||||
payload = template.async_render_with_possible_json_value(
|
|
||||||
payload,
|
|
||||||
self._state,
|
|
||||||
variables=variables,
|
|
||||||
)
|
|
||||||
|
|
||||||
if payload is not None and self.device_class in (
|
if payload is not None and self.device_class in (
|
||||||
SensorDeviceClass.DATE,
|
SensorDeviceClass.DATE,
|
||||||
@ -221,16 +213,8 @@ class MqttSensor(MqttEntity, SensorEntity):
|
|||||||
self._state = payload
|
self._state = payload
|
||||||
|
|
||||||
def _update_last_reset(msg):
|
def _update_last_reset(msg):
|
||||||
payload = msg.payload
|
payload = self._last_reset_template(msg.payload)
|
||||||
|
|
||||||
template = self._config.get(CONF_LAST_RESET_VALUE_TEMPLATE)
|
|
||||||
if template is not None:
|
|
||||||
variables = {"entity_id": self.entity_id}
|
|
||||||
payload = template.async_render_with_possible_json_value(
|
|
||||||
payload,
|
|
||||||
self._state,
|
|
||||||
variables=variables,
|
|
||||||
)
|
|
||||||
if not payload:
|
if not payload:
|
||||||
_LOGGER.debug("Ignoring empty last_reset message from '%s'", msg.topic)
|
_LOGGER.debug("Ignoring empty last_reset message from '%s'", msg.topic)
|
||||||
return
|
return
|
||||||
|
@ -24,7 +24,7 @@ from homeassistant.helpers.reload import async_setup_reload_service
|
|||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from . import PLATFORMS, subscription
|
from . import PLATFORMS, MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
@ -128,9 +128,9 @@ class MqttSwitch(MqttEntity, SwitchEntity, RestoreEntity):
|
|||||||
|
|
||||||
self._optimistic = config[CONF_OPTIMISTIC]
|
self._optimistic = config[CONF_OPTIMISTIC]
|
||||||
|
|
||||||
template = self._config.get(CONF_VALUE_TEMPLATE)
|
self._value_template = MqttValueTemplate(
|
||||||
if template is not None:
|
self._config.get(CONF_VALUE_TEMPLATE), entity=self
|
||||||
template.hass = self.hass
|
).async_render_with_possible_json_value
|
||||||
|
|
||||||
async def _subscribe_topics(self):
|
async def _subscribe_topics(self):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
@ -139,10 +139,7 @@ class MqttSwitch(MqttEntity, SwitchEntity, RestoreEntity):
|
|||||||
@log_messages(self.hass, self.entity_id)
|
@log_messages(self.hass, self.entity_id)
|
||||||
def state_message_received(msg):
|
def state_message_received(msg):
|
||||||
"""Handle new MQTT state messages."""
|
"""Handle new MQTT state messages."""
|
||||||
payload = msg.payload
|
payload = self._value_template(msg.payload)
|
||||||
template = self._config.get(CONF_VALUE_TEMPLATE)
|
|
||||||
if template is not None:
|
|
||||||
payload = template.async_render_with_possible_json_value(payload)
|
|
||||||
if payload == self._state_on:
|
if payload == self._state_on:
|
||||||
self._state = True
|
self._state = True
|
||||||
elif payload == self._state_off:
|
elif payload == self._state_off:
|
||||||
|
@ -12,7 +12,7 @@ from homeassistant.helpers.dispatcher import (
|
|||||||
async_dispatcher_send,
|
async_dispatcher_send,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import subscription
|
from . import MqttValueTemplate, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_DISCOVERY_HASH,
|
ATTR_DISCOVERY_HASH,
|
||||||
@ -143,12 +143,10 @@ class MQTTTagScanner:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _setup_from_config(self, config):
|
def _setup_from_config(self, config):
|
||||||
self._value_template = lambda value, error_value: value
|
self._value_template = MqttValueTemplate(
|
||||||
if CONF_VALUE_TEMPLATE in config:
|
config.get(CONF_VALUE_TEMPLATE),
|
||||||
value_template = config.get(CONF_VALUE_TEMPLATE)
|
hass=self.hass,
|
||||||
value_template.hass = self.hass
|
).async_render_with_possible_json_value
|
||||||
|
|
||||||
self._value_template = value_template.async_render_with_possible_json_value
|
|
||||||
|
|
||||||
async def setup(self):
|
async def setup(self):
|
||||||
"""Set up the MQTT tag scanner."""
|
"""Set up the MQTT tag scanner."""
|
||||||
@ -171,7 +169,7 @@ class MQTTTagScanner:
|
|||||||
"""Subscribe to MQTT topics."""
|
"""Subscribe to MQTT topics."""
|
||||||
|
|
||||||
async def tag_scanned(msg):
|
async def tag_scanned(msg):
|
||||||
tag_id = self._value_template(msg.payload, error_value="").strip()
|
tag_id = self._value_template(msg.payload, "").strip()
|
||||||
if not tag_id: # No output from template, ignore
|
if not tag_id: # No output from template, ignore
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ from homeassistant.core import callback
|
|||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.icon import icon_for_battery_level
|
from homeassistant.helpers.icon import icon_for_battery_level
|
||||||
|
|
||||||
from .. import subscription
|
from .. import MqttValueTemplate, subscription
|
||||||
from ... import mqtt
|
from ... import mqtt
|
||||||
from ..const import CONF_COMMAND_TOPIC, CONF_ENCODING, CONF_QOS, CONF_RETAIN
|
from ..const import CONF_COMMAND_TOPIC, CONF_ENCODING, CONF_QOS, CONF_RETAIN
|
||||||
from ..debug_info import log_messages
|
from ..debug_info import log_messages
|
||||||
@ -244,7 +244,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
|
|||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
for tpl in self._templates.values():
|
for tpl in self._templates.values():
|
||||||
if tpl is not None:
|
if tpl is not None:
|
||||||
tpl.hass = self.hass
|
tpl = MqttValueTemplate(tpl, entity=self)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@log_messages(self.hass, self.entity_id)
|
@log_messages(self.hass, self.entity_id)
|
||||||
@ -256,7 +256,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
|
|||||||
):
|
):
|
||||||
battery_level = self._templates[
|
battery_level = self._templates[
|
||||||
CONF_BATTERY_LEVEL_TEMPLATE
|
CONF_BATTERY_LEVEL_TEMPLATE
|
||||||
].async_render_with_possible_json_value(msg.payload, error_value=None)
|
].async_render_with_possible_json_value(msg.payload, None)
|
||||||
if battery_level:
|
if battery_level:
|
||||||
self._battery_level = int(battery_level)
|
self._battery_level = int(battery_level)
|
||||||
|
|
||||||
@ -266,7 +266,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
|
|||||||
):
|
):
|
||||||
charging = self._templates[
|
charging = self._templates[
|
||||||
CONF_CHARGING_TEMPLATE
|
CONF_CHARGING_TEMPLATE
|
||||||
].async_render_with_possible_json_value(msg.payload, error_value=None)
|
].async_render_with_possible_json_value(msg.payload, None)
|
||||||
if charging:
|
if charging:
|
||||||
self._charging = cv.boolean(charging)
|
self._charging = cv.boolean(charging)
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
|
|||||||
):
|
):
|
||||||
cleaning = self._templates[
|
cleaning = self._templates[
|
||||||
CONF_CLEANING_TEMPLATE
|
CONF_CLEANING_TEMPLATE
|
||||||
].async_render_with_possible_json_value(msg.payload, error_value=None)
|
].async_render_with_possible_json_value(msg.payload, None)
|
||||||
if cleaning:
|
if cleaning:
|
||||||
self._cleaning = cv.boolean(cleaning)
|
self._cleaning = cv.boolean(cleaning)
|
||||||
|
|
||||||
@ -286,7 +286,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
|
|||||||
):
|
):
|
||||||
docked = self._templates[
|
docked = self._templates[
|
||||||
CONF_DOCKED_TEMPLATE
|
CONF_DOCKED_TEMPLATE
|
||||||
].async_render_with_possible_json_value(msg.payload, error_value=None)
|
].async_render_with_possible_json_value(msg.payload, None)
|
||||||
if docked:
|
if docked:
|
||||||
self._docked = cv.boolean(docked)
|
self._docked = cv.boolean(docked)
|
||||||
|
|
||||||
@ -296,7 +296,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
|
|||||||
):
|
):
|
||||||
error = self._templates[
|
error = self._templates[
|
||||||
CONF_ERROR_TEMPLATE
|
CONF_ERROR_TEMPLATE
|
||||||
].async_render_with_possible_json_value(msg.payload, error_value=None)
|
].async_render_with_possible_json_value(msg.payload, None)
|
||||||
if error is not None:
|
if error is not None:
|
||||||
self._error = cv.string(error)
|
self._error = cv.string(error)
|
||||||
|
|
||||||
@ -318,7 +318,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
|
|||||||
):
|
):
|
||||||
fan_speed = self._templates[
|
fan_speed = self._templates[
|
||||||
CONF_FAN_SPEED_TEMPLATE
|
CONF_FAN_SPEED_TEMPLATE
|
||||||
].async_render_with_possible_json_value(msg.payload, error_value=None)
|
].async_render_with_possible_json_value(msg.payload, None)
|
||||||
if fan_speed:
|
if fan_speed:
|
||||||
self._fan_speed = fan_speed
|
self._fan_speed = fan_speed
|
||||||
|
|
||||||
|
@ -238,6 +238,35 @@ async def test_command_template_variables(hass, mqtt_mock):
|
|||||||
assert state.state == "beer"
|
assert state.state == "beer"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_value_template_value(hass):
|
||||||
|
"""Test the rendering of MQTT value template."""
|
||||||
|
|
||||||
|
variables = {"id": 1234, "some_var": "beer"}
|
||||||
|
|
||||||
|
# test rendering value
|
||||||
|
tpl = template.Template("{{ value_json.id }}", hass)
|
||||||
|
val_tpl = mqtt.MqttValueTemplate(tpl, hass=hass)
|
||||||
|
assert val_tpl.async_render_with_possible_json_value('{"id": 4321}') == "4321"
|
||||||
|
|
||||||
|
# test variables at rendering
|
||||||
|
tpl = template.Template("{{ value_json.id }} {{ some_var }}", hass)
|
||||||
|
val_tpl = mqtt.MqttValueTemplate(tpl, hass=hass)
|
||||||
|
assert (
|
||||||
|
val_tpl.async_render_with_possible_json_value(
|
||||||
|
'{"id": 4321}', variables=variables
|
||||||
|
)
|
||||||
|
== "4321 beer"
|
||||||
|
)
|
||||||
|
|
||||||
|
# test with default value if an error occurs due to an invalid template
|
||||||
|
tpl = template.Template("{{ value_json.id | as_datetime }}")
|
||||||
|
val_tpl = mqtt.MqttValueTemplate(tpl, hass=hass)
|
||||||
|
assert (
|
||||||
|
val_tpl.async_render_with_possible_json_value('{"otherid": 4321}', "my default")
|
||||||
|
== "my default"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_service_call_without_topic_does_not_publish(hass, mqtt_mock):
|
async def test_service_call_without_topic_does_not_publish(hass, mqtt_mock):
|
||||||
"""Test the service call if topic is missing."""
|
"""Test the service call if topic is missing."""
|
||||||
with pytest.raises(vol.Invalid):
|
with pytest.raises(vol.Invalid):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user