# Analog Gauge Server 本目录把 [ethz-asl/analog_gauge_reader](https://github.com/ethz-asl/analog_gauge_reader) 作为被动调用模型接入统一 URL `POST /v1/inference`: - category:`gauge.analog` - model ID:`ethz-analog-gauge-reader@1` - 输入:一张 JPEG 或 PNG - 输出:`scalar` 读数与可选单位 - artifact:`original`、`annotated`、`diagnostics` 客户端只选择 category;Python 版本、项目路径、三个模型路径和超时全部由 [configs/server_gauge.yaml](../../configs/server_gauge.yaml) 的服务端配置控制。 服务端默认限制输入图像不超过 25,000,000 像素。worker 直接从 JPEG/PNG 头读取宽高, 在 Pillow/OpenCV 解码或模型推理之前拒绝超限图像;部署时可通过 `max_pixels` 在 1 到 250,000,000 之间调整。该限制与 HTTP 请求字节限制分别控制解压后尺寸和传输体积。 ## 一次性准备 1. 确认上游项目和 Git LFS 模型文件已经完整: ```bash git -C /home/xtkuang/Projects/cmvr/changan_robot/analog_gauge_reader lfs pull ``` 2. 创建隔离的 Python 3.8 worker 环境: ```bash bash server/gauge/worker/bootstrap.sh ``` 3. 若仓库位置不同,修改配置中的 `python_executable` 和 `project_root`。三个模型路径可用 相对于 `project_root` 的路径。 ## 校验与启动 根项目 HTTP 服务仍运行在 Python 3.10 环境;不要把 MMOCR/MMCV 安装到根 `.venv`: ```bash uv sync --locked --extra server --group dev uv run --no-sync cmvr-edge-ai validate \ --config configs/server_gauge.yaml uv run --no-sync cmvr-edge-ai serve \ --config configs/server_gauge.yaml \ --log-level INFO \ --log-format text ``` 默认队列容量为 1,同一个 worker 串行处理请求,不让上游模型的可变状态并发执行。 请求超时为 300 秒,HTTP 超时为 360 秒,给首次加载 DINO/MMOCR 权重留出空间。 若服务监听非 loopback 地址,必须配置 Bearer token,并默认使用 TLS;只有受信隔离网络 可显式设置 `allow_insecure_remote: true`。远程请求需要携带 `Authorization: Bearer `,健康探针不需要认证。 没有检测到仪表、刻度数字或指针时返回 `no_result`;模型 checkpoint、依赖或部署故障 返回 `failed`,不会伪装成“没有识别结果”。 ## 请求示例 下面的脚本只把图像和稳定业务 category 发给统一入口: ```bash python - <<'PY' import base64 import json from pathlib import Path from urllib.request import Request, urlopen path = Path("/path/to/gauge.jpg") payload = { "schema_version": "cmvr.inference-request/v1", "category": "gauge.analog", "inputs": [{ "kind": "image", "name": "image", "media_type": "image/jpeg", "encoding": "base64", "data": base64.b64encode(path.read_bytes()).decode("ascii"), }], "requested_artifact_roles": ["annotated", "diagnostics"], } request = Request( "http://127.0.0.1:8081/v1/inference", data=json.dumps(payload).encode("utf-8"), headers={"Content-Type": "application/json"}, ) print(urlopen(request, timeout=360).read().decode("utf-8")) PY ``` 真实模型首次请求可能较慢;轻量协议测试使用 fake upstream project,不加载约 1.2 GB 的 模型权重。