Skip to main content
Glama
andy-qingcai

PPK2 MCP Server

by andy-qingcai

PPK2 MCP Server

Nordic Semiconductor Power Profiler Kit II (PPK2) 的 Model Context Protocol (MCP) 服务器。 让 LLM 直接完成功耗剖析:控制硬件采集电流(500 nA–2000 mA @ 100 kSa/s + 8 路逻辑口)、 给 DUT 供电(源表 0.8–5 V),采集数据落盘 npz,再做离线分析——统计、功耗分段、 电池续航估算,回答"睡眠电流多少 / 活动占空比多少 / 一节 CR2032 能跑多久"。

  • 开发方式:DDD(四层 + 依赖倒置),见 docs/PLAN.md

  • 协议逆向与真机验证笔记:docs/NOTES.md(真机 18 项自检 0 FAIL)

  • 19 个 MCP 工具:连接/配置/采集落盘/离线分析

  • 采样数据只落盘(npz),工具返回摘要 + 包络 + 路径,绝不内联数组

  • 协议层自研(规避 GPLv2 的 ppk2-api),对照 Nordic 官方开源 app 逐条验证, 增加了官方 app 同款的模 64 计数器丢样检测(IRNAS 库没有)

快速开始

cd /Users/andylos/mcp_gen/PPK2
python3 -m venv .venv
.venv/bin/pip install -e . pytest
.venv/bin/python -m pytest tests/            # 56 个测试:mock 设备全栈 + MCP 协议级
.venv/bin/python scripts/probe_device.py     # 真机端到端自检(18 项)
PPK2_MOCK=1 .venv/bin/ppk2-mcp               # 无硬件演示(mock 设备)

PPK2 经 USB CDC 串口连接(免驱);插入后绿灯亮即可,无需其他配置。 macOS 上会出现两个 cu.usbmodem* 口,服务器自动探测 0x19 应答识别命令口。

配置(环境变量)

变量

默认

说明

PPK2_PORT

自动发现

指定串口(跳过探测)

PPK2_DATA_DIR

./data

采集 npz 保存目录

PPK2_CAPTURE_MAX_S

60

capture 工具时长上限(长采集用 start/stop)

PPK2_TIMEOUT

15

普通操作超时(秒)

PPK2_MOCK

1 = 内存模拟设备(无硬件演示/CI)

接入 MCP 客户端

ZCode(.zcode/settings.json)或 Claude Desktop:

{
  "mcpServers": {
    "ppk2": {
      "command": "/Users/andylos/mcp_gen/PPK2/.venv/bin/python",
      "args": ["-m", "ppk2_mcp.server"],
      "cwd": "/Users/andylos/mcp_gen/PPK2",
      "env": {
        "PPK2_DATA_DIR": "/Users/andylos/mcp_gen/PPK2/data"
      }
    }
  }
}

工具总览(19 个)

分组

工具

系统/连接 (5)

list_devices connect disconnect get_status raw_command(逃生舱;RESET 需 confirm)

配置 (5)

set_mode(AMPERE/SOURCE) set_source_voltage(800-5000mV) set_dut_power set_resistor_range(锁定/恢复自动) set_spike_filtering

采集 (4)

capture(定长→落盘→摘要+包络) start_capture/stop_capture(长采集) get_capture_status

离线分析 (5)

analyze_capture(统计+子窗+包络) detect_activity_segments(功耗分段/占空比) estimate_battery_life(续航) read_logic_channels(逻辑口 stats/edges) list_captures

典型工作流

list_devices -> connect -> set_mode(AMPERE)      # 或 SOURCE + set_source_voltage(3300)
capture(5.0)                                      # 采集 5s,返回摘要+1000 点包络+路径
analyze_capture("cap_x", start_s=1, end_s=2)     # 子窗统计(µC 电量 / µJ 能量)
detect_activity_segments("cap_x", threshold_ua=50, min_duration_s=0.01)
estimate_battery_life(capture_id="cap_x", capacities_mah=[120, 240])
read_logic_channels("cap_x", channel=0, mode="edges")   # 逻辑口与电流同步采样

DUT 供电流程:SOURCE 模式下 set_source_voltage(3300)set_dut_power(true)capture(...)set_dut_power(false)。图表语义与官方 app 一致:SPM 模式 显示的仍是负载电流,电压即设定值。

架构(DDD)

interfaces(server.py 组合根,19 工具)
   └── application(PPK2Service 用例编排,不变式校验)
          └── domain(值对象/换算器+尖峰滤波状态机/分析服务纯函数/Port 接口)
                 └── infrastructure 实现 Port:串口协议+设备网关 / npz 仓库 / mock 设备

依赖方向自外向内;domain 零 IO 零框架。测试金字塔:领域纯函数 → 协议编解码 (真机元数据 fixture)→ mock 设备全栈用例 → FastMCP 协议级内存会话。

已知边界

  • 设备未校准(Calibrated: 0)时按官方缺省系数换算,工具响应带告警; 校准请在官方 nRF Connect Power Profiler 中完成

  • 模式切换/DUT 上电后设备有预热延迟,首采样本数可能偏低——响应带告警,建议重采

  • raw_command 发 0x20(RESET)会触发 USB 重枚举,服务器自动清理会话, 需重新 connect

  • 长采集(start/stop)无时长上限,但 npz 体积 ≈500 KB/s,注意磁盘