# fpv_link_stability **Repository Path**: Mikelucis/fpv_link_stability ## Basic Information - **Project Name**: fpv_link_stability - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-10 - **Last Updated**: 2026-08-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # FPV Link Stability GUI 独立 Qt6 Widgets 小工具:在 Windows / Android 上并行测量图传链路稳定性。 | 通道 | 作用 | | --- | --- | | **iperf3** | 吞吐、丢包、抖动(对齐 [`tools/fpv_link_iperf_test.ps1`](../fpv_link_iperf_test.ps1)) | | **UDP 序列探针** | 递增 `seq` + echo,独立统计丢包 / 乱序 / RTT(及 RTT/2 单向估算) | 本工具**不**并入主应用 `fgroundcontrol`,也不做图传画面 OCR / glass-to-glass。 手测步骤见 [`TEST.md`](TEST.md)。数据如何判读见 [`INTERPRETATION.md`](INTERPRETATION.md)。 ## 拓扑 ```text 天空端 Client(常 Windows) ──无线图传──► 地面端 Server(常 Android / RK) ``` UI 里 iperf 与探针的 Client/Server 角色可分别配置。默认端口: | 服务 | 端口 | | --- | ---: | | iperf3 | 5201 | | Seq probe | 17001 | ## 依赖 - Qt 6.10+:`Core`、`Widgets`、`Network`、`Concurrent` - CMake ≥ 3.21 - **内嵌** [esnet/iperf 3.19](https://github.com/esnet/iperf)(`third_party/iperf` + `libiperf_embed`,默认 `FPV_EMBED_IPERF=ON`) - 外部 **iperf3** 可执行文件(可选回退;UI Backend 可选 External) Windows MinGW / llvm-mingw 与 **Android arm64** 已验证可链接内嵌 libiperf(Windows 走 `wincompat` 实验层;Android 走 NDK/Bionic + `android_stubs`)。官方不支持原生 Windows,长稳/Stop 请优先短测或回退外部二进制。 ## Windows 构建 ```powershell # llvm-mingw Release(推荐,与 Qt Creator kit 一致) $env:QT_DIR = "C:\Qt\6.10.3\llvm-mingw_64" cmake --preset windows-llvm-mingw-release cmake --build build-windows-llvm-mingw-release ``` 首次链接会在 `build-windows-llvm-mingw-release/app/` 下执行 `windeployqt`(Widgets,无 QML)。手动重部署: ```powershell cmake --build build-windows-llvm-mingw-release --target fpv-deploy-qt ``` 运行:`build-windows-llvm-mingw-release/app/fpv_link_stability.exe` ### Windows 安装包(IFW) 参照 fgroundcontrol,使用 Qt Installer Framework 打离线安装包。详见 [`tools/ifw/README.md`](tools/ifw/README.md)。 ```powershell pwsh -File .\tools\ifw\build.ps1 -PayloadDir ".\build-windows-llvm-mingw-release\app" ``` 输出:`tools\ifw\out\FPVLinkStability--Setup.exe` 或启用 CMake 目标(`-DFPV_WIN_ENABLE_IFW_PACKAGING=ON`): ```powershell cmake --build build-windows-llvm-mingw-release --target fpv-package-ifw ``` ### 手动 CMake(无 preset) MSVC: ```powershell cmake -S . -B build -G Ninja ` -DCMAKE_PREFIX_PATH=C:/Qt/6.10.3/msvc2022_64 ` -DCMAKE_BUILD_TYPE=Release cmake --build build ``` MinGW: ```powershell cmake -S . -B build -G Ninja ` -DCMAKE_PREFIX_PATH=C:/Qt/6.10.3/mingw_64 ` -DCMAKE_BUILD_TYPE=Release ` -DFPV_EMBED_IPERF=ON cmake --build build ``` llvm-mingw: ```powershell cmake -S . -B build -G Ninja ` -DCMAKE_PREFIX_PATH=C:/Qt/6.10.3/llvm-mingw_64 ` -DCMAKE_BUILD_TYPE=Release cmake --build build ``` MSVC 与 MinGW **不要混用**(`CMAKE_PREFIX_PATH` 的 kit 须与编译器一致)。 iperf 路径示例(External 后端):`%USERPROFILE%\Desktop\iperf3\iperf3.exe` ## Android 构建 Windows 一键脚本(本机已验证 arm64 Release APK): ```powershell # 需要 JDK 17+(推荐 F:\JDK-21.0.2);勿用 JAVA_HOME=JDK 8 $env:FPV_JAVA_HOME = "F:\JDK-21.0.2" # 可选覆盖 .\tools\fpv_link_stability\build_android_apk_windows.ps1 -Reconfigure -BuildType Release ``` 默认环境: | 变量 | 本机默认 | | --- | --- | | `ANDROID_SDK_ROOT` | `C:\Qt\Android` | | `ANDROID_NDK_ROOT` | `C:\Qt\Android\ndk\27.2.12479018` | | `QT_HOST_PATH` | `C:\Qt\6.10.3\mingw_64` | | Qt Android kit | `C:\Qt\6.10.3\android_arm64_v8a` | 产出: - `tools/fpv_link_stability/build-android-arm64/android-build/fpv_link_stability.apk` - 同目录 Gradle 产物:`android-build-release-unsigned.apk`(未签名,可用 `adb install -r` 安装调试) 手动 cmake(等价): ```powershell $env:ANDROID_SDK_ROOT = "C:\Qt\Android" $env:ANDROID_NDK_ROOT = "$env:ANDROID_SDK_ROOT\ndk\27.2.12479018" $env:JAVA_HOME = "F:\JDK-21.0.2" $env:QT_HOST_PATH = "C:\Qt\6.10.3\mingw_64" cmake -S tools/fpv_link_stability -B tools/fpv_link_stability/build-android-arm64 -G Ninja ` -DCMAKE_TOOLCHAIN_FILE=C:/Qt/6.10.3/android_arm64_v8a/lib/cmake/Qt6/qt.toolchain.cmake ` -DANDROID_SDK_ROOT=$env:ANDROID_SDK_ROOT ` -DANDROID_NDK_ROOT=$env:ANDROID_NDK_ROOT ` -DQT_HOST_PATH=$env:QT_HOST_PATH ` -DQT_ANDROID_ABIS=arm64-v8a ` -DANDROID_ABI=arm64-v8a ` -DANDROID_PLATFORM=android-28 ` -DCMAKE_BUILD_TYPE=Release ` -DFPV_EMBED_IPERF=ON cmake --build tools/fpv_link_stability/build-android-arm64 --target apk ``` 权限见 [`android/AndroidManifest.xml`](android/AndroidManifest.xml)(`INTERNET` / Wi‑Fi 状态等)。minSdk 28。 ### UI 布局 | 平台 | 布局 | | --- | --- | | **Windows** | 左右双栏:iperf \| Probe;iperf 页内嵌实时日志 | | **Android** | 横屏触控:顶栏(IP + New/Export/IPs)+ Tab **iperf / Probe / Session** | 两端 iperf / Probe 页结构对齐: 1. 表单(Mode/Role、主机端口等;Server 模式会隐藏 Client 专用项) 2. 操作按钮:均有 **Start** / **Start as Server** / **Stop**(iperf 另有预设) 3. 状态条(running / idle / error) 4. **摘要卡**:标题 + 四格指标 + 备注 - iperf:RX / TX / Loss / Jitter - Probe:Loss / RTT p50 / RTT p95 / Jitter(备注含 sent/recv/reorder 等) 5. iperf 另有 **实时日志**(桌面 `QPlainTextEdit`;Android `QListWidget`,嵌在摘要下方,整页可滚) **Session** Tab(仅 Android):本机 IPv4 全文 + 导出目录完整路径(不再放日志)。 ### 表单记忆 启动时自动恢复上次的连接与测试参数(`QSettings`,组织名 `FairlandGroup` / 应用名 `fpv_link_stability`): | 组 | 字段 | | --- | --- | | **iperf** | Mode、Backend、Protocol、Server host、Port、UDP -b/-l、Duration、Reverse、外部二进制路径 | | **probe** | Role、Bind port、Peer host/port、pps、Duration、timeout | 在 **开始测试**、窗口关闭 / 析构时写入。改完 IP 后点一次 Start(或正常退出)即可记住。 ### 摘要与 live 刷新 嵌入 libiperf 时开启 **JSON stream**:每个 interval 推一次进度,摘要卡会 **live 更新**(同一条 live 记录被覆盖;结束后 commit 为最终结果)。 **UDP 收发语义(易误解):** | 角色 | 测试中(live) | 结束后 | | --- | --- | --- | | Client 发送(默认,未勾 Reverse) | 通常只有 **TX**;RX/Loss/Jitter 常为 `-` | 一般会带上 Server 回传的 **RX / Loss / Jitter** | | Client 接收(勾选 **Reverse (-R)**)或本机为接收端 | interval 即可看到 Loss / Jitter | 与 live 一致,多为接收侧统计 | Loss / Jitter 由 **接收端** 计算;发送端 interval JSON 不含这些字段,属 iperf 行为,不是 UI 漏刷。 ### Android 上的 iperf 默认 **内嵌 libiperf**(Backend = Auto / Embedded),无需再 push 外部 `iperf3` 二进制。External 仍可作为回退: ```text adb push iperf3 /data/local/tmp/iperf3 adb shell chmod 755 /data/local/tmp/iperf3 ``` 地面端先开 **iperf Server**(或本 APK 内嵌 Server),天空端再开 Client。 序列探针不依赖 iperf,可单独验证丢包与 RTT。安装示例: ```powershell adb install -r tools/fpv_link_stability/build-android-arm64/android-build/fpv_link_stability.apk ``` ## 推荐用法 1. 地面端开 **探针 Server**(端口 17001),天空端开 **探针 Client**(pps 建议 100–500)。 2. 地面端开 **iperf Server**,天空端用预设: - `Quick UDP 5M/15s` - `Stability 5M/600s` - `TCP 60s` 3. 需要过程中看丢包/抖动时:天空端勾选 **Reverse (-R)**,或直接看地面 Server 侧最终摘要。 4. 双测并行时保持探针低 pps,避免探针流量抬高 iperf 丢包。 5. **Export** 写出会话目录;Android 完整路径见 **Session** 页。 ## 导出字段 默认目录:`Documents/fpv_link_stability//` | 文件 | 内容 | | --- | --- | | `00_meta.txt` | 会话元数据 | | `00_summary.csv` | iperf 汇总(`phase,config,rx_mbps,tx_mbps,loss_pct,jitter_ms,...`) | | `iperf_*.txt` | 原始 iperf 日志 | | `probe_summary.csv` | 探针汇总(sent/recv/lost/RTT 分位等) | | `probe_rtt_samples.csv` | RTT 样本(过大时均匀抽样) | 与 PowerShell 脚本字段对应:`rx_mbps` / `loss_pct` / `jitter_ms` 同 [`Get-IperfReceiverUdpSummary`](../fpv_link_iperf_test.ps1)。 ## 探针协议 当前版本 **v2**(32 字节,大端)。仍兼容接收 **v1**(24 字节、无 CRC)。 ### v2 报文布局 | Offset | 字段 | | ---: | --- | | 0 | `magic` u32 = `0x46505653` (`FPVS`) | | 4 | `flags` u32:bit0=`has_crc`;bits 8–15=`version`(v2 = 2) | | 8 | `seq` u64 | | 16 | `send_ns` u64(client 单调时钟) | | 24 | `crc32` u32,覆盖字节 `[0..23]`(IEEE / Ethernet 多项式) | | 28 | 保留(0) | ### v1(兼容) | Offset | 字段 | | ---: | --- | | 0 | `magic` | | 4 | `flags` = 0 | | 8 | `seq` u64 | | 16 | `send_ns` u64 | ### 行为 - Client **始终发送 v2**;Server 仅对校验通过的报文 echo。 - **Loss**:超时未收到 echo;**Corrupt**:magic 正确但 CRC 失败(链路/bit 损坏信号)。 - **Truncated** / **Foreign**:长度不足或非 `FPVS` 报文(端口噪声/其它 UDP)。 - RTT = `now - send_ns`;无时钟同步时**不以单向时延为验收依据**;UI one-way est = RTT p50 / 2。 ## 验收建议 - Loopback:本机探针 Server + Client,loss≈0,RTT 应极低。 - 跨设备:先探针再 iperf UDP 5M;测中看摘要卡 live + 日志 interval;测完核对 CSV 与四格指标。 - Android:保持应用前台;长稳勿依赖后台保活(WakeLock 为二期)。 - 解读 Loss/Jitter:默认 Client 发送时测中可为 `-`;要过程指标用 Reverse,或以结束后摘要为准。 - 组合判读、经验区间、常见误读:见 [`INTERPRETATION.md`](INTERPRETATION.md)。