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 from sensors.opticalSensor import OpticalSensor 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()