import threading, queue, time, csv, os, statistics class DeviceWorker: def __init__(self, sm, dev, outdir, filter_window_size=10, interval=0.1): self.sm = sm self.dev = dev self.serial = getattr(dev, "serial", "UNKNOWN") self.filter_window_size = filter_window_size self.interval = interval self.outdir = outdir self.cmdq = queue.Queue() self.stop_evt = threading.Event() self.running = False self.reader_t = threading.Thread(target=self.reader_loop, daemon=True) self.writer_t = threading.Thread(target=self.writer_loop, daemon=True) self.writer_q = queue.Queue(maxsize=50) # 1 Wert/Sek → reicht dicke 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): key = {0:"A",1:"B"}.get(ch, str(ch).upper()) self.dev.channels[key].mode = mode def reader_loop(self): last_log = 0.0 while not self.stop_evt.is_set(): # Start/Stop Kommandos try: cmd, _ = self.cmdq.get_nowait() if cmd == "start" and not self.running: self.sm.start() self.running = True elif cmd == "stop" and self.running: self.running = False self.sm.stop() except queue.Empty: pass if not self.running: time.sleep(0.05) continue try: # exakt wie dein Single-Loop: samples = self.dev.read(self.filter_window_size, -1) # ggf. read(n) if not samples: time.sleep(self.interval) continue vA = statistics.mean(row[0] for row in samples) vB = statistics.mean(row[2] for row in samples) now = time.time() if now - last_log >= 1.0: # 1 Hz logging try: self.writer_q.put((now, vA, vB), timeout=0.2) last_log = now except queue.Full: pass # selten, bei 1Hz praktisch nie except Exception as e: print(f"[{self.serial}] Read-Fehler: {e}") time.sleep(0.02) # Loop-Rate wie bei dir: 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: w = csv.writer(f) w.writerow(["timestamp","A","B"]) 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() # 1 Zeile/Sek → ok except Exception as e: print(f"[{self.serial}] Writer-Fehler: {e}") finally: print(f"[{self.serial}] Datei geschlossen: {fn}") def shutdown(self): self.stop() self.stop_evt.set()