import time import queue import tkinter as tk import numpy as np from gui.popup import CalibrationPopUp from gui.graph import Graph from gui.logScreen import LogScreen import logHandler class MainWindow(tk.Frame): def __init__(self, root, conf, ac_sensor, opt_sensor, mag_sensor): self.root = root self.conf = conf self.ac_sensor = ac_sensor self.opt_sensor = opt_sensor self.mag_sensor = mag_sensor self.log_handler = logHandler.get_log_handler() self.popup_window = None self.log_window = None self.mainWindow = None tk.Frame.__init__(self, root) # data plot at left side self.graph = Graph(self) self.graph.pack(fill=tk.BOTH, side=tk.LEFT, expand=True) # frame at right side self.controls = tk.Frame(self, borderwidth=4) self.controls.pack(fill=tk.BOTH, side=tk.RIGHT) self.controlsUpdateTime = 0 self.ac_dro_val_sums = np.ndarray((4), dtype=np.float) self.ac_dro_val_count = 0 self.ac_dro_x = tk.StringVar() self.ac_dro_y = tk.StringVar() self.ac_dro_t1 = tk.StringVar() self.ac_dro_t2 = tk.StringVar() self.ac_label = tk.Label(self.controls, text="Acoustic Sensor", anchor="c", font=("Helvatica", 10, 'bold')) self.ac_label.pack(side="top", fill="both", expand=False) tk.Label(self.controls, textvariable=self.ac_dro_x, anchor="nw").pack(side="top", fill="both", expand=False) tk.Label(self.controls, textvariable=self.ac_dro_y, anchor="nw").pack(side="top", fill="both", expand=False) tk.Label(self.controls, textvariable=self.ac_dro_t1, anchor="nw").pack(side="top", fill="both", expand=False) tk.Label(self.controls, textvariable=self.ac_dro_t2, anchor="nw").pack(side="top", fill="both", expand=False) self.opt_dro_val_sums = np.ndarray((4), dtype=np.float) self.opt_dro_val_count = 0 self.opt_dro_x = tk.StringVar() self.opt_dro_y = tk.StringVar() self.opt_dro_offset = tk.StringVar() self.opt_dro_size = tk.StringVar() self.opt_label = tk.Label(self.controls, text="Optical Sensor", anchor="c", font=("Helvatica", 10, 'bold')) self.opt_label.pack(side="top", fill="both", expand=False) tk.Label(self.controls, textvariable=self.opt_dro_x, anchor="nw").pack(side="top", fill="both", expand=False) tk.Label(self.controls, textvariable=self.opt_dro_y, anchor="nw").pack(side="top", fill="both", expand=False) tk.Label(self.controls, textvariable=self.opt_dro_offset, anchor="nw").pack(side="top", fill="both", expand=False) tk.Label(self.controls, textvariable=self.opt_dro_size, anchor="nw").pack(side="top", fill="both", expand=False) self.mag_dro_val_sums = np.ndarray((4), dtype=np.float) self.mag_dro_val_count = 0 self.mag_label = tk.Label(self.controls, text="Magnetic Sensor", anchor="c", font=("Helvatica", 10, 'bold')) self.mag_label.pack(side="top", fill="both", expand=False) self.mag_dro_x = tk.StringVar() self.mag_dro_y = tk.StringVar() self.mag_dro_offset_x = tk.StringVar() self.mag_dro_offset_y = tk.StringVar() tk.Label(self.controls, textvariable=self.mag_dro_x, anchor = "nw").pack(side = "top", fill = "both", expand = False) tk.Label(self.controls, textvariable=self.mag_dro_y, anchor = "nw").pack(side = "top", fill = "both", expand = False) tk.Label(self.controls, textvariable=self.mag_dro_x, anchor = "nw").pack(side = "top", fill = "both", expand = False) tk.Label(self.controls, textvariable=self.mag_dro_y, anchor = "nw").pack(side = "top", fill = "both", expand = False) self.quit_button = tk.Button(self.controls, text="Quit", command=self.root.destroy, height=2, foreground="red") self.quit_button.pack(side="bottom", fill="both") self.calibrate_submenu_button = tk.Button(self.controls, text="Calibrate", command=self.calibrate_submenu, height=2) self.calibrate_submenu_button.pack_forget() self.calibrate_all_button = tk.Button(self.controls, text="Calibrate All", command=self.calibrate_all, height=2) self.calibrate_all_button.pack_forget() self.calibrateac_button = tk.Button(self.controls, text="Calibrate AC", command=self.calibrate_ac, height=2) self.calibrateac_button.pack_forget() self.calibrateopt_button = tk.Button(self.controls, text = "Calibrate OPT", command = self.calibrate_opt,height = 2) self.calibrateopt_button.pack_forget() self.calibratemag_button = tk.Button(self.controls, text = "Calibrate MAG", command = self.calibrate_mag,height = 2) self.calibratemag_button.pack_forget() self.clear_button = tk.Button(self.controls, text="Clear graph", command=self.graph.clear, height=2) self.clear_button.pack_forget() self.logscreen_button = tk.Button(self.controls, text="Log", command=self.open_log, height=2) self.logscreen_button.pack_forget() self.menu_button = tk.Button(self.controls, text="Menu", command=self.menu, height=2) self.menu_button.pack(side="bottom", fill="both") self.menu_back_button = tk.Button(self.controls, text="Back", command=self.back, height=2) self.menu_back_button.pack_forget() def update(self): if not self.root.winfo_exists(): return ac_positions = [] # aggregate measurements while self.ac_sensor.queue.qsize() > 0: name, data = self.ac_sensor.queue.get() if name == "data": ac_positions.append(data[0:2]) self.ac_dro_val_sums += data self.ac_dro_val_count += 1 opt_positions = [] while self.opt_sensor.queue.qsize() > 0: name, data = self.opt_sensor.queue.get() if name == "data": opt_positions.append(data[0:2]) self.opt_dro_val_sums += data self.opt_dro_val_count += 1 mag_positions = [] while self.mag_sensor.queue.qsize() > 0: name, data = self.mag_sensor.queue.get() if name == "data": mag_positions.append(data[0:2]) self.mag_dro_val_sums += data self.mag_dro_val_count += 1 # graph shows all values as a line self.graph.update([ac_positions, opt_positions, mag_positions]) # update status color if self.ac_sensor.dummyActive: self.ac_label.config(fg="white", bg="red") elif len(ac_positions) > 0: self.ac_label.config(fg="white", bg="green") else: self.ac_label.config(fg="black", bg="yellow") if not self.opt_sensor.success: self.opt_label.config(fg="white", bg="red") elif len(opt_positions) > 0: self.opt_label.config(fg="white", bg="green") else: self.opt_label.config(fg="black", bg="yellow") if not self.mag_sensor.success: self.mag_label.config(fg="white", bg="red") elif len(mag_positions) > 0: self.mag_label.config(fg="white", bg="green") else: self.mag_label.config(fg="black", bg="yellow") # readouts will only be updated so often if self.controlsUpdateTime + 0.4 < time.time(): self.controlsUpdateTime = time.time() # they display the average of all values if self.ac_dro_val_count > 0: self.ac_dro_val_sums /= self.ac_dro_val_count else: self.ac_dro_val_sums.fill(0) self.ac_dro_x.set("X: {:.1f} mm".format(self.ac_dro_val_sums[0])) self.ac_dro_y.set("Y: {:.1f} mm".format(self.ac_dro_val_sums[1])) self.ac_dro_t1.set("t1: {:.3f} ms".format(self.ac_dro_val_sums[2]/1000)) self.ac_dro_t2.set("t2: {:.3f} ms".format(self.ac_dro_val_sums[3]/1000)) self.ac_dro_val_sums.fill(0) self.ac_dro_val_count = 0 if self.opt_dro_val_count > 0: self.opt_dro_val_sums /= self.opt_dro_val_count else: self.opt_dro_val_sums.fill(0) self.opt_dro_x.set("X: {:.1f} mm".format(self.opt_dro_val_sums[0])) self.opt_dro_y.set("Y: {:.1f} mm".format(self.opt_dro_val_sums[1])) self.opt_dro_offset.set("X Offset: {:.1f} %".format(self.opt_dro_val_sums[2]*100)) self.opt_dro_size.set("Y Offset: {:.1f} %".format(self.opt_dro_val_sums[3]*100)) self.opt_dro_val_sums.fill(0) self.opt_dro_val_count = 0 if self.mag_dro_val_count > 0: self.mag_dro_val_sums /= self.mag_dro_val_count else: self.mag_dro_val_sums.fill(0) self.mag_dro_x.set("X: {:.1f} mT".format(self.mag_dro_val_sums[0])) self.mag_dro_y.set("Y: {:.1f} mT".format(self.mag_dro_val_sums[1])) self.mag_dro_offset_x.set("X Offset: {:.1f} %".format(self.mag_dro_val_sums[2]*100)) self.mag_dro_offset_y.set("Y: {:.1f} %".format(self.mag_dro_val_sums[3]*100)) if self.popup_window: self.popup_window.update() if self.log_window: self.log_window.update() self.root.after(30, self.update) def calibrate_submenu(self): self.calibrate_submenu_button.pack_forget() self.menu_button.pack_forget() self.clear_button.pack_forget() self.logscreen_button.pack_forget() self.menu_back_button.pack(side="bottom", fill="both") self.calibratemag_button.pack(side="bottom", fill="both") self.calibrateopt_button.pack(side="bottom", fill="both") self.calibrateac_button.pack(side="bottom", fill="both") self.calibrat_all_button.pack(side="bottom", fill="both") def calibrate_all(self): pass def calibrate_ac(self): self.ac_sensor.start_calibration() if not self.popup_window or not self.pu_root.winfo_exists(): # create new window self.pu_root = tk.Toplevel(self.root) self.pu_root.wm_transient(self.root) self.pu_root.wm_title("Acoustic Sensor Calibration") # make it centered x = (self.pu_root.winfo_screenwidth() - 500) / 2 y = (self.pu_root.winfo_screenheight() - 200) / 2 self.pu_root.geometry(f'500x200+{int(x)}+{int(y)}') # deactivate mainWindow self.pu_root.grab_set() self.popup_window = CalibrationPopUp(self.pu_root, self.ac_sensor.calibration_state, self.conf) self.popup_window.pack(side="top", fill="both", expand=True) def calibrate_opt(self): pass def calibrate_mag(self): ### self.mag_sensor.start_calibration() if not self.popup_window or not self.pu_root.winfo_exists(): # create new window self.pu_root = tk.Toplevel(self.root) self.pu_root.wm_transient(self.root) self.pu_root.wm_title("Magnetic Sensor Calibration") # make it centered x = (self.pu_root.winfo_screenwidth() - 500) / 2 y = (self.pu_root.winfo_screenheight() - 200) / 2 self.pu_root.geometry(f'500x200+{int(x)}+{int(y)}') # deactivate mainWindow self.pu_root.grab_set() self.popup_window = CalibrationPopUp(self.pu_root, self.mag_sensor.calibration_state, self.conf) self.popup_window.pack(side="top", fill="both", expand=True) def open_log(self): #create new window self.log_root = tk.Toplevel(self.root) self.log_root.wm_transient(self.root) self.log_root.wm_title("Logs") #center x = (self.log_root.winfo_screenwidth() - 780) / 2 y = (self.log_root.winfo_screenheight() - 400) / 2 self.log_root.geometry(f'780x400+{int(x)}+{int(y)}') # deactivate mainWindow self.log_root.grab_set() self.log_window = LogScreen(self.log_root) self.log_window.pack(side="top", fill="both", expand=True) # Menu Button def menu(self): self.menu_back_button.pack(side="bottom", fill="both") self.calibrate_submenu_button.pack(side="bottom", fill="both") self.clear_button.pack(side="bottom", fill="both") self.logscreen_button.pack(side="bottom", fill="both") self.menu_button.pack_forget() #Back Button def back(self): self.calibratemag_button.pack_forget() self.calibrateopt_button.pack_forget() self.calibrateac_button.pack_forget() self.clear_button.pack_forget() self.logscreen_button.pack_forget() self.calibrate_submenu_button.pack_forget() self.menu_button.pack(side="bottom", fill="both") self.menu_back_button.pack_forget()