"""Unit tests for H32 Medulla raw dlog → station frame export helpers.""" from __future__ import annotations import struct import sys from pathlib import Path import numpy as np ROOT = Path(__file__).resolve().parents[1] TOOLS = ROOT / "tools" sys.path.insert(0, str(TOOLS)) sys.path.insert(0, str(TOOLS / "rscap_v2")) from export_h32_rscap_station import export_station_h32_dlog, is_h32_raw_dlog_station # noqa: E402 from h32_dlog.difop import CHANNELS, HORIZONTAL_START, VERTICAL_START, parse_difop_angles # noqa: E402 from h32_dlog.dobject import discover_records, iter_payloads, resolve_dlog_root # noqa: E402 from h32_dlog.load_session import load_h32_dlog_lidar # noqa: E402 from h32_dlog.payload_v1 import ( # noqa: E402 MsopPacketItem, build_difop_payload, build_msop_batch_payload, parse_difop_payload, parse_msop_batch_payload, ) from h32_msop import PACKET_LENGTH, iter_h32_frames_polar_from_packets # noqa: E402 def _make_msop_packet(*, seconds: int = 100, microseconds: int = 5000, az_deg: float = 10.0) -> bytes: packet = bytearray(PACKET_LENGTH) packet[17] = 1 packet[20:26] = int(seconds).to_bytes(6, "big") packet[26:30] = int(microseconds).to_bytes(4, "big") az_raw = int(round(az_deg * 100)) for block in range(12): offset = 42 + block * 100 packet[offset] = 255 packet[offset + 1] = 238 packet[offset + 2] = (az_raw >> 8) & 0xFF packet[offset + 3] = az_raw & 0xFF idx = offset + 4 for _ch in range(CHANNELS): packet[idx] = (1600 >> 8) & 0xFF packet[idx + 1] = 1600 & 0xFF packet[idx + 2] = 10 idx += 3 return bytes(packet) def _write_signed_angle(buf: bytearray, index: int, degrees: float) -> None: sign = 1 if degrees < 0 else 0 raw = int(round(abs(degrees) * 100)) buf[index] = sign buf[index + 1] = (raw >> 8) & 0xFF buf[index + 2] = raw & 0xFF def _make_difop_packet(*, vertical: list[float], horizontal: list[float] | None = None) -> bytes: packet = bytearray(1248) horiz = horizontal if horizontal is not None else [0.0] * CHANNELS for channel, angle in enumerate(vertical): _write_signed_angle(packet, VERTICAL_START + channel * 3, angle) for channel, angle in enumerate(horiz): _write_signed_angle(packet, HORIZONTAL_START + channel * 3, angle) return bytes(packet) def _write_dorec_record( path: Path, *, object_name: str, ticks: int, record_id: str, payload: bytes, ) -> int: path.parent.mkdir(parents=True, exist_ok=True) name_b = object_name.encode("ascii") id_b = record_id.encode("ascii") blob = ( bytes([len(name_b)]) + name_b + struct.pack("= 1 assert any((out / "frames").glob("*.npz"))