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_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_val_sums = tk.StringVar() self.mag_dro_val_count = 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.calibrateac_button = tk.Button(self.controls, text="Calibrate AC", command=self.calibrate_ac, height=4) self.calibrateac_button.pack_forget() self.calibratemc_button = tk.Button(self.controls, text = "Calibrate MC", command = self.calibrate_mc,height = 4) self.calibratemc_button.pack_forget() self.clear_button = tk.Button(self.controls, text="Clear graph", command=self.graph.clear, height=4) self.clear_button.pack_forget() self.logscreen_button = tk.Button(self.controls, text="Log", command=self.open_log, height=4) self.logscreen_button.pack_forget() self.menu_button = tk.Button(self.controls, text="Menu", command=self.menu, height=4) self.menu_button.pack(side="bottom", fill="both") self.menu_back_button = tk.Button(self.controls, text="Back", command=self.back, height=4) 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.: 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("offset: {:.1f} %".format(self.opt_dro_val_sums[2]*100)) self.opt_dro_size.set("size: {:.1f} %".format(self.opt_dro_val_sums[3]*100)) self.opt_dro_val_sums.fill(0) self.opt_dro_val_count = 0 if self.popup_window: self.popup_window.update() if self.log_window: self.log_window.update() self.root.after(30, self.update) 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_mc(self): pass 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.calibrateac_button.pack(side="bottom", fill="both") self.calibratemc_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.calibrateac_button.pack_forget() self.calibratemc_button.pack_forget() self.clear_button.pack_forget() self.logscreen_button.pack_forget() self.menu_button.pack(side="bottom", fill="both") self.menu_back_button.pack_forget()