我正在构建一个应用程序,该应用程序使用MQTT通过简单的GUI发布/接收数据以显示接收到的数据以及打开/关闭切换,如果发生更改,则使用MQTT发布消息。
该应用程序可以正常运行,但是太笨拙了。
我使用了CProfile,发现分配给它最多时间的函数是“ select.select”,所以我的问题是如何提高代码的性能。 CProfile Output(sort=tottime) CProfile Output(sort=cumtime)
注意:我试图在不同的线程上运行MQTT,但是我必须访问Tkinter不允许的MQTT函数中的Tkinter对象(这是我的理解)
其余代码(如果需要):https://www.codepile.net/pile/K2VvKz2y
from tkinter import *
import paho.mqtt.client as mqtt
import gui
running = True
def update_running():
global running
running = False
root.destroy()
def update_meters(topic, value):
if topic == "home/office/temperature":
office_temperature_meter.reading.set(value)
elif topic == "home/bed/temperature":
bed_temperature_meter.reading.set(value)
elif topic == "home/living/temperature":
living_temperature_meter.reading.set(value)
def on_connect(client, userdata, flags, rc):
print("Connected With Result Code "+rc)
def on_message(client, userdata, message):
print(message.topic + " Received: " + message.payload.decode())
update_meters(message.topic, message.payload.decode())
# Establishing Connection
broker_url = "iot.eclipse.org"
broker_port = 1883
client = mqtt.Client("G2K_RaspberryPie3_x01")
client.on_connect = on_connect
client.on_message = on_message
client.connect(broker_url, broker_port)
client.subscribe("home/office/temperature", qos=1)
client.subscribe("home/bed/temperature", qos=1)
client.subscribe("home/living/temperature", qos=1)
###########
# Initiating Main Application Window
root = Tk()
root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))
root.focus_set()
root.title("G2K: Smart Home")
root.protocol("WM_DELETE_WINDOW", update_running)
###########
# Office Frame
office_frame = gui.FrameCreate(250, 650, "LightGrey", 20, 20, "Office", 85)
root.update()
office_lights_button = gui.ToggleButton(10, 100, "Lights", office_frame.frame)
office_conditioner_button = gui.ToggleButton(10, 200, "Air Conditioner", office_frame.frame)
office_temperature_meter = gui.ReadingMeter(10, 300, "Temperature", office_frame.frame)
###########
# Bedroom Frame
bed_frame = gui.FrameCreate(250, 650, "LightGrey", 300, 20, "Bedroom", 75)
root.update()
bed_lights_button = gui.ToggleButton(10, 100, "Lights", bed_frame.frame)
bed_conditioner_button = gui.ToggleButton(10, 200, "Air Conditioner", bed_frame.frame)
bed_temperature_meter = gui.ReadingMeter(10, 300, "Temperature", bed_frame.frame)
###########
# Livingroom Frame
living_frame = gui.FrameCreate(250, 650, "LightGrey", 590, 20, "Living Room", 60)
root.update()
living_lights_button = gui.ToggleButton(10, 100, "Lights", living_frame.frame)
living_conditioner_button = gui.ToggleButton(10, 200, "Air Conditioner", living_frame.frame)
living_temperature_meter = gui.ReadingMeter(10, 300, "Temperature", living_frame.frame)
###########
while 1:
if running:
# constantly update the GUI
root.update()
# constantly check if any messages arrived on subscribed topics
client.loop()
# Check if state is not changed, to avoid sending redundant requests.
if office_lights_button.button_state != office_lights_button.button_prev_state:
client.publish(topic="home/office/light", payload=int(office_lights_button.button_state), qos=1,
retain=False)
office_lights_button.button_prev_state = office_lights_button.button_state
if office_conditioner_button.button_state != office_conditioner_button.button_prev_state:
client.publish(topic="home/office/conditioner", payload=int(office_conditioner_button.button_state), qos=1,
retain=False)
office_conditioner_button.button_prev_state = office_conditioner_button.button_state
# Check if state is not changed, to avoid sending redundant requests.
if bed_lights_button.button_state != bed_lights_button.button_prev_state:
client.publish(topic="home/bed/light", payload=int(bed_lights_button.button_state), qos=1,
retain=False)
bed_lights_button.button_prev_state = bed_lights_button.button_state
if bed_conditioner_button.button_state != bed_conditioner_button.button_prev_state:
client.publish(topic="home/bed/conditioner", payload=int(bed_conditioner_button.button_state), qos=1,
retain=False)
bed_conditioner_button.button_prev_state = bed_conditioner_button.button_state
# Check if state is not changed, to avoid sending redundant requests.
if living_lights_button.button_state != living_lights_button.button_prev_state:
client.publish(topic="home/living/light", payload=int(living_lights_button.button_state), qos=1,
retain=False)
living_lights_button.button_prev_state = living_lights_button.button_state
if living_conditioner_button.button_state != living_conditioner_button.button_prev_state:
client.publish(topic="home/living/conditioner", payload=int(bed_conditioner_button.button_state), qos=1,
retain=False)
living_conditioner_button.button_prev_state = living_conditioner_button.button_state
答案 0 :(得分:0)
尝试客户端类 loop_start()
方法。由于它运行一个单独的线程,它不会过多地影响 GUI 的主循环。我只在 pyqt5 中尝试过,但它也可以与 tk 一起使用。
移除 while true 循环并在最后添加 client.loop_start()
和 tks mainloop。