diff options
| author | Christian Kolset <christian.kolset@gmail.com> | 2026-09-21 00:16:15 -0600 |
|---|---|---|
| committer | Christian Kolset <christian.kolset@gmail.com> | 2026-09-21 00:16:15 -0600 |
| commit | 4ab2eea9af5338485303d421476fa874e5af6841 (patch) | |
| tree | 43aee9e91d25e854fd215a7c9ee7fdc003e1c854 /core/acquisition.py | |
| parent | a0473245f1f453bfc87ea1bc9bd479311e8a944b (diff) | |
Fix Buffer size setting never being applied; add Safety Switch control type
- Buffer size (samples) in Settings > Acquisition was captured into the
settings dict but never read anywhere — SignalBuffer always used the
hardcoded MAX_BUFFER=20_000 constant (which happens to match the
dialog's default, hence it looking like the value "reverts"). Add
AcquisitionEngine.set_buffer_size(), wired in on startup and on Settings
apply; existing buffers are rebuilt at the new size in place, keeping
their most recent samples.
- New "Safety Switch" control type: an On/Off Switch that's disabled
outright until acquisition is running, with a lock icon shown while
disabled. AcquisitionEngine gains a run_state_changed(bool) signal
(emitted from start()/stop()); ControlWidget gains a
_check_safety_lock() hook (no-op by default, called uniformly by
ControlPanel on every widget) that SafetySwitch overrides. engine is
now threaded through to every ControlWidget for this. Persists via
ControlSpec.control_type alone — no schema change needed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'core/acquisition.py')
| -rw-r--r-- | core/acquisition.py | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/core/acquisition.py b/core/acquisition.py index eeeb4c8..c900adf 100644 --- a/core/acquisition.py +++ b/core/acquisition.py @@ -77,6 +77,7 @@ class AcquisitionEngine(QObject): # switched lb/kgF/N/ozF on its own front panel log_started(filepath) log_stopped(filepath) + run_state_changed(running) # emitted from start()/stop() """ new_data = pyqtSignal(float, list) @@ -84,10 +85,14 @@ class AcquisitionEngine(QObject): channel_unit_changed = pyqtSignal(str, str, str) log_started = pyqtSignal(str) log_stopped = pyqtSignal(str) + run_state_changed = pyqtSignal(bool) # True on start(), False on stop() — + # e.g. ControlPanel's safety-interlock + # controls listen for this def __init__(self, poll_interval_ms: int = 100): super().__init__() self._interval = poll_interval_ms / 1000.0 + self._buffer_size: int = MAX_BUFFER # see set_buffer_size() self._devices: List[BaseDevice] = [] self._buffers: Dict[str, Dict[str, SignalBuffer]] = {} self._last_units: Dict[Tuple[str, str], str] = {} @@ -106,12 +111,27 @@ class AcquisitionEngine(QObject): def add_device(self, dev: BaseDevice): self._devices.append(dev) self._buffers[dev.info.device_id] = { - ch.signal_id: SignalBuffer() + ch.signal_id: SignalBuffer(maxlen=self._buffer_size) for ch in dev.info.signals } for ch in dev.info.signals: self._last_units[(dev.info.device_id, ch.signal_id)] = ch.unit + def set_buffer_size(self, n: int): + """Change how much history each Signal's buffer holds — settings_ + window.py's "Buffer size (samples)" field, applied live rather than + only on the next device add/reconfigure. Rebuilds every existing + buffer at the new size, keeping its most recent samples (a maxlen + deque naturally drops the oldest first as it's extended past + capacity, so growing loses nothing and shrinking keeps the tail).""" + self._buffer_size = n + for dev_bufs in self._buffers.values(): + for ch_id, buf in list(dev_bufs.items()): + new_buf = SignalBuffer(maxlen=n) + new_buf.times.extend(buf.times) + new_buf.values.extend(buf.values) + dev_bufs[ch_id] = new_buf + def on_device_reconfigured(self, device_id: str): """Reconcile buffers with a device's current channel list — reconfigure() can add/remove channels (e.g. Signals count changed), and buffers keyed @@ -125,7 +145,7 @@ class AcquisitionEngine(QObject): bufs.pop(stale_id, None) for ch in dev.info.signals: if ch.signal_id not in bufs: - bufs[ch.signal_id] = SignalBuffer() + bufs[ch.signal_id] = SignalBuffer(maxlen=self._buffer_size) self._last_units[(device_id, ch.signal_id)] = ch.unit for key in [k for k in self._last_units if k[0] == device_id and k[1] not in valid_ids]: self._last_units.pop(key, None) @@ -176,12 +196,14 @@ class AcquisitionEngine(QObject): self._running = True self._thread = threading.Thread(target=self._loop, daemon=True, name="DAQ-Acq") self._thread.start() + self.run_state_changed.emit(True) def stop(self): self._running = False if self._thread: self._thread.join(timeout=3.0) self.stop_logging() + self.run_state_changed.emit(False) # ── Logging ────────────────────────────────────────────────────────── |
