串口監控基礎框架使用說明
撰寫人: 范紹捷/動力組/5~9代
目錄
簡介
這是一個基於 ttkbootstrap 的uart監控基礎框架,提供了基本的串口通信界面和日誌記錄功能。
安裝需求
pip install ttkbootstrap
pip install pyserial
基本使用
初始化程序
from base_monitor import BaseMonitor
app = BaseMonitor(title="監控程序")
app.run()
參數設置
初始化時可設置的參數:
- title :窗口標題(默認:"監視器")
- size :窗口大小(默認:"500x600")
- theme :界面主題(默認:"darkly")
可用主題:
darkly、cosmo、flatly、litera、minty、lumen、sandstone、yeti、pulse、united、morph
自定義開發
繼承基礎類
class CustomMonitor(BaseMonitor):
def __init__(self):
super().__init__(title="自定義監控")
可重寫的方法
- create_data_panel :自定義數據顯示面板
def create_data_panel(self):
data_frame = ttk.LabelFrame(self.main_container, text="自定義數據", padding=10)
data_frame.pack(fill=X, pady=10)
# 添加自己的顯示元件
- start_monitor :實現數據接收邏輯
def start_monitor(self):
try:
self.serial = serial.Serial(
port=self.port_var.get(),
baudrate=int(self.baud_var.get()),
timeout=1
)
# 添加數據處理邏輯
except Exception as e:
self.log_message(f"啟動失敗: {str(e)}")
- stop_monitor :實現停止邏輯
def stop_monitor(self):
if self.serial:
self.serial.close()
self.serial = None
日誌記錄
使用 log_message 方法記錄日誌:
self.log_message("自定義消息")
注意事項
- 串口連接前請確保選擇了正確的端口和波特率
- 程序退出時會自動關閉串口連接
- 建議在子類中實現異常處理機制
完整程式
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import threading
import serial
import serial.tools.list_ports
class BaseMonitor:
def __init__(self, title="監視器", size="500x600", theme="darkly"):
self.root = ttk.Window(title=title, themename=theme, resizable=(False, False))
self.root.geometry(size)
# 狀態變量
self.is_running = False
# 創建界面
self.create_widgets()
def create_widgets(self):
# 主容器
self.main_container = ttk.Frame(self.root, padding=10)
self.main_container.pack(fill=BOTH, expand=YES)
# 控制區域
self.create_control_panel()
# 數據顯示區域
self.create_data_panel()
# 日誌區域
self.create_log_panel()
def create_control_panel(self):
"""控制面板 - 可在子類中重寫"""
control_frame = ttk.LabelFrame(self.main_container, text="控制面板", padding=10)
control_frame.pack(fill=X, pady=5)
# 端口設置
port_frame = ttk.Frame(control_frame)
port_frame.pack(fill=X, pady=5)
ttk.Label(port_frame, text="端口:").pack(side=LEFT, padx=5)
self.port_var = ttk.StringVar()
self.port_combo = ttk.Combobox(port_frame, textvariable=self.port_var)
self.port_combo.pack(side=LEFT, fill=X, expand=YES)
# 刷新端口按鈕
ttk.Button(
port_frame,
text="刷新",
command=self.refresh_ports,
style="info.TButton",
width=8
).pack(side=LEFT, padx=5)
# 波特率設置
baud_frame = ttk.Frame(control_frame)
baud_frame.pack(fill=X, pady=5)
ttk.Label(baud_frame, text="波特率:").pack(side=LEFT, padx=5)
self.baud_var = ttk.StringVar(value="9600")
baud_choices = ['9600', '19200', '38400', '57600', '115200']
ttk.Combobox(baud_frame, textvariable=self.baud_var, values=baud_choices).pack(side=LEFT, fill=X, expand=YES)
# 控制按鈕
self.control_btn = ttk.Button(
control_frame,
text="連接",
command=self.toggle_running,
style="primary.TButton"
)
self.control_btn.pack(pady=10)
# 初始化端口列表
self.refresh_ports()
def refresh_ports(self):
"""更新可用的串口列表"""
ports = [port.device for port in serial.tools.list_ports.comports()]
self.port_combo['values'] = ports
if ports:
self.port_var.set(ports[0])
else:
self.port_var.set('')
self.log_message("未檢測到可用的串口")
def toggle_running(self):
"""切換運行狀態"""
self.is_running = not self.is_running
if self.is_running:
self.control_btn.configure(text="斷開", style="danger.TButton")
self.status_label.configure(text="已連接", style="success.TLabel")
self.log_message("串口連接成功")
self.start_monitor()
else:
self.control_btn.configure(text="連接", style="primary.TButton")
self.status_label.configure(text="未連接", style="danger.TLabel")
self.log_message("串口已斷開")
self.stop_monitor()
def create_data_panel(self):
"""數據顯示面板 - 可在子類中重寫"""
data_frame = ttk.LabelFrame(self.main_container, text="數據顯示", padding=10)
data_frame.pack(fill=X, pady=10)
# 狀態顯示
self.status_label = ttk.Label(
data_frame,
text="未運行",
style="danger.TLabel"
)
self.status_label.pack(pady=5)
def create_log_panel(self):
"""日誌面板"""
log_frame = ttk.LabelFrame(self.main_container, text="系統日誌", padding=10)
log_frame.pack(fill=BOTH, expand=YES, pady=5)
self.log_text = ttk.Text(log_frame, height=10, width=40)
self.log_text.pack(fill=BOTH, expand=YES)
scrollbar = ttk.Scrollbar(log_frame, orient="vertical", command=self.log_text.yview)
scrollbar.pack(side=RIGHT, fill=Y)
self.log_text.configure(yscrollcommand=scrollbar.set)
def toggle_running(self):
"""切換運行狀態"""
self.is_running = not self.is_running
if self.is_running:
self.control_btn.configure(text="停止", style="danger.TButton")
self.status_label.configure(text="運行中", style="success.TLabel")
self.log_message("系統啟動")
self.start_monitor()
else:
self.control_btn.configure(text="開始", style="primary.TButton")
self.status_label.configure(text="未運行", style="danger.TLabel")
self.log_message("系統停止")
self.stop_monitor()
def start_monitor(self):
"""啟動監控 - 在子類中實現"""
pass
def stop_monitor(self):
"""停止監控 - 在子類中實現"""
pass
def log_message(self, message):
"""記錄日誌消息"""
import time
self.log_text.insert(END, f"{time.strftime('%H:%M:%S')} - {message}\n")
self.log_text.see(END)
def run(self):
"""運行程序"""
self.root.mainloop()
if __name__ == "__main__":
# 基礎使用示例
app = BaseMonitor(title="基礎監視器")
app.run()