import paho.mqtt.client as mqtt import json import logging import threading from typing import Optional import uuid import threading import requests from os import getenv logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) MQTT_CLIENT_ID = f"MCPMQTT-{uuid.uuid4().hex[:8]}" def getConfig_url(array): url = "http://lzwcai-demp-corp-manager:8086/system/config/getConfig" data = [array] try: response = requests.post(url, json=data, timeout=5) response.raise_for_status() data = response.json()['data'] return data[0]['configValue'] except Exception as e: print(f"Error fetching config for {array}: {e}") return None class MQTTHandler: def __init__(self): self.client = mqtt.Client() self.tasks = {} # {task_id: task_data} self._lock = threading.Lock() # 获取MQTT配置,提供默认值 self.mqtt_username = getenv('MQTT_USERNAME') or 'lzwc' self.mqtt_password = getenv('MQTT_PASSWORD') or 'Lzwc@4187.' mqtt_broker_raw = getenv('MQTT_BROKER') or 'tcp://dempmana.lzwcai.com' # 移除协议前缀,只保留主机名 self.mqtt_broker = mqtt_broker_raw.replace('tcp://', '').replace('mqtt://', '') mqtt_port_str = getenv('MQTT_PORT') self.mqtt_port = int(mqtt_port_str) if mqtt_port_str else 1883 # 记录配置信息 logger.info(f"MQTT配置 - Broker: {self.mqtt_broker}, Port: {self.mqtt_port}, Username: {self.mqtt_username}") if not getenv('MQTT_BROKER'): logger.warning("MQTT_BROKER环境变量未设置,使用默认值") if not mqtt_port_str: logger.warning("MQTT_PORT环境变量未设置,使用默认端口1883") self.client.username_pw_set(self.mqtt_username, self.mqtt_password) self.client.on_connect = self._on_connect self.client.on_message = self._on_message self.client.on_disconnect = self._on_disconnect try: logger.info(f"正在连接 MQTT 代理: {self.mqtt_broker}:{self.mqtt_port}") self.client.connect(self.mqtt_broker, self.mqtt_port, 60) self.client.loop_start() except Exception as e: logger.error(f"连接 MQTT 失败: {e}") def _on_connect(self, client, userdata, flags, rc): """MQTT 连接回调""" if rc == 0: logger.info("已成功连接到 MQTT 代理服务器") else: logger.error(f"连接 MQTT 代理服务器失败,返回码: {rc}") def get_status(self, task_id: str = None): """获取任务状态 Args: task_id: 可选参数,指定任务ID。如果为None则返回所有任务状态 Returns: 如果指定task_id则返回该任务的状态,否则返回所有任务状态 """ with self._lock: if task_id: return self.tasks.get(task_id, {}).copy() return {k: v.copy() for k, v in self.tasks.items()} def _on_message(self, client, userdata, msg): try: payload = json.loads(msg.payload.decode()) logger.info(f"[MQTT] topic={msg.topic} msg: {payload}") # task_id = payload.get('task_id') # if task_id and task_id in self.tasks: # with self._lock: # self.tasks[task_id].update({ # 'status': payload.get('status', 'UNKNOWN'), # 'description': payload.get('description', '') # }) except Exception as e: logger.error(f"[错误] 处理消息失败: {e}") def _on_disconnect(self, client, userdata, rc): """MQTT 断开连接回调""" if rc != 0: logger.warning("意外断开与 MQTT 代理服务器的连接。") try: logger.info("尝试重新连接 MQTT...") client.reconnect() except Exception as e: logger.error(f"重新连接 MQTT 失败: {e}") # 单例模式 _instance: Optional[MQTTHandler] = None def get_mcpmqtt_handler() -> MQTTHandler: """获取单例""" global _instance if _instance is None: _instance = MQTTHandler() return _instance