Add mqtt sensor configurable state encoding for sensor and binary_sensor platform (#60447)
* Add mqtt sensor state encoding * Make encoding attribute not specific to states * Move encoding attribute to schema base
This commit is contained in:
parent
7469f083fd
commit
2a2a20fcb3
8 changed files with 76 additions and 7 deletions
|
@ -57,6 +57,7 @@ from .const import (
|
||||||
CONF_BIRTH_MESSAGE,
|
CONF_BIRTH_MESSAGE,
|
||||||
CONF_BROKER,
|
CONF_BROKER,
|
||||||
CONF_COMMAND_TOPIC,
|
CONF_COMMAND_TOPIC,
|
||||||
|
CONF_ENCODING,
|
||||||
CONF_QOS,
|
CONF_QOS,
|
||||||
CONF_RETAIN,
|
CONF_RETAIN,
|
||||||
CONF_STATE_TOPIC,
|
CONF_STATE_TOPIC,
|
||||||
|
@ -65,6 +66,7 @@ from .const import (
|
||||||
DATA_MQTT_CONFIG,
|
DATA_MQTT_CONFIG,
|
||||||
DEFAULT_BIRTH,
|
DEFAULT_BIRTH,
|
||||||
DEFAULT_DISCOVERY,
|
DEFAULT_DISCOVERY,
|
||||||
|
DEFAULT_ENCODING,
|
||||||
DEFAULT_PREFIX,
|
DEFAULT_PREFIX,
|
||||||
DEFAULT_QOS,
|
DEFAULT_QOS,
|
||||||
DEFAULT_RETAIN,
|
DEFAULT_RETAIN,
|
||||||
|
@ -200,7 +202,10 @@ CONFIG_SCHEMA = vol.Schema(
|
||||||
extra=vol.ALLOW_EXTRA,
|
extra=vol.ALLOW_EXTRA,
|
||||||
)
|
)
|
||||||
|
|
||||||
SCHEMA_BASE = {vol.Optional(CONF_QOS, default=DEFAULT_QOS): _VALID_QOS_SCHEMA}
|
SCHEMA_BASE = {
|
||||||
|
vol.Optional(CONF_QOS, default=DEFAULT_QOS): _VALID_QOS_SCHEMA,
|
||||||
|
vol.Optional(CONF_ENCODING, default=DEFAULT_ENCODING): cv.string,
|
||||||
|
}
|
||||||
|
|
||||||
MQTT_BASE_PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend(SCHEMA_BASE)
|
MQTT_BASE_PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend(SCHEMA_BASE)
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ ABBREVIATIONS = {
|
||||||
"dev_cla": "device_class",
|
"dev_cla": "device_class",
|
||||||
"dock_t": "docked_topic",
|
"dock_t": "docked_topic",
|
||||||
"dock_tpl": "docked_template",
|
"dock_tpl": "docked_template",
|
||||||
|
"e": "encoding",
|
||||||
"en": "enabled_by_default",
|
"en": "enabled_by_default",
|
||||||
"err_t": "error_topic",
|
"err_t": "error_topic",
|
||||||
"err_tpl": "error_template",
|
"err_tpl": "error_template",
|
||||||
|
|
|
@ -28,7 +28,7 @@ from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from . import PLATFORMS, subscription
|
from . import PLATFORMS, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import 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
|
||||||
from .mixins import (
|
from .mixins import (
|
||||||
MQTT_ENTITY_COMMON_SCHEMA,
|
MQTT_ENTITY_COMMON_SCHEMA,
|
||||||
|
@ -200,6 +200,7 @@ class MqttBinarySensor(MqttEntity, BinarySensorEntity):
|
||||||
"topic": self._config[CONF_STATE_TOPIC],
|
"topic": self._config[CONF_STATE_TOPIC],
|
||||||
"msg_callback": state_message_received,
|
"msg_callback": state_message_received,
|
||||||
"qos": self._config[CONF_QOS],
|
"qos": self._config[CONF_QOS],
|
||||||
|
"encoding": self._config[CONF_ENCODING] or None,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,6 +13,7 @@ CONF_AVAILABILITY = "availability"
|
||||||
CONF_BROKER = "broker"
|
CONF_BROKER = "broker"
|
||||||
CONF_BIRTH_MESSAGE = "birth_message"
|
CONF_BIRTH_MESSAGE = "birth_message"
|
||||||
CONF_COMMAND_TOPIC = "command_topic"
|
CONF_COMMAND_TOPIC = "command_topic"
|
||||||
|
CONF_ENCODING = "encoding"
|
||||||
CONF_QOS = ATTR_QOS
|
CONF_QOS = ATTR_QOS
|
||||||
CONF_RETAIN = ATTR_RETAIN
|
CONF_RETAIN = ATTR_RETAIN
|
||||||
CONF_STATE_TOPIC = "state_topic"
|
CONF_STATE_TOPIC = "state_topic"
|
||||||
|
@ -24,6 +25,7 @@ DATA_MQTT_CONFIG = "mqtt_config"
|
||||||
DEFAULT_PREFIX = "homeassistant"
|
DEFAULT_PREFIX = "homeassistant"
|
||||||
DEFAULT_BIRTH_WILL_TOPIC = DEFAULT_PREFIX + "/status"
|
DEFAULT_BIRTH_WILL_TOPIC = DEFAULT_PREFIX + "/status"
|
||||||
DEFAULT_DISCOVERY = True
|
DEFAULT_DISCOVERY = True
|
||||||
|
DEFAULT_ENCODING = "utf-8"
|
||||||
DEFAULT_QOS = 0
|
DEFAULT_QOS = 0
|
||||||
DEFAULT_PAYLOAD_AVAILABLE = "online"
|
DEFAULT_PAYLOAD_AVAILABLE = "online"
|
||||||
DEFAULT_PAYLOAD_NOT_AVAILABLE = "offline"
|
DEFAULT_PAYLOAD_NOT_AVAILABLE = "offline"
|
||||||
|
|
|
@ -33,7 +33,7 @@ from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from . import PLATFORMS, subscription
|
from . import PLATFORMS, subscription
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import 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
|
||||||
from .mixins import (
|
from .mixins import (
|
||||||
MQTT_ENTITY_COMMON_SCHEMA,
|
MQTT_ENTITY_COMMON_SCHEMA,
|
||||||
|
@ -252,6 +252,7 @@ class MqttSensor(MqttEntity, SensorEntity):
|
||||||
"topic": self._config[CONF_STATE_TOPIC],
|
"topic": self._config[CONF_STATE_TOPIC],
|
||||||
"msg_callback": message_received,
|
"msg_callback": message_received,
|
||||||
"qos": self._config[CONF_QOS],
|
"qos": self._config[CONF_QOS],
|
||||||
|
"encoding": self._config[CONF_ENCODING] or None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
|
|
@ -10,13 +10,10 @@ from homeassistant.core import HassJob, callback
|
||||||
from homeassistant.helpers import config_validation as cv, template
|
from homeassistant.helpers import config_validation as cv, template
|
||||||
|
|
||||||
from .. import mqtt
|
from .. import mqtt
|
||||||
from .const import CONF_QOS, CONF_TOPIC
|
from .const import CONF_ENCODING, CONF_QOS, CONF_TOPIC, DEFAULT_ENCODING, DEFAULT_QOS
|
||||||
|
|
||||||
# mypy: allow-untyped-defs
|
# mypy: allow-untyped-defs
|
||||||
|
|
||||||
CONF_ENCODING = "encoding"
|
|
||||||
DEFAULT_ENCODING = "utf-8"
|
|
||||||
DEFAULT_QOS = 0
|
|
||||||
|
|
||||||
TRIGGER_SCHEMA = cv.TRIGGER_BASE_SCHEMA.extend(
|
TRIGGER_SCHEMA = cv.TRIGGER_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
|
|
|
@ -373,6 +373,39 @@ async def test_setting_sensor_value_via_mqtt_message_and_template2(
|
||||||
assert "template output: 'ILLEGAL'" in caplog.text
|
assert "template output: 'ILLEGAL'" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_setting_sensor_value_via_mqtt_message_and_template_and_raw_state_encoding(
|
||||||
|
hass, mqtt_mock, caplog
|
||||||
|
):
|
||||||
|
"""Test processing a raw value via MQTT."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
binary_sensor.DOMAIN,
|
||||||
|
{
|
||||||
|
binary_sensor.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"encoding": "",
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"payload_on": "ON",
|
||||||
|
"payload_off": "OFF",
|
||||||
|
"value_template": "{%if value|bitwise_and(1)-%}ON{%else%}OFF{%-endif-%}",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("binary_sensor.test")
|
||||||
|
assert state.state == STATE_OFF
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "test-topic", b"\x01")
|
||||||
|
state = hass.states.get("binary_sensor.test")
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "test-topic", b"\x00")
|
||||||
|
state = hass.states.get("binary_sensor.test")
|
||||||
|
assert state.state == STATE_OFF
|
||||||
|
|
||||||
|
|
||||||
async def test_setting_sensor_value_via_mqtt_message_empty_template(
|
async def test_setting_sensor_value_via_mqtt_message_empty_template(
|
||||||
hass, mqtt_mock, caplog
|
hass, mqtt_mock, caplog
|
||||||
):
|
):
|
||||||
|
|
|
@ -894,6 +894,35 @@ async def test_entity_category(hass, mqtt_mock):
|
||||||
|
|
||||||
|
|
||||||
async def test_value_template_with_entity_id(hass, mqtt_mock):
|
async def test_value_template_with_entity_id(hass, mqtt_mock):
|
||||||
|
"""Test processing a raw value via MQTT."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
sensor.DOMAIN,
|
||||||
|
{
|
||||||
|
sensor.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"encoding": "",
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unit_of_measurement": "fav unit",
|
||||||
|
"value_template": "{{ value | bitwise_and(255) }}",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "test-topic", b"\xff")
|
||||||
|
state = hass.states.get("sensor.test")
|
||||||
|
|
||||||
|
assert state.state == "255"
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "test-topic", b"\x01\x10")
|
||||||
|
state = hass.states.get("sensor.test")
|
||||||
|
|
||||||
|
assert state.state == "16"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_value_template_with_raw_data(hass, mqtt_mock):
|
||||||
"""Test the access to attributes in value_template via the entity_id."""
|
"""Test the access to attributes in value_template via the entity_id."""
|
||||||
assert await async_setup_component(
|
assert await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue