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:
Jan Bouwhuis 2021-11-30 14:04:24 +01:00 committed by GitHub
parent 7469f083fd
commit 2a2a20fcb3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 76 additions and 7 deletions

View file

@ -57,6 +57,7 @@ from .const import (
CONF_BIRTH_MESSAGE,
CONF_BROKER,
CONF_COMMAND_TOPIC,
CONF_ENCODING,
CONF_QOS,
CONF_RETAIN,
CONF_STATE_TOPIC,
@ -65,6 +66,7 @@ from .const import (
DATA_MQTT_CONFIG,
DEFAULT_BIRTH,
DEFAULT_DISCOVERY,
DEFAULT_ENCODING,
DEFAULT_PREFIX,
DEFAULT_QOS,
DEFAULT_RETAIN,
@ -200,7 +202,10 @@ CONFIG_SCHEMA = vol.Schema(
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)

View file

@ -46,6 +46,7 @@ ABBREVIATIONS = {
"dev_cla": "device_class",
"dock_t": "docked_topic",
"dock_tpl": "docked_template",
"e": "encoding",
"en": "enabled_by_default",
"err_t": "error_topic",
"err_tpl": "error_template",

View file

@ -28,7 +28,7 @@ from homeassistant.util import dt as dt_util
from . import PLATFORMS, subscription
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 .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
@ -200,6 +200,7 @@ class MqttBinarySensor(MqttEntity, BinarySensorEntity):
"topic": self._config[CONF_STATE_TOPIC],
"msg_callback": state_message_received,
"qos": self._config[CONF_QOS],
"encoding": self._config[CONF_ENCODING] or None,
}
},
)

View file

@ -13,6 +13,7 @@ CONF_AVAILABILITY = "availability"
CONF_BROKER = "broker"
CONF_BIRTH_MESSAGE = "birth_message"
CONF_COMMAND_TOPIC = "command_topic"
CONF_ENCODING = "encoding"
CONF_QOS = ATTR_QOS
CONF_RETAIN = ATTR_RETAIN
CONF_STATE_TOPIC = "state_topic"
@ -24,6 +25,7 @@ DATA_MQTT_CONFIG = "mqtt_config"
DEFAULT_PREFIX = "homeassistant"
DEFAULT_BIRTH_WILL_TOPIC = DEFAULT_PREFIX + "/status"
DEFAULT_DISCOVERY = True
DEFAULT_ENCODING = "utf-8"
DEFAULT_QOS = 0
DEFAULT_PAYLOAD_AVAILABLE = "online"
DEFAULT_PAYLOAD_NOT_AVAILABLE = "offline"

View file

@ -33,7 +33,7 @@ from homeassistant.util import dt as dt_util
from . import PLATFORMS, subscription
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 .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
@ -252,6 +252,7 @@ class MqttSensor(MqttEntity, SensorEntity):
"topic": self._config[CONF_STATE_TOPIC],
"msg_callback": message_received,
"qos": self._config[CONF_QOS],
"encoding": self._config[CONF_ENCODING] or None,
}
@callback

View file

@ -10,13 +10,10 @@ from homeassistant.core import HassJob, callback
from homeassistant.helpers import config_validation as cv, template
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
CONF_ENCODING = "encoding"
DEFAULT_ENCODING = "utf-8"
DEFAULT_QOS = 0
TRIGGER_SCHEMA = cv.TRIGGER_BASE_SCHEMA.extend(
{

View file

@ -373,6 +373,39 @@ async def test_setting_sensor_value_via_mqtt_message_and_template2(
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(
hass, mqtt_mock, caplog
):

View file

@ -894,6 +894,35 @@ async def test_entity_category(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."""
assert await async_setup_component(
hass,