diff --git a/device_worker.py b/device_worker.py index ff7180e..d1368df 100644 --- a/device_worker.py +++ b/device_worker.py @@ -1,4 +1,7 @@ -import threading, queue, time, csv, os, statistics +import os, sys, time, csv, statistics, threading, queue + +scriptDir = os.path.dirname(os.path.realpath(__file__)) +DEFAULT_OUTDIR = os.path.join(scriptDir, "logs") class DeviceWorker: """ @@ -8,10 +11,11 @@ class DeviceWorker: - 1 Hz Logging (eine CSV-Zeile pro Sekunde) Wichtig: kontrolliert NICHT die Session! """ - def __init__(self, dev, outdir="./logs", filter_window_size=10, interval=0.1): + def __init__(self, dev, outdir=DEFAULT_OUTDIR, filter_window_size=10, interval=0.1): self.dev = dev self.serial = getattr(dev, "serial", "UNKNOWN") self.outdir = outdir + self._log_path = None self.filter_window_size = filter_window_size self.interval = interval @@ -25,30 +29,27 @@ class DeviceWorker: # ---- API ---- def start(self): + print(f"[{self.serial}] Worker.start()") if not self._reader_t.is_alive(): self._reader_t.start() if not self._writer_t.is_alive(): self._writer_t.start() self._cmdq.put(("start", None)) def stop(self): + print(f"[{self.serial}] Worker.stop()") self._cmdq.put(("stop", None)) - def shutdown(self): - self.stop() - self._stop_evt.set() - - def set_mode(self, ch, mode): - key = {0: "A", 1: "B"}.get(ch, str(ch).upper()) - self.dev.channels[key].mode = mode - - # ---- Threads ---- def _reader_loop(self): + print(f"[{self.serial}] Reader gestartet (interval={self.interval}, n={self.filter_window_size})") last_log = 0.0 while not self._stop_evt.is_set(): - # Kommandos try: cmd, _ = self._cmdq.get_nowait() - if cmd == "start": self._running = True - elif cmd == "stop": self._running = False + if cmd == "start": + self._running = True + print(f"[{self.serial}] RUNNING") + elif cmd == "stop": + self._running = False + print(f"[{self.serial}] STOPPED") except queue.Empty: pass @@ -57,9 +58,12 @@ class DeviceWorker: continue try: - # wie im Single-Logger: n Samples holen, mitteln - # WICHTIG: kleiner Timeout, damit der Thread nie "fest" hängt - samples = self.dev.read(self.filter_window_size, 50) # timeout ~50 ms + # WÄHLE HIER DIE SIGNATUR, DIE DEIN SINGLE-LOGGER NUTZT: + # Beispiel A (deine Datei ließ 'read(n, 500, True)' vermuten): + samples = self.dev.read(self.filter_window_size, 500, True) + # Beispiel B (andere pysmu-Versionen): + # samples = self.dev.read(self.filter_window_size, -1) + if not samples: time.sleep(self.interval) continue @@ -68,34 +72,38 @@ class DeviceWorker: vB = statistics.mean(row[2] for row in samples) now = time.time() - if now - last_log >= 1.0: # 1 Hz ins File - try: - self._writer_q.put((now, vA, vB), timeout=0.2) - last_log = now - except queue.Full: - pass + if now - last_log >= 1.0: + self._writer_q.put((now, vA, vB)) + last_log = now + except Exception as e: print(f"[{self.serial}] Read-Fehler: {e}") - time.sleep(0.02) + time.sleep(0.05) - # Loop-Takt exakt wie beim Single-Logger time.sleep(max(0.05, self.interval)) def _writer_loop(self): - os.makedirs(self.outdir, exist_ok=True) - fn = os.path.join(self.outdir, f"{time.strftime('%Y%m%d_%H%M%S')}_{self.serial}.csv") try: - with open(fn, "w", newline="") as f: + os.makedirs(self.outdir, exist_ok=True) + except Exception as e: + print(f"[{self.serial}] os.makedirs-Fehler für '{self.outdir}': {e}") + return + + self._log_path = os.path.join(self.outdir, f"{time.strftime('%Y%m%d_%H%M%S')}_{self.serial}.csv") + print(f"[{self.serial}] Writer startet → {self._log_path}") + + try: + with open(self._log_path, "w", newline="") as f: w = csv.writer(f) - w.writerow(["timestamp", "A", "B"]) + w.writerow(["timestamp", "A", "B"]) # Datei wird JETZT angelegt while not (self._stop_evt.is_set() and self._writer_q.empty()): try: ts, vA, vB = self._writer_q.get(timeout=0.5) except queue.Empty: continue w.writerow([ts, vA, vB]) - f.flush() # bei 1 Hz ok + f.flush() except Exception as e: - print(f"[{self.serial}] Writer-Fehler: {e}") + print(f"[{self.serial}] Writer-Fehler ({self._log_path}): {e}") finally: - print(f"[{self.serial}] Datei geschlossen: {fn}") \ No newline at end of file + print(f"[{self.serial}] Writer beendet: {self._log_path}") \ No newline at end of file diff --git a/gui_main.py b/gui_main.py index e91ef11..a0bb579 100644 --- a/gui_main.py +++ b/gui_main.py @@ -1,7 +1,10 @@ -import sys +import sys, os from PyQt5.QtWidgets import QApplication, QWidget, QListWidget, QListWidgetItem, QVBoxLayout, QPushButton, QLabel, QHBoxLayout from multi_logger import MultiLogger +scriptDir = os.path.dirname(os.path.realpath(__file__)) +DEFAULT_OUTDIR = os.path.join(scriptDir, "logs") + class ListItemWidget(QWidget): def __init__(self, label, worker): super().__init__() @@ -48,11 +51,9 @@ class MainWindow(QWidget): if __name__ == "__main__": # 1) Logger + Geräte - ml = MultiLogger(outdir="./logs", filter_window_size=10, interval=0.1) + ml = MultiLogger(outdir=DEFAULT_OUTDIR, filter_window_size=10, interval=0.1) print("Gefundene Geräte:", [w.serial for w in ml.workers]) ml.set_default_modes() - - # 2) Session EINMAL im Hauptthread starten (wie beim Single-Logger!) ml.start_session() # 3) GUI