Refactor mqtt callbacks for humidifier (#118116)

pull/118141/head
Jan Bouwhuis 2024-05-25 23:11:07 +02:00 committed by GitHub
parent b4acadc992
commit 6580a07308
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 144 additions and 146 deletions

View File

@ -3,6 +3,7 @@
from __future__ import annotations
from collections.abc import Callable
from functools import partial
import logging
from typing import Any
@ -51,12 +52,7 @@ from .const import (
CONF_STATE_VALUE_TEMPLATE,
PAYLOAD_NONE,
)
from .debug_info import log_messages
from .mixins import (
MqttEntity,
async_setup_entity_entry_helper,
write_state_on_attr_change,
)
from .mixins import MqttEntity, async_setup_entity_entry_helper
from .models import (
MqttCommandTemplate,
MqttValueTemplate,
@ -284,164 +280,166 @@ class MqttHumidifier(MqttEntity, HumidifierEntity):
topics: dict[str, dict[str, Any]],
topic: str,
msg_callback: Callable[[ReceiveMessage], None],
tracked_attributes: set[str],
) -> None:
"""Add a subscription."""
qos: int = self._config[CONF_QOS]
if topic in self._topic and self._topic[topic] is not None:
topics[topic] = {
"topic": self._topic[topic],
"msg_callback": msg_callback,
"msg_callback": partial(
self._message_callback, msg_callback, tracked_attributes
),
"entity_id": self.entity_id,
"qos": qos,
"encoding": self._config[CONF_ENCODING] or None,
}
@callback
def _state_received(self, msg: ReceiveMessage) -> None:
"""Handle new received MQTT message."""
payload = self._value_templates[CONF_STATE](msg.payload)
if not payload:
_LOGGER.debug("Ignoring empty state from '%s'", msg.topic)
return
if payload == self._payload["STATE_ON"]:
self._attr_is_on = True
elif payload == self._payload["STATE_OFF"]:
self._attr_is_on = False
elif payload == PAYLOAD_NONE:
self._attr_is_on = None
@callback
def _action_received(self, msg: ReceiveMessage) -> None:
"""Handle new received MQTT message."""
action_payload = self._value_templates[ATTR_ACTION](msg.payload)
if not action_payload or action_payload == PAYLOAD_NONE:
_LOGGER.debug("Ignoring empty action from '%s'", msg.topic)
return
try:
self._attr_action = HumidifierAction(str(action_payload))
except ValueError:
_LOGGER.error(
"'%s' received on topic %s. '%s' is not a valid action",
msg.payload,
msg.topic,
action_payload,
)
return
@callback
def _current_humidity_received(self, msg: ReceiveMessage) -> None:
"""Handle new received MQTT message for the current humidity."""
rendered_current_humidity_payload = self._value_templates[
ATTR_CURRENT_HUMIDITY
](msg.payload)
if rendered_current_humidity_payload == self._payload["HUMIDITY_RESET"]:
self._attr_current_humidity = None
return
if not rendered_current_humidity_payload:
_LOGGER.debug("Ignoring empty current humidity from '%s'", msg.topic)
return
try:
current_humidity = round(float(rendered_current_humidity_payload))
except ValueError:
_LOGGER.warning(
"'%s' received on topic %s. '%s' is not a valid humidity",
msg.payload,
msg.topic,
rendered_current_humidity_payload,
)
return
if current_humidity < 0 or current_humidity > 100:
_LOGGER.warning(
"'%s' received on topic %s. '%s' is not a valid humidity",
msg.payload,
msg.topic,
rendered_current_humidity_payload,
)
return
self._attr_current_humidity = current_humidity
@callback
def _target_humidity_received(self, msg: ReceiveMessage) -> None:
"""Handle new received MQTT message for the target humidity."""
rendered_target_humidity_payload = self._value_templates[ATTR_HUMIDITY](
msg.payload
)
if not rendered_target_humidity_payload:
_LOGGER.debug("Ignoring empty target humidity from '%s'", msg.topic)
return
if rendered_target_humidity_payload == self._payload["HUMIDITY_RESET"]:
self._attr_target_humidity = None
return
try:
target_humidity = round(float(rendered_target_humidity_payload))
except ValueError:
_LOGGER.warning(
"'%s' received on topic %s. '%s' is not a valid target humidity",
msg.payload,
msg.topic,
rendered_target_humidity_payload,
)
return
if (
target_humidity < self._attr_min_humidity
or target_humidity > self._attr_max_humidity
):
_LOGGER.warning(
"'%s' received on topic %s. '%s' is not a valid target humidity",
msg.payload,
msg.topic,
rendered_target_humidity_payload,
)
return
self._attr_target_humidity = target_humidity
@callback
def _mode_received(self, msg: ReceiveMessage) -> None:
"""Handle new received MQTT message for mode."""
mode = str(self._value_templates[ATTR_MODE](msg.payload))
if mode == self._payload["MODE_RESET"]:
self._attr_mode = None
return
if not mode:
_LOGGER.debug("Ignoring empty mode from '%s'", msg.topic)
return
if not self.available_modes or mode not in self.available_modes:
_LOGGER.warning(
"'%s' received on topic %s. '%s' is not a valid mode",
msg.payload,
msg.topic,
mode,
)
return
self._attr_mode = mode
def _prepare_subscribe_topics(self) -> None:
"""(Re)Subscribe to topics."""
topics: dict[str, Any] = {}
@callback
@log_messages(self.hass, self.entity_id)
@write_state_on_attr_change(self, {"_attr_is_on"})
def state_received(msg: ReceiveMessage) -> None:
"""Handle new received MQTT message."""
payload = self._value_templates[CONF_STATE](msg.payload)
if not payload:
_LOGGER.debug("Ignoring empty state from '%s'", msg.topic)
return
if payload == self._payload["STATE_ON"]:
self._attr_is_on = True
elif payload == self._payload["STATE_OFF"]:
self._attr_is_on = False
elif payload == PAYLOAD_NONE:
self._attr_is_on = None
self.add_subscription(topics, CONF_STATE_TOPIC, state_received)
@callback
@log_messages(self.hass, self.entity_id)
@write_state_on_attr_change(self, {"_attr_action"})
def action_received(msg: ReceiveMessage) -> None:
"""Handle new received MQTT message."""
action_payload = self._value_templates[ATTR_ACTION](msg.payload)
if not action_payload or action_payload == PAYLOAD_NONE:
_LOGGER.debug("Ignoring empty action from '%s'", msg.topic)
return
try:
self._attr_action = HumidifierAction(str(action_payload))
except ValueError:
_LOGGER.error(
"'%s' received on topic %s. '%s' is not a valid action",
msg.payload,
msg.topic,
action_payload,
)
return
self.add_subscription(topics, CONF_ACTION_TOPIC, action_received)
@callback
@log_messages(self.hass, self.entity_id)
@write_state_on_attr_change(self, {"_attr_current_humidity"})
def current_humidity_received(msg: ReceiveMessage) -> None:
"""Handle new received MQTT message for the current humidity."""
rendered_current_humidity_payload = self._value_templates[
ATTR_CURRENT_HUMIDITY
](msg.payload)
if rendered_current_humidity_payload == self._payload["HUMIDITY_RESET"]:
self._attr_current_humidity = None
return
if not rendered_current_humidity_payload:
_LOGGER.debug("Ignoring empty current humidity from '%s'", msg.topic)
return
try:
current_humidity = round(float(rendered_current_humidity_payload))
except ValueError:
_LOGGER.warning(
"'%s' received on topic %s. '%s' is not a valid humidity",
msg.payload,
msg.topic,
rendered_current_humidity_payload,
)
return
if current_humidity < 0 or current_humidity > 100:
_LOGGER.warning(
"'%s' received on topic %s. '%s' is not a valid humidity",
msg.payload,
msg.topic,
rendered_current_humidity_payload,
)
return
self._attr_current_humidity = current_humidity
self.add_subscription(
topics, CONF_CURRENT_HUMIDITY_TOPIC, current_humidity_received
topics, CONF_STATE_TOPIC, self._state_received, {"_attr_is_on"}
)
@callback
@log_messages(self.hass, self.entity_id)
@write_state_on_attr_change(self, {"_attr_target_humidity"})
def target_humidity_received(msg: ReceiveMessage) -> None:
"""Handle new received MQTT message for the target humidity."""
rendered_target_humidity_payload = self._value_templates[ATTR_HUMIDITY](
msg.payload
)
if not rendered_target_humidity_payload:
_LOGGER.debug("Ignoring empty target humidity from '%s'", msg.topic)
return
if rendered_target_humidity_payload == self._payload["HUMIDITY_RESET"]:
self._attr_target_humidity = None
return
try:
target_humidity = round(float(rendered_target_humidity_payload))
except ValueError:
_LOGGER.warning(
"'%s' received on topic %s. '%s' is not a valid target humidity",
msg.payload,
msg.topic,
rendered_target_humidity_payload,
)
return
if (
target_humidity < self._attr_min_humidity
or target_humidity > self._attr_max_humidity
):
_LOGGER.warning(
"'%s' received on topic %s. '%s' is not a valid target humidity",
msg.payload,
msg.topic,
rendered_target_humidity_payload,
)
return
self._attr_target_humidity = target_humidity
self.add_subscription(
topics, CONF_TARGET_HUMIDITY_STATE_TOPIC, target_humidity_received
topics, CONF_ACTION_TOPIC, self._action_received, {"_attr_action"}
)
self.add_subscription(
topics,
CONF_CURRENT_HUMIDITY_TOPIC,
self._current_humidity_received,
{"_attr_current_humidity"},
)
self.add_subscription(
topics,
CONF_TARGET_HUMIDITY_STATE_TOPIC,
self._target_humidity_received,
{"_attr_target_humidity"},
)
self.add_subscription(
topics, CONF_MODE_STATE_TOPIC, self._mode_received, {"_attr_mode"}
)
@callback
@log_messages(self.hass, self.entity_id)
@write_state_on_attr_change(self, {"_attr_mode"})
def mode_received(msg: ReceiveMessage) -> None:
"""Handle new received MQTT message for mode."""
mode = str(self._value_templates[ATTR_MODE](msg.payload))
if mode == self._payload["MODE_RESET"]:
self._attr_mode = None
return
if not mode:
_LOGGER.debug("Ignoring empty mode from '%s'", msg.topic)
return
if not self.available_modes or mode not in self.available_modes:
_LOGGER.warning(
"'%s' received on topic %s. '%s' is not a valid mode",
msg.payload,
msg.topic,
mode,
)
return
self._attr_mode = mode
self.add_subscription(topics, CONF_MODE_STATE_TOPIC, mode_received)
self._sub_state = subscription.async_prepare_subscribe_topics(
self.hass, self._sub_state, topics