183 lines
6.3 KiB
Python
183 lines
6.3 KiB
Python
import json
|
|
import logging
|
|
|
|
import paho.mqtt.client as mqtt
|
|
import threading
|
|
import queue
|
|
import time
|
|
|
|
# MQTT 代理地址和端口
|
|
broker = "8.137.54.85" # 公共 MQTT 代理(免费)
|
|
port = 1883 # MQTT 默认端口
|
|
|
|
# 主题
|
|
topic = "ai/tottle/uvmodule"
|
|
# 配置日志
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(levelname)s - %(message)s'
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# 创建消息队列
|
|
message_queue = queue.Queue()
|
|
# 全局消息队列(可选,如果多个客户端需要共享消息)
|
|
global_message_queue = queue.Queue()
|
|
|
|
|
|
# uv_message_queue = queue.Queue()
|
|
|
|
# 接收消息并做本地缓存
|
|
# message_receive_queue = queue.Queue()
|
|
# # 暂时考虑只存储最新一条消息
|
|
# message_receive_queue = None
|
|
|
|
class MQTTClient:
|
|
def __init__(self, broker, port, topic, use_global_queue=False):
|
|
self.broker = broker
|
|
self.port = port
|
|
self.topic = topic
|
|
self.client = mqtt.Client()
|
|
self.client.on_connect = self.on_connect
|
|
self.client.on_message = self.on_message # 绑定消息回调
|
|
self.use_global_queue = use_global_queue # 是否使用全局队列
|
|
self.local_mess = None
|
|
self.local_message_queue = queue.Queue() if not use_global_queue else None # 本地队列
|
|
self.client.connect(broker, port)
|
|
self.client.loop_start() # 启动网络线程
|
|
|
|
def on_connect(self, client, userdata, flags, rc):
|
|
"""连接成功时自动订阅主题"""
|
|
if rc == 0:
|
|
print(f"[MQTT] 成功连接到代理 {self.broker}:{self.port}")
|
|
self.client.subscribe(self.topic)
|
|
else:
|
|
print(f"[MQTT] 连接失败,错误代码: {rc}")
|
|
|
|
def on_message(self, client, userdata, msg):
|
|
"""收到消息时的回调"""
|
|
try:
|
|
payload = msg.payload.decode("utf-8")
|
|
# message_data = {
|
|
# "topic": msg.topic,
|
|
# "payload": payload,
|
|
# "qos": msg.qos,
|
|
# "retain": msg.retain,
|
|
# "ts": int(time.time() * 1000) # 毫秒级时间戳
|
|
# }
|
|
# data = json.loads(payload) # 解析为字典
|
|
message_data = json.loads(payload) # 解析为字典
|
|
# if self.use_global_queue:
|
|
# global_message_queue.put(message_data) # 存入全局队列
|
|
# else:
|
|
# self.local_message_queue.put(message_data) # 存入本地队列
|
|
print(f"on_message {message_data}")
|
|
# 增加格式验证,非法格式不做录入
|
|
if (message_data is not None
|
|
and message_data["task_id"] is not None
|
|
and message_data["list_s3_url"] is not None
|
|
and message_data["list_func_id"] is not None): #接收ai-tottle 消息
|
|
global_message_queue.put(message_data) # 存入全局队列
|
|
# self.local_mess=message_data
|
|
# print(f"[MQTT 接收] 主题: {msg.topic}, 消息: {payload}")
|
|
except Exception as e:
|
|
print(f"[MQTT 错误] 消息处理失败: {e}")
|
|
|
|
def publish_message(self, message):
|
|
"""发布消息"""
|
|
self.client.publish(self.topic, message)
|
|
print(f"[MQTT 发送] 主题: {self.topic}, 消息: {message}")
|
|
|
|
def publish_uv_result(self,topic, message):
|
|
"""发布消息"""
|
|
self.client.publish(topic, message)
|
|
print(f"[MQTT 发送] 主题: {self.topic}, 消息: {message}")
|
|
|
|
def get_messages(self, timeout=1):
|
|
"""
|
|
获取消息(支持超时)
|
|
- 如果使用全局队列,从 global_message_queue 获取
|
|
- 否则从本地队列获取
|
|
"""
|
|
messages = None
|
|
# target_queue = global_message_queue if self.use_global_queue else self.local_message_queue
|
|
start_time = time.time()
|
|
while time.time() - start_time < timeout:
|
|
try:
|
|
msg = global_message_queue.get()
|
|
if msg:
|
|
messages =msg
|
|
except queue.Empty:
|
|
break
|
|
return messages
|
|
|
|
def close(self):
|
|
"""关闭连接"""
|
|
self.client.loop_stop()
|
|
self.client.disconnect()
|
|
print("[MQTT] 已断开连接")
|
|
|
|
|
|
# 生产者线程:将消息放入队列
|
|
def producer_thread():
|
|
# message_queue.put(mess)
|
|
for i in range(100):
|
|
message = f"Message {i}"
|
|
message_queue.put(message)
|
|
print(f"生产者线程:已将消息放入队列: {message}")
|
|
# time.sleep(1) # 模拟生产间隔
|
|
|
|
|
|
# 消费者线程:从队列中取出消息并发布
|
|
def consumer_thread(mqtt_client):
|
|
print("consumer_thread")
|
|
# while True:
|
|
# try:
|
|
# message = message_queue.get(timeout=1) # 设置超时以避免无限阻塞
|
|
# mqtt_client.publish_message(message)
|
|
# message_queue.task_done() # 标记任务完成
|
|
# except queue.Empty:
|
|
# print("消费者线程:队列为空,等待中...")
|
|
# time.sleep(3) # 避免频繁检查队列
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# 初始化 MQTT 客户端
|
|
mqtt_client = MQTTClient(broker, port, topic)
|
|
|
|
|
|
|
|
while True:
|
|
try:
|
|
raw_message = global_message_queue.get() # 阻塞等待消息
|
|
if raw_message is None: # 终止信号
|
|
break
|
|
|
|
logger.debug(f"处理原始消息: {raw_message}")
|
|
|
|
try:
|
|
# 解析JSON消息
|
|
# task_data = json.loads(raw_message)
|
|
logger.info(f"收到新任务: {raw_message}")
|
|
print(f"收到新任务: {raw_message}")
|
|
|
|
# # 处理任务
|
|
# result = process_uv_task(task_data)
|
|
#
|
|
# # 发布结果
|
|
# if result:
|
|
# mqtt_manager.publish(MQTT_PUBLISH_TOPIC, result)
|
|
|
|
except json.JSONDecodeError:
|
|
logger.error("无效的JSON格式")
|
|
except Exception as e:
|
|
logger.error(f"消息处理过程中发生错误: {e}")
|
|
|
|
except KeyboardInterrupt:
|
|
logger.info("收到中断信号,停止消息处理...")
|
|
break
|
|
except Exception as e:
|
|
logger.error(f"消息处理循环发生未预期错误: {e}")
|
|
time.sleep(1) # 避免频繁错误导致CPU占用过高
|
|
|