From fc0e7329a4d1cc0cf37bb8d6806550a21582a20f Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 6 Aug 2025 16:21:19 +0200 Subject: [PATCH] MainCode/adalm1000_logger.py aktualisiert Initializing new session... Found 2 device(s) in session Device error: Read error: No samples received Device error: Read error: No samples received close to working --- MainCode/adalm1000_logger.py | 168 ++++++++++++++++++++++++++++------- 1 file changed, 137 insertions(+), 31 deletions(-) diff --git a/MainCode/adalm1000_logger.py b/MainCode/adalm1000_logger.py index 9f62fa5..a4a991f 100644 --- a/MainCode/adalm1000_logger.py +++ b/MainCode/adalm1000_logger.py @@ -17,6 +17,21 @@ from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QH from PyQt5.QtCore import Qt, QTimer, pyqtSignal, pyqtSlot, QObject, QThread from PyQt5 import sip import pysmu +import pysmu.libsmu +from pysmu.exceptions import SessionError + +class PatchedSession(pysmu.Session): + def __init__(self, ignore_dataflow=False, queue_size=0): + try: + super().__init__(ignore_dataflow=ignore_dataflow, queue_size=queue_size) + except SessionError as e: + if "failed scanning and/or adding all supported devices" in str(e): + print("⚠️ Ignored add_all() busy-device error, continuing...") + # The parent __init__ still runs and creates a session object + # We'll manually add devices later in init_device() + else: + raise + class DeviceDisconnectedError(Exception): pass @@ -972,53 +987,68 @@ class BatteryTester(QMainWindow): self.main_layout.addWidget(self.canvas, 1) def init_device(self): - """Initialize ADALM1000 with proper device selection and session handling""" + """Initialize ADALM1000 with proper permission handling""" try: - # Clean up existing session + # Clean up previous session if exists if hasattr(self, 'session'): try: self.session.end() - del self.session except Exception as e: - print(f"Error cleaning up session: {e}") + print(f"Session cleanup error: {e}") + del self.session - time.sleep(0.5) # Brief pause for USB re-enumeration + # Debug USB devices + print("Checking USB devices...") + usb_info = os.popen("lsusb -d 064b:784c -v").read() + print(usb_info) - # Initialize new session - self.session = pysmu.Session(ignore_dataflow=True, queue_size=10000) - if not self.session.devices: + # Check if devices are present + if "064b:784c" not in usb_info: raise DeviceDisconnectedError("No ADALM1000 devices detected") - # Populate device selector - self.device_combo.clear() - for dev in self.session.devices: - self.device_combo.addItem(dev.serial) + # Initialize new session with permission handling + print("Initializing new session...") + try: + # First try with normal permissions + self.session = pysmu.Session(ignore_dataflow=True, queue_size=10000) + except (OSError, pysmu.exceptions.SessionError) as e: + if "permission" in str(e).lower() or "not permitted" in str(e): + print("Permission error detected - requesting elevated privileges") + self.request_usb_permissions() + # Try again after permission request + self.session = pysmu.Session(ignore_dataflow=True, queue_size=10000) + else: + raise - # Select first device by default - self.dev = self.session.devices[0] - self.device_combo.setCurrentIndex(0) + # Get and store available devices _einmal_ + self.device_list = list(self.session.devices) + print(f"Found {len(self.device_list)} device(s) in session") + + if not self.device_list: + raise DeviceDisconnectedError("No ADALM1000 devices available") - # Configure channels + # Use the first available device + self.dev = self.device_list[0] + + # Configure device self.dev.channels['A'].mode = pysmu.Mode.HI_Z self.dev.channels['B'].mode = pysmu.Mode.HI_Z self.dev.channels['A'].constant(0) self.dev.channels['B'].constant(0) - # Start session for the selected device - device_index = self.session.devices.index(self.dev) - self.session.start(device_index) + # Start session + self.session.start(0) + self.session_active = True # Update UI self.status_light.setStyleSheet("background-color: green; border-radius: 10px;") self.connection_label.setText(f"Connected: {self.dev.serial}") - self.status_bar.showMessage(f"Ready - Device {self.dev.serial}") - self.session_active = True - self.start_button.setEnabled(True) - + self.device_combo.clear() + self.device_combo.addItem(self.dev.serial) + # Start measurement thread if hasattr(self, 'measurement_thread'): self.measurement_thread.stop() - self.measurement_thread.wait(500) self.measurement_thread = MeasurementThread(self.dev, self.interval) self.measurement_thread.update_signal.connect(self.update_measurements) @@ -1026,11 +1056,84 @@ class BatteryTester(QMainWindow): self.measurement_thread.start() except Exception as e: + print(f"INIT ERROR DETAILS: {str(e)}") self.handle_device_error(str(e)) + def request_usb_permissions(self): + """Handle USB permission issues with user interaction""" + msg = QMessageBox(self) + msg.setIcon(QMessageBox.Critical) + msg.setWindowTitle("USB Permission Required") + msg.setText("Permission needed to access ADALM1000 devices") + msg.setInformativeText( + "The application needs elevated privileges to access USB devices.\n\n" + "Please choose an option:" + ) + + # Add buttons + sudo_button = msg.addButton("Run as Administrator", QMessageBox.ActionRole) + udev_button = msg.addButton("Fix Permissions", QMessageBox.ActionRole) + cancel_button = msg.addButton(QMessageBox.Cancel) + + msg.exec_() + + if msg.clickedButton() == sudo_button: + # Restart with sudo + QMessageBox.information(self, "Restarting", + "The application will restart with administrator privileges") + args = sys.argv[:] + args.insert(0, sys.executable) + os.execvp("sudo", ["sudo"] + args) + + elif msg.clickedButton() == udev_button: + # Create udev rule + rule_content = ( + '# ADALM1000 USB permissions\n' + 'SUBSYSTEM=="usb", ATTR{idVendor}=="064b", ATTR{idProduct}=="784c", MODE="0666"\n' + ) + + try: + # Try to create udev rule + rule_path = "/etc/udev/rules.d/52-adalm1000.rules" + with open(rule_path, "w") as f: + f.write(rule_content) + + # Apply rules + os.system("sudo udevadm control --reload-rules") + os.system("sudo udevadm trigger") + + QMessageBox.information(self, "Permissions Fixed", + "USB permissions configured. Please reconnect devices.") + except Exception as e: + QMessageBox.critical(self, "Error", + f"Failed to set permissions: {str(e)}\n\n" + "Please run these commands manually:\n\n" + f"echo '{rule_content}' | sudo tee {rule_path}\n" + "sudo udevadm control --reload-rules\n" + "sudo udevadm trigger") + + def manual_device_init(self): + """Manual device initialization workaround""" + try: + # Simulate device detection + self.device_combo.clear() + self.device_combo.addItem("ADALM1000-1 (Simulated)") + self.device_combo.addItem("ADALM1000-2 (Simulated)") + + # Mock connection + self.status_light.setStyleSheet("background-color: orange; border-radius: 10px;") + self.connection_label.setText("Simulated Devices") + self.session_active = True + self.start_button.setEnabled(True) + + QMessageBox.warning(self, "Simulation Mode", + "Using simulated devices - real hardware not detected") + except Exception as e: + print(f"Manual init failed: {e}") + def change_device(self, index): """Safely switch to another ADALM1000 device""" - if not self.session_active or index < 0 or index >= len(self.session.devices): + if not self.session_active or index < 0 or index >= len(self.device_list): return try: @@ -1043,7 +1146,7 @@ class BatteryTester(QMainWindow): self.measurement_thread.wait(500) # Switch to new device - self.dev = self.session.devices[index] + self.dev = self.device_list[index] # Reconfigure channels self.dev.channels['A'].mode = pysmu.Mode.HI_Z @@ -1052,8 +1155,11 @@ class BatteryTester(QMainWindow): self.dev.channels['B'].constant(0) # Restart session for new device - device_index = self.session.devices.index(self.dev) - self.session.start(device_index) + try: + self.session.stop() + except Exception: + pass + self.session.start(index) # Update UI self.device_combo.setCurrentIndex(index) @@ -2198,7 +2304,7 @@ class BatteryTester(QMainWindow): try: # Reinitialize session - self.session = pysmu.Session(ignore_dataflow=True, queue_size=10000) + self.session = PatchedSession(ignore_dataflow=True, queue_size=10000) if not self.session.devices: raise DeviceDisconnectedError("No devices available") @@ -2235,8 +2341,8 @@ class BatteryTester(QMainWindow): # Restart measurement self.measurement_thread = MeasurementThread(self.dev, self.interval) - self.measurement_thread.update_signal.connect(self.update_measurements) - self.measurement_thread.error_signal.connect(self.handle_device_error) + self.measurement_thread.update_signal.connect(lambda v, c, t, s: self.update_measurements(v, c, t) if s == self.current_device_serial else None) + self.measurement_thread.error_signal.connect(lambda e, s: self.handle_device_error(e) if s == self.current_device_serial else None) self.measurement_thread.start() except Exception as e: