Code cleanup

This commit is contained in:
Christoffer Martinsson 2025-05-15 10:58:23 +02:00
parent 6695e63c9d
commit 22c5b33d5e

View File

@ -2,10 +2,11 @@ import tkinter as tk
from tkinter.font import Font from tkinter.font import Font
import serial import serial
import os import os
import json import json
import threading import threading
import time import time
class SerialManager: class SerialManager:
def __init__(self, port="/dev/ttyUSB0", baud_rate=115200, reconnect_interval=2): def __init__(self, port="/dev/ttyUSB0", baud_rate=115200, reconnect_interval=2):
self.port_name = port self.port_name = port
@ -23,7 +24,9 @@ class SerialManager:
with self.lock: with self.lock:
if self.ser is None or not self.ser.is_open: if self.ser is None or not self.ser.is_open:
try: try:
self.ser = serial.Serial(self.port_name, self.baud_rate, timeout=1) self.ser = serial.Serial(
self.port_name, self.baud_rate, timeout=1
)
print(f"[INFO] Connected to {self.port_name}") print(f"[INFO] Connected to {self.port_name}")
except serial.SerialException as e: except serial.SerialException as e:
print(f"[WARN] Serial port error: {e}") print(f"[WARN] Serial port error: {e}")
@ -34,8 +37,8 @@ class SerialManager:
with self.lock: with self.lock:
if self.ser and self.ser.is_open: if self.ser and self.ser.is_open:
try: try:
self.ser.write((command + '\n').encode('utf-8')) self.ser.write((command + "\n").encode("utf-8"))
response = self.ser.readline().decode('utf-8').strip() response = self.ser.readline().decode("utf-8").strip()
return response return response
except Exception as e: except Exception as e:
print(f"[ERROR] Failed to send/receive: {e}") print(f"[ERROR] Failed to send/receive: {e}")
@ -48,8 +51,10 @@ class SerialManager:
if self.ser and self.ser.is_open: if self.ser and self.ser.is_open:
self.ser.close() self.ser.close()
# Set DPI scale for Wayland # Set DPI scale for Wayland
os.environ['GDK_SCALE'] = '2' os.environ["GDK_SCALE"] = "2"
# Load saved window geometry if exists # Load saved window geometry if exists
def load_window_geometry(): def load_window_geometry():
@ -60,6 +65,7 @@ def load_window_geometry():
except FileNotFoundError: except FileNotFoundError:
return "1080x200+100+100" # Default geometry if no settings file return "1080x200+100+100" # Default geometry if no settings file
# Save the window geometry when closing the app # Save the window geometry when closing the app
def save_window_geometry(): def save_window_geometry():
geometry = app.geometry() geometry = app.geometry()
@ -67,55 +73,68 @@ def save_window_geometry():
with open("settings.json", "w") as f: with open("settings.json", "w") as f:
json.dump(settings, f) json.dump(settings, f)
# Serial configuration # Serial configuration
ser = SerialManager(port='/dev/ttyUSB0') ser = SerialManager(port="/dev/ttyUSB0")
def send_command(cmd): def send_command(cmd):
return ser.send_command(cmd) return ser.send_command(cmd)
def get_id(): def get_id():
return send_command('*IDN?') return send_command("*IDN?")
def get_multimeter_data(): def get_multimeter_data():
rawdata = send_command(f'CONFigure:ALL?') rawdata = send_command(f"CONFigure:ALL?")
return rawdata return rawdata
def get_powersupply_data(): def get_powersupply_data():
rawdata = send_command(f'MEASure:ALL:INFO?') rawdata = send_command(f"MEASure:ALL:INFO?")
return rawdata return rawdata
def set_res_mode(): def set_res_mode():
rawdata = send_command(f'[SENSe:]FUNCtion:RESistance') rawdata = send_command(f"[SENSe:]FUNCtion:RESistance")
time.sleep(0.1) time.sleep(0.1)
rawdata = send_command(f'[SENSe:]RESistance:RANGe:AUTO ON') rawdata = send_command(f"[SENSe:]RESistance:RANGe:AUTO ON")
return rawdata return rawdata
def set_res200_mode(): def set_res200_mode():
rawdata = send_command(f'[SENSe:]FUNCtion:RESistance') rawdata = send_command(f"[SENSe:]FUNCtion:RESistance")
time.sleep(0.1) time.sleep(0.1)
rawdata = send_command(f'[SENSe:]RESistance:RANGe 200') rawdata = send_command(f"[SENSe:]RESistance:RANGe 200")
return rawdata return rawdata
def set_cont_mode(): def set_cont_mode():
rawdata = send_command(f'[SENSe:]FUNCtion:CONTinuity') rawdata = send_command(f"[SENSe:]FUNCtion:CONTinuity")
return rawdata return rawdata
def set_diod_mode(): def set_diod_mode():
rawdata = send_command(f'[SENSe:]FUNCtion:DIODe') rawdata = send_command(f"[SENSe:]FUNCtion:DIODe")
return rawdata return rawdata
def set_voltdc_mode(): def set_voltdc_mode():
rawdata = send_command(f'[SENSe:]FUNCtion:VOLTage:DC') rawdata = send_command(f"[SENSe:]FUNCtion:VOLTage:DC")
return rawdata return rawdata
def set_voltac_mode(): def set_voltac_mode():
rawdata = send_command(f'[SENSe:]FUNCtion:VOLTage:AC') rawdata = send_command(f"[SENSe:]FUNCtion:VOLTage:AC")
return rawdata return rawdata
def set_cap_mode(): def set_cap_mode():
rawdata = send_command(f'[SENSe:]FUNCtion:CAPacitance') rawdata = send_command(f"[SENSe:]FUNCtion:CAPacitance")
return rawdata return rawdata
# --- GUI Setup --- # --- GUI Setup ---
def fetch_device_info(): def fetch_device_info():
# Fetch the device ID and Channel data # Fetch the device ID and Channel data
@ -125,12 +144,17 @@ def fetch_device_info():
if len(multimeter_data.split(",")) >= 4: if len(multimeter_data.split(",")) >= 4:
# Update the labels # Update the labels
multimeter_type_var.set(multimeter_data.split(",")[0]) multimeter_type_var.set(multimeter_data.split(",")[0])
multimeter_data_var.set(multimeter_data.split(",")[1].replace("+","").replace("Ohm",'\u2126')) multimeter_data_var.set(
multimeter_range_var.set(multimeter_data.split(",")[3].replace("Ohm",'\u2126')) multimeter_data.split(",")[1].replace("+", "").replace("Ohm", "\u2126")
)
multimeter_range_var.set(
multimeter_data.split(",")[3].replace("Ohm", "\u2126")
)
# Schedule this function to be called again after 100ms # Schedule this function to be called again after 100ms
app.after(100, fetch_device_info) app.after(100, fetch_device_info)
app = tk.Tk() app = tk.Tk()
app.title("SPM6103") app.title("SPM6103")
# Load and apply the saved geometry (size + position) # Load and apply the saved geometry (size + position)
@ -138,7 +162,9 @@ app.geometry(load_window_geometry())
app.configure(bg="black") app.configure(bg="black")
# For cleanup on exit # For cleanup on exit
app.protocol("WM_DELETE_WINDOW", lambda: [save_window_geometry(), ser.stop(), app.quit()]) app.protocol(
"WM_DELETE_WINDOW", lambda: [save_window_geometry(), ser.stop(), app.quit()]
)
multimeter_type_var = tk.StringVar() multimeter_type_var = tk.StringVar()
multimeter_data_var = tk.StringVar() multimeter_data_var = tk.StringVar()
@ -151,6 +177,7 @@ fontBig = Font(size=24)
resize_after_id = None resize_after_id = None
def apply_font_resize(): def apply_font_resize():
width = app.winfo_width() width = app.winfo_width()
@ -158,33 +185,38 @@ def apply_font_resize():
fontMedium.configure(size=max(14, int(width * 0.02))) fontMedium.configure(size=max(14, int(width * 0.02)))
fontBig.configure(size=max(24, int(width * 0.09))) fontBig.configure(size=max(24, int(width * 0.09)))
def resize_loop(): def resize_loop():
apply_font_resize() apply_font_resize()
app.after(200, resize_loop) app.after(200, resize_loop)
resize_loop() # start it once resize_loop() # start it once
# Configure grid to be fully responsive # Configure grid to be fully responsive
app.rowconfigure(0, weight=20) # Top - big app.rowconfigure(0, weight=20) # Top - big
app.rowconfigure(1, weight=1) # Bottom - small app.rowconfigure(1, weight=1) # Bottom - small
app.columnconfigure(0, weight=1, uniform="equal", minsize=100) app.columnconfigure(0, weight=1, uniform="equal", minsize=100)
for i in range(7): for i in range(7):
app.columnconfigure(i+1, weight=1, uniform="equal") app.columnconfigure(i + 1, weight=1, uniform="equal")
# Labels # Labels
# Type and Range # Type and Range
tk.Label(app, textvariable=multimeter_type_var, font=fontMedium, bg="black", fg="lightgrey") \ tk.Label(
.grid(column=0, columnspan=1, row=1, sticky="nsw", padx=0, pady=0) app, textvariable=multimeter_type_var, font=fontMedium, bg="black", fg="lightgrey"
).grid(column=0, columnspan=1, row=1, sticky="nsw", padx=0, pady=0)
tk.Label(app, textvariable=multimeter_range_var, font=fontMedium, bg="black", fg="lightgrey") \ tk.Label(
.grid(column=0, columnspan=1, row=0, sticky="nw", padx=0, pady=0) app, textvariable=multimeter_range_var, font=fontMedium, bg="black", fg="lightgrey"
).grid(column=0, columnspan=1, row=0, sticky="nw", padx=0, pady=0)
# Data # Data
tk.Label(app, textvariable=multimeter_data_var, font=fontBig, bg="black", fg="#afd787") \ tk.Label(
.grid(column=1, columnspan=6, row=0, rowspan=1, sticky="nsew", padx=0, pady=10) app, textvariable=multimeter_data_var, font=fontBig, bg="black", fg="#afd787"
).grid(column=1, columnspan=6, row=0, rowspan=1, sticky="nsew", padx=0, pady=10)
# Buttons # Buttons
buttons = [ buttons = [
("RES", set_res_mode), ("RES", set_res_mode),
("RES200", set_res200_mode), ("RES200", set_res200_mode),
@ -196,9 +228,16 @@ buttons = [
] ]
for i, (label, cmd) in enumerate(buttons, start=1): for i, (label, cmd) in enumerate(buttons, start=1):
tk.Button(app, text=label, command=cmd, font=fontSmall, bg="black", tk.Button(
fg="#444444", highlightbackground="black", borderwidth=0) \ app,
.grid(column=i, row=1, sticky="nsew", padx=0, pady=0) 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)
# Initial fetch to start the auto-update process # Initial fetch to start the auto-update process