目的:
一个具备收发功能的mqtt通讯服务器
Debug
由于旧版代码有一些报错,参考官方源码,针对性进行一些删改,主要改动在方法connect_mqtt()
def connect_mqtt():
# For paho-mqtt 2.0.0, you need to add the properties parameter.
def on_connect(client, userdata, flags, rc, properties):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
# For paho-mqtt 2.0.0, you need to set callback_api_version.
client = mqtt_client.Client(client_id=client_id, callback_api_version=mqtt_client.CallbackAPIVersion.VERSION2)
# client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
return client
client无法像Rust中那样进行clone,所以想办法绕开它,这里将订阅和连接绑定在一起,则不会在初始化订阅时报错了
# 将连接与订阅绑在一起,防止复用client导致连接冲突
def connect_mqtt():
# For paho-mqtt 2.0.0, you need to add the properties parameter.
def on_connect(client, userdata, flags, rc, properties):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
# For paho-mqtt 2.0.0, you need to set callback_api_version.
client = mqtt_client.Client(client_id=client_id, callback_api_version=mqtt_client.CallbackAPIVersion.VERSION2)
# client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
client.subscribe(su_topic[0])
print("订阅完成")
return client
根据需要,又做了一些扩展性修改
整理汇总
测试脚本(mqtt_one.py)
from paho.mqtt import client as mqtt_client
from threading import Thread
import time
broker = 'broker.emqx.io'
port = 1883
su_topic = [("python_mqtt_server",2),("python_mqtt_command",2)] #订阅频道,数组格式为(topic,qos)
pu_topic = ["python_mqtt_server"] #发布频道
client_id = 'python_mqtt_center'
# 将连接与订阅绑在一起,防止复用client导致连接冲突
def connect_mqtt():
# For paho-mqtt 2.0.0, you need to add the properties parameter.
def on_connect(client, userdata, flags, rc, properties):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
# For paho-mqtt 2.0.0, you need to set callback_api_version.
client = mqtt_client.Client(client_id=client_id, callback_api_version=mqtt_client.CallbackAPIVersion.VERSION2)
# client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
subscribe_many(client)
print("订阅完成")
return client
# 订阅多个频道
def subscribe_many(client):
# 根据client源码可知,订阅支持的数组格式是(topic,qos)
client.subscribe(su_topic)
# 收到信息的回调函数
def on_message(client, userdata, msg):
print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
# 这里可以编写一些收到信息后的处理,比如收到什么信息开启什么任务,任务完成后再调publish发布信息给终端等等........
# ----------处理例子------------------
r_msg=msg.payload.decode()
if int(r_msg)%2==0:
print("收到偶数")
# -----------------------------------
# 发布信息函数
def publish(client):
for i in range(1,11):
time.sleep(1)
msg = f"{i}"
result = client.publish(pu_topic[0], msg)
# result: [0, 1]
status = result[0]
if status == 0:
print(f"Send `{msg}` to topic `{pu_topic[0]}`")
else:
print(f"Failed to send message to topic {pu_topic[0]}")
if __name__ == '__main__':
client = connect_mqtt()
client.on_message = on_message #重写回调函数,可以在方法体里,根据需求改收到信息后干什么
# 多线程,这里启动一个发布任务的线程,模拟有一个发布消息的客户端
thread1 = Thread(target=publish,args=(client,))
# --*如要要实现流水线式的收发,则可以将线程内方法改为任务队列处理,用一个全局变量管理任务执行,执行后再publish
thread1.start()
client.loop_forever() #这个要加,监听(on_message)与loop_forever配套
# thread1.join() #由于进程堵塞在上方,再join也无意义了
#------------------------------------------------------------------
# client.loop_start() #如果只是发布 那么这个要加,发布与loop_start与stop配套
# publish(client)
# client.loop_stop()