Fix handling undecoded mqtt sensor payloads (#118633)

pull/118845/head
Jan Bouwhuis 2024-06-02 21:25:05 +02:00 committed by Paulus Schoutsen
parent 9366a4e69b
commit 3653a51288
2 changed files with 50 additions and 10 deletions

View File

@ -237,28 +237,32 @@ class MqttSensor(MqttEntity, RestoreSensor):
payload = msg.payload
if payload is PayloadSentinel.DEFAULT:
return
new_value = str(payload)
if not isinstance(payload, str):
_LOGGER.warning(
"Invalid undecoded state message '%s' received from '%s'",
payload,
msg.topic,
)
return
if self._numeric_state_expected:
if new_value == "":
if payload == "":
_LOGGER.debug("Ignore empty state from '%s'", msg.topic)
elif new_value == PAYLOAD_NONE:
elif payload == PAYLOAD_NONE:
self._attr_native_value = None
else:
self._attr_native_value = new_value
self._attr_native_value = payload
return
if self.device_class in {
None,
SensorDeviceClass.ENUM,
} and not check_state_too_long(_LOGGER, new_value, self.entity_id, msg):
self._attr_native_value = new_value
} and not check_state_too_long(_LOGGER, payload, self.entity_id, msg):
self._attr_native_value = payload
return
try:
if (payload_datetime := dt_util.parse_datetime(new_value)) is None:
if (payload_datetime := dt_util.parse_datetime(payload)) is None:
raise ValueError
except ValueError:
_LOGGER.warning(
"Invalid state message '%s' from '%s'", msg.payload, msg.topic
)
_LOGGER.warning("Invalid state message '%s' from '%s'", payload, msg.topic)
self._attr_native_value = None
return
if self.device_class == SensorDeviceClass.DATE:

View File

@ -110,6 +110,42 @@ async def test_setting_sensor_value_via_mqtt_message(
assert state.attributes.get("unit_of_measurement") == "fav unit"
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
"name": "test",
"state_topic": "test-topic",
"unit_of_measurement": "%",
"device_class": "battery",
"encoding": "",
}
}
}
],
)
async def test_handling_undecoded_sensor_value(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the setting of the value via MQTT."""
await mqtt_mock_entry()
state = hass.states.get("sensor.test")
assert state.state == STATE_UNKNOWN
async_fire_mqtt_message(hass, "test-topic", b"88")
state = hass.states.get("sensor.test")
assert state.state == STATE_UNKNOWN
assert (
"Invalid undecoded state message 'b'88'' received from 'test-topic'"
in caplog.text
)
@pytest.mark.parametrize(
"hass_config",
[