#!/usr/bin/env python3 """0.25ms 下 A/B:静默 vs 模拟 spi_test 前端轮询。""" import json, time, urllib.request, os ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) LAB = os.path.join(ROOT, "lab", "skip_meter") def post(p, b=None, timeout=5): d = json.dumps(b or {}).encode() r = urllib.request.Request("http://127.0.0.1:8090"+p, data=d, headers={"Content-Type":"application/json"}) with urllib.request.urlopen(r, timeout=timeout) as resp: return json.loads(resp.read().decode()) def snap(): st = post("/api/motor/state") dbg = post("/api/motor/dbg") return { "cycles": st.get("cycles") or 0, "skip_total": dbg.get("skip_total") or 0, "gseq": (st.get("head") or {}).get("global_seq") or 0, "period": st.get("period_ms"), "wkc": st.get("wkc"), "pcore": st.get("pcore_mask"), "cyc_us": st.get("cyc_us"), } def rate(a, b, dt): dc = b["cycles"] - a["cycles"] ds = (b["skip_total"] - a["skip_total"]) # may wrap? long long, no return { "dt": round(dt, 3), "pdo_hz": round(dc / dt, 1) if dt else None, "late_per_s": round(ds / dt, 2) if dt else None, "skip_frac": round(100.0 * ds / dc, 2) if dc else None, "gseq_per_s": round(((b["gseq"] - a["gseq"]) & 0xFFFFFFFF) / dt, 1) if dt else None, "dcyc": dc, "dskip": ds, } def arm_period(ms): try: post("/api/motor/stop") except Exception: pass time.sleep(0.15) post("/api/motor/period", {"period_ms": ms}) time.sleep(0.15) post("/api/motor/start") time.sleep(0.5) print("ensure 0.25ms") arm_period(0.25) time.sleep(3) # --- A: fully quiet --- a0 = snap() t0 = time.time() # no HTTP time.sleep(10) a1 = snap() A = rate(a0, a1, time.time() - t0) print("QUIET", json.dumps(A, ensure_ascii=False)) print(" cyc_us", json.dumps(a1.get("cyc_us"), ensure_ascii=False)) # --- B: hammer like spi_test (state+load+dbg+rxraw) --- time.sleep(1) b0 = snap() t0 = time.time() n = 0 while time.time() - t0 < 10: try: post("/api/motor/state") post("/api/app/load") post("/api/motor/dbg") post("/api/motor/rxraw") n += 1 except Exception as e: print("hammer err", e) break time.sleep(0.05) # ~20Hz full set, similar to busy panel b1 = snap() B = rate(b0, b1, time.time() - t0) print("HAMMER", json.dumps(B, ensure_ascii=False), "polls", n) print(" cyc_us", json.dumps(b1.get("cyc_us"), ensure_ascii=False)) # --- C: only motor/state at max (no dbg/rxraw) --- time.sleep(1) c0 = snap() t0 = time.time() n = 0 while time.time() - t0 < 10: try: post("/api/motor/state") n += 1 except Exception: break time.sleep(0.05) c1 = snap() C = rate(c0, c1, time.time() - t0) print("STATE_ONLY", json.dumps(C, ensure_ascii=False), "polls", n) out = {"quiet": A, "hammer": B, "state_only": C, "quiet_cyc": a1.get("cyc_us"), "hammer_cyc": b1.get("cyc_us")} path = os.path.join(LAB, f"summary_fe_ab_{int(time.time())}.json") json.dump(out, open(path, "w", encoding="utf-8"), ensure_ascii=False, indent=2) print("WROTE", path)