Track completed Single acquisitions and persist recent addresses

This commit is contained in:
2026-10-07 12:32:29 +03:00
parent 6047ceac89
commit c011c2957b
4 changed files with 103 additions and 1 deletions

View File

@@ -0,0 +1,56 @@
"""Editable recent-address selector with portable, per-interface JSON storage."""
import json
from pathlib import Path
try:
from PySide6.QtCore import QSignalBlocker
from PySide6.QtWidgets import QComboBox, QSizePolicy
except ImportError:
from PySide2.QtCore import QSignalBlocker
from PySide2.QtWidgets import QComboBox, QSizePolicy
class AddressHistoryBox(QComboBox):
def __init__(self, filename, parent=None):
super().__init__(parent)
self.filename = Path(filename)
self.interface = 'Ethernet'
self.history = {}
self.setEditable(True)
self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.setInsertPolicy(QComboBox.InsertPolicy.NoInsert)
try:
saved = json.loads(self.filename.read_text(encoding='utf8'))
if isinstance(saved, dict):
self.history = {key: [x for x in items if isinstance(x, str) and x.strip()][:20]
for key, items in saved.items() if isinstance(items, list)}
except (OSError, ValueError):
pass
self.set_interface(self.interface)
def text(self):
return self.currentText()
def setText(self, text):
self.setEditText(text)
def setPlaceholderText(self, text):
self.lineEdit().setPlaceholderText(text)
def set_interface(self, interface):
self.interface = interface
with QSignalBlocker(self):
self.clear()
self.addItems(self.history.get(interface, []))
if not self.count():
self.setEditText('')
def remember(self):
address = self.currentText().strip()
if not address:
return
previous = self.history.get(self.interface, [])
self.history[self.interface] = [address] + [x for x in previous if x.casefold()!=address.casefold()][:19]
self.filename.parent.mkdir(parents=True, exist_ok=True)
temporary = self.filename.with_suffix('.tmp')
temporary.write_text(json.dumps(self.history, ensure_ascii=False, indent=2), encoding='utf8')
temporary.replace(self.filename)
self.set_interface(self.interface)

View File

@@ -97,6 +97,19 @@ class DPO4034:
return True
raise ValueError("Некорректное состояние сбора: " + state)
def acquisition_status(self):
if self.instrument is None:
raise RuntimeError("Прибор не подключён")
fields = self.instrument.query("ACQUIRE:STATE?;:ACQUIRE:STOPAFTER?;:ACQUIRE:NUMACQ?").strip().split(";")
if len(fields) != 3:
raise ValueError("Некорректное состояние сбора")
state, mode, count = (value.strip().upper() for value in fields)
if state not in ("0", "1", "OFF", "ON", "STOP", "RUN"):
raise ValueError("Некорректное состояние сбора")
if mode not in ("RUNSTOP", "RUNST", "SEQUENCE", "SEQ"):
raise ValueError("Некорректный режим сбора")
return state in ("1", "ON", "RUN"), mode in ("SEQUENCE", "SEQ"), int(count)
def settings(self, channel="CH1"):
self._channel(channel)
if self.instrument is None:

View File

@@ -0,0 +1,24 @@
"""Read completed Single records once, without interfering with acquisition."""
class CaptureState:
def __init__(self):
self.armed = False
self.delivered = None
def arm(self):
self.armed = True
def ready(self, status):
running, single, count = status
if not single:
self.armed = False
self.delivered = None
return running
if running or count == 0:
self.armed = True
return False
return count > 0 and (self.armed or self.delivered != count)
def consumed(self, status):
if status[1]:
self.delivered = status[2]
self.armed = False

View File

@@ -3,6 +3,7 @@ from dataclasses import dataclass
from queue import Queue
from threading import Thread
import csv
from .tektronix_capture_state import CaptureState
from .tektronix import DPO4034, Waveform
from .plot_decimation import pixel_envelope
@@ -36,6 +37,7 @@ class ScopeSession:
def _run(self, factory):
client = factory()
state = CaptureState()
try:
while True:
action, args = self.commands.get()
@@ -44,11 +46,14 @@ class ScopeSession:
try:
if action == "capture" and len(args) in (4, 5):
automatic = len(args) == 5 and args[4]
if automatic and not client.is_running():
status = client.acquisition_status() if automatic else None
if automatic and not state.ready(status):
value = None
else:
value = client.capture(*args[:3])
value = CaptureFrame(value, prepare_preview(value, args[3]))
if automatic:
state.consumed(status)
elif action == "export":
filename, waves = args
with open(filename, "w", newline="", encoding="utf-8-sig") as stream:
@@ -62,6 +67,10 @@ class ScopeSession:
writer.writerow([stamp * 1000, *(w.values[index] for w in waves)])
value = filename
else:
if action == "connect":
state = CaptureState()
if action == "acquisition" and args[0] == "single":
state.arm()
value = getattr(client, action)(*args)
self.results.put((action, value, None))
except Exception as exc: