观前提醒,本文主要内容为Python实现MQTT服务器连接及话题发布&Python窗体实现
MQTT服务器的搭建详见http://www.guyuehome.com/44993
设计目标:
- 实现遥控水龙头开关
- 实现遥控水龙头定时开关
- 实现可视化的交互界面
根据上述设计目标,该程序大致可分为三个部分:
- MQTT连接与发布实现
- 交互窗体及控件实现
- 程序主逻辑实现
一、Python实现MQTT连接及话题发布
在Python中,连接到MQTT服务器以及实现消息的发布和订阅通常使用paho-mqtt
客户端库。以下是使用这个库实现连接、发布和订阅的详细解释:
连接到MQTT服务器
通过以下步骤即可实现对MQTT服务器的连接
- 导入paho-mqtt库中的客户端模块。
- 创建一个新的mqtt.Client实例。
- 设置连接回调函数,该回调在客户端连接到服务器时被调用。
- 连接到MQTT服务器,提供MQTT服务器的地址和端口。
- 启动客户端的网络循环。
import paho.mqtt.client as mqtt_client
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client("client-id")
client.on_connect = on_connect
client.connect("broker_address", 1883)
client.loop_start()
- import paho.mqtt.client as mqtt_client: 这行代码引入了 Paho MQTT 客户端库,并将其重命名为 mqtt_client 以便在后面的代码中使用。
- def on_connect(client, userdata, flags, rc): 这行定义了一个名为 on_connect 的回调函数,它在客户端连接到 MQTT 代理(Broker)时被调用。该函数接收四个参数:客户端实例对象、用户定义的任何类型的数据、连接响应标志和连接结果代码。
- if rc == 0: 这行代码检查连接结果代码 (rc)。如果 rc 等于 0,表示连接成功。
- client = mqtt_client.Client("client-id"): 这行创建一个 MQTT 客户端对象,并为其分配一个用户定义的客户端 ID。
- client.on_connect = on_connect: 这行将 on_connect 函数设置为连接到 MQTT 代理时的回调函数。
- client.connect("broker_address", 1883): 这行使客户端尝试连接到运行在指定地址 ("broker_address") 和端口 (1883) 的 MQTT 代理。
- client.loop_start(): 这行启动了一个新的线程,用于处理网络循环的调度和重连。这是非阻塞的,会在后台运行。
发布消息
def publish_message():
client.publish("python/mqtt", "Hello MQTT")
- def publish_message(): 这行代码定义了一个名为 publish_message 的函数,它不需要任何参数。
- client.publish("python/mqtt", "Hello MQTT"): 这行代码使用 publish 方法向 "python/mqtt" 这个主题发布一个消息。消息的内容是 "Hello MQTT"。
订阅话题
- 设置消息回调函数,该回调在收到订阅话题的消息时被调用。
- 使用subscribe方法订阅一个话题。
def on_message(client, userdata, message):
print(f"Received message '{str(message.payload.decode())}' on topic '{message.topic}'")
client.on_message = on_message
client.subscribe("topic")
- def on_message(client, userdata, message): 这行定义了一个名为 on_message 的回调函数,当客户端从订阅的主题接收到消息时调用此函数。函数接收三个参数:客户端实例对象、用户定义的任何类型的数据和接收到的消息对象。
- print(f"Received message '{str(message.payload.decode())}' on topic '{message.topic}'"): 这行代码在接收到消息时打印出接收到的消息内容和主题。消息内容通过调用 message.payload.decode() 从字节格式转换为字符串格式。
- client.on_message = on_message: 这行将 on_message 函数设置为接收到来自订阅主题的消息时的回调函数。
- client.subscribe("topic"): 这行代码让客户端订阅名为 "topic" 的主题。当有新消息发布到此主题时,on_message 函数将被调用。
完整代码
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected successfully to MQTT broker")
else:
print("Connection failed with code %d" % rc)
def publish_message():
client.publish("python/mqtt", "Hello MQTT")
client = mqtt.Client()
client.on_connect = on_connect
client.connect("mqtt.eclipse.org", 1883, 60)
# Starting the loop
client.loop_start()
publish_message()
在这段代码中,我们创建了一个mqtt.Client实例,连接到了MQTT服务器,并且发布了一个消息。注意,我们使用了client.loop_start()来启动网络循环,这个调用会在后台线程中处理网络事件,包括重新连接和重新发送。
运行程序,通过输出我们可以判断程序已经成功连接到了MQTT服务器并发布话题:
二、Python实现窗体显示和控件
使用Python的Tkinter库来创建一个简单的图形用户界面(GUI)应用程序。这个程序将显示一个窗体,窗体内包含一个输入栏(文本框)和一个按钮。用户可以在文本框中输入文本,然后点击按钮后,输入的文本将显示在窗体内的一个标签上。
步骤1:导入Tkinter库
首先,我们需要导入Tkinter库以及tkinter.messagebox模块,后者用于显示弹出消息框。
import tkinter as tk
from tkinter import messagebox
步骤2:创建主窗口
接着,我们将创建一个主窗口,并设置它的标题和大小。
window = tk.Tk()
window.title("GUI App with Tkinter")
window.geometry('400x200')
- window = tk.Tk(): 这行代码创建了一个 Tkinter 窗口对象,这个窗口是所有其他 Tkinter 组件(如按钮、标签等)的容器。通常我们称这个窗口为主窗口或根窗口。
- window.title("GUI App with Tkinter"): 这行代码设置了窗口的标题为 "GUI App with Tkinter"。这个标题将出现在窗口的标题栏上。
- window.geometry('400x200'): 这行代码设置了窗口的初始大小为 400 像素宽和 200 像素高。geometry 方法接收一个字符串参数,该字符串的格式为 'widthxheight',其中 width 和 height 是窗口的宽度和高度的像素值。
步骤3:添加输入栏和按钮
我们需要一个文本框让用户输入内容,以及一个按钮来执行一个动作(在这种情况下,是显示输入的文本)。
# 输入栏
entry = tk.Entry(window, width=50)
entry.pack()
# 按钮执行的动作
def on_button_click():
user_input = entry.get()
messagebox.showinfo("Message", f"You entered: {user_input}")
# 按钮
button = tk.Button(window, text="Display Input", command=on_button_click)
button.pack()
- entry = tk.Entry(window, width=50): 这行代码创建了一个 Entry 组件,它是一个基本的文本输入框,用户可以在其中输入文本。参数 window 表示这个 Entry 组件是 window 的子组件,width=50 设置了输入框的宽度为 50 个字符。
- entry.pack(): 这行代码将输入框添加到窗口中。pack 是一个布局管理器,用于控制组件的位置和大小。调用 pack 后,组件会自动调整大小以适应其内容,并放在其父组件中的合适位置。
- def on_button_click(): 这行代码定义了一个函数,这个函数将在按钮被点击时执行。
- user_input = entry.get(): 这行代码从输入框中获取用户输入的文本。
- messagebox.showinfo("Message", f"You entered: {user_input}"): 这行代码调用 messagebox.showinfo 函数来显示一个信息对话框,对话框的标题是 "Message",内容是 "You entered: " 后接用户输入的文本。
- button = tk.Button(window, text="Display Input", command=on_button_click): 这行代码创建了一个 Button 组件,按钮的文本是 "Display Input",当按钮被点击时,command 参数指定的 on_button_click 函数将被执行。
- button.pack(): 这行代码将按钮添加到窗口中。
步骤4:启动事件循环
最后,我们需要启动应用程序的事件循环,这样它才能等待用户的操作,比如按键点击。
window.mainloop()
将上述代码放在一起,运行:
import tkinter as tk
from tkinter import messagebox
# 创建主窗口
window = tk.Tk()
window.title("GUI App with Tkinter")
window.geometry('400x200')
# 输入栏
entry = tk.Entry(window, width=50)
entry.pack()
# 按钮执行的动作
def on_button_click():
user_input = entry.get()
messagebox.showinfo("Message", f"You entered: {user_input}")
# 按钮
button = tk.Button(window, text="Display Input", command=on_button_click)
button.pack()
# 启动事件循环
window.mainloop()
三、完整程序实现:
完整程序:
import tkinter as tk
from tkinter import ttk
from paho.mqtt import client as mqtt_client
import time
# MQTT服务器配置
broker = '192.168.3.222'
port = 1883
topic = "slt"
client_id = f'python-mqtt-{int(time.time())}'
# 连接MQTT服务器的函数
def connect_mqtt():
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.on_connect = on_connect
client.connect(broker, port)
return client
# 发布消息的函数
def publish(client, msg):
result = client.publish(topic, msg)
status = result[0]
if status == 0:
print(f"Send `{msg}` to topic `{topic}`")
else:
print(f"Failed to send message to topic {topic}")
# 创建定时器,定时发布消息
def on_timer(client, interval, progress_var):
publish(client, "0")
progress_var.set(0) # 重置进度条
update_progress_bar(progress_var, interval, interval) # 更新进度条
# 更新进度条的函数
def update_progress_bar(progress_var, interval, max_time):
progress_step = 100 / (max_time / 1000)
new_progress = progress_var.get() + progress_step
if new_progress < 100:
progress_var.set(new_progress)
root.after(1000, update_progress_bar, progress_var, interval-1000, max_time)
else:
progress_var.set(100) # 完成
# 开关按钮的回调函数
def on_publish(client, msg):
publish(client, msg)
# 设置定时器时间的回调函数
def set_timer(progress_var):
try:
interval = int(timer_entry.get()) * 1000 # 将秒转换为毫秒
progress_var.set(0) # 重置进度条
root.after(interval, on_timer, client, interval, progress_var) # 设置定时器
except ValueError:
print("Please enter an integer value for the timer interval.")
# 创建GUI窗口
root = tk.Tk()
root.title("MQTT Publisher")
root.geometry("400x150") # 设置窗口大小
# 定时器设置区域
timer_frame = tk.Frame(root)
timer_frame.pack(side=tk.TOP, fill=tk.X)
timer_label = tk.Label(timer_frame, text="Timer (s):")
timer_label.pack(side=tk.LEFT)
timer_entry = tk.Entry(timer_frame, width=5)
timer_entry.pack(side=tk.LEFT)
progress_var = tk.DoubleVar() # 进度条变量
progress_bar = ttk.Progressbar(timer_frame, variable=progress_var, length=100, mode='determinate')
progress_bar.pack(side=tk.LEFT, padx=5)
btn_set_timer = tk.Button(timer_frame, text="Set Timer", width=10, command=lambda: set_timer(progress_var))
btn_set_timer.pack(side=tk.LEFT, padx=5)
# 创建开关按钮
btn_on = tk.Button(root, text="ON", width=10, height=2, command=lambda: on_publish(client, "1"))
btn_on.pack(pady=5)
btn_off = tk.Button(root, text="OFF", width=10, height=2, command=lambda: on_publish(client, "0"))
btn_off.pack(pady=5)
# 连接MQTT
client = connect_mqtt()
client.loop_start()
# 启动GUI循环
root.mainloop()
程序功能&逻辑分析:
这个Python程序使用了tkinter和paho-mqtt库来创建一个简单的图形用户界面(GUI),同时实现了MQTT客户端的功能。程序的逻辑可以分为几个主要部分:
- MQTT服务器配置
定义了MQTT服务器的配置信息,包括服务器地址、端口和主题。
程序为MQTT客户端生成了一个基于当前时间戳的唯一client_id。 - MQTT连接与消息发布
connect_mqtt()函数负责创建一个MQTT客户端实例,并设置连接回调函数on_connect。如果连接成功,将打印成功消息;如果连接失败,将打印错误代码。
publish()函数用于向指定的MQTT主题发布消息。发布成功时会打印提示信息,失败则打印错误信息。 - GUI与定时器逻辑
程序创建了一个Tkinter窗口,其中包含定时器设置、进度条、以及开/关按钮。
on_timer()函数作为定时器回调,每次定时器到期时将发布一个"0"消息,并重置进度条。
update_progress_bar()函数负责定期更新进度条的进度,直到进度达到100%。
on_publish()函数是按钮的回调,当按钮按下时,将发布"1"或"0"消息。
set_timer()函数从文本框获取用户输入的定时器间隔(秒),并设置定时器。 - GUI布局
使用Tkinter的Frame、Label、Entry、Button和Progressbar组件创建了用户界面。
progress_var是一个DoubleVar对象,用于与进度条组件进行数据绑定。
使用pack()方法安排组件在窗口中的位置。 - 程序运行
程序首先尝试连接到MQTT服务器,并开始MQTT客户端的事件循环。
启动Tkinter的主事件循环,等待用户操作。
整体上,这个程序是一个MQTT消息发布器,带有一个用户界面,允许用户开启/关闭消息发布,并设定一个定时器来周期性地发布消息。程序通过图形界面提供用户交互,同时在后台处理MQTT通信,展示了如何将MQTT通信与GUI应用程序结合起来。
评论(0)
您还未登录,请登录后发表或查看评论