Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/comportdetection #26

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 53 additions & 50 deletions dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from usr.panel_config import save_pane_states, load_pane_states, saveFileExists
import serial.tools.list_ports


# title, row, width, height
frames_config = [
("Interlocks", 0, None, 2), # Moved to the top row
("Oil System", 1, 50, 150),
Expand All @@ -27,12 +27,16 @@
]

class EBEAMSystemDashboard:
PORT_INFO = {
"AD0K0ZIEA" : "Interlocks"
}
def __init__(self, root, com_ports):
self.root = root
self.com_ports = com_ports
self.set_com_ports = set(serial.tools.list_ports.comports())

self.root.title("EBEAM Control System Dashboard")


# if save file exists call it and open it
if saveFileExists():
self.load_saved_pane_state()
Expand All @@ -56,6 +60,9 @@ def __init__(self, root, com_ports):
# Set up different subsystems within their respective frames
self.create_subsystems()

# start constant check for available COM ports
self._check_for_port_changes()

def setup_main_pane(self):
"""Initialize the main layout pane and its rows."""
self.main_pane = tk.PanedWindow(self.root, orient='vertical', sashrelief=tk.RAISED)
Expand All @@ -69,7 +76,6 @@ def setup_main_pane(self):
def create_frames(self):
"""Create frames for different systems and controls within the dashboard."""
global frames_config
global frames_config

for title, row, width, height in frames_config:
if width and height and title:
Expand Down Expand Up @@ -151,13 +157,10 @@ def add_title(self, frame, title):
label = tk.Label(frame, text=title, font=("Helvetica", 10, "bold"))
label.pack(pady=0, fill=tk.X)

# saves data to file when button is pressed
# saves data to file when button is pressed
def save_current_pane_state(self):
save_pane_states(frames_config, self.frames, self.main_pane)
save_pane_states(frames_config, self.frames, self.main_pane)

# gets data in save config file (as dict) and updates the global var of frames_config
# gets data in save config file (as dict) and updates the global var of frames_config
def load_saved_pane_state(self):
savedData = load_pane_states()
Expand Down Expand Up @@ -231,9 +234,6 @@ def create_com_port_frame(self, parent_frame):
self.com_port_frame = ttk.Frame(parent_frame)
self.com_port_frame.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)

self.com_port_button = ttk.Button(self.com_port_frame, text="Configure COM Ports", command=self.toggle_com_port_menu)
self.com_port_button.pack(side=tk.TOP, anchor='w')

self.com_port_menu = ttk.Frame(self.com_port_frame)
self.com_port_menu.pack(side=tk.TOP, fill=tk.X, expand=True)
self.com_port_menu.pack_forget() # Initially hidden
Expand All @@ -251,44 +251,47 @@ def create_com_port_frame(self, parent_frame):
dropdown.pack(side=tk.RIGHT)
self.port_dropdowns[subsystem] = dropdown

ttk.Button(self.com_port_menu, text="Apply", command=self.apply_com_port_changes).pack(pady=5)

def toggle_com_port_menu(self):
if self.com_port_menu.winfo_viewable():
self.com_port_menu.pack_forget()
self.com_port_button.config(text="Configure COM Ports")
else:
self.update_available_ports()
self.com_port_menu.pack(after=self.com_port_button, fill=tk.X, expand=True)
self.com_port_button.config(text="Hide COM Port Configuration")

def update_available_ports(self):
available_ports = [port.device for port in serial.tools.list_ports.comports()]
for dropdown in self.port_dropdowns.values():
current_value = dropdown.get()
dropdown['values'] = available_ports
if current_value in available_ports:
dropdown.set(current_value)
elif available_ports:
dropdown.set(available_ports[0])
else:
dropdown.set('')

def apply_com_port_changes(self):
new_com_ports = {subsystem: var.get() for subsystem, var in self.port_selections.items()}
self.update_com_ports(new_com_ports)
self.toggle_com_port_menu()

def update_com_ports(self, new_com_ports):
self.com_ports = new_com_ports
# TODO: update the COM ports for each subsystem

for subsystem_name, subsystem in self.subsystems.items():
if hasattr(subsystem, 'update_com_port'):
if subsystem_name == 'Vacuum System':
subsystem.update_com_port(new_com_ports.get('VTRXSubsystem'))
elif subsystem_name == 'Cathode Heating':
subsystem.update_com_ports(new_com_ports)
else:
self.logger.warning(f"Subsystem {subsystem_name} does not have an update_com_port method")
self.logger.info(f"COM ports updated: {self.com_ports}")
def _check_for_port_changes(self):
"""
Compares the current available comports to the last set

Finally:
Calls itself to be cheack again
"""
nowPorts = set(serial.tools.list_ports.comports())

dif = self.set_com_ports - nowPorts
added_ports = nowPorts - self.set_com_ports

try:
# Process removed ports
for port in dif:
if port.serial_number in self.PORT_INFO:
self.logger.warning(f"Lost connection to {self.PORT_INFO[port.serial_number]} on {port}")
self._update_com_ports(self.PORT_INFO[port.serial_number], None)

# Process added ports
for port in added_ports:
if port.serial_number in self.PORT_INFO:
self.logger.info(f"Attempting to connect {self.PORT_INFO[port.serial_number]} to {port}")
self._update_com_ports(self.PORT_INFO[port.serial_number], port)
except Exception as e:
self.logger.warning(f"Error was thrown when either removing or adding a comport: {e}")

finally:
self.set_com_ports = nowPorts
self.root.after(500, self._check_for_port_changes)

def _update_com_ports(self, subsystem, port):
"""
Calls to update subsystems with change in comport
"""
if subsystem == None:
raise ValueError("_update_com_ports was called with invalid args")
strPort = port.device if port != None else None
if subsystem in self.subsystems.keys():
if subsystem == "Interlocks" or subsystem == "Vacuum System":
self.subsystems[subsystem].update_com_port(strPort)
#TODO: Need to add Vacuum system and Cathode Heating

self.logger.info(f"COM ports updated: {self.com_ports}")