Skip to content

Commit

Permalink
Fix handling undecoded mqtt sensor payloads (#118633)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbouwh authored Jun 2, 2024
1 parent afc29fd commit 375f481
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 10 deletions.
24 changes: 14 additions & 10 deletions homeassistant/components/mqtt/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,28 +237,32 @@ def _update_state(self, msg: ReceiveMessage) -> None:
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:
Expand Down
36 changes: 36 additions & 0 deletions tests/components/mqtt/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
[
Expand Down

0 comments on commit 375f481

Please sign in to comment.