Add RFG UDP source to rph_radar
This commit is contained in:
@@ -4,6 +4,7 @@ import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import pty
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
@@ -16,14 +17,15 @@ from unittest import mock
|
||||
import numpy as np
|
||||
|
||||
from python_app.hardware_full.rph_radar.service import RphRadarService
|
||||
from python_app.hardware_full.rph_radar.tty_reader import RphRadarTtyReader
|
||||
from python_app.hardware_full.rph_radar import stream_reader
|
||||
from python_app.hardware_full.rph_radar.stream_reader import RphRadarStreamReader
|
||||
from python_app.hardware_full.rph_radar.protocol import RphRadarStreamParser
|
||||
from python_app.hardware_full.librevna_driver.models import SweepResult
|
||||
from python_app.models.dataset_model import ComboKey
|
||||
from python_app.models.run_config_schema import RunConfigModel
|
||||
from python_app.orchestration.process_supervisor import ProcessSupervisor
|
||||
from python_app.scripts import rph_radar_raw_producer as producer
|
||||
from python_app.tests.test_rph_radar_protocol import packet
|
||||
from python_app.tests.test_rph_radar_protocol import packet, rfg_datagram
|
||||
|
||||
|
||||
def config():
|
||||
@@ -35,11 +37,61 @@ def config():
|
||||
})
|
||||
|
||||
|
||||
class RphRadarTtyReaderTest(unittest.TestCase):
|
||||
class RfgStreamServiceTest(unittest.TestCase):
|
||||
def test_udp_stream_delivers_complete_sweeps_of_the_laser_task_length(self):
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as probe:
|
||||
probe.bind(("127.0.0.1", 0))
|
||||
port = probe.getsockname()[1]
|
||||
rfg = RunConfigModel.from_dict({
|
||||
"radar": {"model": "rph_radar", "driver_mode": "native",
|
||||
"rph_radar": {"source": "rfg_udp", "udp_bind": f"127.0.0.1:{port}"},
|
||||
"laser_control": {"mode": "variation", "variation": {
|
||||
"min_value": 30.0, "max_value": 30.15, "step": 0.05, "time_step": 50}}},
|
||||
"switches": {"port1": {"positions": 1}, "port2": {"positions": 1}},
|
||||
"run": {"continuous": False, "combos": [{"input": 0, "output": 0}]},
|
||||
})
|
||||
service = RphRadarService(rfg)
|
||||
service.open()
|
||||
self.addCleanup(service.close)
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as board:
|
||||
for datagram in (rfg_datagram(7, 2, 3), rfg_datagram(8, 0, 1, 2, 3), rfg_datagram(9, 0)):
|
||||
board.sendto(datagram, ("127.0.0.1", port))
|
||||
raw = service.read_raw_sweep()
|
||||
self.assertEqual(raw.steps.tolist(), [0, 1, 2, 3]) # ceil((9879 - 9830) / 16) DAC codes
|
||||
self.assertFalse(raw.dirty)
|
||||
self.assertEqual(raw.capture_end_ns - raw.capture_start_ns, 4 * 50_000)
|
||||
|
||||
|
||||
class RfgClockJumpTest(unittest.TestCase):
|
||||
def test_a_realtime_step_drops_queued_datagrams_and_the_sweep_in_progress(self):
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as probe:
|
||||
probe.bind(("127.0.0.1", 0))
|
||||
port = probe.getsockname()[1]
|
||||
assembler = mock.Mock(feed=mock.Mock(return_value=[]))
|
||||
reader = RphRadarStreamReader(f"127.0.0.1:{port}", assembler)
|
||||
real_offset, step = stream_reader._clock_offset_ns, [0]
|
||||
with mock.patch.object(stream_reader, "_clock_offset_ns", lambda: real_offset() + step[0]):
|
||||
reader.open()
|
||||
self.addCleanup(reader.close)
|
||||
step[0] = 2_000_000 # REALTIME stepped 2 ms after bind (stamps stay real, so forward)
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as board:
|
||||
board.sendto(rfg_datagram(1, 0), ("127.0.0.1", port))
|
||||
deadline = time.monotonic() + 1
|
||||
while not assembler.reset.called and time.monotonic() < deadline:
|
||||
time.sleep(.005)
|
||||
assembler.feed.assert_not_called()
|
||||
board.sendto(rfg_datagram(1, 1), ("127.0.0.1", port))
|
||||
while not assembler.feed.called and time.monotonic() < deadline:
|
||||
time.sleep(.005)
|
||||
assembler.reset.assert_called_once()
|
||||
assembler.feed.assert_called_once()
|
||||
|
||||
|
||||
class RphRadarStreamReaderTest(unittest.TestCase):
|
||||
def test_pty_delivers_latest_complete_clean_sweeps_by_pair(self):
|
||||
master, slave = pty.openpty()
|
||||
tty.setraw(slave)
|
||||
reader = RphRadarTtyReader(os.ttyname(slave))
|
||||
reader = RphRadarStreamReader(os.ttyname(slave))
|
||||
reader.open()
|
||||
try:
|
||||
os.write(master, packet(source_id=1, combo=(0, 0))
|
||||
@@ -216,7 +268,7 @@ class RphRadarConfigTest(unittest.TestCase):
|
||||
with mock.patch("python_app.hardware_full.rph_radar.service._prepare_tty_path_for_collector") as unlink, \
|
||||
mock.patch.object(RphRadarService, "_start_process") as start, \
|
||||
mock.patch.object(RphRadarService, "_wait_for_tty"), \
|
||||
mock.patch("python_app.hardware_full.rph_radar.service.RphRadarTtyReader"):
|
||||
mock.patch("python_app.hardware_full.rph_radar.service.RphRadarStreamReader"):
|
||||
with self.assertRaisesRegex(RuntimeError, "did not stop"):
|
||||
service.open()
|
||||
unlink.assert_not_called()
|
||||
|
||||
Reference in New Issue
Block a user