python实现mqtt消息转Tcp消息

config.json

python 复制代码
{
    "mqtt_host": "broker.emqx.io",
    "mqtt_port": 1883,
    "mqtt_username": "your_username",
    "mqtt_password": "your_password",
    "publish_topic": "test/topic/publish",
    "subscribe_topic": "test/topic/subscribe",
    "tcp_port": 54321
}
复制代码
mqtt_tcp_bridge.py
python 复制代码
import json
import logging
import socket
import socketserver
import threading
from paho.mqtt import client as mqtt_client

# 配置日志格式
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

# 全局变量和锁,用于管理TCP客户端连接
tcp_clients = []
tcp_clients_lock = threading.Lock()

def load_config(config_file='config.json'):
    """加载配置文件"""
    try:
        with open(config_file, 'r') as f:
            config = json.load(f)
        logging.info("配置文件加载成功")
        return config
    except Exception as e:
        logging.error(f"加载配置文件失败: {e}")
        raise

def on_mqtt_connect(client, userdata, flags, rc):
    """MQTT连接回调"""
    if rc == 0:
        logging.info("MQTT连接成功")
        # 订阅配置中的主题
        client.subscribe(userdata['subscribe_topic'])
    else:
        logging.error(f"MQTT连接失败,错误码:{rc}")

def on_mqtt_message(client, userdata, msg):
    """MQTT消息接收回调"""
    try:
        data = msg.payload.decode()
        logging.info(f"收到订阅消息: {data} (主题: {msg.topic})")
        # 将消息转发给所有TCP客户端
        with tcp_clients_lock:
            for conn in tcp_clients.copy():  # 使用copy避免迭代时修改
                try:
                    conn.sendall(data.encode() + b'\n')  # 添加换行符便于客户端读取
                except Exception as e:
                    logging.error(f"发送数据到TCP客户端失败: {e}")
                    tcp_clients.remove(conn)
    except Exception as e:
        logging.error(f"处理MQTT消息失败: {e}")

class TCPRequestHandler(socketserver.BaseRequestHandler):
    """TCP请求处理类"""
    def handle(self):
        # 客户端连接时添加到列表
        with tcp_clients_lock:
            tcp_clients.append(self.request)
        logging.info(f"新的客户端连接: {self.client_address}")
        
        # 获取MQTT客户端实例用于发布消息
        mqtt_client = self.server.mqtt_client
        publish_topic = self.server.publish_topic
        
        while True:
            try:
                data = self.request.recv(1024)
                if not data:
                    break  # 客户端断开连接
                message = data.decode().strip()
                logging.info(f"收到客户端数据: {message}")
                # 发布到MQTT主题
                mqtt_client.publish(publish_topic, message)
            except (ConnectionResetError, BrokenPipeError):
                break
            except Exception as e:
                logging.error(f"处理客户端数据错误: {e}")
                break
        
        # 客户端断开时移除
        with tcp_clients_lock:
            if self.request in tcp_clients:
                tcp_clients.remove(self.request)
        logging.info(f"客户端断开: {self.client_address}")

class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    """支持多线程的TCP服务器"""
    daemon_threads = True  # 主程序退出时自动结束线程
    allow_reuse_address = True  # 允许地址复用

def run_mqtt_client(config, server):
    """运行MQTT客户端"""
    client = mqtt_client.Client()
    client.user_data_set(config)  # 传递配置数据
    client.on_connect = on_mqtt_connect
    client.on_message = on_mqtt_message
    
    # 设置用户名密码
    if config.get('mqtt_username'):
        client.username_pw_set(config['mqtt_username'], config['mqtt_password'])
    
    try:
        client.connect(config['mqtt_host'], config['mqtt_port'])
        server.mqtt_client = client  # 将MQTT客户端实例绑定到服务器
        client.loop_start()
        return client
    except Exception as e:
        logging.error(f"MQTT连接错误: {e}")
        raise

def main():
    # 加载配置
    config = load_config()
    server_config = {
        'host': '0.0.0.0',
        'port': config['tcp_port'],
        'publish_topic': config['publish_topic']
    }
    
    # 启动TCP服务器
    with ThreadingTCPServer(
        (server_config['host'], server_config['port']), TCPRequestHandler
    ) as server:
        server.publish_topic = server_config['publish_topic']
        logging.info(f"TCP服务器启动,监听 {server_config['host']}:{server_config['port']}")
        
        # 启动MQTT客户端并绑定到服务器实例
        mqtt_client = run_mqtt_client(config, server)
        
        try:
            server.serve_forever()
        except KeyboardInterrupt:
            logging.info("收到中断信号,关闭服务器...")
            server.shutdown()
            mqtt_client.loop_stop()
            logging.info("服务器已关闭")

if __name__ == '__main__':
    main()
python 复制代码
pip install paho-mqtt

python mqtt_tcp_bridge.py
相关推荐
无奈笑天下4 小时前
银河麒麟高级服务器操作系统【双网卡绑定之bond0】操作方法
linux·运维·服务器·网络·经验分享
飞Link4 小时前
【网络与 AI 工程的交叉】多模态模型的数据传输特点:视频、音频、文本混合通道
网络·人工智能·音视频
一执念4 小时前
网络和互联网通信的本质
网络
老蒋新思维4 小时前
创客匠人峰会实录:知识变现的场景化革命 —— 创始人 IP 如何在垂直领域建立变现壁垒
网络·人工智能·tcp/ip·重构·知识付费·创始人ip·创客匠人
老蒋新思维4 小时前
创客匠人峰会深度解析:智能体驱动知识变现的数字资产化路径 —— 创始人 IP 的长期增长密码
人工智能·网络协议·tcp/ip·重构·知识付费·创始人ip·创客匠人
测试19984 小时前
功能测试、自动化测试、性能测试的区别
自动化测试·python·功能测试·测试工具·职场和发展·性能测试·安全性测试
M158227690555 小时前
六通道 CAN 集线器在消防报警主机系统中的应用方案
网络
盈创力和20075 小时前
当抱杆箱也上云:如何用 LoRa/NB-IoT 打造一个会“告警”的智能户外电气箱?
网络·物联网
Data_agent5 小时前
1688获得1688店铺所有商品API,python请求示例
java·开发语言·python
MonkeyKing_sunyuhua5 小时前
国内Dockerfile的配置,提高打包速度
linux·运维·网络