WOKWI ESP32 DHT22 溫度濕度 上下限設定
溫度下限值:現在與「繼電器 1」處於 row 2。
溫度上限值:現在與「繼電器 3」處於 row 4。
濕度下限值:現在與「繼電器 4」處於 row 6。
濕度上限值:現在與「繼電器 6」處於 row 8。
字體顏色:當繼電器狀態切換為 ON 時,對應的 OFF/ON 字樣會變成紅色。
ESP-MQTT 範例來處理 TCP/SSL/WebSocket 連線和消息收發。 - MQTT Broker: 訊息的中介站 (例如
test.mosquitto.org)。 - Topic: 訊息的分類主題 (例如
home/livingroom/temperature)。 - Publish (發布者): 將感測器數據發送到 Topic。
- Subscribe (訂閱者): 訂閱 Topic 接收消息。
import tkinter as tk
from tkinter import font
import paho.mqtt.client as mqtt
# --- MQTT 配置 ---
BROKER = "mqttgo.io"
PORT = 1883
TOPICS = {
"temp": "alex9ufo/dht22/temp",
"humi": "alex9ufo/dht22/humi",
}
RELAY_TOPICS = [
"alex9ufo/relay1", "alex9ufo/relay2", "alex9ufo/relay3",
"alex9ufo/relay4", "alex9ufo/relay5", "alex9ufo/relay6"
]
class MQTTApp:
def __init__(self, root):
self.root = root
self.root.title("ESP32 監控系統")
self.root.geometry("700x500")
self.label_font = font.Font(size=12)
self.val_font = font.Font(size=12, weight="bold")
# 變數初始化
self.current_temp = tk.StringVar(value="--")
self.current_humi = tk.StringVar(value="--")
self.mqtt_status = tk.StringVar(value="斷線")
self.relay_status = [tk.StringVar(value="OFF") for _ in range(6)]
self.relay_labels = []
self.setup_ui()
self.client = mqtt.Client()
self.client.on_connect = self.on_connect
self.client.on_message = self.on_message
try:
self.client.connect(BROKER, PORT, 60)
self.client.loop_start()
except:
self.mqtt_status.set("連線失敗")
def setup_ui(self):
# 設定整體網格權重
for i in range(12): self.root.grid_rowconfigure(i, weight=1)
for i in range(4): self.root.grid_columnconfigure(i, weight=1)
# --- 第一行:目前溫濕度 ---
tk.Label(self.root, text="目前溫度:", font=self.label_font).grid(row=0, column=0, sticky="e")
tk.Label(self.root, textvariable=self.current_temp, font=self.val_font, fg="blue", relief="sunken", width=12).grid(row=0, column=1, padx=5)
tk.Label(self.root, text="目前濕度:", font=self.label_font).grid(row=0, column=2, sticky="e")
tk.Label(self.root, textvariable=self.current_humi, font=self.val_font, fg="blue", relief="sunken", width=12).grid(row=0, column=3, padx=5)
# --- 繼電器與設定值佈局 (依圖片位置) ---
pins = ["23", "22", "21", "19", "18", "5"]
# 1. 繼電器1 (23) 與 溫度下限值 (Row 2)
tk.Label(self.root, text=f"繼電器1 ({pins[0]})狀態:", font=self.label_font).grid(row=2, column=0, sticky="e")
lbl1 = tk.Label(self.root, textvariable=self.relay_status[0], font=self.val_font, relief="sunken", width=12)
lbl1.grid(row=2, column=1, padx=5); self.relay_labels.append(lbl1)
tk.Label(self.root, text="溫度下限值:", font=self.label_font).grid(row=2, column=2, sticky="e")
self.ent_t_low = tk.Entry(self.root, width=15); self.ent_t_low.insert(0, "20"); self.ent_t_low.grid(row=2, column=3)
# 2. 繼電器2 (22) (Row 3)
tk.Label(self.root, text=f"繼電器2 ({pins[1]})狀態:", font=self.label_font).grid(row=3, column=0, sticky="e")
lbl2 = tk.Label(self.root, textvariable=self.relay_status[1], font=self.val_font, relief="sunken", width=12)
lbl2.grid(row=3, column=1, padx=5); self.relay_labels.append(lbl2)
# 3. 繼電器3 (21) 與 溫度上限值 (Row 4)
tk.Label(self.root, text=f"繼電器3 ({pins[2]})狀態:", font=self.label_font).grid(row=4, column=0, sticky="e")
lbl3 = tk.Label(self.root, textvariable=self.relay_status[2], font=self.val_font, relief="sunken", width=12)
lbl3.grid(row=4, column=1, padx=5); self.relay_labels.append(lbl3)
tk.Label(self.root, text="溫度上限值:", font=self.label_font).grid(row=4, column=2, sticky="e")
self.ent_t_high = tk.Entry(self.root, width=15); self.ent_t_high.insert(0, "30"); self.ent_t_high.grid(row=4, column=3)
# --- 中間空行 (Row 5) ---
# 4. 繼電器4 (19) 與 濕度下限值 (Row 6)
tk.Label(self.root, text=f"繼電器4 ({pins[3]})狀態:", font=self.label_font).grid(row=6, column=0, sticky="e")
lbl4 = tk.Label(self.root, textvariable=self.relay_status[3], font=self.val_font, relief="sunken", width=12)
lbl4.grid(row=6, column=1, padx=5); self.relay_labels.append(lbl4)
tk.Label(self.root, text="濕度下限值:", font=self.label_font).grid(row=6, column=2, sticky="e")
self.ent_h_low = tk.Entry(self.root, width=15); self.ent_h_low.insert(0, "40"); self.ent_h_low.grid(row=6, column=3)
# 5. 繼電器5 (18) (Row 7)
tk.Label(self.root, text=f"繼電器5 ({pins[4]})狀態:", font=self.label_font).grid(row=7, column=0, sticky="e")
lbl5 = tk.Label(self.root, textvariable=self.relay_status[4], font=self.val_font, relief="sunken", width=12)
lbl5.grid(row=7, column=1, padx=5); self.relay_labels.append(lbl5)
# 6. 繼電器6 (5) 與 濕度上限值 (Row 8)
tk.Label(self.root, text=f"繼電器6 ({pins[5]})狀態:", font=self.label_font).grid(row=8, column=0, sticky="e")
lbl6 = tk.Label(self.root, textvariable=self.relay_status[5], font=self.val_font, relief="sunken", width=12)
lbl6.grid(row=8, column=1, padx=5); self.relay_labels.append(lbl6)
tk.Label(self.root, text="濕度上限值:", font=self.label_font).grid(row=8, column=2, sticky="e")
self.ent_h_high = tk.Entry(self.root, width=15); self.ent_h_high.insert(0, "70"); self.ent_h_high.grid(row=8, column=3)
# --- 底部:MQTT 連線狀態 ---
tk.Label(self.root, text="MQTT連線狀態:", font=self.label_font).grid(row=10, column=0, sticky="e")
tk.Label(self.root, textvariable=self.mqtt_status, font=self.val_font, fg="green", relief="sunken", width=12).grid(row=10, column=1, padx=5)
def on_connect(self, client, userdata, flags, rc):
if rc == 0:
self.mqtt_status.set("已連線")
client.subscribe(TOPICS["temp"])
client.subscribe(TOPICS["humi"])
def on_message(self, client, userdata, msg):
try:
val = float(msg.payload.decode())
if msg.topic == TOPICS["temp"]:
self.current_temp.set(f"{val} °C")
self.check_logic(val, "temp")
elif msg.topic == TOPICS["humi"]:
self.current_humi.set(f"{val} %")
self.check_logic(val, "humi")
except: pass
def check_logic(self, current_val, mode):
try:
if mode == "temp":
low, high = float(self.ent_t_low.get()), float(self.ent_t_high.get())
indices = [0, 1, 2]
else:
low, high = float(self.ent_h_low.get()), float(self.ent_h_high.get())
indices = [3, 4, 5]
states = ["OFF", "OFF", "OFF"]
if current_val < low: states[0] = "ON"
elif current_val > high: states[2] = "ON"
else: states[1] = "ON"
for i, idx in enumerate(indices):
self.relay_status[idx].set(states[i])
# 狀態為 ON 時顯示紅色
self.relay_labels[idx].config(fg="red" if states[i] == "ON" else "black")
self.client.publish(RELAY_TOPICS[idx], states[i])
except: pass
if __name__ == "__main__":
root = tk.Tk()
app = MQTTApp(root)
root.mainloop()


















沒有留言:
張貼留言