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 遥控器可用频率列表

文档生成完毕。

复制代码
相关推荐
码农coding5 小时前
android12 WindowManagerService窗口的布局过程
android·源码
杉氧8 小时前
状态管理变迁史:为什么我们放弃了 Redux 选择 Zustand?
android·前端·react native
三少爷的鞋11 小时前
别再靠 Code Review 守底线:我做了一个静态分析项目 RedLine
android
y = xⁿ19 小时前
DeepSeek Harness 学习日记:关于Agent接口,工具调用的底层实现
android·java·学习
2601_962066491 天前
【Sql Server】Update中的From语句,以及常见更新操作方式
android·java·数据库
用户69371750013841 天前
曾经安卓开发人手一个的 EventBus,为什么现在没人爱用了?
android·android studio
九皇叔叔1 天前
MySQL ORDER BY 性能优化详解:Using filesort、联合索引、ASC/DESC 与覆盖索引
android·adb
OriginCoding1 天前
用 AI Agent 协作完成一个 Android TOTP 应用:从需求边界到 v1.0.0
android·ai编程
杉氧1 天前
React 灵魂:深入剖析 Hooks 与副作用(Side Effects)陷阱
android·前端·react native