遥控器 App 交互架构与问题导读(RC-2000 / RC-3000 通用)
阅读对象: 产品、测试、售后、管理层——无需读懂代码,也能理解「数据怎么流」「问题可能出在哪」。
技术细节: 见CODE_REVIEW_jetwave-rc-2000.md、CODE_REVIEW_jetwave-rc-3000.md
1. 用一句话说清楚
遥控器里装了一个 Android 应用(waverider),它负责四件事:
- 连上冲浪板上的电脑(ECU),看清速度、电量、故障
- 读手柄油门,把「你想跑多快」发给板子
- 航行时每秒记一笔账(位置、油门、故障码等)
- 结束后把账本上传到云端,后台才能看到 轨迹分析页
近期用户反馈的 断联、板体失速、无法控制,在数据里主要对应三类信号:
| 用户感受 | 数据里的名字 | 数值 |
|---|---|---|
| 板子失速、动力没了 | ESC 失速保护 | esc = 131072 |
| 过压保护 | ESC 过压保护 | esc = 4194304 |
| 和板子通信断了 | ECU:ESC 通信故障 | ecu = 1073741824 |
2. 整体交互架构(五层)
flowchart TB
subgraph 用户层
U[用户手柄油门/按键]
UI[屏幕: 速度 电量 故障弹窗]
end
subgraph 遥控器App["遥控器 App (waverider)"]
HF[主界面 HomeFragment<br/>航行/记日志/弹故障]
DH[协议解析 DataHandler]
UP[上传 UploadSailingRecordUtil]
end
subgraph 连接层["连接方式(两项目默认不同)"]
BLE[板载蓝牙]
SP[串口+星闪/增强蓝牙模块]
end
subgraph 板子端["冲浪板电子设备"]
ECU[ECU 主控]
ESC[ESC 电调/电机]
BMS[电池管理]
end
subgraph 云端
OSS[阿里云 OSS 存 txt 明细]
API[JetWave 后台 API]
WEB[管理后台可视化<br/>/analysis/日志id]
end
U --> HF
HF --> UI
HF -->|每秒记一笔| DB[(手机本地数据库)]
HF -->|发油门/收心跳| DH
DH --> BLE
DH --> SP
BLE --> ECU
SP --> ECU
ECU --> ESC
ECU --> BMS
ECU -->|心跳含故障码| DH
DH -->|EventBus 通知| HF
HF -->|结束航行| UP
DB --> UP
UP --> OSS
UP --> API
API --> WEB
OSS --> WEB
两项目唯一重大差别(连接层默认):
| 项目 | 默认怎么连板子 |
|---|---|
| RC-2000 | 板载 蓝牙 直连 |
| RC-3000 | 星闪(先走串口 AT 命令,再透传数据) |
3. 关键业务逻辑说明
3.1 开机 → 连接板子
sequenceDiagram
participant 用户
participant App as 遥控器App
participant 连接 as 蓝牙或星闪服务
participant 板子 as ECU
用户->>App: 打开应用 / 进入主界面
App->>连接: 启动 BleService 或 SerialPortService
连接->>板子: 扫描 / 配对 / AT建链
板子-->>连接: 连接成功
连接->>App: 通知「已连接」
App->>板子: 请求设备信息(版本号等)
板子-->>App: 返回 ECU/BMS/ESC 版本
Note over 连接,App: ⚠️风险① 切换蓝牙/星闪时<br/>旧连接未干净断开
Note over App: ⚠️风险② 协议解析器全局共用<br/>多线程可能串包
普通人理解: 就像手机连蓝牙耳机,连不上或连上又掉,后面所有速度、故障都不可信。
3.2 航行中:油门怎么变成板子动作
flowchart LR
A[手柄霍尔传感器<br/>读油门角度] --> B[App 显示油门条]
B --> C[通过 MAVLink 消息<br/>发给 ECU]
C --> D[ECU 控制 ESC/电机]
D --> E[板子运动]
E --> F[ECU 每秒回传心跳<br/>速度/电流/故障码]
F --> G[App 更新仪表盘]
F --> H[App 写入本地轨迹<br/>约1秒1条]
style A fill:#e8f4e8
style H fill:#e8f4e8
与「失速不可控」的关系:
- 数据里常见:油门 > 0,但 motorSpeed = 0,且 esc = 131072(失速保护)
- 说明:人还在加油门,板子保护态不输出——是保护逻辑或通信问题,不是用户没推油门
flowchart TB
subgraph 正常
N1[油门推] --> N2[ECU收到] --> N3[电机转]
end
subgraph 异常_日志中常见
A1[油门推] --> A2[ECU/ESC报失速131072]
A2 --> A3[电机不转或无力]
A3 --> A4[用户感觉失控]
end
3.3 故障是怎么产生、显示、写进日志的
flowchart TB
START[ECU/ESC 检测到异常] --> CODE[置位故障码<br/>esc或ecu字段]
CODE --> MAV[MAVLink 心跳包<br/>每秒发给 App]
MAV --> PARSE[DataHandler 解析]
PARSE --> BUS[EventBus 广播]
BUS --> UI{HomeFragment}
UI --> POP[弹窗提示用户]
UI --> SLS[阿里云埋点 SLS]
UI --> DB[写入轨迹表<br/>escEventCode/ecuEventCode]
DB --> OSS[航行结束上传 OSS]
OSS --> BACK[后台 analysis/id 页面]
style CODE fill:#ffe0e0
style PARSE fill:#fff3cd
style UI fill:#fff3cd
三类故障在 App 里的处理(代码已命名):
| 故障码 | App 常量名 | 用户可能看到 |
|---|---|---|
| esc=131072 | ESC_FAULT_STALL_PROTECTION | 失速相关提示 + 埋点 |
| esc=4194304 | ESC_FAULT_OVERVOLTAGE_PROTECTION | 过压相关提示 + 埋点 |
| ecu=1073741824 | FAULT_ESC_COMMUNICATION | ESC 通信异常提示 + 埋点 |
⚠️ 逻辑风险③(两项目共有):
App 用「故障码 等于 某一个数」判断,如果板子一次上报 多个故障同时存在,界面可能 只认一个,漏报其它故障。
3.4 结束航行 → 上传云端
sequenceDiagram
participant 用户
participant App
participant 本地 as 本地DB+txt文件
participant OSS
participant 后台
用户->>App: 停止航行
App->>本地: 汇总轨迹点(含esc/ecu码)
App->>本地: 生成 txt<br/>命名: 遥控器SN_1_用户ID_时间.txt
App->>OSS: 上传 txt
OSS-->>App: 返回 objectKey
App->>后台: 上报轨迹元数据
后台->>后台: 生成日志 id
Note over 后台: 可视化 URL<br/>.../analysis/{id}
Note over App: ⚠️风险④ isUpload标志<br/>可能重复上传或卡死
Note over App: ⚠️风险⑤ 上传成功即删本地文件<br/>失败难重传
普通人理解: 后台看到的每一条「飞行日志」,就是这次生成的 txt;我们分析的 719 条 CSV,每一行对应一个这样的 txt。
4. 问题环节总览图(按链路标红)
flowchart TB
subgraph 环节1_连接
L1A[蓝牙/星闪连接]
L1B[SerialPortService 状态机复杂]
R1((风险: 断联))
end
subgraph 环节2_协议
L2A[字节流 → Parser 解析]
R2((风险: 多线程串包))
end
subgraph 环节3_控制
L3A[油门读取 vs 下发]
L3B[ECU/ESC 保护态]
R3((风险: 失速131072<br/>有油门无电机))
end
subgraph 环节4_故障逻辑
L4A[心跳里的 esc/ecu 码]
L4B[弹窗 + 写数据库]
R4((风险: 只判断单一故障码))
end
subgraph 环节5_上传
L5A[SQLite → JSON → OSS]
R5((风险: 上传竞态/删文件))
end
subgraph 环节6_环境
L6A[RC-3000 测试域名]
R6B[线程池过大200]
R6((风险: 性能/环境错配))
end
L1A --> L1B --> L2A --> L3A --> L3B --> L4A --> L4B --> L5A
L1B -.-> R1
L2A -.-> R2
L3B -.-> R3
L4B -.-> R4
L5A -.-> R5
L6A -.-> R6
L6B -.-> R6
5. 两项目差异(一张表看懂)
| 对比 | RC-2000 | RC-3000 |
|---|---|---|
| 默认连接 | 蓝牙 | 星闪 |
| 云端 API | 生产 api.jetwave.ai | 测试 surfdev.aliyu.vip |
| 功能 | 核心航行 | + 对讲、AI、NFC、地图 |
| 油门硬件 | yyadc 霍尔 | kth5762 霍尔 + 开机校准 |
| 故障码/上传格式 | 相同 | 相同 |
| 代码风险点 | 相同 | 相同 + 更多后台服务 |
排查建议: 对比两项目设备的 断联率、失速率,若 3000 明显更高,优先查 星闪链路;若两项目都高,优先查 ESC 固件 + Parser 线程安全。
6. 和「一个月飞行日志」怎么对上号
flowchart LR
A[用户航行] --> B[App 每秒记录<br/>含 esc/ecu 码]
B --> C[上传 OSS txt]
C --> D[入库 CSV 汇总行]
D --> E[我们脚本筛选<br/>STALL/OV/ECU]
E --> F[报告+后台链接<br/>analysis/id]
G[代码 EscFaultMask] -.定义一致.-> B
H[代码 EcuFaultMask] -.定义一致.-> B
| 日志分析结论 | 在架构哪一环 |
|---|---|
| 32 条有失速码 131072 | 环节3 ESC 保护 + 环节4 写入 |
| 6 条有过压 4194304 | 环节3 大电流/电压 + 环节4 |
| ecu 1073741824 常与 stall 同会话 | 环节1 通信 + 环节2 解析 |
| STALL+ECU 但很少同时有过压 | 说明不是过压引起,查通信/失速恢复 |
7. 会前 3 分钟怎么讲(口述稿)
- 遥控器 App 是 连接板子 → 推油门 → 每秒记日志 → 上传云端 四条线。
- 用户说的失速、断联,在数据里主要是 三个数字:131072、4194304、1073741824,和代码里故障定义 一致。
- 问题 不一定在 App 算错,更可能在 连接掉线、ESC 保护不恢复、上传/解析并发;3000 还要多看 星闪 和 测试环境域名。
- 每条问题日志可在后台点开:
https://manager.jetwave.cn/motion/trajectoryHistory/analysis/{id}。 - 优先查设备:5G002872、6A000193、6A000540(失速主导),5C002991、5G001585(过压)。
8. 快速优化改进(一页纸)
详细方案见两份 CODE_REVIEW 第 11/12 章。
本周必做 Top 5(两项目同步)
| 序号 | 改什么 | 为什么 |
|---|---|---|
| 1 | MAVLink 解析放 单线程 | 现在多线程共用一个 Parser,可能「假断联、假故障」 |
| 2 | 故障判断改成 位运算 | 板子可能同时报失速+通信故障,现在只认一个 |
| 3 | 上传加 原子锁,失败别删文件 | 避免传不上去或传两次 |
| 4 | 线程池从 200 收到 4 | 遥控器 CPU 扛不住,通信会卡 |
| 5 | 3000 确认 生产 API 域名 | 否则日志进测试环境,查问题白查 |
3000 多加 2 条
- 星闪断线:3 秒无心跳就重连,重连中别发油门
- 航行时:对讲/地图降资源,别和 ECU 抢线程
固件必须并行
- 失速 131072:保护后能否恢复? 不能就改 ESC 策略
- 通信 1073741824:ECU 和 ESC 之间 是否超时
9. 相关报告索引
| 文档 | 用途 |
|---|---|
| 本文 | 架构图 + 业务逻辑 + 问题环节(通俗) |
CODE_REVIEW_jetwave-rc-2000.md |
RC2000 技术审查 + §11 快速改进 |
CODE_REVIEW_jetwave-rc-3000.md |
RC3000 技术审查 + §12 快速改进 |
FAULT_FILTER_STALL_OV_ECU_REPORT.md |
49 条故障日志清单+链接 |
MEETING_FULL_ANALYSIS_REPORT.md |
719 条数据分析总报告 |