Android遥控器对频详解

一、模块总览

对频(Pairing / 绑定)是遥控器与天空端设备之间的射频链路建立过程。本工程主要包含以下对频相关子模块:

功能 主 Fragment / Activity 核心 Key 入口
开始对频 D2dFragment / D2dActivity KeyRequestPairing 点击"对频"按钮
停止对频 D2dFragment / D2dActivity KeyRequestStopPair 点击"停止对频"按钮
新增接收机(绑定) D2dFragment / D2dActivity KeyRequestPairingAtSetMac 点击"新增接收机"按钮
解绑/断开 D2dActivity KeyRequestStopPair 停止对频时自动触发
连接状态 D2dFragment / D2dActivity KeyRawSignalQuality 实时监听 JSON
信号质量 NewuiG12SignalFragment KeyG12RCScanChanInfo / KeyG12SkyScanChanInfo / KeyRawSignalQuality 1秒定时器轮询
MAC 地址读取 NewuiG12MacPairFragment KeyMAC 读取/设置接收机 MAC

二、核心数据模型

2.1 PairParam(对频参数)

java 复制代码
// com/skydroid/rcsdk/common/airlink/PairParam.java
public final class PairParam {
    private String mac;   // 目标接收机 MAC 地址(8位字符串)
    private int timeout;  // 对频超时时间(秒),默认 1 秒
}

构造方式:new PairParam(mac, 0, 2, null) → 实际等价于 (mac, timeout=1)

2.2 ChanInfo(信道扫描信息)

java 复制代码
// com/skydroid/rcsdk/common/airlink/ChanInfo.java
public final class ChanInfo {
    private boolean autoMode;   // 是否自动跳频模式
    private int chanNum;        // 信道数量
    private long[] freq;        // 各信道频率数组
    private int[] power;        // 各信道信号强度数组(dBm)
}

2.3 GLinkThroughput(链路吞吐量)

java 复制代码
// com/skydroid/rcsdk/common/airlink/GLinkThroughput.java
public final class GLinkThroughput {
    private long txPhy;   // 物理层发送速率(kbps)
    private long txReal;  // 实际发送速率(kbps)
    private long rxPhy;   // 物理层接收速率(kbps)
    private long rxReal;  // 实际接收速率(kbps)
}

2.4 GLinkSkyDevice(天空端设备枚举)

java 复制代码
// com/skydroid/rcsdk/common/airlink/GLinkSkyDevice.java
public enum GLinkSkyDevice {
    UNKNOWN(0),  // 未识别
    GR01(1),     // GR01 接收机
    GR03(2),     // GR03 接收机
    TR01(3),     // TR01 中继器
    GR02(4),     // GR02 接收机
    YL20(5),     // YL20 设备
}

2.5 BandValue(频段枚举)

java 复制代码
// com/skydroid/rcsdk/common/airlink/BandValue.java
public enum BandValue {
    UNKNOWN,
    Band_1G,
    Band_2G,
    Band_5G
}

三、开始对频(Pairing)

3.1 触发入口

D2dFragment.sendReset() 或 D2dActivity.sendReset(),用户点击"对频"按钮触发。

3.2 流程

ini 复制代码
用户点击"对频"按钮
    ↓
sendReset()
    ↓
Toast 提示 "对频中..."(R.string.frequency_ing)
    ↓
判断设备类型(isG_RC_App() / isG_RC()):
    ├── G 系列遥控器(G12/G20/G30/TC3 等):
    │       KeyManager.action(KeyRequestPairing, callback)
    │           → 下发对频请求到遥控器
    │           → onSuccess → 启动配对状态检查线程
    │   └── 非 G 系列:
    │           通过 UDP 发送 AT 命令:"AT+WPS\r\n"
    │           设置 isStartPair = true
    │           设置 isCanShowPairEnd = true
    ↓
启动 pairCheckStatusThread(后台线程,每 500ms 检查一次)
    ↓
检查 InternalKey.isAr8030Pairing():
    ├── true  → tvPairing 显示可见(对频进行中)
    └── false → isStartPair = false,隐藏 tvPairing(对频结束/超时)
    ↓
1 秒后设置 isCanShowPairEnd = true(允许显示配对成功/失败提示)

3.3 SDK Key

Key 方向 数据类型 说明
RemoteControllerKey.KeyRequestPairing 写(action) EmptyMsg 请求开始对频
InternalKey.KeyRequestPairingAtSetMac 写(set) PairParam 指定 MAC 进行绑定

四、停止对频(Stop Pairing)

4.1 触发入口

D2dFragment.m401initData$lambda11() 或 D2dActivity.m948onCreate$lambda8(),用户点击"停止对频"按钮触发。

4.2 流程

scss 复制代码
用户点击"停止对频"按钮
    ↓
KeyManager.action(KeyRequestStopPair, callback)
    ↓
onResult(null) → Toast "停止对频中..."(R.string.msg_stoping_pair)
onResult(exception) → 不提示
    ↓
pairCheckStatusThread.interrupt()(中断检查线程)
isStartPair = false

4.3 SDK Key

Key 方向 数据类型 说明
RemoteControllerKey.KeyRequestStopPair 写(action) EmptyMsg 请求停止对频

五、新增接收机(绑定 / Add Receiver)

5.1 触发入口

D2dFragment.m403initData$lambda12() 或 D2dActivity.m950onCreate$lambda9(),用户点击"新增接收机"按钮触发。

5.2 流程

scss 复制代码
用户点击"新增接收机"按钮
    ↓
getMac()
    → KeyManager.get(KeyMAC, callback)
    → onSuccess(mac) → getMacStr = mac
    → showReceiverDialog2()(弹出确认对话框,显示接收机 MAC)
    ↓
用户确认 → setMac(getMacStr)
    ↓
校验 MAC:
    ├── 为空  → Toast "设置失败"
    ├── 长度≠8 → Toast "设置失败"
    └── 合法 → 继续
    ↓
构建 PairParam(mac, 0, 2, null),从 edittextTimeOut 读取超时值(默认 5 秒)
    ↓
KeyManager.set(KeyRequestPairingAtSetMac, pairParam, callback)
    ↓
onResult(null) → 绑定成功
onResult(exception) → 绑定失败

5.3 SDK Key

Key 方向 数据类型 说明
AirLinkKey.KeyMAC 读(get) String 读取本地设备 MAC
AirLinkKey.KeyRequestPairingAtSetMac 写(set) PairParam 指定 MAC 绑定接收机

六、解绑(Unbind / Disconnected)

解绑逻辑与停止对频合并处理:

ini 复制代码
KeyManager.action(KeyRequestStopPair)
    ↓
遥控器断开与天空端的链路
    ↓
KeyRawSignalQuality 回调 dev_connect = false
    ↓
d2dConnection 显示"未连接"

无独立解绑 Key,通过 KeyRequestStopPair 完成。


七、连接状态

7.1 信号质量监听(G 系列)

vbnet 复制代码
onResume()
    ↓
KeyManager.listen(KeyRawSignalQuality, keyRawSignalQualityListener)
    ↓
回调 KeyListener.onValueChange(key, rawJson)
    ↓
解析 JSON,提取以下字段:
    ├── "dev_connect"  → Boolean:是否已连接
    ├── "signal"       → Integer:信号强度值
    ├── "ap_tx_chan"   → Integer:地面端当前发射信道
    ├── "dev_tx_chan"  → Integer:天空端当前发射信道
    └── 其他调试字段(ap_*/dev_* 前缀)
    ↓
runOnUiThread → 更新 UI
    ├── d2dConnection.setText(getConnectedStr(context, dev_connect))
    ├── tvCHANNEL 显示详细状态信息
    └── 若 dev_connect=true 且 isCanShowPairEnd=true:
            → Toast "对频成功"(R.string.contraband_successful)

7.2 连接超时检测

ini 复制代码
每次收到有效信号数据时:
    → handler.removeCallbacks(checkTimeoutRunnable)
    → checkTimeoutRunning = false
    → handler.postDelayed(checkTimeoutRunnable, 5000ms)
    ↓
5 秒内未收到新数据:
    → checkTimeoutRunnable 触发
    → d2dConnection 显示"未连接"
    → 左侧/中间/右侧 TextView 清空

7.3 连接状态工具函数

java 复制代码
// com/skydroid/business/util/StringUtils.java
getConnectedStr(Context, boolean isConnected)   → "已连接" / "未连接"
getNewuiConnectedStr(Context, boolean isConnected) → 新版 UI 连接字符串

7.4 设备类型分支(GLinkSkyDevice)

NewuiWirelessSettingsFragment 监听 KeyGLinkSkyDevice 回调,动态显示/隐藏功能项:

java 复制代码
isGR02()  → gLinkSkyDevices 包含 GR02 → 显示类型 2 UI
isTR01()  → gLinkSkyDevices 包含 TR01 → 显示类型 1 UI
else      → 显示类型 0 UI(基础模式)

所有情况下 mLyBackupStartRealy(中继启动)默认隐藏。


八、信号质量与信道扫描

8.1 实时信号质量(Signal Fragment)

NewuiG12SignalFragment 实现信道扫描图显示:

scss 复制代码
onResume() → timerTask.start()(1秒周期)
    ↓
定时器触发:
    KeyManager.get(KeyG12RCScanChanInfo)   → 地面端信道功率
    KeyManager.get(KeyG12SkyScanChanInfo)  → 天空端信道功率
    ↓
onSuccess(ChanInfo) → setLineChartDatas(power[], isSky, currChan)
    → 更新 BarChart(Y 轴:-110 ~ -50 dBm)
    → 绿色柱:噪声最小,蓝色柱:当前信道
    ↓
KeyManager.listen(KeyRawSignalQuality)  → 实时更新当前信道
    → skyChan = dev_tx_chan(天空端当前信道)
    → rcChan  = ap_tx_chan(地面端当前信道)

8.2 频段配置

java 复制代码
// AirLinkKey 相关 Key
KeyRCGetBandInfo     → 获取遥控器频段信息(GetBandInfo)
KeySkyGetBandInfo    → 获取天空端频段信息
KeyRCSetBand         → 设置遥控器频段(BandValue)
KeySkySetBand        → 设置天空端频段
KeyRCSetBandAutoMode → 设置自动跳频模式
KeySkySetBandAutoMode
KeyRCSetBandSave     → 保存频段设置
KeySkySetBandSave

8.3 带宽与跳频

Key 类型 说明
KeyRCSetEqualBandwidthMode Boolean 地面端等带宽模式
KeySkySetEqualBandwidthMode Boolean 天空端等带宽模式
KeySetFrameChangeDuration SetFrameChangeDuration 跳频帧间隔
KeySetAutoMCS Boolean 自动 MCS 模式
KeySkySetAutoMCSDuration SetAutoAndDuration 自动 MCS 时长
KeySetBandwidthDuration Long 带宽持续时间
KeyRCSetReTxCount Integer 地面端重传次数
KeySkySetReTxCount Integer 天空端重传次数
KeyRCFreqList long\[\] 地面端可用频率列表
KeyGLinkSpeedMode GLinkSpeedMode 链路速度模式

8.4 信号质量 Key(各设备)

Key 类型 设备
KeySignalQuality Integer 通用
KeyRawSignalQuality String(JSON) G 系列
KeyRawSignalQuality2 String(JSON) G 系列(备用)
KeyH12SignalQuality Integer H12
KeyH16SignalQuality Integer H16(已废弃)
KeyH16RawSignalQuality String H16(已废弃)
KeyH30SignalQuality Integer H30(已废弃)

九、MAC 地址管理

9.1 读取 MAC

scss 复制代码
NewuiG12MacPairFragment.onResume()
    → KeyManager.get(KeyMAC, callback)
    → onSuccess(mac) → etMac.setText(mac)

9.2 设置 MAC(仅写入本地值)

scss 复制代码
buttonTvSaveOnClick()
    → 校验 MAC 长度 = 8
    → KeyManager.set(KeyMAC, mac, callback)

9.3 对频时绑定 MAC

ini 复制代码
setMac(mac, usePair=true)
    → PairParam(mac, timeout=1)
    → KeyManager.set(KeyRequestPairingAtSetMac, pairParam, callback)

十、D2D(Device-to-Device)链路

D2dController 通过 Android 系统 D2D Service 实现设备间直连:

java 复制代码
// com/fishsemi/sdk/d2dcontrol/D2dController.java
start()           → bindToD2DService()(绑定 D2DService)
stop()            → unbindToD2DService()(解绑)
requestPairAir()  → requestD2dFreqNegotiation()(请求对频)

监听回调:

  • onD2DServiceStatusChanged → 连接状态变化
  • onD2DSignalStrengthChanged → 信号强度变化(LTE RSRQ/RSRP)
  • onRequestFreqNegotiationDone → 对频结果(成功/失败)

十一、完整流程图

scss 复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                           开始对频流程                                   │
│                                                                         │
│  用户点击"对频" ──→ sendReset()                                         │
│                      │                                                    │
│                      ▼                                                    │
│              KeyManager.action(KeyRequestPairing)                        │
│                      │                                                    │
│                      ▼                                                    │
│              后台线程轮询 isAr8030Pairing()                               │
│                  ├── true  → tvPairing 可见(对频中)                     │
│                  └── false → 隐藏 tvPairing                              │
│                      │                                                    │
│                      ▼                                                    │
│              1秒后 isCanShowPairEnd = true                                │
│                      │                                                    │
│                      ▼                                                    │
│              KeyRawSignalQuality 回调 dev_connect=true                    │
│                      │                                                    │
│                      ▼                                                    │
│              Toast "对频成功" ✓                                           │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────┐
│                          新增接收机流程                                   │
│                                                                         │
│  用户点击"新增接收机" → getMac()                                        │
│                        │                                                  │
│                        ▼                                                  │
│              KeyManager.get(KeyMAC)                                      │
│                        │                                                  │
│                        ▼                                                  │
│              showReceiverDialog2()(弹窗确认 MAC)                        │
│                        │                                                  │
│                        ▼                                                  │
│              setMac(mac)                                                 │
│                ├── 校验 MAC 长度 = 8                                     │
│                └── PairParam(mac, timeout)                               │
│                        │                                                  │
│                        ▼                                                  │
│              KeyManager.set(KeyRequestPairingAtSetMac, pairParam)        │
│                        │                                                  │
│                        ▼                                                  │
│              绑定结果提示                                                  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

十二、关键类速查

类 路径 作用
D2dFragment h12ptool/newuifragment/D2dFragment.java 对频主页面(新 UI)
D2dActivity h12ptool/p006ui/activity/D2dActivity.java 对频页面(旧 UI)
NewuiG12MacPairFragment h12ptool/newuifragment/NewuiG12MacPairFragment.java MAC 读取/设置页面
NewuiG12SignalFragment h12ptool/newuifragment/NewuiG12SignalFragment.java 信号质量图表
NewuiWirelessSettingsFragment h12ptool/newuifragment/NewuiWirelessSettingsFragment.java 无线设置入口
D2dController fishsemi/sdk/d2dcontrol/D2dController.java D2D 系统级控制器
AirLinkKey rcsdk/key/AirLinkKey.java 对频/信号质量相关所有 Key 定义
RemoteControllerKey rcsdk/key/RemoteControllerKey.java 对频动作 Key(Start/Stop)
InternalKey rcsdk/internal/InternalKey.java 内部状态 Key(Ar8030Pairing)
PairParam rcsdk/common/airlink/PairParam.java 对频参数(MAC + 超时)
ChanInfo rcsdk/common/airlink/ChanInfo.java 信道扫描数据
GLinkThroughput rcsdk/common/airlink/GLinkThroughput.java 链路吞吐量
GLinkSkyDevice rcsdk/common/airlink/GLinkSkyDevice.java 天空端设备类型
StringUtils business/util/StringUtils.java 连接状态字符串工具

十三、SDK Key 汇总(对频相关)

对频动作 Key

Key 方法 参数类型 说明
KeyRequestPairing action EmptyMsg 开始对频
KeyRequestStopPair action EmptyMsg 停止对频
KeyRequestPairingAtSetMac set PairParam 指定 MAC 绑定

状态监听 Key

Key 读取方法 返回值类型 说明
KeyRawSignalQuality listen String (JSON) 原始信号质量(含 dev_connect)
KeyRawSignalQuality2 listen String (JSON) 备用信号质量
KeySignalQuality listen Integer 通用信号强度
KeyGLinkSkyDevice listen GLinkSkyDevice[] 已连接的天空端设备列表
KeyGLinkThroughput get GLinkThroughput 链路吞吐量(RX/TX kbps)
KeyMAC get String 设备 MAC 地址

信道/频段 Key

Key 说明
KeyG12RCScanChanInfo G12 地面端信道扫描信息
KeyG12SkyScanChanInfo G12 天空端信道扫描信息
KeyRCGetBandInfo 获取遥控器频段信息
KeySkyGetBandInfo 获取天空端频段信息
KeyRCSetBand 设置遥控器频段
KeySkySetBand 设置天空端频段
KeyRCSetBandSave 保存遥控器频段
KeySkySetBandSave 保存天空端频段
KeyRCSetBandAutoMode 遥控器自动跳频模式
KeySkySetBandAutoMode 天空端自动跳频模式
KeyRCFreqList 遥控器可用频率列表

文档生成完毕。

复制代码
相关推荐
用户2181697049301 小时前
Kotlin 语法二
android
妖星1 小时前
android 源码分析surfaceFinger是如何通过设置属性启动bootanim
android
JoyMonitor1 小时前
APK mmap 内存增长定位:pagemap 与 DEX 结构联合定位方法
android
有什么事1 小时前
永久虚拟免费云手机能实现吗,本地安卓容器与云端托管的技术边界
android·智能手机
妖星1 小时前
Android 源码 .rc 语法详解
android
JMchen1 小时前
实战项目一——实现一个高性能图片滤镜App
android·c++·性能优化
白帽攻防录2 小时前
SRC 挖洞:Android 蓝牙预认证 RCE 深度复盘,CVE-2026-55330 怎么在蓝牙范围内零交互攻破手机
android·网络安全·智能手机·src漏洞挖掘
vilya2 小时前
手机端 Agent 是怎么跑起来的:决策循环、四道护栏、两条红线
android·agent
2501_915921432 小时前
详细教程:使用Perfdog工具测量iOS应用的功耗性能与优化方法
android·macos·ios·小程序·uni-app·cocoa·iphone
hunterandroid3 小时前
android方案 : Multiplatform 跨平台开发实战:一套代码,多端运行
android·前端