From e219f6ec025e5f18cd939f5ce6720ea94b769770 Mon Sep 17 00:00:00 2001 From: awe Date: Mon, 27 Jul 2026 21:41:14 +0300 Subject: [PATCH] Add laser temperature monitoring for current-variation runs Independent monitor + checker for CHANGE_CURRENT_LD1 variation, where the board sweeps LD1 current autonomously while both laser temperatures must stay on their static setpoints. Nothing previously verified that the setpoints were actually reached, so a stale temperature silently corrupted measurements. New package python_app/hardware_full/laser_control/monitoring/: - session.py: LaserVariationSession snapshot (targets + tolerance frozen at start) - readings_channel.py: JSONL append/tail channel for per-sweep readings - monitor.py: LaserTemperatureMonitor polls the board once per sweep, publishes - checker.py: LaserTemperatureChecker validates temp1/temp2 vs targets (0.03 C), warns to console per laser with anti-spam state CLI entry points scripts/laser_temp_monitor.py and scripts/laser_temp_checker.py run as independent processes communicating via IPC files. Also: add temp_tolerance_c to LaserVariationModeModel (schema + codec round-trip) and write the session snapshot from apply_kamil_adc_laser_control's variation path so the checker works with pipeline-started runs too. Tests in tests/test_laser_temp_monitoring.py (17 cases); existing laser-control protocol and config-codec suites remain green. Co-Authored-By: Claude Opus 4.8 (1M context) --- python_app/scripts/laser_temp_monitor.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/python_app/scripts/laser_temp_monitor.py b/python_app/scripts/laser_temp_monitor.py index b8a21e0..86a8d67 100644 --- a/python_app/scripts/laser_temp_monitor.py +++ b/python_app/scripts/laser_temp_monitor.py @@ -26,6 +26,7 @@ from python_app.hardware_full.laser_control.controller import ( DEVICE_MAIN_MESSAGE_ID, LaserController, ) +from python_app.hardware_full.laser_control.exceptions import PortBusyError from python_app.hardware_full.laser_control.models import VariationType from python_app.hardware_full.laser_control.monitoring import ( DEFAULT_READINGS_PATH, @@ -114,7 +115,13 @@ def main() -> int: pi_coeff2_p=laser.pi_coeff2_p, pi_coeff2_i=laser.pi_coeff2_i, ) - controller.connect() + try: + controller.connect() + except PortBusyError as exc: + # Expected, benign conflict: the manual-control UI (or another monitor) + # already owns the port. Exit cleanly with guidance, not a traceback. + logger.error("%s", exc) + return 2 try: if args.start: _start_variation(controller, variation)