Fix handling None
or empty value for numeric MQTT sensor (#87004)
* Allow `None` for numeric sensor, ignore empty val * Add test case with omitting a value * Use _numeric_state_expected property * Only respect None if numeric state is expected
This commit is contained in:
parent
42008c50f3
commit
c78cae4483
2 changed files with 68 additions and 7 deletions
|
@ -38,7 +38,7 @@ from homeassistant.util import dt as dt_util
|
|||
|
||||
from . import subscription
|
||||
from .config import MQTT_RO_SCHEMA
|
||||
from .const import CONF_ENCODING, CONF_QOS, CONF_STATE_TOPIC
|
||||
from .const import CONF_ENCODING, CONF_QOS, CONF_STATE_TOPIC, PAYLOAD_NONE
|
||||
from .debug_info import log_messages
|
||||
from .mixins import (
|
||||
MQTT_ENTITY_COMMON_SCHEMA,
|
||||
|
@ -272,13 +272,19 @@ class MqttSensor(MqttEntity, RestoreSensor):
|
|||
payload = self._template(msg.payload, PayloadSentinel.DEFAULT)
|
||||
if payload is PayloadSentinel.DEFAULT:
|
||||
return
|
||||
if self.device_class not in {
|
||||
SensorDeviceClass.DATE,
|
||||
SensorDeviceClass.TIMESTAMP,
|
||||
}:
|
||||
self._attr_native_value = str(payload)
|
||||
new_value = str(payload)
|
||||
if self._numeric_state_expected:
|
||||
if new_value == "":
|
||||
_LOGGER.debug("Ignore empty state from '%s'", msg.topic)
|
||||
elif new_value == PAYLOAD_NONE:
|
||||
self._attr_native_value = None
|
||||
else:
|
||||
self._attr_native_value = new_value
|
||||
return
|
||||
if (payload_datetime := dt_util.parse_datetime(str(payload))) is None:
|
||||
if self.device_class is None:
|
||||
self._attr_native_value = new_value
|
||||
return
|
||||
if (payload_datetime := dt_util.parse_datetime(new_value)) is None:
|
||||
_LOGGER.warning(
|
||||
"Invalid state message '%s' from '%s'", msg.payload, msg.topic
|
||||
)
|
||||
|
|
|
@ -169,6 +169,61 @@ async def test_setting_sensor_native_value_handling_via_mqtt_message(
|
|||
assert log == ("Invalid state message" in caplog.text)
|
||||
|
||||
|
||||
async def test_setting_numeric_sensor_native_value_handling_via_mqtt_message(
|
||||
hass: ha.HomeAssistant,
|
||||
mqtt_mock_entry_with_yaml_config,
|
||||
) -> None:
|
||||
"""Test the setting of a numeric sensor value via MQTT."""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
mqtt.DOMAIN,
|
||||
{
|
||||
mqtt.DOMAIN: {
|
||||
sensor.DOMAIN: {
|
||||
"name": "test",
|
||||
"state_topic": "test-topic",
|
||||
"value_template": "{{ value_json.power }}",
|
||||
"device_class": "power",
|
||||
"unit_of_measurement": "W",
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await mqtt_mock_entry_with_yaml_config()
|
||||
|
||||
# float value
|
||||
async_fire_mqtt_message(hass, "test-topic", '{ "power": 45.3, "current": 5.24 }')
|
||||
state = hass.states.get("sensor.test")
|
||||
assert state.attributes.get("device_class") == "power"
|
||||
assert state.state == "45.3"
|
||||
|
||||
# null value, native value should be None
|
||||
async_fire_mqtt_message(hass, "test-topic", '{ "power": null, "current": 5.34 }')
|
||||
state = hass.states.get("sensor.test")
|
||||
assert state.state == "unknown"
|
||||
|
||||
# int value
|
||||
async_fire_mqtt_message(hass, "test-topic", '{ "power": 20, "current": 5.34 }')
|
||||
state = hass.states.get("sensor.test")
|
||||
assert state.state == "20"
|
||||
|
||||
# int value
|
||||
async_fire_mqtt_message(hass, "test-topic", '{ "power": "21", "current": 5.34 }')
|
||||
state = hass.states.get("sensor.test")
|
||||
assert state.state == "21"
|
||||
|
||||
# ignore empty value, native sensor value should not change
|
||||
async_fire_mqtt_message(hass, "test-topic", '{ "power": "", "current": 5.34 }')
|
||||
state = hass.states.get("sensor.test")
|
||||
assert state.state == "21"
|
||||
|
||||
# omitting value, causing it to be ignored, native sensor value should not change (template warning will be logged though)
|
||||
async_fire_mqtt_message(hass, "test-topic", '{ "current": 5.34 }')
|
||||
state = hass.states.get("sensor.test")
|
||||
assert state.state == "21"
|
||||
|
||||
|
||||
async def test_setting_sensor_value_expires_availability_topic(
|
||||
hass, mqtt_mock_entry_with_yaml_config, caplog
|
||||
):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue