Files
DCU_DesktopController/scripts/ecat_sweep_common.py
T

55 lines
2.2 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""ECAT native 主站的采样公共件:HTTP 调用 + 计数器差分。
固件 1.6.15 覆盖窗口布局下,各计数器的口径并不一致,混用会静默算错:
* bridge.rx_count / head.global_seq —— u32,**回绕**
* bridge.drop —— u16,**回绕**;段 1/段 3 单格"未取先覆"数,恒等于 λ − 实测Hz
* rx_batch.lost(主站按 seq 空洞算的单拍丢帧) / pending(从站窗口 OVF) ——
**每拍回填清零的单拍值**(ecat_native.c:461),不是累计计数:拿它做差得速率恒为 0,
拿轮询见过的最大值当总丢帧也只是下界
* app/load.rx_torn / pdo_reentry —— u16,**饱和**(到 65535 就停,不是回绕)
饱和量按回绕算会把"已封顶"误报成"发生了 6 万多次",故二者分开处理。
"""
import json
import urllib.request
SATURATE = 65535 # u16 饱和计数的顶
def post(url, path, body=None, timeout=6.0):
req = urllib.request.Request(
url + path, data=json.dumps(body or {}).encode("utf-8"),
headers={"Content-Type": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=timeout) as r:
return json.loads(r.read().decode("utf-8"))
def delta_wrap(a, b, bits=16):
"""回绕计数器的增量。真值下降(重启清零)会表现为一个巨大的正数,
调用方须用 sanity 上界剔除 —— 这里只负责把模数算对。"""
m = 1 << bits
return (b - a) % m
def delta_saturate(a, b):
"""饱和计数的增量。返回 (增量, 是否已封顶)。
封顶后增量恒为 0 —— 读数 0 既可能是"真没发生"也可能是"早发生了但计不动",
报告里必须写成下界而不是精确值。
"""
if b >= SATURATE:
return 0, True
if b < a:
return 0, False # 计数器被回填清零:该窗口作废,不臆造增量
return b - a, False
def percentile(values, q):
"""小样本分位数(最近邻)。不引 numpy,采样窗口只有百来个点。"""
if not values:
return None
s = sorted(values)
i = min(len(s) - 1, max(0, int(round(q * (len(s) - 1)))))
return s[i]