Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove mqtt sensor support for last_reset_topic #93792

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
59 changes: 8 additions & 51 deletions homeassistant/components/mqtt/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
ReceiveMessage,
ReceivePayloadType,
)
from .util import get_mqtt_data, valid_subscribe_topic
from .util import get_mqtt_data

_LOGGER = logging.getLogger(__name__)

Expand All @@ -73,36 +73,11 @@
DEFAULT_FORCE_UPDATE = False


def validate_options(conf: ConfigType) -> ConfigType:
"""Validate options.

If last reset topic is present it must be same as the state topic.
"""
if (
CONF_LAST_RESET_TOPIC in conf
and CONF_STATE_TOPIC in conf
and conf[CONF_LAST_RESET_TOPIC] != conf[CONF_STATE_TOPIC]
):
_LOGGER.warning(
"'%s' must be same as '%s'", CONF_LAST_RESET_TOPIC, CONF_STATE_TOPIC
)

if CONF_LAST_RESET_TOPIC in conf and CONF_LAST_RESET_VALUE_TEMPLATE not in conf:
_LOGGER.warning(
"'%s' must be set if '%s' is set",
CONF_LAST_RESET_VALUE_TEMPLATE,
CONF_LAST_RESET_TOPIC,
)

return conf


_PLATFORM_SCHEMA_BASE = MQTT_RO_SCHEMA.extend(
{
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
vol.Optional(CONF_LAST_RESET_TOPIC): valid_subscribe_topic,
vol.Optional(CONF_LAST_RESET_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_SUGGESTED_DISPLAY_PRECISION): cv.positive_int,
Expand All @@ -112,8 +87,10 @@ def validate_options(conf: ConfigType) -> ConfigType:
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)

PLATFORM_SCHEMA_MODERN = vol.All(
# Deprecated in HA Core 2021.11.0 https://github.com/home-assistant/core/pull/54840
# Removed in HA Core 2023.6.0
cv.removed(CONF_LAST_RESET_TOPIC),
_PLATFORM_SCHEMA_BASE,
validate_options,
)

# Configuring MQTT Sensors under the sensor platform key was deprecated in
Expand All @@ -123,9 +100,10 @@ def validate_options(conf: ConfigType) -> ConfigType:
)

DISCOVERY_SCHEMA = vol.All(
cv.deprecated(CONF_LAST_RESET_TOPIC),
# Deprecated in HA Core 2021.11.0 https://github.com/home-assistant/core/pull/54840
# Removed in HA Core 2023.6.0
cv.removed(CONF_LAST_RESET_TOPIC),
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
validate_options,
)


Expand Down Expand Up @@ -319,10 +297,7 @@ def _update_last_reset(msg: ReceiveMessage) -> None:
def message_received(msg: ReceiveMessage) -> None:
"""Handle new MQTT messages."""
_update_state(msg)
if CONF_LAST_RESET_VALUE_TEMPLATE in self._config and (
CONF_LAST_RESET_TOPIC not in self._config
or self._config[CONF_LAST_RESET_TOPIC] == self._config[CONF_STATE_TOPIC]
):
if CONF_LAST_RESET_VALUE_TEMPLATE in self._config:
_update_last_reset(msg)
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)

Expand All @@ -333,24 +308,6 @@ def message_received(msg: ReceiveMessage) -> None:
"encoding": self._config[CONF_ENCODING] or None,
}

@callback
@log_messages(self.hass, self.entity_id)
def last_reset_message_received(msg: ReceiveMessage) -> None:
"""Handle new last_reset messages."""
_update_last_reset(msg)
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)

if (
CONF_LAST_RESET_TOPIC in self._config
and self._config[CONF_LAST_RESET_TOPIC] != self._config[CONF_STATE_TOPIC]
):
topics["last_reset_topic"] = {
"topic": self._config[CONF_LAST_RESET_TOPIC],
"msg_callback": last_reset_message_received,
"qos": self._config[CONF_QOS],
"encoding": self._config[CONF_ENCODING] or None,
}

self._sub_state = subscription.async_prepare_subscribe_topics(
self.hass, self._sub_state, topics
)
Expand Down
137 changes: 23 additions & 114 deletions tests/components/mqtt/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,117 +480,44 @@ async def test_setting_sensor_value_via_mqtt_json_message_and_default_current_st
"state_class": "total",
"state_topic": "test-topic",
"unit_of_measurement": "fav unit",
"last_reset_topic": "last-reset-topic",
"last_reset_value_template": "{{ value_json.last_reset }}",
"value_template": "{{ value_json.state }}",
}
}
}
],
)
async def test_setting_sensor_last_reset_via_mqtt_message(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the setting of the last_reset property via MQTT."""
await mqtt_mock_entry()

async_fire_mqtt_message(hass, "last-reset-topic", "2020-01-02 08:11:00")
state = hass.states.get("sensor.test")
assert state.attributes.get("last_reset") == "2020-01-02T08:11:00"
assert "'last_reset_topic' must be same as 'state_topic'" in caplog.text
assert (
"'last_reset_value_template' must be set if 'last_reset_topic' is set"
in caplog.text
)


@pytest.mark.parametrize(
"hass_config",
("message", "last_reset", "state"),
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
"name": "test",
"state_class": "total",
"state_topic": "test-topic",
"unit_of_measurement": "fav unit",
"last_reset_topic": "last-reset-topic",
}
}
}
(
'{ "last_reset": "2020-01-02 08:11:00" }',
"2020-01-02T08:11:00",
STATE_UNKNOWN,
),
(
'{ "last_reset": "2020-01-02 08:11:03", "state": 10.0 }',
"2020-01-02T08:11:03",
"10.0",
),
('{ "last_reset": null, "state": 10.1 }', None, "10.1"),
('{ "last_reset": "", "state": 10.1 }', None, "10.1"),
],
)
@pytest.mark.parametrize("datestring", ["2020-21-02 08:11:00", "Hello there!"])
async def test_setting_sensor_bad_last_reset_via_mqtt_message(
async def test_setting_sensor_last_reset_via_mqtt_json_message(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
datestring,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test the setting of the last_reset property via MQTT."""
await mqtt_mock_entry()

async_fire_mqtt_message(hass, "last-reset-topic", datestring)
state = hass.states.get("sensor.test")
assert state.attributes.get("last_reset") is None
assert "Invalid last_reset message" in caplog.text


@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
"name": "test",
"state_class": "total",
"state_topic": "test-topic",
"unit_of_measurement": "fav unit",
"last_reset_topic": "last-reset-topic",
}
}
}
],
)
async def test_setting_sensor_empty_last_reset_via_mqtt_message(
hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the last_reset property via MQTT."""
await mqtt_mock_entry()

async_fire_mqtt_message(hass, "last-reset-topic", "")
state = hass.states.get("sensor.test")
assert state.attributes.get("last_reset") is None


@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
"name": "test",
"state_class": "total",
"state_topic": "test-topic",
"unit_of_measurement": "fav unit",
"last_reset_topic": "last-reset-topic",
"last_reset_value_template": "{{ value_json.last_reset }}",
}
}
}
],
)
async def test_setting_sensor_last_reset_via_mqtt_json_message(
hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator
message: str,
last_reset: str,
state: str,
) -> None:
"""Test the setting of the value via MQTT with JSON payload."""
await mqtt_mock_entry()

async_fire_mqtt_message(
hass, "last-reset-topic", '{ "last_reset": "2020-01-02 08:11:00" }'
)
state = hass.states.get("sensor.test")
assert state.attributes.get("last_reset") == "2020-01-02T08:11:00"
async_fire_mqtt_message(hass, "test-topic", message)
sensor_state = hass.states.get("sensor.test")
assert sensor_state.attributes.get("last_reset") == last_reset
assert sensor_state.state == state


@pytest.mark.parametrize(
Expand All @@ -608,19 +535,6 @@ async def test_setting_sensor_last_reset_via_mqtt_json_message(
},
}
},
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
"name": "test",
"state_class": "total",
"state_topic": "test-topic",
"unit_of_measurement": "kWh",
"value_template": "{{ value_json.value | float / 60000 }}",
"last_reset_value_template": "{{ utcnow().fromtimestamp(value_json.time / 1000, tz=utcnow().tzinfo) }}",
"last_reset_topic": "test-topic",
},
}
},
],
)
async def test_setting_sensor_last_reset_via_mqtt_json_message_2(
Expand All @@ -640,11 +554,6 @@ async def test_setting_sensor_last_reset_via_mqtt_json_message_2(
state = hass.states.get("sensor.test")
assert float(state.state) == pytest.approx(0.015796176944444445)
assert state.attributes.get("last_reset") == "2021-08-19T15:05:00+00:00"
assert "'last_reset_topic' must be same as 'state_topic'" not in caplog.text
assert (
"'last_reset_value_template' must be set if 'last_reset_topic' is set"
not in caplog.text
)


@pytest.mark.parametrize(
Expand Down