Files
homeassistant_config/config/custom_components/pyscript/mqtt.py
2024-08-09 06:45:02 +02:00

92 lines
2.6 KiB
Python

"""Handles mqtt messages and notification."""
import json
import logging
from homeassistant.components import mqtt
from .const import LOGGER_PATH
_LOGGER = logging.getLogger(LOGGER_PATH + ".mqtt")
class Mqtt:
"""Define mqtt functions."""
#
# Global hass instance
#
hass = None
#
# notify message queues by mqtt message topic
#
notify = {}
notify_remove = {}
def __init__(self):
"""Warn on Mqtt instantiation."""
_LOGGER.error("Mqtt class is not meant to be instantiated")
@classmethod
def init(cls, hass):
"""Initialize Mqtt."""
cls.hass = hass
@classmethod
def mqtt_message_handler_maker(cls, subscribed_topic):
"""Closure for mqtt_message_handler."""
async def mqtt_message_handler(mqttmsg):
"""Listen for MQTT messages."""
func_args = {
"trigger_type": "mqtt",
"topic": mqttmsg.topic,
"payload": mqttmsg.payload,
"qos": mqttmsg.qos,
}
try:
func_args["payload_obj"] = json.loads(mqttmsg.payload)
except ValueError:
pass
await cls.update(subscribed_topic, func_args)
return mqtt_message_handler
@classmethod
async def notify_add(cls, topic, queue):
"""Register to notify for mqtt messages of given topic to be sent to queue."""
if topic not in cls.notify:
cls.notify[topic] = set()
_LOGGER.debug("mqtt.notify_add(%s) -> adding mqtt subscription", topic)
cls.notify_remove[topic] = await mqtt.async_subscribe(
cls.hass, topic, cls.mqtt_message_handler_maker(topic), encoding="utf-8", qos=0
)
cls.notify[topic].add(queue)
@classmethod
def notify_del(cls, topic, queue):
"""Unregister to notify for mqtt messages of given topic for given queue."""
if topic not in cls.notify or queue not in cls.notify[topic]:
return
cls.notify[topic].discard(queue)
if len(cls.notify[topic]) == 0:
cls.notify_remove[topic]()
_LOGGER.debug("mqtt.notify_del(%s) -> removing mqtt subscription", topic)
del cls.notify[topic]
del cls.notify_remove[topic]
@classmethod
async def update(cls, topic, func_args):
"""Deliver all notifications for an mqtt message on the given topic."""
_LOGGER.debug("mqtt.update(%s, %s, %s)", topic, vars, func_args)
if topic in cls.notify:
for queue in cls.notify[topic]:
await queue.put(["mqtt", func_args.copy()])