microfix
This commit is contained in:
@@ -31,7 +31,9 @@ from contextlib import suppress
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import statistics
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
@@ -65,6 +67,60 @@ DO8_FREQ_REF_ARGS = [
|
||||
]
|
||||
COLLECTOR_PATH = "build/bin/kamil_adc_collector"
|
||||
|
||||
# Hardware the daemon / a prior collector may be holding, and how to free it.
|
||||
# Mirrors what start.sh does before an interactive launch (stop the daemon, kill
|
||||
# an orphaned collector) so this tool can grab the L-Card E-502 + lasers too.
|
||||
RADAR_SERVICE_NAME = "radar.service"
|
||||
COLLECTOR_PROCESS_PATTERN = "kamil_adc_collector"
|
||||
# The E-502 is not reacquirable the instant it is released; wait before opening.
|
||||
_DEVICE_SETTLE_SECONDS = 8.0
|
||||
|
||||
|
||||
def _release_radar_hardware(*, settle_seconds: float = _DEVICE_SETTLE_SECONDS) -> None:
|
||||
"""Free the L-Card E-502 + lasers before we open our own collector.
|
||||
|
||||
Mirrors ``start.sh`` on an interactive launch: stop the headless
|
||||
``radar.service`` daemon (if active) so it releases the hardware, then kill any
|
||||
orphaned ``kamil_adc_collector`` a prior (e.g. SSH-killed) run left holding the
|
||||
device. Both steps are best-effort and non-fatal — the collector's own
|
||||
open-retry covers the residual settle time — this just removes the usual reason
|
||||
it never frees up. Passwordless ``sudo systemctl stop radar.service`` is
|
||||
provisioned in ``/etc/sudoers.d/radar``.
|
||||
"""
|
||||
freed = False
|
||||
|
||||
systemctl = shutil.which("systemctl")
|
||||
if systemctl is not None:
|
||||
is_active = subprocess.run(
|
||||
[systemctl, "is-active", "--quiet", RADAR_SERVICE_NAME],
|
||||
check=False,
|
||||
).returncode == 0
|
||||
if is_active:
|
||||
logger.info("Stopping %s so it releases the radar hardware...", RADAR_SERVICE_NAME)
|
||||
stopped = subprocess.run(
|
||||
["sudo", systemctl, "stop", RADAR_SERVICE_NAME], check=False
|
||||
).returncode == 0
|
||||
if stopped:
|
||||
freed = True
|
||||
else:
|
||||
logger.warning(
|
||||
"Could not stop %s (need passwordless sudo?); continuing anyway",
|
||||
RADAR_SERVICE_NAME,
|
||||
)
|
||||
|
||||
pkill = shutil.which("pkill")
|
||||
if pkill is not None:
|
||||
# pkill returns 0 when it matched & signalled at least one process.
|
||||
if subprocess.run(
|
||||
[pkill, "-9", "-f", COLLECTOR_PROCESS_PATTERN], check=False
|
||||
).returncode == 0:
|
||||
logger.info("Killed orphaned %s process(es) holding the device", COLLECTOR_PROCESS_PATTERN)
|
||||
freed = True
|
||||
|
||||
if freed:
|
||||
logger.info("Waiting %.0fs for the L-Card E-502 to settle...", settle_seconds)
|
||||
time.sleep(settle_seconds)
|
||||
|
||||
|
||||
def _open_with_retry(service: KamilAdcService, *, attempts: int = 4, delay_s: float = 8.0) -> None:
|
||||
"""Open the collector, retrying the transient E-502 device-busy after a close.
|
||||
@@ -519,6 +575,11 @@ def main() -> int:
|
||||
parser.add_argument("--warmup", type=int, default=10, help="Sweeps to discard first (default 10)")
|
||||
parser.add_argument("--apply", action="store_true", help="Write the calibration back to --config")
|
||||
parser.add_argument("--no-laser", action="store_true", help="Skip laser setup (already running)")
|
||||
parser.add_argument(
|
||||
"--no-release",
|
||||
action="store_true",
|
||||
help="Do not stop radar.service / kill orphaned collectors before opening",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--diagnose",
|
||||
action="store_true",
|
||||
@@ -541,6 +602,11 @@ def main() -> int:
|
||||
config.radar.kamil_adc.executable_path = COLLECTOR_PATH
|
||||
config.radar.kamil_adc.args = list(DO8_FREQ_REF_ARGS)
|
||||
|
||||
# Free the device the headless daemon / an orphaned collector may be holding,
|
||||
# so opening our own collector does not fail with E-502 device-busy.
|
||||
if not args.no_release:
|
||||
_release_radar_hardware()
|
||||
|
||||
if not args.no_laser:
|
||||
logger.info("Applying laser control...")
|
||||
apply_kamil_adc_laser_control(config)
|
||||
|
||||
Reference in New Issue
Block a user