8 changed files with 655 additions and 48 deletions
@ -0,0 +1,250 @@ |
|||||
|
# EC800K TCP 透传模式优化方案 |
||||
|
|
||||
|
## 1. 适用范围 |
||||
|
|
||||
|
当前工程使用 Quectel EC800K,通过 UART2 连接模块,通过 `AT+QIOPEN` 的透传模式承载 TCP 数据: |
||||
|
|
||||
|
```text |
||||
|
AT+QIOPEN=1,0,"TCP",<server>,<port>,0,2 |
||||
|
``` |
||||
|
|
||||
|
飞控数据保持原有透传路径,不增加新的 TCP 连接,也不要求第一阶段解析完整 MAVLink 数据。 |
||||
|
|
||||
|
## 2. 目标 |
||||
|
|
||||
|
- 保持飞控数据的透明传输。 |
||||
|
- 使用服务器现有的 MAVLink 心跳检测下行链路。 |
||||
|
- 使用 EC800K 的 TCP keepalive 处理网络黑洞。 |
||||
|
- 正确处理 `NO CARRIER` 和分包 URC。 |
||||
|
- TCP 断开时优先关闭 Socket 并重连,只有 AT 状态机无响应时才复位模块。 |
||||
|
- 避免重复发送 `QIOPEN` 和连续快速重连。 |
||||
|
|
||||
|
## 3. 连接初始化 |
||||
|
|
||||
|
在 `QIOPEN` 前完成 PDP 激活和透传参数配置: |
||||
|
|
||||
|
```text |
||||
|
AT+QIACT? |
||||
|
AT+QIACT=1 // PDP 未激活时执行 |
||||
|
AT+QICFG="transpktsize",512 |
||||
|
AT+QICFG="transwaittm",0 |
||||
|
AT+QICFG="passiveclosed",1 |
||||
|
AT+QICFG="tcp/keepalive",1,30,25,3 |
||||
|
``` |
||||
|
|
||||
|
实际配置前先执行: |
||||
|
|
||||
|
```text |
||||
|
AT+QICFG=? |
||||
|
``` |
||||
|
|
||||
|
确认当前 EC800K 固件支持的参数范围。`tcp/keepalive` 中的 `interval_time` 必须遵守当前固件文档范围,不能直接使用其他模块的参数。 |
||||
|
|
||||
|
配置后查询并记录: |
||||
|
|
||||
|
```text |
||||
|
AT+QICFG="passiveclosed" |
||||
|
AT+QICFG="tcp/keepalive" |
||||
|
AT+QICFG="transpktsize" |
||||
|
AT+QICFG="transwaittm" |
||||
|
``` |
||||
|
|
||||
|
## 4. 透传状态机 |
||||
|
|
||||
|
建议将连接状态划分为: |
||||
|
|
||||
|
```text |
||||
|
DISCONNECTED |
||||
|
CONNECTING |
||||
|
TRANSPARENT_CONNECTED |
||||
|
SUSPECTED |
||||
|
EXITING_TRANSPARENT |
||||
|
CLOSING |
||||
|
RECONNECT_WAIT |
||||
|
``` |
||||
|
|
||||
|
正常连接流程: |
||||
|
|
||||
|
```text |
||||
|
DISCONNECTED |
||||
|
-> QIACT |
||||
|
-> CONNECTING |
||||
|
-> QIOPEN |
||||
|
-> 收到 CONNECT |
||||
|
-> TRANSPARENT_CONNECTED |
||||
|
``` |
||||
|
|
||||
|
一次连接尝试只能发送一次 `QIOPEN`。等待 `CONNECT` 或 `+QIOPEN:<connectID>,<err>` 后再决定成功或失败,不能在一个循环条件中重复发送同一条 `QIOPEN`。 |
||||
|
|
||||
|
重连间隔建议退避: |
||||
|
|
||||
|
```text |
||||
|
1 秒 -> 2 秒 -> 5 秒 -> 10 秒 -> 30 秒 |
||||
|
``` |
||||
|
|
||||
|
## 5. 服务器心跳检测 |
||||
|
|
||||
|
服务器连接建立后会定期发送 MAVLink 心跳包。第一阶段先不解析 MAVLink,只要透传接收路径收到服务器数据,就更新: |
||||
|
|
||||
|
```text |
||||
|
last_server_rx_tick |
||||
|
server_rx_bytes |
||||
|
server_rx_read_events |
||||
|
``` |
||||
|
|
||||
|
设备超时应设置为服务器心跳周期的 2~3 倍: |
||||
|
|
||||
|
| 服务器心跳周期 | 建议设备超时 | |
||||
|
|---|---:| |
||||
|
| 3 秒 | 10~12 秒 | |
||||
|
| 5 秒 | 15 秒左右 | |
||||
|
| 10 秒 | 25~30 秒 | |
||||
|
|
||||
|
当前已确认服务器每 3 秒发送一次 MAVLink 心跳,工程宏 `LTE_SERVER_SILENCE_TIMEOUT_SEC` 设置为 `15`,允许连续丢失多个心跳后再进入恢复流程。若服务器心跳周期发生变化,应同步调整该值。一般应设置为心跳周期的 2~3 倍,并保留网络抖动余量。 |
||||
|
|
||||
|
不要只允许丢失一个心跳包就重连。超时后先标记 `SUSPECTED`,停止普通发送,再执行恢复流程。 |
||||
|
|
||||
|
第一阶段的“任意下行数据”只用于快速验证链路,不能证明收到的必然是 MAVLink HEARTBEAT,也不能证明服务器一定收到了设备上行数据。读取次数也不等于 MAVLink 包数量,因此应记录为 `server_rx_read_events`。后续如果需要严格判断心跳,再使用现有 MAVLink 库只识别 `MAVLINK_MSG_ID_HEARTBEAT`,不解析其他消息。服务器如果没有固定下行心跳,不能使用该方法作为连接判断。 |
||||
|
|
||||
|
## 6. 断连事件处理 |
||||
|
|
||||
|
### 6.1 `NO CARRIER` |
||||
|
|
||||
|
在透传模式下,EC800K 因网络错误或 Socket 断开通常会上报: |
||||
|
|
||||
|
```text |
||||
|
NO CARRIER |
||||
|
``` |
||||
|
|
||||
|
模块会退出透传模式。程序应支持完整和分包匹配: |
||||
|
|
||||
|
```text |
||||
|
记录断连原因 |
||||
|
停止 UART3 -> UART2 的发送 |
||||
|
connect_sta = false |
||||
|
执行 AT+QICLOSE=0 |
||||
|
进入 RECONNECT_WAIT |
||||
|
``` |
||||
|
|
||||
|
收到 `NO CARRIER` 后通常不需要再次发送 `+++`,因为模块已经退出透传模式。 |
||||
|
|
||||
|
### 6.2 服务器心跳超时 |
||||
|
|
||||
|
如果超过配置的心跳超时时间没有收到服务器数据: |
||||
|
|
||||
|
```text |
||||
|
TRANSPARENT_CONNECTED |
||||
|
-> SUSPECTED |
||||
|
-> 暂停飞控数据发送 |
||||
|
-> 严格退出透传 |
||||
|
-> QICLOSE |
||||
|
-> QIOPEN 重连 |
||||
|
``` |
||||
|
|
||||
|
### 6.3 `+++` 退出透传 |
||||
|
|
||||
|
只有在程序仍处于透传模式、但需要主动恢复时才发送 `+++`。必须满足: |
||||
|
|
||||
|
```text |
||||
|
发送前至少 1 秒没有其他 UART 数据 |
||||
|
+++ 输入期间没有其他数据 |
||||
|
发送后至少 1 秒没有其他数据 |
||||
|
等待模块返回 OK |
||||
|
``` |
||||
|
|
||||
|
执行期间必须暂停飞控发送线程,否则 `+++` 可能被当作普通 TCP 数据发送。 |
||||
|
|
||||
|
暂停不能只依赖 `connect_sta=false`。所有 UART2 写路径必须检查统一的发送闸门,必要时使用互斥锁,确保停止当前写操作后再等待 1 秒静默。`+++`、退出后的 AT 命令和恢复透传必须与飞控发送互斥。 |
||||
|
|
||||
|
## 7. Socket 恢复和模块复位 |
||||
|
|
||||
|
推荐恢复顺序: |
||||
|
|
||||
|
```text |
||||
|
NO CARRIER 或心跳超时 |
||||
|
-> 停止业务发送 |
||||
|
-> 必要时 +++ 并等待 OK |
||||
|
-> AT+QICLOSE=0 |
||||
|
-> 查询/恢复 PDP |
||||
|
-> 单次 QIOPEN |
||||
|
-> 收到 CONNECT 后恢复透传 |
||||
|
``` |
||||
|
|
||||
|
以下情况才执行 EC800K 复位: |
||||
|
|
||||
|
- `+++` 超时; |
||||
|
- `AT+QICLOSE` 超时; |
||||
|
- `AT+QIACT` 长时间无响应; |
||||
|
- 连续多个 AT 命令无响应; |
||||
|
- UART2 长时间没有任何模块响应。 |
||||
|
|
||||
|
TCP 断开本身不等于 EC800K 死机,不能每次 `NO CARRIER` 都直接复位模块。 |
||||
|
|
||||
|
AT 等待时间必须按官方上限设计:`QIACT` 最长可达 150 秒,`QIOPEN` 建议最长等待 150 秒,`QICLOSE` 默认最长约 10 秒,`QIDEACT` 最长可达 40 秒。当前工程的 7 秒和 500 毫秒等待不能直接用于这些命令,否则会把模块仍在处理的请求误判为超时。一次 `QIOPEN` 超时后必须先完成清理和退避,不能立即重复发送。 |
||||
|
|
||||
|
## 8. TCP keepalive 与业务心跳的关系 |
||||
|
|
||||
|
```text |
||||
|
AT+QICFG="tcp/keepalive",1,30,25,3 |
||||
|
``` |
||||
|
|
||||
|
用于 TCP 协议栈探测对端是否仍可达。它不能确认服务器业务程序是否处理了飞控心跳,也不能替代服务器的 MAVLink 心跳。 |
||||
|
|
||||
|
`AT+QICFG="passiveclosed",1` 用于处理服务器 FIN/RST 已经到达模块的被动关闭。网络黑洞导致 FIN 没有到达时,仍需依靠 TCP keepalive 或服务器心跳超时。 |
||||
|
|
||||
|
## 9. 日志内容 |
||||
|
|
||||
|
建议在断连日志中记录: |
||||
|
|
||||
|
```text |
||||
|
断连原因 |
||||
|
server_rx_bytes |
||||
|
server_rx_read_events |
||||
|
age_server_rx |
||||
|
心跳超时次数 |
||||
|
当前连接状态 |
||||
|
重连退避时间 |
||||
|
UART2 收发字节和错误计数 |
||||
|
CSQ/CEREG/PDP 状态 |
||||
|
AT 最后一条命令、结果和耗时 |
||||
|
``` |
||||
|
|
||||
|
这些信息可以初步区分: |
||||
|
|
||||
|
- 模块明确报告 TCP 断开; |
||||
|
- 服务器心跳停止; |
||||
|
- 网络黑洞导致模块尚未收到 FIN; |
||||
|
- UART 丢数据或溢出; |
||||
|
- PDP/注册状态异常; |
||||
|
- AT 状态机无响应。 |
||||
|
|
||||
|
## 10. 内存预算 |
||||
|
|
||||
|
第一阶段不解析 MAVLink,只增加计时器、状态和计数器: |
||||
|
|
||||
|
```text |
||||
|
纯状态字段:约 32~64 字节 |
||||
|
加 UART2 发送互斥对象:通常约 100~300 字节,取决于 RT-Thread 配置 |
||||
|
Flash:约 1~3 KB |
||||
|
``` |
||||
|
|
||||
|
不新增线程,不新增大块动态内存。 |
||||
|
|
||||
|
如果后续只增加一个 MAVLink HEARTBEAT 识别器,而不是解析所有消息,预计额外增加: |
||||
|
|
||||
|
```text |
||||
|
RAM:约 50~100 字节 |
||||
|
Flash:约 1~2 KB |
||||
|
``` |
||||
|
|
||||
|
## 11. 实施顺序 |
||||
|
|
||||
|
1. 确认服务器实际 MAVLink 心跳周期。 |
||||
|
2. 增加 `passiveclosed` 和 `tcp/keepalive` 配置及查询日志。 |
||||
|
3. 增加服务器下行数据计时器和超时状态。 |
||||
|
4. 修正 `NO CARRIER` 分包解析。 |
||||
|
5. 修正 `QIOPEN` 重复发送问题。 |
||||
|
6. 实现 `QICLOSE` 优先、复位兜底的恢复流程。 |
||||
|
7. 实现严格的 `+++` 退出保护。 |
||||
|
8. 增加重连退避和断连诊断日志。 |
||||
|
9. 根据现场日志决定是否增加轻量级 MAVLink HEARTBEAT 识别。 |
||||
Loading…
Reference in new issue