Files
django-relay-controller/relaycontroller/home/process.py
T
2026-03-10 13:10:32 +01:00

110 lines
3.0 KiB
Python

'''
Created on 23 janv. 2026
@author: denis
'''
import json
from threading import Thread, Event
from celery import Task
from celery.exceptions import Ignore
from celery.utils.log import get_task_logger
from redis import Redis
from django.conf import settings
from modules.mqttc import MqttBase as MqttClient
RELAY_SUB_TOPIC = "relay/+/#"
ZIGBEE_SUB_TOPIC = "zigbee2mqtt/#"
class Mqttc:
task = None
conf = dict(
host=settings.MQTT_HOST,
port=settings.MQTT_PORT,
username=settings.MQTT_USERNAME,
password=settings.MQTT_PASSWORD,
ca_cert=settings.MQTT_CA_CERT,
keepalive=60,
topic_base=f"{settings.MQTT_ORIGINE}",
topic_subs=[
[RELAY_SUB_TOPIC, 0],
#[ZIGBEE_SUB_TOPIC, 0],
]
)
logger = get_task_logger(__name__)
redis = Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0, decode_responses=True)
mqttc = Mqttc()
class MqttProcess(Task):
def __init__(self):
super().__init__()
self.stop_event = Event()
self.mqtt = MqttClient(on_messages=self._on_mqtt_message, **mqttc.conf)
def __call__(self, *args, **kwargs):
return self.start(*args, **kwargs)
def start(self, *args, **kwargs):
try:
self.mqtt.startMQTT()
self.start_redis_subscriber()
except Exception as e:
logger.error(e)
raise Ignore()
def stop(self):
try:
self.stop_event.set()
self.mqtt.stopMQTT()
logger.info(f"Listening stop.")
except Exception as e:
logger.error(e)
def start_redis_subscriber(self):
self.redis_subscriber = Thread(target=self._listen_to_redis, daemon=True)
self.redis_subscriber.start()
def _on_mqtt_message(self, topic, payload):
try:
#logger.info(f"---- on_mqtt_message {topic}: {payload}")
if topic.startswith(RELAY_SUB_TOPIC[:-3]):
uuid = topic.split('/')[1]
redis.publish(f'relay_{uuid}', json.dumps({"type": "mqtt", "topic": topic, "payload": payload}))
else:
redis.publish('mqtt_message', json.dumps({"type": "mqtt", "topic": topic, "payload": payload}))
except Exception as e:
logger.error(f'on_mqtt_message: {e}')
logger.error(topic)
logger.error(payload)
def _listen_to_redis(self):
try:
pubsub = redis.pubsub()
pubsub.subscribe(f"mqtt_pub")
logger.info(f"---- listen mqtt_message via redis")
for message in pubsub.listen():
if self.stop_event.is_set():
break
data = json.loads(str(message.get('data')))
if not isinstance(data, dict):
continue
if data.get("type") == "mqtt":
self.mqtt._publish_message(data["topic"], **data["payload"])
finally:
pubsub.unsubscribe()
pubsub.close()