#!/usr/bin/env python3 """Measure real scan time against C3 (192.168.0.240) using EXACT gateway batching logic.""" import json import time import sys from pathlib import Path from pymodbus.client import ModbusTcpClient REG_MAP = Path(__file__).parent.parent / "docs" / "register-map-c3.json" HOST = "192.168.0.240" PORT = 502 RUNS = 5 def load_regs(): with open(REG_MAP) as f: return json.load(f)["registers"] def build_batches(regs): """ EXACT gateway logic (gateway.cpp:123-173): 1. Sort registers by address 2. For each batch: start_addr = first register's addr 3. Collect all registers where: addr + count - batch_start <= 120 4. Read count = last.addr + last.count - batch_start """ sorted_regs = sorted(regs, key=lambda r: r["addr"]) batches = [] MAX_BATCH = 120 i = 0 while i < len(sorted_regs): batch_start = sorted_regs[i]["addr"] j = i while j < len(sorted_regs): e = sorted_regs[j] if e["addr"] + e["count"] - batch_start > MAX_BATCH: break j += 1 # j-1 is the last register in this batch last = sorted_regs[j - 1] read_count = last["addr"] + last["count"] - batch_start batches.append((batch_start, read_count)) i = j return batches def main(): regs = load_regs() batches = build_batches(regs) total_regs = len(regs) total_words = sum(r["count"] for r in regs) print(f"Registers: {total_regs}, Total words: {total_words}, Batches: {len(batches)}") print(f"Target: {HOST}:{PORT}") print() client = ModbusTcpClient(HOST, port=PORT, timeout=5) if not client.connect(): print("ERROR: connection failed"); sys.exit(1) times = [] for run in range(1, RUNS + 1): t0 = time.perf_counter() errors = 0 for i, (addr, count) in enumerate(batches): resp = client.read_holding_registers(addr, count=count) if resp.isError(): errors += 1 elapsed = (time.perf_counter() - t0) * 1000 times.append(elapsed) print(f"run{run}: {elapsed:.1f} ms (batches {len(batches)}, errors {errors})") client.close() times.sort() print(f"\n---") print(f"Min: {times[0]:.1f} ms") print(f"Max: {times[-1]:.1f} ms") print(f"Avg: {sum(times)/len(times):.1f} ms") print(f"Median: {times[len(times)//2]:.1f} ms") if __name__ == "__main__": main()