import threading, queue, time, csv, os CHUNK = 2000 SAMPLE_RATE = 100_000.0 # 100 kS/s DT = 1.0 / SAMPLE_RATE OUTDIR = "logs" FLUSH_EVERY = 50 os.makedirs(OUTDIR, exist_ok=True) class DeviceController: def __init__(self, sess, dev): self.sess = sess # <— Session referenzieren self.dev = dev self.cmdq = queue.Queue() self.stop_evt = threading.Event() self.running = False self.writer_q = queue.Queue(maxsize=50) self.reader_t = threading.Thread(target=self.reader_loop, daemon=True) self.writer_t = threading.Thread(target=self.writer_loop, daemon=True) def start(self): 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): self.cmdq.put(("stop", None)) def set_mode(self, ch, mode): # BUGFIX: nicht rekursiv sich selbst aufrufen! self.dev.channels[ch].mode = mode def reader_loop(self): while not self.stop_evt.is_set(): try: cmd, arg = self.cmdq.get_nowait() if cmd == "start" and not self.running: # Continuous Session-Stream starten (für alle Devices) self.sess.start(0) # <— statt dev.run(0) self.running = True elif cmd == "stop" and self.running: self.sess.end() # <— Session sauber beenden # optional: Puffer leeren # self.sess.flush(-1, True) # falls verfügbar in deiner Version self.running = False elif cmd == "mode": ch, mode = arg self.dev.channels[ch].mode = mode except queue.Empty: pass if self.running: try: # Lies jeweils CHUNK Samples (blockierend bis voll) data = self.dev.read(CHUNK, -1) # -> [[VA, IA, VB, IB], ...] vsA = [row[0] for row in data] vsB = [row[2] for row in data] self.writer_q.put((time.time(), vsA, vsB)) except Exception: time.sleep(0.001) else: time.sleep(0.01) def writer_loop(self): os.makedirs(OUTDIR, exist_ok=True) ts0 = None fn = os.path.join(OUTDIR, f"{time.strftime('%Y%m%d_%H%M%S')}_{self.dev.serial}.csv") chunks_written = 0 sample_idx = 0 try: with open(fn, "w", newline="") as f: w = csv.writer(f) # Long-Format: eine Zeile pro Kanalwert w.writerow(["t_rel_s", "ch", "value"]) while not (self.stop_evt.is_set() and self.writer_q.empty()): try: ts, va, vb = self.writer_q.get(timeout=0.2) except Exception: continue if ts0 is None: ts0 = ts # Sicherstellen, dass A und B gleich lang sind if len(va) != len(vb): n = min(len(va), len(vb)) va, vb = va[:n], vb[:n] # Zeitindex aus Sample-Index ableiten (konstante Rate) for i, (a, b) in enumerate(zip(va, vb)): t_rel = (sample_idx + i) * DT w.writerow([t_rel, "A", a]) w.writerow([t_rel, "B", b]) sample_idx += len(va) chunks_written += 1 if chunks_written % FLUSH_EVERY == 0: f.flush() # optional: os.fsync(f.fileno()) except Exception as e: print(f"[{self.dev.serial}] Writer-Fehler: {e}") finally: print(f"[{self.dev.serial}] Datei geschlossen: {fn}")