From 1bc6db3f377e64b815ef49fb85781a560de0920c Mon Sep 17 00:00:00 2001 From: Christoffer Martinsson Date: Sun, 13 Apr 2025 18:06:19 +0200 Subject: [PATCH] Edit spm6103_viewer.py --- spm6103_viewer.py | 100 +++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/spm6103_viewer.py b/spm6103_viewer.py index 905dd1f..a9fca63 100644 --- a/spm6103_viewer.py +++ b/spm6103_viewer.py @@ -3,7 +3,52 @@ from tkinter.font import Font import serial import os import json +import threading +import time +class SerialManager: + def __init__(self, port_name="/dev/ttyUSB0", baud_rate=115200, reconnect_interval=2): + self.port_name = port_name + self.baud_rate = baud_rate + self.reconnect_interval = reconnect_interval + self.ser = None + self.lock = threading.Lock() + self.running = True + self.thread = threading.Thread(target=self._monitor_serial) + self.thread.daemon = True + self.thread.start() + + def _monitor_serial(self): + while self.running: + with self.lock: + if self.ser is None or not self.ser.is_open: + try: + self.ser = serial.Serial(self.port_name, self.baud_rate, timeout=1) + print(f"[INFO] Connected to {self.port_name}") + except serial.SerialException as e: + print(f"[WARN] Serial port error: {e}") + self.ser = None + time.sleep(self.reconnect_interval) + + def send_command(self, command): + with self.lock: + if self.ser and self.ser.is_open: + try: + self.ser.write((command + '\n').encode('utf-8')) + response = self.ser.readline().decode('utf-8').strip() + return response + except Exception as e: + print(f"[ERROR] Failed to send/receive: {e}") + self.ser = None + return "Serial not connected" + + def stop(self): + self.running = False + self.thread.join() + if self.ser and self.ser.is_open: + self.ser.close() + +# Set DPI scale for Wayland os.environ['GDK_SCALE'] = '2' # Load saved window geometry if exists @@ -23,21 +68,10 @@ def save_window_geometry(): json.dump(settings, f) # Serial configuration -port = '/dev/ttyUSB0' # Adjust to your specific port -baud_rate = 115200 # Adjust to your device's baud rate +ser = SerialManager(port='/dev/ttyUSB0') -try: - ser = serial.Serial(port, baud_rate, timeout=1) -except serial.SerialException as e: - ser = None - print(f"Serial port error: {e}") - -def send_command(command): - if not ser: - return "Serial port not available" - ser.write((command + '\n').encode('utf-8')) - response = ser.readline().decode('utf-8').strip() - return response +def send_command(cmd): + return ser.send_command(cmd) def get_id(): if not ser: @@ -121,8 +155,8 @@ app.title("OWON SPM6103") app.geometry(load_window_geometry()) app.configure(bg="black") -# Add a window close event to save the geometry -app.protocol("WM_DELETE_WINDOW", lambda: [save_window_geometry(), app.quit()]) +# For cleanup on exit +app.protocol("WM_DELETE_WINDOW", lambda: [save_window_geometry(), serial_manager.stop(), app.quit()]) multimeter_type_var = tk.StringVar() multimeter_data_var = tk.StringVar() @@ -135,7 +169,6 @@ fontBig = Font(size=24) resize_after_id = None - def apply_font_resize(): width = app.winfo_width() @@ -157,8 +190,6 @@ app.columnconfigure(0, weight=1, uniform="equal", minsize=100) for i in range(7): app.columnconfigure(i+1, weight=1, uniform="equal") -button_fg = "#444444" - # Labels # Type and Range tk.Label(app, textvariable=multimeter_type_var, font=fontMedium, bg="black", fg="lightgrey") \ @@ -172,26 +203,21 @@ tk.Label(app, textvariable=multimeter_data_var, font=fontBig, bg="black", fg="li .grid(column=1, columnspan=6, row=0, rowspan=1, sticky="nsew", padx=0, pady=10) # Buttons -tk.Button(app, text="RES", command=set_res_mode, font=fontSmall, bg="black", fg=button_fg, highlightbackground="black", borderwidth=0) \ - .grid(column=1, row=1, sticky="nsew", padx=0, pady=0) +buttons = [ + ("RES", set_res_mode), + ("RES200", set_res200_mode), + ("CONT", set_cont_mode), + ("VOLT:DC", set_voltdc_mode), + ("VOLT:AC", set_voltac_mode), + ("DIOD", set_diod_mode), + ("CAP", set_cap_mode), +] -tk.Button(app, text="RES200", command=set_res200_mode, font=fontSmall, bg="black", fg=button_fg, highlightbackground="black", borderwidth=0) \ - .grid(column=2, row=1, sticky="nsew", padx=0, pady=0) +for i, (label, cmd) in enumerate(buttons, start=1): + tk.Button(app, text=label, command=cmd, font=fontSmall, + bg="black", fg=#444444, highlightbackground="black", borderwidth=0) \ + .grid(column=i, row=1, sticky="nsew", padx=0, pady=0) -tk.Button(app, text="CONT", command=set_cont_mode, font=fontSmall, bg="black", fg=button_fg, highlightbackground="black", borderwidth=0) \ - .grid(column=3, row=1, sticky="nsew", padx=0, pady=0) - -tk.Button(app, text="VOLT:DC", command=set_voltdc_mode, font=fontSmall, bg="black", fg=button_fg, highlightbackground="black", borderwidth=0) \ - .grid(column=4, row=1, sticky="nsew", padx=0, pady=0) - -tk.Button(app, text="VOLT:AC", command=set_voltac_mode, font=fontSmall, bg="black", fg=button_fg, highlightbackground="black", borderwidth=0) \ - .grid(column=5, row=1, sticky="nsew", padx=0, pady=0) - -tk.Button(app, text="DIOD", command=set_diod_mode, font=fontSmall, bg="black", fg=button_fg, highlightbackground="black", borderwidth=0) \ - .grid(column=6, row=1, sticky="nsew", padx=0, pady=0) - -tk.Button(app, text="CAP", command=set_cap_mode, font=fontSmall, bg="black", fg=button_fg, highlightbackground="black", borderwidth=0) \ - .grid(column=7, row=1, sticky="nsew", padx=0, pady=0) # Initial fetch to start the auto-update process fetch_device_info()