diff --git a/cold.py b/cold.py
index 3005456..0f6bc41 100755
--- a/cold.py
+++ b/cold.py
@@ -19,13 +19,14 @@
check_door_status,
check_light_safe_to_turn_on,
check_marta_safe,
+ soft_interlock_loop,
)
from caen.caenGUIall import caenGUIall
from Inner_tracker_GUI.caenGUIall_v2 import caenGUI8LV
from db.module_db import ModuleDB
+from power_supply.power_supply_ctrl import PowerSupplyController
from db.utils import *
-
# Configure logging
logger = logging.getLogger("integration")
@@ -49,6 +50,11 @@ def __init__(self):
self.update_timer.timeout.connect(self.update_ui)
self.update_timer.start(1000) # Update every second
+ # Setup soft interlock timer (5-second interval, independent of UI updates)
+ self.soft_interlock_timer = QTimer()
+ self.soft_interlock_timer.timeout.connect(self.soft_interlock_check)
+ self.soft_interlock_timer.start(5000)
+
# Connect to MQTT broker at startup
self.connect_mqtt()
@@ -62,6 +68,11 @@ def closeEvent(self, event):
self.update_timer.stop()
logger.debug("Stopped update timer")
+ # Stop the soft interlock timer
+ if hasattr(self, "soft_interlock_timer"):
+ self.soft_interlock_timer.stop()
+ logger.debug("Stopped soft interlock timer")
+
# Cleanup Thermal Camera tab if it exists
if hasattr(self, "thermal_camera_tab"):
self.thermal_camera_tab.cleanup()
@@ -125,7 +136,9 @@ def setup_ui(self):
# Load the MARTA Cold Room tab from UI file
# Create a temporary QMainWindow to load the UI
temp_window = QtWidgets.QMainWindow()
- marta_ui_file = os.path.join(os.path.dirname(__file__), "coldroom", "marta_coldroom.ui")
+ marta_ui_file = os.path.join(
+ os.path.dirname(__file__), "coldroom", "marta_coldroom.ui"
+ )
uic.loadUi(marta_ui_file, temp_window)
# Create a QWidget for our tab and get the central widget from temp_window
@@ -160,14 +173,18 @@ def setup_ui(self):
self.tab_widget.addTab(self.module_db.ui.tab_2, "Module Inventory")
self.tab_widget.addTab(self.module_db.ui.moduleDetailsTab, "Module Details")
self.module_db.ui.viewDetailsPB.clicked.connect(
- lambda: self.tab_widget.setCurrentIndex(self.tab_widget.indexOf(self.module_db.ui.moduleDetailsTab))
+ lambda: self.tab_widget.setCurrentIndex(
+ self.tab_widget.indexOf(self.module_db.ui.moduleDetailsTab)
+ )
)
self.module_db.ui.selectModulePB.setEnabled(False)
self.modules_list_tab.db_url = self.module_db.db_url
# Load settings tab from UI file
self.settings_tab = QtWidgets.QWidget()
- settings_ui_file = os.path.join(os.path.dirname(__file__), "coldroom", "settings_coldroom.ui")
+ settings_ui_file = os.path.join(
+ os.path.dirname(__file__), "coldroom", "settings_coldroom.ui"
+ )
uic.loadUi(settings_ui_file, self.settings_tab)
self.tab_widget.addTab(self.settings_tab, "Settings")
@@ -175,6 +192,10 @@ def setup_ui(self):
self.IT_caen_tab = caenGUI8LV()
self.tab_widget.addTab(self.IT_caen_tab, "IT CAEN")
+ # Add Power Supply tab
+ self.power_supply_tab = PowerSupplyController()
+ self.tab_widget.addTab(self.power_supply_tab, "Power Supply")
+
# Pre-fill settings with values from system
self.load_settings_to_ui()
self.get_ring_id()
@@ -190,10 +211,15 @@ def setup_ui(self):
def get_ring_id(self):
self.number_of_modules = 0 # Add default at the start
- self.ring_id=get_ring_from_cable("I1") #hardcode the single harting cable I1
+ # self.ring_id=get_ring_from_cable("I1") #hardcode the single harting cable I1
+ self.ring_id = get_ring_from_cable(
+ "I1", db_url=self.module_db.db_url
+ ) # hardcode the single harting cable I1
if self.ring_id == None:
- ring_history_file = os.path.join(os.path.dirname(__file__), "ring_history.txt")
-
+ ring_history_file = os.path.join(
+ os.path.dirname(__file__), "ring_history.txt"
+ )
+
if os.path.exists(ring_history_file):
with open(ring_history_file, "r") as f:
lines = f.readlines()
@@ -201,8 +227,8 @@ def get_ring_id(self):
self.ring_id = lines[-1].strip()
else:
self.ring_id = None
-
- #TODO: move this to the right place so it works also when ring ID LineEdit is updated
+
+ # TODO: move this to the right place so it works also when ring ID LineEdit is updated
if self.ring_id != None:
self.modules_list_tab.ring_id_LE.setText(self.ring_id)
logger.info(f"Loaded ring ID from history: {self.ring_id}")
@@ -214,7 +240,10 @@ def get_ring_id(self):
elif self.ring_id.startswith("L3_"):
self.number_of_modules = 36
self.modules_list_tab.populate_from_config(
- self.caen_tab, self.mounted_modules, self.number_of_modules, self.thermal_camera_tab
+ self.caen_tab,
+ self.mounted_modules,
+ self.number_of_modules,
+ self.thermal_camera_tab,
)
return self.ring_id
@@ -232,9 +261,13 @@ def setup_ring_id(self):
elif self.ring_id.startswith("L3_"):
self.number_of_modules = 36
else:
- self.message_box.setText("Invalid ring ID format. Must start with L1_, L2_, or L3_.")
+ self.message_box.setText(
+ "Invalid ring ID format. Must start with L1_, L2_, or L3_."
+ )
self.message_box.exec_()
- self.modules_list_tab.populate_from_config(self.caen_tab, self.mounted_modules, self.number_of_modules)
+ self.modules_list_tab.populate_from_config(
+ self.caen_tab, self.mounted_modules, self.number_of_modules
+ )
def save_ring_id(self):
ring_history_file = os.path.join(os.path.dirname(__file__), "ring_history.txt")
@@ -243,22 +276,30 @@ def save_ring_id(self):
logger.info(f"Ring ID {self.ring_id} saved successfully.")
def get_mounted_modules(self):
- self.mounted_modules = get_modules_on_ring(self.ring_id, db_url=self.module_db.db_url)
+ self.mounted_modules = get_modules_on_ring(
+ self.ring_id, db_url=self.module_db.db_url
+ )
for module_name in self.mounted_modules:
- self.mounted_modules[module_name].update(get_module_endpoints(module_name, db_url=self.module_db.db_url))
self.mounted_modules[module_name].update(
- {"speed": get_module_speed(module_name, db_url=self.module_db.db_url)}
+ get_module_endpoints(module_name, db_url=self.module_db.db_url)
)
self.mounted_modules[module_name].update(
- {"fuseId": get_module_fuse_id(module_name, db_url=self.module_db.db_url)}
+ {"speed": get_module_speed(module_name, db_url=self.module_db.db_url)}
)
self.mounted_modules[module_name].update(
{
- "temperature_offsets": get_module(module_name, db_url=self.module_db.db_url).get(
- "temperature_offsets", {}
+ "fuseId": get_module_fuse_id(
+ module_name, db_url=self.module_db.db_url
)
}
)
+ self.mounted_modules[module_name].update(
+ {
+ "temperature_offsets": get_module(
+ module_name, db_url=self.module_db.db_url
+ ).get("temperature_offsets", {})
+ }
+ )
logger.debug(f"Mounted modules for ring {self.ring_id}: {self.mounted_modules}")
return self.mounted_modules
@@ -266,11 +307,21 @@ def load_settings_to_ui(self):
# Fill settings UI with current values
self.settings_tab.brokerLineEdit.setText(self.system.settings["mqtt"]["broker"])
self.settings_tab.portSpinBox.setValue(self.system.settings["mqtt"]["port"])
- self.settings_tab.martaTopicLineEdit.setText(self.system.settings["MARTA"]["mqtt_topic"])
- self.settings_tab.coldroomTopicLineEdit.setText(self.system.settings["Coldroom"]["mqtt_topic"])
- self.settings_tab.co2SensorTopicLineEdit.setText(self.system.settings["Coldroom"]["co2_sensor_topic"])
- self.settings_tab.thermalCameraTopicLineEdit.setText(self.system.settings["ThermalCamera"]["mqtt_topic"])
- self.settings_tab.cleanroomTopicLineEdit.setText(self.system.settings["Cleanroom"]["mqtt_topic"])
+ self.settings_tab.martaTopicLineEdit.setText(
+ self.system.settings["MARTA"]["mqtt_topic"]
+ )
+ self.settings_tab.coldroomTopicLineEdit.setText(
+ self.system.settings["Coldroom"]["mqtt_topic"]
+ )
+ self.settings_tab.co2SensorTopicLineEdit.setText(
+ self.system.settings["Coldroom"]["co2_sensor_topic"]
+ )
+ self.settings_tab.thermalCameraTopicLineEdit.setText(
+ self.system.settings["ThermalCamera"]["mqtt_topic"]
+ )
+ self.settings_tab.cleanroomTopicLineEdit.setText(
+ self.system.settings["Cleanroom"]["mqtt_topic"]
+ )
def connect_signals(self):
# Module list
@@ -287,66 +338,88 @@ def configure_line_edit(field_name, placeholder):
le.setStyleSheet("QLineEdit { color: grey; }")
# Connect signals
- le.textChanged.connect(lambda: le.setStyleSheet("QLineEdit { color: black; }"))
- le.editingFinished.connect(lambda: le.setPlaceholderText(placeholder) if le.text() == "" else None)
+ le.textChanged.connect(
+ lambda: le.setStyleSheet("QLineEdit { color: black; }")
+ )
+ le.editingFinished.connect(
+ lambda: (
+ le.setPlaceholderText(placeholder) if le.text() == "" else None
+ )
+ )
# Light controls
- self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_light_on_PB").clicked.connect(
- self.coldroom_light_on
- )
- self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_light_off_PB").clicked.connect(
- self.coldroom_light_off
- )
+ self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_light_on_PB"
+ ).clicked.connect(self.coldroom_light_on)
+ self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_light_off_PB"
+ ).clicked.connect(self.coldroom_light_off)
# Dry air controls
- self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_dry_air_on_PB").clicked.connect(
- self.coldroom_dry_air_on
- )
- self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_dry_air_off_PB").clicked.connect(
- self.coldroom_dry_air_off
- )
+ self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_dry_air_on_PB"
+ ).clicked.connect(self.coldroom_dry_air_on)
+ self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_dry_air_off_PB"
+ ).clicked.connect(self.coldroom_dry_air_off)
# Dry air bypass controls
- self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_dry_air_bypass_on_PB").clicked.connect(
- self.coldroom_dry_air_bypass_on
- )
- self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_dry_air_bypass_off_PB").clicked.connect(
- self.coldroom_dry_air_bypass_off
- )
+ self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_dry_air_bypass_on_PB"
+ ).clicked.connect(self.coldroom_dry_air_bypass_on)
+ self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_dry_air_bypass_off_PB"
+ ).clicked.connect(self.coldroom_dry_air_bypass_off)
# Door controls
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_door_toggle_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_door_toggle_PB"
+ )
if button:
button.clicked.connect(self.toggle_coldroom_door)
# Temperature controls
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_temp_ctrl_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_temp_ctrl_PB"
+ )
if button:
button.clicked.connect(self.toggle_coldroom_temp_control)
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_run_start")
- if button:
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_run_start"
+ )
+ if button and self.system._martacoldroom:
button.clicked.connect(self.system._martacoldroom.run)
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_run_stop")
- if button:
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_run_stop"
+ )
+ if button and self.system._martacoldroom:
button.clicked.connect(self.system._martacoldroom.stop)
configure_line_edit("coldroom_temp_LE", "-30°C to 30°C")
configure_line_edit("coldroom_humidity_LE", "0% to 50%")
# Temperature setpoint label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "coldroom_temp_set_point_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "coldroom_temp_set_point_label"
+ )
if label:
logger.debug("Connected temperature set point label")
# Humidity setpoint label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "coldroom_humidity_set_point_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "coldroom_humidity_set_point_label"
+ )
if label:
logger.debug("Connected humidity set point label")
# Temperature control LED
- ctrl_temp_led = self.marta_coldroom_tab.findChild(QtWidgets.QFrame, "ctrl_temp_LED")
+ ctrl_temp_led = self.marta_coldroom_tab.findChild(
+ QtWidgets.QFrame, "ctrl_temp_LED"
+ )
if ctrl_temp_led:
logger.debug("Connected temperature control LED")
# Humidity control LED
- ctrl_humidity_led = self.marta_coldroom_tab.findChild(QtWidgets.QFrame, "ctrl_humidity_LED")
+ ctrl_humidity_led = self.marta_coldroom_tab.findChild(
+ QtWidgets.QFrame, "ctrl_humidity_LED"
+ )
if ctrl_humidity_led:
logger.debug("Connected humidity control LED")
# Light control LED
@@ -358,136 +431,206 @@ def configure_line_edit(field_name, placeholder):
if dry_air_led:
logger.debug("Connected dry air control LED")
# Safe to open LED
- safe_to_open_led = self.marta_coldroom_tab.findChild(QtWidgets.QFrame, "safe_to_open_LED")
+ safe_to_open_led = self.marta_coldroom_tab.findChild(
+ QtWidgets.QFrame, "safe_to_open_LED"
+ )
if safe_to_open_led:
logger.debug("Connected safe to open LED")
# Door state label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "coldroom_door_state_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "coldroom_door_state_label"
+ )
if label:
logger.debug("Connected door state label")
+ # Soft interlock LED
+ soft_interlock_led = self.marta_coldroom_tab.findChild(
+ QtWidgets.QFrame, "soft_interlock_LED"
+ )
+ if soft_interlock_led:
+ logger.debug("Connected soft interlock LED")
+ # Soft interlock message label
+ soft_interlock_msg = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "soft_interlock_msg"
+ )
+ if soft_interlock_msg:
+ logger.debug("Connected soft interlock message label")
# Temperature setpoint controls
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_temp_set_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_temp_set_PB"
+ )
if button:
button.clicked.connect(self.set_coldroom_temperature)
# Humidity controls
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_humidity_ctrl_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_humidity_ctrl_PB"
+ )
if button:
button.clicked.connect(self.toggle_coldroom_humidity_control)
# Humidity setpoint controls
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_humidity_set_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_humidity_set_PB"
+ )
if button:
button.clicked.connect(self.set_coldroom_humidity)
# Run controls
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_run_toggle_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_run_toggle_PB"
+ )
if button:
button.clicked.connect(self.toggle_coldroom_run)
# Reset alarms
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "coldroom_reset_alarms_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "coldroom_reset_alarms_PB"
+ )
if button:
button.clicked.connect(self.reset_coldroom_alarms)
# MARTA CO2 Plant controls
# Temperature controls
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "marta_temp_set_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "marta_temp_set_PB"
+ )
if button:
button.clicked.connect(self.set_marta_temperature)
- configure_line_edit("marta_temp_LE", "-30°C to 18°C") # Placeholder for temperature input
+ configure_line_edit(
+ "marta_temp_LE", "-30°C to 18°C"
+ ) # Placeholder for temperature input
# Speed controls
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "marta_speed_set_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "marta_speed_set_PB"
+ )
if button:
button.clicked.connect(self.set_marta_speed)
- configure_line_edit("marta_speed_LE", "5000 to 6000 RPM") # Placeholder for speed input
+ configure_line_edit(
+ "marta_speed_LE", "5000 to 6000 RPM"
+ ) # Placeholder for speed input
# Flow controls
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "marta_flow_set_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "marta_flow_set_PB"
+ )
if button:
button.clicked.connect(self.set_marta_flow)
- configure_line_edit("marta_flow_LE", "0 to 5 L/min") # Placeholder for flow input
+ configure_line_edit(
+ "marta_flow_LE", "0 to 5 L/min"
+ ) # Placeholder for flow input
# Supply temperature label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "marta_temp_supply_value_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "marta_temp_supply_value_label"
+ )
if label:
logger.debug("Connected supply temperature label")
# Return temperature label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "marta_temp_return_value_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "marta_temp_return_value_label"
+ )
if label:
logger.debug("Connected return temperature label")
# Supply pressure label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "marta_pressure_supply_value_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "marta_pressure_supply_value_label"
+ )
if label:
logger.debug("Connected supply pressure label")
# Return pressure label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "marta_pressure_return_value_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "marta_pressure_return_value_label"
+ )
if label:
logger.debug("Connected return pressure label")
# Speed label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "marta_speed_value_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "marta_speed_value_label"
+ )
if label:
logger.debug("Connected speed label")
# Temperature Set Point Label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "marta_temp_set_point_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "marta_temp_set_point_label"
+ )
if label:
logger.debug("Connected temperature set point label")
# Speed Set Point Label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "marta_speed_set_point_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "marta_speed_set_point_label"
+ )
if label:
logger.debug("Connected speed set point label")
# Flow Set Point Label
- label = self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "marta_flow_set_point_label")
+ label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "marta_flow_set_point_label"
+ )
if label:
logger.debug("Connected flow set point label")
# Other MARTA controls
# Start chiller button
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "marta_chiller_start_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "marta_chiller_start_PB"
+ )
if button:
button.clicked.connect(self.start_marta_chiller)
# Start CO2 button
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "marta_co2_start_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "marta_co2_start_PB"
+ )
if button:
button.clicked.connect(self.start_marta_co2)
# Stop CO2 button
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "marta_co2_stop_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "marta_co2_stop_PB"
+ )
if button:
button.clicked.connect(self.stop_marta_co2)
# Stop chiller button
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "marta_chiller_stop_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "marta_chiller_stop_PB"
+ )
if button:
button.clicked.connect(self.stop_marta_chiller)
# Clear alarms button
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "marta_alarms_clear_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "marta_alarms_clear_PB"
+ )
if button:
button.clicked.connect(self.clear_marta_alarms)
# Reconnect button
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "marta_reconnect_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "marta_reconnect_PB"
+ )
if button:
button.clicked.connect(self.reconnect_marta)
# Refresh button
- button = self.marta_coldroom_tab.findChild(QtWidgets.QPushButton, "marta_refresh_PB")
+ button = self.marta_coldroom_tab.findChild(
+ QtWidgets.QPushButton, "marta_refresh_PB"
+ )
if button:
button.clicked.connect(self.refresh_marta)
# Flow active checkbox
- checkbox = self.marta_coldroom_tab.findChild(QtWidgets.QCheckBox, "marta_flow_active_CB")
+ checkbox = self.marta_coldroom_tab.findChild(
+ QtWidgets.QCheckBox, "marta_flow_active_CB"
+ )
if checkbox:
checkbox.clicked.connect(self.toggle_marta_flow_active)
@@ -501,28 +644,40 @@ def configure_line_edit(field_name, placeholder):
logger.debug(f"Found checkbox: {checkbox.objectName()}")
# Update validators to match placeholder ranges
- temp_lineedit_coldroom = self.marta_coldroom_tab.findChild(QtWidgets.QLineEdit, "coldroom_temp_LE")
+ temp_lineedit_coldroom = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLineEdit, "coldroom_temp_LE"
+ )
if temp_lineedit_coldroom:
- temp_lineedit_coldroom.setValidator(QtGui.QDoubleValidator(-30, 30, 2)) # Matches placeholder
+ temp_lineedit_coldroom.setValidator(
+ QtGui.QDoubleValidator(-30, 30, 2)
+ ) # Matches placeholder
- humid_lineedit_coldroom = self.marta_coldroom_tab.findChild(QtWidgets.QLineEdit, "coldroom_humidity_LE")
+ humid_lineedit_coldroom = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLineEdit, "coldroom_humidity_LE"
+ )
if humid_lineedit_coldroom:
humid_lineedit_coldroom.setValidator(QtGui.QDoubleValidator(0, 50, 2))
# Add input validation for numeric fields
- temp_lineedit = self.marta_coldroom_tab.findChild(QtWidgets.QLineEdit, "marta_temp_LE")
+ temp_lineedit = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLineEdit, "marta_temp_LE"
+ )
if temp_lineedit:
validator = QtGui.QDoubleValidator(-30, 18, 2) # min, max, decimals
temp_lineedit.setValidator(validator)
# Add input validation for numeric fields
- speed_lineedit = self.marta_coldroom_tab.findChild(QtWidgets.QLineEdit, "marta_speed_LE")
+ speed_lineedit = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLineEdit, "marta_speed_LE"
+ )
if speed_lineedit:
validator = QtGui.QDoubleValidator(5000, 6000, 0) # min, max, decimals
speed_lineedit.setValidator(validator)
# Add input validation for numeric fields
- flow_lineedit = self.marta_coldroom_tab.findChild(QtWidgets.QLineEdit, "marta_flow_LE")
+ flow_lineedit = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLineEdit, "marta_flow_LE"
+ )
if flow_lineedit:
validator = QtGui.QDoubleValidator(0, 5, 2) # min, max, decimals
flow_lineedit.setValidator(validator)
@@ -551,6 +706,48 @@ def connect_mqtt(self):
self.statusBar().showMessage(error_msg)
logger.error(error_msg)
+ def soft_interlock_check(self):
+ logger.info("Called soft Interlock")
+ used_caen_channels = self.modules_list_tab.get_used_channels()
+ logger.info(f"Used CAEN channels for safety checks: {used_caen_channels}")
+ alarm_publish = (
+ (lambda msg: self.system._martacoldroom._client.publish("/alarm", msg))
+ if self.system._martacoldroom
+ else None
+ )
+ logger.info(f"Alarm publish function: {alarm_publish}")
+ is_safe, msg = soft_interlock_loop(
+ self.system.status,
+ self.caen_tab.last_response,
+ used_caen_channels,
+ self.caen_tab,
+ publish_alarm=alarm_publish,
+ )
+ logger.info(f"Soft interlock result: is_safe={is_safe}, msg={msg}")
+
+ soft_interlock_led = self.marta_coldroom_tab.findChild(
+ QtWidgets.QFrame, "soft_interlock_LED"
+ )
+ if soft_interlock_led:
+ status_color = "green" if is_safe else "red"
+ soft_interlock_led.setStyleSheet("background-color: white;")
+ QTimer.singleShot(
+ 500,
+ lambda led=soft_interlock_led, color=status_color: led.setStyleSheet(
+ f"background-color: {color};"
+ ),
+ )
+ logger.info(f"Updated soft interlock LED: {status_color} with pulse")
+
+ soft_interlock_msg_label = self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "soft_interlock_msg"
+ )
+ if soft_interlock_msg_label:
+ soft_interlock_msg_label.setText(msg)
+ logger.info(f"Updated soft interlock message: {msg}")
+
+ logger.info("Completed soft interlock loop")
+
def update_ui(self):
"""Update UI with current system status"""
try:
@@ -573,43 +770,79 @@ def update_ui(self):
logger.debug(f"Updating Cleanroom UI with status: {cleanroom}")
# Temperature
- label = central.findChild(QtWidgets.QLabel, "cleanroom_temp_value_label")
- if label and "temperature" in cleanroom and cleanroom["temperature"] is not None:
+ label = central.findChild(
+ QtWidgets.QLabel, "cleanroom_temp_value_label"
+ )
+ if (
+ label
+ and "temperature" in cleanroom
+ and cleanroom["temperature"] is not None
+ ):
temp_value = cleanroom["temperature"]
label.setText(f"{temp_value:.1f}")
logger.debug(f"Updated Cleanroom temperature: {temp_value}")
# Humidity
- label = central.findChild(QtWidgets.QLabel, "cleanroom_humidity_value_label")
- if label and "humidity" in cleanroom and cleanroom["humidity"] is not None:
+ label = central.findChild(
+ QtWidgets.QLabel, "cleanroom_humidity_value_label"
+ )
+ if (
+ label
+ and "humidity" in cleanroom
+ and cleanroom["humidity"] is not None
+ ):
humid_value = cleanroom["humidity"]
label.setText(f"{humid_value:.1f}")
logger.debug(f"Updated Cleanroom humidity: {humid_value}")
# Dewpoint
- label = central.findChild(QtWidgets.QLabel, "cleanroom_dewpoint_value_label")
- if label and "dewpoint" in cleanroom and cleanroom["dewpoint"] is not None:
+ label = central.findChild(
+ QtWidgets.QLabel, "cleanroom_dewpoint_value_label"
+ )
+ if (
+ label
+ and "dewpoint" in cleanroom
+ and cleanroom["dewpoint"] is not None
+ ):
dewpoint = cleanroom["dewpoint"]
label.setText(f"{dewpoint:.1f}")
logger.debug(f"Updated Cleanroom dewpoint: {dewpoint}")
# Pressure
- label = central.findChild(QtWidgets.QLabel, "cleanroom_pressure_value_label")
- if label and "pressure" in cleanroom and cleanroom["pressure"] is not None:
+ label = central.findChild(
+ QtWidgets.QLabel, "cleanroom_pressure_value_label"
+ )
+ if (
+ label
+ and "pressure" in cleanroom
+ and cleanroom["pressure"] is not None
+ ):
pressure = cleanroom["pressure"]
label.setText(f"{pressure:.1f}")
logger.debug(f"Updated Cleanroom pressure: {pressure}")
- label = central.findChild(QtWidgets.QLabel, "cleanroom_last_update_value_label")
- if label and "last_update" in cleanroom and cleanroom["last_update"] is not None:
+ label = central.findChild(
+ QtWidgets.QLabel, "cleanroom_last_update_value_label"
+ )
+ if (
+ label
+ and "last_update" in cleanroom
+ and cleanroom["last_update"] is not None
+ ):
last_update = cleanroom["last_update"]
label.setText(f"{last_update}")
logger.debug(f"Updated Cleanroom last update: {last_update}")
- label = central.findChild(QtWidgets.QLabel, "cleanroom_last_update_value_label_2")
+ label = central.findChild(
+ QtWidgets.QLabel, "cleanroom_last_update_value_label_2"
+ )
if label:
- delta_t_update = self.system._martacoldroom._cleanroom_last_update_elapsed_time
- delta_t_update = time.strftime("%H:%M:%S", time.gmtime(delta_t_update))
+ delta_t_update = (
+ self.system._martacoldroom._cleanroom_last_update_elapsed_time
+ )
+ delta_t_update = time.strftime(
+ "%H:%M:%S", time.gmtime(delta_t_update)
+ )
label.setText(delta_t_update)
logger.debug(f"Updated Cleanroom delta t update: {delta_t_update}")
@@ -621,15 +854,21 @@ def update_ui(self):
coldroom = self.system.status["coldroom"]
logger.debug(f"Updating Coldroom UI with status: {coldroom}")
- temp_control_active = coldroom.get("ch_temperature", {}).get("status", False)
- hum_control_active = coldroom.get("ch_humidity", {}).get("status", False)
+ temp_control_active = coldroom.get("ch_temperature", {}).get(
+ "status", False
+ )
+ hum_control_active = coldroom.get("ch_humidity", {}).get(
+ "status", False
+ )
# =========================================================================================== COLDROOM TEMPERATURE PROCESS ===========================================================================================
# Temperature Current Value
if "ch_temperature" in coldroom:
# Current temperature
- label = central.findChild(QtWidgets.QLabel, "coldroom_temp_value_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "coldroom_temp_value_label"
+ )
if label:
temp_value = coldroom["ch_temperature"].get("value", "?")
label.setText(f"{temp_value:.1f}")
@@ -639,7 +878,9 @@ def update_ui(self):
if "ch_temperature" in coldroom:
if "status" in coldroom["ch_temperature"]:
# Update Temperature control LED
- ctrl_temp_led = central.findChild(QtWidgets.QFrame, "ctrl_temp_LED")
+ ctrl_temp_led = central.findChild(
+ QtWidgets.QFrame, "ctrl_temp_LED"
+ )
if ctrl_temp_led:
ctrl_temp_led.setStyleSheet(
"background-color: green;"
@@ -671,7 +912,9 @@ def update_ui(self):
# Temperature setpoint label
if "ch_temperature" in coldroom:
if "setpoint" in coldroom["ch_temperature"]:
- label = central.findChild(QtWidgets.QLabel, "coldroom_temp_set_point_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "coldroom_temp_set_point_label"
+ )
if label:
temp_setpoint = coldroom["ch_temperature"]["setpoint"]
label.setText(f"{temp_setpoint:.1f}")
@@ -682,7 +925,9 @@ def update_ui(self):
# Humidity Current Value
if "ch_humidity" in coldroom:
# Current humidity
- label = central.findChild(QtWidgets.QLabel, "coldroom_humidity_value_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "coldroom_humidity_value_label"
+ )
if label:
humid_value = coldroom["ch_humidity"].get("value", "?")
label.setText(f"{humid_value:.1f}")
@@ -692,7 +937,9 @@ def update_ui(self):
if "ch_humidity" in coldroom:
if "status" in coldroom["ch_humidity"]:
# Update Humidity control LED
- ctrl_humidity_led = central.findChild(QtWidgets.QFrame, "ctrl_humidity_LED")
+ ctrl_humidity_led = central.findChild(
+ QtWidgets.QFrame, "ctrl_humidity_LED"
+ )
if ctrl_humidity_led:
ctrl_humidity_led.setStyleSheet(
"background-color: green;"
@@ -704,7 +951,9 @@ def update_ui(self):
)
# Humidity setpoint lineedit
- lineedit = central.findChild(QtWidgets.QLineEdit, "coldroom_humidity_LE")
+ lineedit = central.findChild(
+ QtWidgets.QLineEdit, "coldroom_humidity_LE"
+ )
if lineedit:
user_has_entered_value = bool(lineedit.text().strip())
# Case 1: User is actively typing - preserve their input
@@ -724,7 +973,9 @@ def update_ui(self):
# Humidity setpoint label
if "ch_humidity" in coldroom:
if "setpoint" in coldroom["ch_humidity"]:
- label = central.findChild(QtWidgets.QLabel, "coldroom_humidity_set_point_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "coldroom_humidity_set_point_label"
+ )
if label:
humid_setpoint = coldroom["ch_humidity"]["setpoint"]
label.setText(f"{humid_setpoint:.1f}")
@@ -732,7 +983,9 @@ def update_ui(self):
# =========================================================================================== COLDROOM DEWPOINT PROCESS ===========================================================================================
# Dewpoint (from coldroom data)
- label = central.findChild(QtWidgets.QLabel, "coldroom_dewpoint_value_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "coldroom_dewpoint_value_label"
+ )
if label and "dew_point_c" in coldroom:
dewpoint = coldroom["dew_point_c"]
label.setText(f"{dewpoint:.1f}")
@@ -745,32 +998,50 @@ def update_ui(self):
light_led = central.findChild(QtWidgets.QFrame, "light_LED")
if light_led:
light_led.setStyleSheet(
- "background-color: yellow;" if coldroom["light"] else "background-color: black;"
+ "background-color: yellow;"
+ if coldroom["light"]
+ else "background-color: black;"
) # LED is yellow when ON
- logger.debug(f"Updated light LED: {'yellow' if coldroom['light'] else 'black'}")
+ logger.debug(
+ f"Updated light LED: {'yellow' if coldroom['light'] else 'black'}"
+ )
if bool(coldroom["light"]) is False:
logger.debug("Light off, check if it is safe")
- used_caen_channels = self.modules_list_tab.get_used_channels()
+ used_caen_channels = (
+ self.modules_list_tab.get_used_channels()
+ )
is_safe = check_light_safe_to_turn_on(
- self.system.status, self.caen_tab.last_response, used_caen_channels
+ self.system.status,
+ self.caen_tab.last_response,
+ used_caen_channels,
+ )
+ button = central.findChild(
+ QtWidgets.QPushButton, "coldroom_light_on_PB"
)
- button = central.findChild(QtWidgets.QPushButton, "coldroom_light_on_PB")
if not is_safe:
logger.debug("not safe")
if button:
button.setEnabled(False)
- logger.debug("Disabled light button due to safety check")
+ logger.debug(
+ "Disabled light button due to safety check"
+ )
else:
if button:
button.setEnabled(True)
- logger.debug("Enabled light button after safety check")
+ logger.debug(
+ "Enabled light button after safety check"
+ )
# Dry air bypass
- dryair_bypass_led = central.findChild(QtWidgets.QFrame, "dryair_bypass_LED")
+ dryair_bypass_led = central.findChild(
+ QtWidgets.QFrame, "dryair_bypass_LED"
+ )
coldroom_air = self.system.status.get("coldroomair", {})
if dryair_bypass_led:
if "air_bypass_status" in coldroom_air:
dryair_bypass_led.setStyleSheet(
- "background-color: green;" if coldroom_air["air_bypass_status"] else "background-color: red;"
+ "background-color: green;"
+ if coldroom_air["air_bypass_status"]
+ else "background-color: red;"
)
logger.debug(
f"Updated dry air bypass LED: {'green' if coldroom_air['air_bypass_status'] else 'red'}"
@@ -783,18 +1054,24 @@ def update_ui(self):
# Door status and LED
if "CmdDoorUnlock_Reff" in coldroom:
door_status = "OPEN" if coldroom["CmdDoorUnlock_Reff"] else "CLOSED"
- label = central.findChild(QtWidgets.QLabel, "coldroom_door_state_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "coldroom_door_state_label"
+ )
if label:
label.setText(door_status)
logger.debug(f"Updated door status: {door_status}")
# =========================================================================================== COLDROOM RUN PROCESS ===========================================================================================
# Update safe to open LED based on door safety check
- safe_to_open_led = central.findChild(QtWidgets.QFrame, "safe_to_open_LED")
+ safe_to_open_led = central.findChild(
+ QtWidgets.QFrame, "safe_to_open_LED"
+ )
if safe_to_open_led:
used_caen_channels = self.modules_list_tab.get_used_channels()
is_safe, door_msg = check_door_safe_to_open(
- self.system.status, self.caen_tab.last_response, used_caen_channels
+ self.system.status,
+ self.caen_tab.last_response,
+ used_caen_channels,
)
# Check co2 values
if "co2_sensor" in self.system.status:
@@ -802,18 +1079,31 @@ def update_ui(self):
if "CO2" in co2_data:
if co2_data["CO2"] > 800:
is_safe = False
- door_msg += "CO2 levels safe: False"
+ # door_msg += "CO2 levels safe: False"
+ door_msg += "CO2 levels safe: NO"
+ door_msg += f" (Current CO2: {co2_data['CO2']:.1f} ppm > 800 ppm)"
else:
- door_msg += "CO2 levels safe: True"
- safe_to_open_led.setStyleSheet("background-color: green;" if is_safe else "background-color: red;")
- logger.debug(f"Updated safe to open LED: {'green' if is_safe else 'red'} (is_safe={is_safe})")
+ # door_msg += "CO2 levels safe: True"
+ door_msg += "CO2 levels safe: Yes"
+ safe_to_open_led.setStyleSheet(
+ "background-color: green;"
+ if is_safe
+ else "background-color: red;"
+ )
+ logger.debug(
+ f"Updated safe to open LED: {'green' if is_safe else 'red'} (is_safe={is_safe})"
+ )
self.system._martacoldroom.publish_door_safety_status(is_safe)
- self.marta_coldroom_tab.findChild(QtWidgets.QLabel, "door_safety_msg").setText(door_msg)
+ self.marta_coldroom_tab.findChild(
+ QtWidgets.QLabel, "door_safety_msg"
+ ).setText(door_msg)
# =========================================================================================== COLDROOM RUN PROCESS ===========================================================================================
# Run status
if "running" in coldroom:
- label = central.findChild(QtWidgets.QLabel, "coldroom_run_state_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "coldroom_run_state_label"
+ )
if label:
run_text = "Running" if coldroom["running"] else "Stopped"
label.setText(run_text)
@@ -826,9 +1116,13 @@ def update_ui(self):
dry_air_led = central.findChild(QtWidgets.QFrame, "dryair_LED")
if dry_air_led:
dry_air_led.setStyleSheet(
- "background-color: green;" if coldroom["dry_air_status"] else "background-color: red;"
+ "background-color: green;"
+ if coldroom["dry_air_status"]
+ else "background-color: red;"
+ )
+ logger.debug(
+ f"Updated dry air LED: {'green' if coldroom['dry_air_status'] else 'red'}"
)
- logger.debug(f"Updated dry air LED: {'green' if coldroom['dry_air_status'] else 'red'}")
# Update CO2 sensor data
if "co2_sensor" in self.system.status:
@@ -905,7 +1199,18 @@ def update_ui(self):
# =========================================================================================== MARTA ===========================================================================================
# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- self.modules_list_tab.marta_safe, self.modules_list_tab.marta_log_msg = check_marta_safe(self.system.status)
+ self.modules_list_tab.marta_safe, self.modules_list_tab.marta_log_msg = (
+ check_marta_safe(self.system.status)
+ )
+
+ # logger.info("Called soft Interlock")
+ # used_caen_channels = self.modules_list_tab.get_used_channels()
+ # logger.info(f"Used CAEN channels for safety checks: {used_caen_channels}")
+ # alarm_publish = (lambda msg: self.system._martacoldroom._client.publish("/alarm", msg)) if self.system._martacoldroom else None
+ # logger.info(f"Alarm publish function: {alarm_publish}")
+ # soft_interlock_loop(self.system.status, self.caen_tab.last_response, used_caen_channels, self.caen_tab, publish_alarm=alarm_publish)
+ # logger.info("Completed soft interlock loop")
+
# Update MARTA CO2 Plant values
if "marta" in self.system.status:
marta = self.system.status["marta"]
@@ -914,38 +1219,50 @@ def update_ui(self):
# =========================================================================================== MARTA FSM STATE PROCESS ===========================================================================================
# Update FSM state
if "fsm_state" in marta:
- state_label = central.findChild(QtWidgets.QLabel, "marta_state_label")
+ state_label = central.findChild(
+ QtWidgets.QLabel, "marta_state_label"
+ )
if state_label:
state_label.setText(marta["fsm_state"])
logger.debug(f"Updated MARTA state: {marta['fsm_state']}")
# Update state-specific UI elements
if marta["fsm_state"] == "ALARM":
# Highlight alarm state
- alarm_frame = central.findChild(QtWidgets.QFrame, "marta_alarm_frame")
+ alarm_frame = central.findChild(
+ QtWidgets.QFrame, "marta_alarm_frame"
+ )
if alarm_frame:
alarm_frame.setStyleSheet("background-color: red;")
# Show alarm message
- alarm_msg = central.findChild(QtWidgets.QLabel, "marta_alarm_msg_label")
+ alarm_msg = central.findChild(
+ QtWidgets.QLabel, "marta_alarm_msg_label"
+ )
if alarm_msg and "alarm_message" in marta:
alarm_msg.setText(marta["alarm_message"])
else:
# Clear alarm highlighting
- alarm_frame = central.findChild(QtWidgets.QFrame, "marta_alarm_frame")
+ alarm_frame = central.findChild(
+ QtWidgets.QFrame, "marta_alarm_frame"
+ )
if alarm_frame:
alarm_frame.setStyleSheet("")
# =========================================================================================== MARTA TEMPERATURE PROCESS ===========================================================================================
# Temperature from TT05_CO2 (Supply)
if "TT05_CO2" in marta:
- label = central.findChild(QtWidgets.QLabel, "marta_temp_supply_value_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "marta_temp_supply_value_label"
+ )
if label:
temp_value = marta["TT05_CO2"]
label.setText(f"{temp_value:.1f}")
logger.debug(f"Updated MARTA supply temperature: {temp_value}")
# Temperature from TT06_CO2 (Return)
if "TT06_CO2" in marta:
- label = central.findChild(QtWidgets.QLabel, "marta_temp_return_value_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "marta_temp_return_value_label"
+ )
if label:
temp_value = marta["TT06_CO2"]
label.setText(f"{temp_value:.1f}")
@@ -963,7 +1280,9 @@ def update_ui(self):
marta_temp_lE_active_flag = True
temp_setpoint = lineedit.text()
lineedit.setText(str(temp_setpoint))
- logger.debug(f"Updated MARTA temperature setpoint: {temp_setpoint}")
+ logger.debug(
+ f"Updated MARTA temperature setpoint: {temp_setpoint}"
+ )
else:
marta_temp_lE_active_flag = False
lineedit.clear()
@@ -971,16 +1290,22 @@ def update_ui(self):
# Temperature setpoint label
if "temperature_setpoint" in marta:
- label = central.findChild(QtWidgets.QLabel, "marta_temp_set_point_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "marta_temp_set_point_label"
+ )
if label:
temp_setpoint = marta["temperature_setpoint"]
label.setText(f"{temp_setpoint:.1f}")
- logger.debug(f"Updated MARTA temperature setpoint: {temp_setpoint}")
+ logger.debug(
+ f"Updated MARTA temperature setpoint: {temp_setpoint}"
+ )
# =========================================================================================== MARTA PRESSURE PROCESS ===========================================================================================
# Pressure from PT05_CO2 (Supply)
if "PT05_CO2" in marta:
- label = central.findChild(QtWidgets.QLabel, "marta_pressure_supply_value_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "marta_pressure_supply_value_label"
+ )
if label:
pressure_value = marta["PT05_CO2"]
label.setText(f"{pressure_value:.3f}")
@@ -988,7 +1313,9 @@ def update_ui(self):
# Pressure from PT06_CO2 (Return)
if "PT06_CO2" in marta:
- label = central.findChild(QtWidgets.QLabel, "marta_pressure_return_value_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "marta_pressure_return_value_label"
+ )
if label:
pressure_value = marta["PT06_CO2"]
label.setText(f"{pressure_value:.3f}")
@@ -997,7 +1324,9 @@ def update_ui(self):
# =========================================================================================== MARTA SPEED PROCESS ===========================================================================================
# Speed
if "LP_speed" in marta:
- label = central.findChild(QtWidgets.QLabel, "marta_speed_value_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "marta_speed_value_label"
+ )
if label:
speed_value = marta["LP_speed"]
label.setText(f"{speed_value:.1f}")
@@ -1024,7 +1353,9 @@ def update_ui(self):
# Speed setpoint label
if "speed_setpoint" in marta:
- label = central.findChild(QtWidgets.QLabel, "marta_speed_set_point_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "marta_speed_set_point_label"
+ )
if label:
speed_setpoint = marta["speed_setpoint"]
label.setText(f"{speed_setpoint:.1f}")
@@ -1035,12 +1366,18 @@ def update_ui(self):
# Flow control LED
if "set_flow_active" in marta:
# Update Flow control LED
- ctrl_flow_led = central.findChild(QtWidgets.QFrame, "marta_flow_flag_LED")
+ ctrl_flow_led = central.findChild(
+ QtWidgets.QFrame, "marta_flow_flag_LED"
+ )
if ctrl_flow_led:
ctrl_flow_led.setStyleSheet(
- "background-color: green;" if marta["set_flow_active"] else "background-color: black;"
+ "background-color: green;"
+ if marta["set_flow_active"]
+ else "background-color: black;"
) # LED is green when ON
- logger.debug(f"Updated flow control LED: {'green' if marta['set_flow_active'] else 'black'}")
+ logger.debug(
+ f"Updated flow control LED: {'green' if marta['set_flow_active'] else 'black'}"
+ )
# Flow setpoint lineedit
if "set_flow_setpoint" in marta:
@@ -1061,7 +1398,9 @@ def update_ui(self):
# Flow setpoint (affects speed)
if "flow_setpoint" in marta:
- label = central.findChild(QtWidgets.QLabel, "marta_flow_set_point_label")
+ label = central.findChild(
+ QtWidgets.QLabel, "marta_flow_set_point_label"
+ )
if label:
flow_setpoint = marta["flow_setpoint"]
label.setText(f"{flow_setpoint:.1f}")
@@ -1083,7 +1422,9 @@ def set_coldroom_temperature(self):
central = self.marta_coldroom_tab
# Check if temperature control is enabled
coldroom = self.system.status.get("coldroom", {})
- if "ch_temperature" not in coldroom or not coldroom.get("ch_temperature", {}).get("status", False):
+ if "ch_temperature" not in coldroom or not coldroom.get(
+ "ch_temperature", {}
+ ).get("status", False):
msg = "Temperature control is not enabled. Please enable temperature control first."
self.statusBar().showMessage(msg)
logger.warning(msg)
@@ -1123,8 +1464,12 @@ def set_coldroom_humidity(self):
central = self.marta_coldroom_tab
# Check if humidity control is enabled
coldroom = self.system.status.get("coldroom", {})
- if "ch_humidity" not in coldroom or not coldroom.get("ch_humidity", {}).get("status", False):
- msg = "Humidity control is not enabled. Please enable humidity control first."
+ if "ch_humidity" not in coldroom or not coldroom.get("ch_humidity", {}).get(
+ "status", False
+ ):
+ msg = (
+ "Humidity control is not enabled. Please enable humidity control first."
+ )
self.statusBar().showMessage(msg)
logger.warning(msg)
return
@@ -1142,11 +1487,15 @@ def set_coldroom_humidity(self):
if 0 <= value <= 50: # Humidity range from UI validator
if self.system._martacoldroom:
self.system._martacoldroom.set_humidity(value)
- msg = f"Set coldroom humidity to {value}%"
- self.statusBar().showMessage(msg)
- logger.info(msg)
+ msg = f"Set coldroom humidity to {value}%"
+ self.statusBar().showMessage(msg)
+ logger.info(msg)
+ else:
+ msg = "MARTA Cold Room client not initialized"
+ self.statusBar().showMessage(msg)
+ logger.error(msg)
else:
- msg = "MARTA Cold Room client not initialized"
+ msg = "Humidity must be between 0% and 50%"
self.statusBar().showMessage(msg)
logger.error(msg)
except ValueError:
@@ -1257,7 +1606,9 @@ def toggle_coldroom_door(self):
# This would normally require safety checks
if self.system._martacoldroom:
# For demo purposes, we're just toggling the state
- self.system._martacoldroom.publish_cmd("door", self.system._martacoldroom._coldroom_client, str(new_state))
+ self.system._martacoldroom.publish_cmd(
+ "door", self.system._martacoldroom._coldroom_client, str(new_state)
+ )
msg = f"Set door to {'OPEN' if new_state else 'CLOSED'}"
self.statusBar().showMessage(msg)
logger.info(msg)
@@ -1312,8 +1663,12 @@ def update_marta_button_states(self, state):
central = self.marta_coldroom_tab
# Get all MARTA control buttons
- start_chiller_btn = central.findChild(QtWidgets.QPushButton, "marta_chiller_start_PB")
- stop_chiller_btn = central.findChild(QtWidgets.QPushButton, "marta_stop_chiller_PB")
+ start_chiller_btn = central.findChild(
+ QtWidgets.QPushButton, "marta_chiller_start_PB"
+ )
+ stop_chiller_btn = central.findChild(
+ QtWidgets.QPushButton, "marta_stop_chiller_PB"
+ )
start_co2_btn = central.findChild(QtWidgets.QPushButton, "marta_co2_start_PB")
stop_co2_btn = central.findChild(QtWidgets.QPushButton, "marta_co2_stop_PB")
@@ -1582,13 +1937,25 @@ def toggle_marta_flow_active(self):
def save_settings(self):
try:
# Update settings object
- self.system.settings["mqtt"]["broker"] = self.settings_tab.brokerLineEdit.text()
+ self.system.settings["mqtt"][
+ "broker"
+ ] = self.settings_tab.brokerLineEdit.text()
self.system.settings["mqtt"]["port"] = self.settings_tab.portSpinBox.value()
- self.system.settings["MARTA"]["mqtt_topic"] = self.settings_tab.martaTopicLineEdit.text()
- self.system.settings["Coldroom"]["mqtt_topic"] = self.settings_tab.coldroomTopicLineEdit.text()
- self.system.settings["Coldroom"]["co2_sensor_topic"] = self.settings_tab.co2SensorTopicLineEdit.text()
- self.system.settings["ThermalCamera"]["mqtt_topic"] = self.settings_tab.thermalCameraTopicLineEdit.text()
- self.system.settings["Cleanroom"]["mqtt_topic"] = self.settings_tab.cleanroomTopicLineEdit.text()
+ self.system.settings["MARTA"][
+ "mqtt_topic"
+ ] = self.settings_tab.martaTopicLineEdit.text()
+ self.system.settings["Coldroom"][
+ "mqtt_topic"
+ ] = self.settings_tab.coldroomTopicLineEdit.text()
+ self.system.settings["Coldroom"][
+ "co2_sensor_topic"
+ ] = self.settings_tab.co2SensorTopicLineEdit.text()
+ self.system.settings["ThermalCamera"][
+ "mqtt_topic"
+ ] = self.settings_tab.thermalCameraTopicLineEdit.text()
+ self.system.settings["Cleanroom"][
+ "mqtt_topic"
+ ] = self.settings_tab.cleanroomTopicLineEdit.text()
# Write to file
with open("settings.yaml", "w") as f:
@@ -1611,12 +1978,17 @@ def save_settings(self):
if __name__ == "__main__":
args = argparse.ArgumentParser(description="Cold Room Control Application")
args.add_argument(
- "--loglevel", "-log", default="WARNING", help="Set the logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)"
+ "--loglevel",
+ "-log",
+ default="WARNING",
+ help="Set the logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)",
)
parsed_args = args.parse_args()
logger = logging.getLogger("integration")
log_level = getattr(logging, parsed_args.loglevel.upper(), logging.WARNING)
- logging.basicConfig(level=log_level, format="%(asctime)s - %(levelname)s - %(message)s")
+ logging.basicConfig(
+ level=log_level, format="%(asctime)s - %(levelname)s - %(message)s"
+ )
app = QtWidgets.QApplication(sys.argv)
window = MainApp()
diff --git a/coldroom/marta_coldroom.py b/coldroom/marta_coldroom.py
index 006372b..6071678 100644
--- a/coldroom/marta_coldroom.py
+++ b/coldroom/marta_coldroom.py
@@ -157,7 +157,9 @@ def on_message(self, client, userdata, msg):
if self._system.has_valid_status():
self._system.safety_flags["door_locked"] = not check_dew_point(self._system.status)
self._system.safety_flags["sleep"] = check_door_status(self._system.status)
- self._system.safety_flags["door_safe"] = check_door_safe_to_open(self._system.status)
+ self._system.safety_flags["door_safe"] = check_door_safe_to_open(
+ self._system.status, self._system.status.get("caen", {}), {"HV": []}
+ )
logger.debug(f"Safety flags updated: {self._system.safety_flags}")
def publish_cmd(self, command, target, payload):
@@ -169,7 +171,7 @@ def publish_cmd(self, command, target, payload):
target (str): Either 'marta' or 'coldroom' or 'cleanroom'
payload: The command payload
"""
- logger.debug("Publishing", command, target, payload)
+ logger.debug(f"Publishing {command} {target} {payload}")
if target == "marta": # Add MARTA topic
topic = f"{self.TOPIC_BASE_MARTA}cmd/{command}"
elif target == "cleanroom": # Add cleanroom topic
diff --git a/coldroom/marta_coldroom.ui b/coldroom/marta_coldroom.ui
index 35c8ea8..4eacd73 100644
--- a/coldroom/marta_coldroom.ui
+++ b/coldroom/marta_coldroom.ui
@@ -94,6 +94,79 @@
+ -
+
+
-
+
+
-
+
+
+
+ 60
+ 60
+
+
+
+
+ 300
+ 300
+
+
+
+ background-color: red;
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+ -
+
+
+
+ 160
+ 60
+
+
+
+
+ 16
+
+
+
+ Soft Interlock
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ -
+
+
+
+ 16
+
+
+
+ -
+
+
+
+
+
diff --git a/coldroom/safety.py b/coldroom/safety.py
index 3a3f2e9..a97bcf5 100644
--- a/coldroom/safety.py
+++ b/coldroom/safety.py
@@ -1,4 +1,5 @@
import os
+from tkinter import NO, YES, YES
import yaml
import logging
@@ -25,7 +26,9 @@ def check_dew_point(system_status):
# Get the three required temperature values
marta_supply_temp = system_status.get("marta", {}).get("TT05_CO2")
marta_return_temp = system_status.get("marta", {}).get("TT06_CO2")
- coldroom_temp = system_status.get("coldroom", {}).get("ch_temperature", {}).get("value")
+ coldroom_temp = (
+ system_status.get("coldroom", {}).get("ch_temperature", {}).get("value")
+ )
# coldroom = system_status.get("coldroom", {})
# logger.debug(f"Coldroom: {coldroom.get('CmdDoorUnlock_Reff')}")
# door_status = system_status.get("coldroom", {}).get("CmdDoorUnlock_Reff")
@@ -52,28 +55,38 @@ def check_dew_point(system_status):
if "coldroom" not in system_status:
logger.debug("Coldroom data not available")
- return False # Conservative approach - if we can't check, assume it's unsafe
+ return (
+ False # Conservative approach - if we can't check, assume it's unsafe
+ )
# Check if environment data exists
- if "cleanroom" not in system_status or "dewpoint" not in system_status["cleanroom"]:
+ if (
+ "cleanroom" not in system_status
+ or "dewpoint" not in system_status["cleanroom"]
+ ):
return False # Conservative approach
- reference_dew_point = system_status["cleanroom"]["dewpoint"] # External dewpoint
+ reference_dew_point = system_status["cleanroom"][
+ "dewpoint"
+ ] # External dewpoint
logger.debug(f"Reference dew point: {reference_dew_point}")
delta = 1 # Allowable delta between dew point and temperature
return min_temperature > reference_dew_point + delta
except Exception as e:
logger.debug(f"Error in check_dew_point: {str(e)}")
- return False # Conservative approach
+ return False, "Error checking dew point safety" # Conservative approach
def check_door_status(system_status):
try:
- if "coldroom" not in system_status or "door_status" not in system_status["coldroom"]:
+ if (
+ "coldroom" not in system_status
+ or "door_status" not in system_status["coldroom"]
+ ):
return False # Conservative approach
return system_status["coldroom"]["CmdDoorUnlock_Reff"] == 1 # Door is open
except Exception as e:
logger.debug(f"Error in check_door_status: {str(e)}")
- return False # Conservative approach
+ return False, "Error checking door status" # Conservative approach
def check_light_status(system_status):
@@ -83,7 +96,7 @@ def check_light_status(system_status):
return system_status["coldroom"]["light"] == 1 # Light is on
except Exception as e:
logger.debug(f"Error in check_light_status: {str(e)}")
- return False # Conservative approach
+ return False, "Error checking light status" # Conservative approach
def check_any_hv_on(caen_ch_status, used_channels):
@@ -98,7 +111,10 @@ def check_any_hv_on(caen_ch_status, used_channels):
return hv_on
except Exception as e:
logger.debug(f"Error in check_any_hv_on: {str(e)}")
- return True
+ return (
+ True,
+ "Error checking high voltage status",
+ ) # Conservative approach - if we can't check, assume it's unsafe
def check_cleanroom_expired(elapsed_time, threshold=600):
@@ -114,21 +130,33 @@ def check_door_safe_to_open(system_status, caen_ch_status, used_channels):
try:
# Check if we have all necessary data
if "coldroom" not in system_status:
- return False # Conservative approach - if we can't check, assume it's unsafe
+ return (
+ False # Conservative approach - if we can't check, assume it's unsafe
+ )
# 1. Check if dew point conditions are safe
- clean_room_expired = check_cleanroom_expired(system_status["cleanroom"]["elapsed_time"])
+ clean_room_expired = check_cleanroom_expired(
+ system_status["cleanroom"]["elapsed_time"]
+ )
if clean_room_expired:
dew_point_safe = False
log_msg += f"!!! Warning: Cleanroom data expired, not able to check dew point !!!\n"
else:
dew_point_safe = check_dew_point(system_status)
- log_msg += f"Dew point safe: {dew_point_safe}\n"
+ if not dew_point_safe:
+ log_msg += f"!!! Warning: Dew point conditions are not safe for opening door !!!\n"
+ log_msg += f"Dew point safe: NO\n"
+ else:
+ log_msg += f"Dew point safe: YES\n"
# 2. Check if high voltage is off
hv_on = check_any_hv_on(caen_ch_status, used_channels)
hv_safe = not hv_on
- log_msg += f"High voltage safe: {hv_safe}\n"
+ if hv_safe == False:
+ log_msg += f"!!! Warning: High voltage is ON, not safe to open door !!!\n"
+ log_msg += f"High voltage safe: NO\n"
+ else:
+ log_msg += f"High voltage safe: YES\n"
# 3. Check if light is off (light should be off when opening door)
# light_off = not check_light_status(system_status)
@@ -148,7 +176,7 @@ def check_door_safe_to_open(system_status, caen_ch_status, used_channels):
except Exception as e:
logger.debug(f"Error in check_door_safe_to_open: {str(e)}")
- return False # Conservative approach - if we can't check, assume it's unsafe
+ return False, "Error checking door safety"
def check_light_safe_to_turn_on(system_status, caen_ch_status, used_channels):
@@ -160,7 +188,9 @@ def check_light_safe_to_turn_on(system_status, caen_ch_status, used_channels):
try:
# Check if we have all necessary data
if "coldroom" not in system_status:
- return False # Conservative approach - if we can't check, assume it's unsafe
+ return (
+ False # Conservative approach - if we can't check, assume it's unsafe
+ )
# Check if high voltage is off
hv_on = check_any_hv_on(caen_ch_status, used_channels)
@@ -191,11 +221,238 @@ def check_marta_safe(system_status):
# def check_marta_on_for_ot
# def check_marta_on_for_it
-#def switch_all_lv_off
+# def switch_all_lv_off
# def soft_interlock_loop: ### describe only highlevel
# if condition then : action
# if ! check_lv_safe_on and something_on : switch_all_lv_off()
-#when performing an active safety action here we send a msg to the alarm topic "/alarm"
\ No newline at end of file
+# when performing an active safety action here we send a msg to the alarm topic "/alarm"
+
+
+def Is_any_lv_on(caen_ch_status, used_channels):
+ """
+ Check if any LV channel is on.
+ Returns True if any LV channel is on, False if all are off.
+ """
+ try:
+ for channel in used_channels["LV"]:
+ if channel is None:
+ continue
+ ch_str = f"caen_{channel}_IsOn"
+ if bool(caen_ch_status.get(ch_str, False)):
+ logger.info(f"LV channel {channel} is ON")
+ return True
+ return False
+ except Exception as e:
+ logger.debug(f"Error in Is_any_lv_on: {str(e)}")
+ return True # Conservative - assume LV is on if we can't check
+
+
+def Is_it_safe_to_on_lv(system_status, caen_ch_status, used_channels):
+ """
+ Check if it's safe to turn on LV channels based on multiple safety conditions.
+ Returns True if it's safe to turn on LV channels, False otherwise.
+ """
+ log_msg = ""
+ try:
+ # Check if we have all necessary data
+ if "coldroom" not in system_status:
+ return (
+ False # Conservative approach - if we can't check, assume it's unsafe
+ )
+
+ # Check if MARTA is running
+ marta_safe, marta_msg = check_marta_safe(system_status)
+ log_msg += f"MARTA safe: {marta_safe} ({marta_msg})\n"
+
+ # It's safe to turn on LV channels if MARTA is safe
+ is_safe = marta_safe
+ return is_safe, log_msg
+
+ except Exception as e:
+ logger.debug(f"Error in Is_it_safe_to_on_lv: {str(e)}")
+ return False, "Error checking LV safety"
+
+
+# def check_lv_safe_on(caen_ch_status, used_channels):
+# """
+# Check if any LV channel is on.
+# Returns True if any LV channel is on, False if all are off.
+# """
+# try:
+# for channel in used_channels["LV"]:
+# if channel is None:
+# continue
+# ch_str = f"caen_{channel}_IsOn"
+# if bool(caen_ch_status.get(ch_str, False)):
+# return True
+# return False
+# except Exception as e:
+# logger.debug(f"Error in check_lv_safe_on: {str(e)}")
+# return True # Conservative - assume LV is on if we can't check
+
+
+def check_marta_on_for_OT(system_status):
+ """
+ Check if MARTA is running for OT (Outer Tracker).
+ Returns True if MARTA is connected and operational.
+ """
+ try:
+ if "marta" not in system_status or "serviceroom" not in system_status:
+ return False
+
+ logger.info(
+ f"Checking MARTA OT status: {system_status['marta'].get('fsm_state', 'N/A')}, OT valve: {system_status['serviceroom'].get('outer_valve', 'N/A')}"
+ )
+ fsm_state = system_status["marta"].get("fsm_state", "")
+ OT_valve = system_status["serviceroom"].get("outer_valve", 0)
+
+ if fsm_state not in ("DISCONNECTED", "NONE", ""):
+ if OT_valve == 1: # Outer valve is open, so OT is likely running
+ logger.info(
+ "MARTA FSM state is good and OT valve is open, treating as running"
+ )
+ return True
+ else:
+ logger.debug(
+ "MARTA FSM state is good but OT valve is closed, treating as not running"
+ )
+ return False
+ else:
+ return False
+ except Exception as e:
+ logger.debug(f"Error in check_marta_on_for_OT: {str(e)}")
+ return False
+
+
+def check_marta_on_for_IT(system_status):
+ """
+ Check if MARTA is running for IT (Inner Tracker).
+ Returns True if MARTA is connected and operational.
+ """
+ try:
+ if "marta" not in system_status or "serviceroom" not in system_status:
+ return False
+ logger.info(
+ f"Checking MARTA IT status: {system_status['marta'].get('fsm_state', 'N/A')}, IT valve: {system_status['serviceroom'].get('inner_valve', 'N/A')}"
+ )
+ fsm_state = system_status["marta"].get("fsm_state", "")
+ IT_valve = system_status["serviceroom"].get("inner_valve", 0)
+ if fsm_state not in ("DISCONNECTED", "NONE", ""):
+ if IT_valve == 1: # Inner valve is open, so IT is likely running
+ logger.info(
+ "MARTA FSM state is good and IT valve is open, treating as running"
+ )
+ return True
+ else:
+ logger.debug(
+ "MARTA FSM state is good but IT valve is closed, treating as not running"
+ )
+ return False
+ else:
+ return False
+ except Exception as e:
+ logger.debug(f"Error in check_marta_on_for_IT: {str(e)}")
+ return False
+
+
+def switch_all_lv_off(caen, used_channels):
+ """
+ Turn off all LV channels.
+ Returns True if all commands were sent successfully.
+ """
+ try:
+ for channel in used_channels["LV"]:
+ logger.info(f"Attempting to turn off LV channel {channel}")
+ if channel is None:
+ continue
+ logger.warning(f"Safety interlock: turning off LV channel {channel}")
+ caen.off(channel)
+ return True
+ except Exception as e:
+ logger.error(f"Error in switch_all_lv_off: {str(e)}")
+ return False
+
+
+def soft_interlock_loop(
+ system_status, caen_ch_status, used_channels, caen, publish_alarm=None
+):
+ """
+ Soft interlock loop - monitors safety conditions and takes protective action.
+
+ High-level logic:
+ if LV is on AND MARTA is not running:
+ → switch all LV off
+ → publish alarm message to /alarm topic
+
+ When performing an active safety action, a message is sent to the alarm topic "/alarm"
+ via the publish_alarm callback.
+
+ Args:
+ system_status (dict): Full system status including MARTA, coldroom, etc.
+ caen_ch_status (dict): CAEN channel status with caen_{channel}_IsOn keys.
+ used_channels (dict): Active channel list {"LV": [...], "HV": [...]}.
+ caen: CAEN control object with on()/off() methods.
+ publish_alarm (callable, optional): Function to publish alarm messages.
+ Signature: publish_alarm(message_string)
+
+ Returns:
+ tuple: (is_safe: bool, message: str)
+ """
+ try:
+ lv_on = Is_any_lv_on(caen_ch_status, used_channels)
+ lv_safe_to_on = Is_it_safe_to_on_lv(
+ system_status, caen_ch_status, used_channels
+ )
+ marta_ot = check_marta_on_for_OT(system_status)
+ marta_it = check_marta_on_for_IT(system_status)
+
+ if lv_on:
+ lv_status = "ON"
+ else:
+ lv_status = "OFF"
+
+ if marta_ot:
+ marta_ot_status = "RUNNING"
+ else:
+ marta_ot_status = "NOT RUNNING"
+
+ if marta_it:
+ marta_it_status = "RUNNING"
+ else:
+ marta_it_status = "NOT RUNNING"
+
+ log_msg = f"\nSoft interlock: LV_on={lv_status}, MARTA_OT={marta_ot_status}, MARTA_IT={marta_it_status}\n"
+ logger.info(log_msg)
+
+ if lv_safe_to_on == False:
+ log_msg += (
+ "\n!!! Warning: Conditions are not safe to turn on LV channels !!!\n"
+ )
+ log_msg += f"\nLV safe to on: NO\n"
+ # switch_all_lv_off(caen, used_channels)
+ else:
+ log_msg += f"\nLV safe to on: YES\n"
+
+ if lv_on and not marta_ot:
+ alarm_msg = (
+ "SAFETY INTERLOCK: LV channels are on but MARTA OT is not running. "
+ "Turning off all LV channels to prevent module damage."
+ )
+ logger.warning(alarm_msg)
+ # switch_all_lv_off(caen, used_channels)
+ if publish_alarm:
+ publish_alarm(alarm_msg)
+ return False, alarm_msg
+ else:
+ log_msg += "\nAll safety conditions met.\n"
+ logger.info(log_msg)
+
+ return True, log_msg
+
+ except Exception as e:
+ err_msg = f"Error in soft_interlock_loop: {str(e)}"
+ logger.error(err_msg)
+ return False, err_msg
diff --git a/power_supply/power_supply.ui b/power_supply/power_supply.ui
index 19fab89..82cb2b2 100644
--- a/power_supply/power_supply.ui
+++ b/power_supply/power_supply.ui
@@ -1,7 +1,7 @@
- MainWindow
-
+ PowerSupply
+
0
@@ -11,184 +11,171 @@
- MainWindow
+ Power Supply
-
-
- -
-
-
- Power Supply Control
-
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- -
-
-
- Set Voltage Value
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- ?
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Set Current
-
-
-
- -
-
-
- ON
-
-
-
- -
-
-
- ?
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- ?
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Set Voltage
-
-
-
- -
-
-
- -
-
-
- Set Curent Value
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- ?
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
-
- 30
- 30
-
-
-
-
- 30
- 30
-
-
-
- background-color: red;
-
-
- QFrame::NoFrame
-
-
- QFrame::Raised
-
-
-
- -
-
-
- Voltage ( v )
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- OFF
-
-
-
- -
-
-
- Current Status ( i )
-
-
- Qt::AlignCenter
-
-
-
-
-
-
-
-
-
-
+
+ -
+
+
+ Power Supply Control
+
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ -
+
+
+ Set Voltage Value
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ ?
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Set Current
+
+
+
+ -
+
+
+ ON
+
+
+
+ -
+
+
+ ?
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ ?
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Set Voltage
+
+
+
+ -
+
+
+ -
+
+
+ Set Curent Value
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ ?
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 30
+ 30
+
+
+
+
+ 30
+ 30
+
+
+
+ background-color: red;
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+ -
+
+
+ Voltage ( v )
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ OFF
+
+
+
+ -
+
+
+ Current Status ( i )
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
diff --git a/power_supply/power_supply_ctrl.py b/power_supply/power_supply_ctrl.py
index 39dbab8..162b571 100644
--- a/power_supply/power_supply_ctrl.py
+++ b/power_supply/power_supply_ctrl.py
@@ -1,7 +1,8 @@
+import os
import sys
import logging
import pyvisa as visa
-from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox
+from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox
from PyQt5.uic import loadUi
from PyQt5.QtCore import QTimer
@@ -16,11 +17,12 @@
)
logger = logging.getLogger(__name__)
-class PowerSupplyController(QMainWindow):
- def __init__(self):
- super(PowerSupplyController, self).__init__()
+class PowerSupplyController(QWidget):
+ def __init__(self, parent=None):
+ super(PowerSupplyController, self).__init__(parent)
# Load the UI file
- loadUi('power_supply.ui', self)
+ ui_path = os.path.join(os.path.dirname(__file__), 'power_supply.ui')
+ loadUi(ui_path, self)
# Initialize status dictionary
self.status = {
@@ -30,15 +32,21 @@ def __init__(self):
'set_voltage': 0.0,
'set_current': 0.0
}
+ self.connected = False
+
+ # Set up timer early so closeEvent doesn't crash on connection failure
+ self.timer = QTimer(self)
# Connect to the power supply
self.connect_to_power_supply()
-
+ if not self.connected:
+ self.timer.stop()
+ return
+
# Connect UI signals to slots
self.setup_ui_connections()
# Set up a timer to periodically update measurements
- self.timer = QTimer(self)
self.timer.timeout.connect(self.update_measurements)
self.timer.start(1000) # Update every 1000ms (1 second)
@@ -57,11 +65,11 @@ def connect_to_power_supply(self):
ip_address = '192.168.0.16'
self.rm = visa.ResourceManager()
self.power_supply = self.rm.open_resource(f'TCPIP0::{ip_address}::INSTR')
+ self.connected = True
print("Successfully connected to power supply")
except Exception as e:
logger.error(f"Failed connection: {e}")
QMessageBox.critical(self, "Connection Error", f"Failed to connect to power supply: {e}")
- self.close()
def setup_ui_connections(self):
"""Connect UI signals to slots"""
@@ -84,7 +92,8 @@ def update_ui(self):
def update_measurements(self):
"""Periodically update the voltage and current measurements"""
- # if self.status['power'] == 'ON':
+ if not self.connected:
+ return
try:
# Read actual voltage and current
voltage = self.power_supply.query('MEAS:VOLT?\x00').strip()
@@ -99,11 +108,11 @@ def update_measurements(self):
self.log_status("Updated measurements")
except Exception as e:
logger.error(f"Error reading measurements: {e}")
- QMessageBox.critical(self, "Measurement Error", f"Failed to read measurements: {e}")
- print(f"Error reading measurements: {e}")
def set_voltage(self):
"""Set the voltage value from the line edit"""
+ if not self.connected:
+ return
try:
voltage = float(self.powsup_voltage_LE.text())
self.power_supply.write(f'APPLY {voltage}\x00')
@@ -119,6 +128,8 @@ def set_voltage(self):
def set_current(self):
"""Set the current value from the line edit"""
+ if not self.connected:
+ return
try:
current = float(self.powsup_current_LE.text())
self.power_supply.write(f'SOUR:CURR {current}\x00')
@@ -134,6 +145,8 @@ def set_current(self):
def power_on(self):
"""Turn the power supply ON"""
+ if not self.connected:
+ return
try:
self.power_supply.write('OUTP:STAT ON\x00')
self.status['power'] = 'ON'
@@ -147,6 +160,8 @@ def power_on(self):
def power_off(self):
"""Turn the power supply OFF"""
+ if not self.connected:
+ return
try:
self.power_supply.write('OUTP:STAT OFF\x00')
self.status['power'] = 'OFF'
@@ -163,7 +178,8 @@ def power_off(self):
def closeEvent(self, event):
"""Ensure proper cleanup when closing the application"""
try:
- self.timer.stop()
+ if hasattr(self, 'timer'):
+ self.timer.stop()
if hasattr(self, 'power_supply'):
self.power_off() # Turn off power supply when closing
self.power_supply.close()
@@ -177,9 +193,14 @@ def closeEvent(self, event):
def main():
app = QApplication(sys.argv)
- window = PowerSupplyController()
+ window = QMainWindow()
+ controller = PowerSupplyController()
+ window.setCentralWidget(controller)
+ window.setWindowTitle("Power Supply")
+ window.resize(controller.width(), controller.height())
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
+ from PyQt5.QtWidgets import QMainWindow
main()