Android遥控器如何监控信号质量

150 阅读10分钟

目录

  1. 实时信号质量指标体系
  2. 遥控器端如何获取信号质量
  3. 信号质量的监听机制
  4. 信号数据的来源分析
  5. 遥控器端的接收技术
  6. 核心技术栈总结
  7. 数据流向全景图

一、实时信号质量指标体系

1.1 核心连接指标

通过 KeyRawSignalQuality(JSON 格式)监听,遥控器端实时上报以下关键字段:

字段名数据类型说明
dev_connectBoolean设备连接状态(核心指标,true=已连接,false=已断开)
signalInteger综合信号强度值(数值越大信号越好)
ap_tx_chanInteger地面端当前发射信道编号(0~N)
dev_tx_chanInteger天空端当前发射信道编号(0~N)

1.2 链路吞吐量指标

通过 KeyGLinkThroughput 获取,每秒轮询一次:

字段类型说明单位
txPhylong物理层发送速率(理论峰值)kbps
txReallong实际有效发送速率(应用层)kbps
rxPhylong物理层接收速率(理论峰值)kbps
rxReallong实际有效接收速率(应用层)kbps

txReal/rxReal 通常远小于 txPhy/rxPhy,因为包含协议开销和重传。

1.3 信道扫描指标

通过 KeyG12RCScanChanInfo(地面端)和 KeyG12SkyScanChanInfo(天空端)获取:

// ChanInfo 数据结构
public final class ChanInfo {
    private boolean autoMode;   // 是否自动跳频模式(true=正在跳频)
    private int chanNum;        // 扫描的信道总数(如 7、13)
    private long[] freq;        // 各信道中心频率(单位 MHz)
    private int[] power;        // 各信道信号功率(单位 dBm)
}

信号功率显示范围:

  • 最小值(YMIN):-110 dBm(极弱信号/纯噪声)
  • 最大值(YMAX):-50 dBm(极强信号)
  • 正常飞行范围:-90 dBm ~ -60 dBm

1.4 LTE D2D 信号指标(青鳉直连方案)

通过 Android 系统 D2D Service 获取:

指标方法数据类型说明
getLteRsrp()int (dBm)参考信号接收功率,范围约 -140 ~ -44 dBm
getLteRsrq()int (dB)参考信号接收质量,范围约 -19.5 ~ -3 dB
getLteSignalStrength()int (0~31)信号强度等级(0=无信号,31=最强)

RSRP 信号质量分级:

RSRP (dBm)信号等级说明
> -85优秀近距离,无延迟风险
-85 ~ -95良好正常飞行范围
-95 ~ -105一般远距离,需注意链路稳定性
< -105较差可能断连,建议返航

1.5 多设备类型区分

KeyGLinkSkyDevice 返回已连接的天空端设备数组(GLinkSkyDevice[]):

枚举值value设备类型
UNKNOWN0未识别设备
GR011GR01 接收机
GR024GR02 接收机
GR032GR03 接收机
TR013TR01 中继器
YL205YL20 配套设备

二、遥控器端如何获取信号质量

2.1 获取方式总览

遥控器端获取信号质量有 三种方式,对应不同的场景和设备类型:

┌─────────────────────────────────────────────────────────────────┐
│                     三种信号获取方式                              │
├─────────────────────────┬───────────────┬───────────────────────┤
│       方式              │    适用场景    │       触发时机          │
├─────────────────────────┼───────────────┼───────────────────────┤
│ KeyManager.listen()     │ 正常飞行模式   │ onResume / 页面启动    │
│ (SDK 回调推送)         │              │                       │
├─────────────────────────┼───────────────┼───────────────────────┤
│ UdpConnectManager       │ 开发调试模式   │ is401DDeveloper=true   │
│ + GetInfoThread         │              │ 时启用                 │
├─────────────────────────┼───────────────┼───────────────────────┤
│ D2dController           │ LTE D2D 直连  │ 使用青鳉 D2D 硬件模块  │
│ + ID2DInfoListener      │              │ 时启用                 │
└─────────────────────────┴───────────────┴───────────────────────┘

2.2 G 系列遥控器(主力方案:SDK 回调)

代码入口: D2dFragment.initConnect()

// 监听信号质量(SDK 主动推送,无需轮询)
KeyManager.INSTANCE.listen(
    AirLinkKey.INSTANCE.getKeyRawSignalQuality(),
    this.keyRawSignalQualityListener
);

回调处理: D2dFragment.m410keyRawSignalQualityListener$lambda6()

回调触发(每收到一条 SDK 数据)
    ↓
解析 JSON:
    ├── dev_connect → Boolean(连接状态)
    ├── signal      → Integer(信号值)
    ├── ap_tx_chan  → Integer(地面端信道)
    └── dev_tx_chan → Integer(天空端信道)
    ↓
重置超时检测计时器(5秒无数据视为断开)
    ↓
runOnUiThread → 更新 UI:
    ├── d2dConnection.setText(getNewuiConnectedStr(context, dev_connect))
    ├── tvLeft / tvCenter / tvRight 显示详细字段
    └── 若 dev_connect=true 且首次对频成功 → Toast "对频成功"

2.3 信道功率扫描(Timer 轮询方案)

代码入口: NewuiG12SignalFragment.onResume()

// 启动 1 秒定时器
private final TimerTask timerTask = new TimerTask(new Runnable() {
    public void run() {
        // 每秒轮询地面端和天空端的信道功率
        KeyManager.INSTANCE.get(
            AirLinkKey.INSTANCE.getKeyG12RCScanChanInfo(),
            callback  // onSuccess → setLineChartDatas(power[], isSky=false)
        );
        KeyManager.INSTANCE.get(
            AirLinkKey.INSTANCE.getKeyG12SkyScanChanInfo(),
            callback  // onSuccess → setLineChartDatas(power[], isSky=true)
        );
    }
}, 1000);  // 1 秒间隔

2.4 吞吐量轮询

// 每秒获取一次链路吞吐量
TimerTask g12ThroughputTask = new TimerTask(..., 1000);
g12ThroughputTask.start();

// 定时器任务内:
KeyManager.INSTANCE.get(
    AirLinkKey.INSTANCE.getKeyGLinkThroughput(),
    new CompletionCallbackWith<GLinkThroughput>() {
        public void onSuccess(GLinkThroughput throughput) {
            gLinkThroughput = throughput;
            // 用于在浮动窗口展示 RX/TX kbps
        }
    }
);

2.5 开发调试模式(UDP 网络方案)

触发条件: AppSettings.INSTANCE.is401DDeveloper() == true

// 创建 UDP Socket(本地 12581 ↔ 天空端 192.168.144.10:12580)
this.udpKey = UdpConnectManager.INSTANCE.createUDPKey(
    12581,              // 本地监听端口
    "192.168.144.10",   // 天空端 IP 地址
    12580               // 天空端发送端口
);

// 启动请求线程
GetInfoThread getInfoThread = new GetInfoThread(udpKey);
getInfoThread.setOnSendDataListener(() -> {
    if (!checkTimeoutRunning) {
        checkTimeoutRunning = true;
        handler.postDelayed(checkTimeoutRunnable, 5000L);
    }
});
getInfoThread.start();  // 周期性发送 "GET_INFO_REQUEST\n"

三、信号质量的监听机制

3.1 KeyManager 监听模型

┌──────────────────────────────────────────────────────────────────┐
│                        KeyManager 架构                            │
│                                                                  │
│  App Layer              SDK Layer             Hardware Layer     │
│  ┌──────────────┐       ┌──────────────┐       ┌────────────┐   │
│  │ KeyListener  │──────→│ KeyManager   │──────→│ Serial/   │   │
│  │  (App注册)   │←──────│  (事件分发)   │←──────│ UDP/USB   │   │
│  └──────────────┘       └──────────────┘       └────────────┘   │
│         ↑                         ↑                      ↑       │
│         │ 回调通知                 │ 数据变化检测          │ 底层读取│
│         └─────────────────────────┘                      │       │
│                                  内部状态机                │       │
└──────────────────────────────────────────────────────────┘

3.2 监听注册生命周期

public class D2dFragment extends NewUIBaseFragment {

    // 1. 在 onViewCreated 时注册监听
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initView();   // → initConnect() → KeyManager.listen()
    }

    // 2. 在 onResume 时重新连接(确保前台活跃)
    @Override
    public void onResume() {
        super.onResume();
        initConnect();  // → KeyManager.listen(KeyRawSignalQuality, listener)
    }

    // 3. 在 onDestroy 时取消监听(防止内存泄漏)
    @Override
    public void onDestroy() {
        super.onDestroy();
        onDestroys();
        // → KeyManager.INSTANCE.cancelListen(this.keyRawSignalQualityListener);
    }
}

3.3 超时检测机制(看门狗)

收到任何有效信号数据时:
    handler.removeCallbacks(checkTimeoutRunnable)   // 取消旧计时器
    checkTimeoutRunning = false
    handler.postDelayed(checkTimeoutRunnable, 5000ms)  // 重置 5 秒计时器

5 秒内未收到新数据 → checkTimeoutRunnable 触发:
    → d2dConnection.setText("未连接")
    → tvLeft / tvCenter / tvRight 清空
    → checkTimeoutRunning = false

设计意图:即使 SDK 回调正常触发,如果 5 秒内没有有效数据,也判定为链路中断,避免 UI 显示过期数据。


四、信号数据的来源分析

4.1 信号数据产生位置

┌─────────────────────────────────────────────────────────────────────┐
│                         信号数据产生源                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   ┌─────────────────────────────────────────────────────────┐      │
│   │                    物理层信号产生                        │      │
│   │                                                         │      │
│   │   ┌──────────────┐         ┌──────────────┐            │      │
│   │   │  地面端射频   │         │  天空端射频   │            │      │
│   │   │  (AP/遥控器)  │◄───────►│  (DEV/无人机) │            │      │
│   │   │   GLink 模块  │  无线   │   GLink 模块  │            │      │
│   │   └──────┬───────┘  链路   └──────┬───────┘            │      │
│   │          │                        │                      │      │
│   │          └────────┬───────────────┘                      │      │
│   │                   ▼                                      │      │
│   │   ┌─────────────────────────────────────┐               │      │
│   │   │         信号质量测量                 │               │      │
│   │   │  • RSSI(接收信号强度指示)           │               │      │
│   │   │  • 当前工作信道                      │               │      │
│   │   │  • 各信道功率谱                      │               │      │
│   │   │  • 传输吞吐量计数器                  │               │      │
│   │   └─────────────────────────────────────┘               │      │
│   │                         │                                │      │
│   │                         ▼                                │      │
│   │   ┌─────────────────────────────────────┐               │      │
│   │   │         固件 MCU 处理                │               │      │
│   │   │  • 定期采集信号寄存器值               │               │      │
│   │   │  • 计算功率统计                      │               │      │
│   │   │  • 组包下发给 App                    │               │      │
│   │   └─────────────────────────────────────┘               │      │
│   │                         │                                │      │
│   └─────────────────────────┼────────────────────────────────┘      │
│                             ▼                                        │
│   ┌─────────────────────────────────────────────────────────┐      │
│   │                 App 层处理(Android)                    │      │
│   │                                                         │      │
│   │   SerialPort / UDP / D2DService                         │      │
│   │        ↓                                                │      │
│   │   rcsdk KeyManager(数据解析与分发)                      │      │
│   │        ↓                                                │      │
│   │   D2dFragment / NewuiG12SignalFragment                  │      │
│   │        ↓                                                │      │
│   │   UI 渲染(TextView / BarChart / FloatWindow)           │      │
│   │                                                         │      │
│   └─────────────────────────────────────────────────────────┘      │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

4.2 各指标的具体来源

指标物理来源测量原理
signalGLink 射频芯片 RSSI 寄存器接收到的参考信号功率,由 RF 前端自动测量
dev_connect协议层心跳检测SDK 持续收到有效数据包 = 连接,超时未收到 = 断开
ap_tx_chan / dev_tx_chanGLink 跳频控制器当前跳频序列中的信道序号
power[](信道功率)频谱扫描逐信道测量接收功率,返回所有信道的功率谱
txReal / rxReal数据链路层计数器应用层实际传输的字节数 ÷ 时间间隔
RSRP(LTE)青鳉 D2D 模块 LTE 接收机3GPP 标准定义的参考信号接收功率

4.3 信号的发出方

信号质量数据由以下实体发出:

1. 遥控器固件 MCU(主信号源)
   发出内容:dev_connect, signal, ap_tx_chan, dev_tx_chan, power[], 吞吐量
   发出方式:串口(UART)→ CDC/FTDI/CH340 → Android USB Host

2. 天空端固件(通过遥控器中转)
   发出内容:天空端信号强度、信道信息
   发出方式:无人机 → 无线链路 → 遥控器固件 → 串口 → App

3. 青鳉 D2D Service(系统服务)
   发出内容:RSRP, RSRQ, SignalStrength
   发出方式:Android binder IPC → ID2DInfoListener 回调

五、遥控器端的接收技术

5.1 技术一:串口/USB 通信(主力)

文件: rcsdk/comm/SerialPort.javarcsdk/comm/AR8030Comm.java

硬件链路:
┌─────────┐    USB OTG    ┌─────────┐    UART    ┌─────────┐
│ Android  │ ←──────────→ │ 转换芯片  │ ←───────→ │ 遥控器   │
│ 手机/Pad │   CDC/FTDI   │ CH340/   │  921600  │  MCU     │
│         │              │ CP2102   │  baud    │ (STM32)  │
└────┬────┘              └────┬─────┘          └────┬────┘
     │                        │                     │
     ▼                        ▼                     ▼
 SerialPort.open()        AR8030Comm             固件协议解析
     │                        │                     │
     └────────┬───────────────┘                     │
              ▼                                     │
       KeyManager 读取线程                           │
              │                                     │
              ▼                                     │
       协议解码 → Key 映射 → 回调 App               │

关键类:

  • SerialPort.java — JNI 封装,调用 /dev/ttyUSBx 等串口设备
  • AR8030Comm.java — AR8030 射频模块通信协议封装
  • CommListener.java — 串口数据监听回调接口
  • TCPComm.java — TCP 网络通信备用方案

5.2 技术二:UDP 网络通信(开发调试)

文件: h12ptool/common/UdpConnectManager.javah12ptool/common/UDPComm.java

网络拓扑(开发版):
┌──────────────┐         UDP         ┌──────────────┐
│   Android192.168.144.10    │   天空端     │
│   App        │ ◄────────────────► │   固件       │
│   Port:12581Port:12580Port:12580 │
└──────────────┘                    └──────────────┘
      │                                  │
      │  定时发送:                       │  收到请求后回复:
      │  "GET_INFO_REQUEST\n"JSON 格式的状态数据
      │  (每秒一次)                       │  (包含所有信号指标)
      └──────────────────────────────────┘

5.3 技术三:Android D2D Service(LTE 直连)

文件: fishsemi/sdk/d2dcontrol/D2dController.java

系统架构:
┌─────────────────────────────────────────────────────────┐
│                   Android 系统层                         │
│                                                         │
│   ┌─────────────────────────────────────────────┐      │
│   │          com.pinecone.telephony.D2DService   │      │
│   │            (青鳉 D2D 系统服务)                 │      │
│   │                                               │      │
│   │   ┌─────────────┐   ┌─────────────┐        │      │
│   │   │ LTE 射频模块 │   │ D2D 协议栈  │        │      │
│   │   │ (青鳉自研)   │   │ (3GPP Rel13)│        │      │
│   │   └─────────────┘   └─────────────┘        │      │
│   └─────────────────────────────────────────────┘      │
│                      ▲  ▲                              │
│                      │  │ AIDL                         │
│   ┌──────────────────┘  └──────────────────┐          │
│   │            ID2DInfoListener             │          │
│   │  onD2DSignalStrengthChanged()           │          │
│   │  onD2DServiceStatusChanged()            │          │
│   └─────────────────────────────────────────┘          │
└─────────────────────────────────────────────────────────┘
                      ▲
                      │ bindService
   ┌──────────────────┘
   ▼
D2dController (App 进程)

使用流程:

// 1. 绑定系统 D2D 服务
Intent intent = new Intent();
intent.setClassName("com.pinecone.telephony", "com.pinecone.telephony.D2DService");
mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

// 2. 注册监听器
mD2DService.registerForD2dInfoChanged(mD2DInfoListener);

// 3. 获取初始信息
mD2DService.requestGetD2dInfo();

// 4. 请求对频
mD2DService.requestD2dFreqNegotiation();

5.4 技术四:超时看门狗

无论使用哪种通信方式,都有一套统一的超时检测机制:

// 每次收到有效数据时重置计时器
handler.removeCallbacks(checkTimeoutRunnable);
checkTimeoutRunning = false;
handler.postDelayed(checkTimeoutRunnable, 5000L);

// 5 秒超时后判定为断开
private final Runnable checkTimeoutRunnable = () -> {
    checkTimeoutRunning = false;
    d2dConnection.setText("未连接");   // 更新连接状态
    tvLeft.setText("");                // 清空详细信息
    tvCenter.setText("");
    tvRight.setText("");
    tvCHANNEL.setText("");
};

六、核心技术栈总结

6.1 通信技术矩阵

技术包路径适用场景优点缺点
SerialPort (USB CDC)rcsdk/comm/所有设备(主力)低延迟、稳定、即插即用需要 USB OTG
UDP Socketh12ptool/common/开发调试版本可在同一 WiFi 下远程调试依赖网络配置
AIDL D2D Servicefishsemi/sdk/d2dcontrol/青鳉 D2D 硬件无需 WiFi,LTE 直连仅支持特定硬件
TCP Commrcsdk/comm/TCPComm.java备用方案长距离传输延迟较高

6.2 关键组件索引

┌────────────────────────────────────────────────────────────────┐
│                      关键文件索引                               │
├────────────────────────────────────────────────────────────────┤
│                                                                │
│  【信号监听入口】                                               │
│  ├── D2dFragment.java:825        KeyRawSignalQuality 监听注册   │
│  ├── D2dActivity.java:565        旧 UI 信号监听注册            │
│  └── NewuiG12SignalFragment.java:80  信道扫描定时器启动         │
│                                                                │
│  【数据回调处理】                                               │
│  ├── D2dFragment.java:166-344    JSON 解析与 UI 更新           │
│  ├── D2dActivity.java:129-214    旧 UI 数据处理                │
│  └── NewuiG12SignalFragment.java:80-111  信道功率图表更新       │
│                                                                │
│  【底层通信封装】                                               │
│  ├── rcsdk/comm/SerialPort.java    JNI 串口操作                │
│  ├── rcsdk/comm/AR8030Comm.java    AR8030 模块通信             │
│  ├── h12ptool/common/UDPComm.java  UDP 数据收发                │
│  ├── h12ptool/common/UdpConnectManager.java UDP 连接管理       │
│  ├── h12ptool/common/GetInfoThread.java   数据请求线程         │
│  └── fishsemi/sdk/d2dcontrol/D2dController.java   D2D 控制    │
│                                                                │
│  【数据模型】                                                   │
│  ├── rcsdk/common/airlink/ChanInfo.java     信道信息           │
│  ├── rcsdk/common/airlink/GLinkThroughput.java  吞吐量          │
│  ├── rcsdk/common/airlink/PairParam.java    对频参数           │
│  └── rcsdk/common/airlink/GLinkSkyDevice.java 设备类型          │
│                                                                │
│  【Key 定义】                                                   │
│  ├── rcsdk/key/AirLinkKey.java        信号质量相关 Key 定义    │
│  └── rcsdk/key/RemoteControllerKey.java 对频动作 Key 定义       │
│                                                                │
└────────────────────────────────────────────────────────────────┘

七、数据流向全景图

┌─────────────────────────────────────────────────────────────────────────────────┐
│                            信号质量数据完整流向                                   │
│                                                                                 │
│  【物理层】                                                                     │
│  ┌──────────────┐         ┌──────────────┐         ┌──────────────┐            │
│  │  地面端 GLink │◄────────►│  无线射频链路  │◄────────►│  天空端 GLink │            │
│  │   射频芯片    │   2.4GHz  │   (跳频扩频)  │   2.4GHz  │   射频芯片    │            │
│  │  (AP侧)      │  跳频通信  │              │  跳频通信  │  (DEV侧)    │            │
│  └──────┬───────┘         └──────────────┘         └──────┬───────┘            │
│         │ RSSI/信道/功率/吞吐量测量                        │                      │
│         └────────────────────────┬───────────────────────┘                      │
│                                  ▼                                               │
│  【固件层】(遥控器 MCU STM32)                                                    │
│  ┌──────────────────────────────────────────────────────────────────┐           │
│  │  • 定时读取 RF 寄存器(RSSI、信道状态)                             │           │
│  │  • 统计链路吞吐量(TX/RX 字节数)                                  │           │
│  │  • 心跳检测(维护 dev_connect 状态)                               │           │
│  │  • 组包:将上述数据封装为二进制协议包                               │           │
│  └──────────────────────────────────────────────────────────────────┘           │
│                                  │                                               │
│                                  ▼ 串口/USB (921600 baud)                         │
│  【SDK 层】(rcsdk Android 库)                                                    │
│  ┌──────────────────────────────────────────────────────────────────┐           │
│  │  SerialPort / UDPComm / D2dController                            │           │
│  │       ↓                                                          │           │
│  │  KeyManager(协议解码 + Key 映射)                                 │           │
│  │       ↓                                                          │           │
│  │  KeyRawSignalQuality → JSON 字符串                                │           │
│  │  KeyGLinkThroughput  → GLinkThroughput 对象                       │           │
│  │  KeyG12RCScanChanInfo→ ChanInfo 对象(地面端)                     │           │
│  │  KeyG12SkyScanChanInfo→ ChanInfo 对象(天空端)                    │           │
│  └──────────────────────────────────────────────────────────────────┘           │
│                                  │                                               │
│                                  ▼ KeyListener 回调                              │
│  【App 层】(D2dFragment / NewuiG12SignalFragment)                                │
│  ┌──────────────────────────────────────────────────────────────────┐           │
│  │  主线程 UI 更新:                                                  │           │
│  │  ├── d2dConnection TextView:显示 "已连接" / "未连接"              │           │
│  │  ├── tvCHANNEL TextView:显示完整 JSON 信息                        │           │
│  │  ├── tvLeft/Center/Right:分栏显示详细指标                          │           │
│  │  ├── BarChart(MPAndroidChart):显示各信道功率分布                  │           │
│  │  └── FloatWindow(悬浮窗):全局显示信号强度和吞吐量                  │           │
│  │                                                                   │           │
│  │  超时检测:                                                        │           │
│  │  └── 5 秒无数据 → 自动切换为"未连接"状态                            │           │
│  └──────────────────────────────────────────────────────────────────┘           │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

八、附录:典型信号数据 JSON 示例

8.1 正常连接状态

{
  "dev_connect": true,
  "signal": -62,
  "ap_tx_chan": 6,
  "dev_tx_chan": 6,
  "ap_signal_strength": -65,
  "dev_signal_strength": -60,
  "acs_chan": 6,
  "work_chan": 6,
  "tx_real": 2400,
  "rx_real": 2350
}

8.2 断开连接状态

{
  "dev_connect": false,
  "signal": -110,
  "ap_tx_chan": -1,
  "dev_tx_chan": -1
}

8.3 对频进行中状态

{
  "dev_connect": false,
  "signal": -105,
  "pairing": true,
  "scan_progress": 3
}

文档生成完毕。