You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

7.4 KiB

EC800K TCP 透传模式优化方案

1. 适用范围

当前工程使用 Quectel EC800K,通过 UART2 连接模块,通过 AT+QIOPEN 的透传模式承载 TCP 数据:

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 激活和透传参数配置:

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

实际配置前先执行:

AT+QICFG=?

确认当前 EC800K 固件支持的参数范围。tcp/keepalive 中的 interval_time 必须遵守当前固件文档范围,不能直接使用其他模块的参数。

配置后查询并记录:

AT+QICFG="passiveclosed"
AT+QICFG="tcp/keepalive"
AT+QICFG="transpktsize"
AT+QICFG="transwaittm"

4. 透传状态机

建议将连接状态划分为:

DISCONNECTED
CONNECTING
TRANSPARENT_CONNECTED
SUSPECTED
EXITING_TRANSPARENT
CLOSING
RECONNECT_WAIT

正常连接流程:

DISCONNECTED
    -> QIACT
    -> CONNECTING
    -> QIOPEN
    -> 收到 CONNECT
    -> TRANSPARENT_CONNECTED

一次连接尝试只能发送一次 QIOPEN。等待 CONNECT+QIOPEN:<connectID>,<err> 后再决定成功或失败,不能在一个循环条件中重复发送同一条 QIOPEN

重连间隔建议退避:

1 秒 -> 2 秒 -> 5 秒 -> 10 秒 -> 30 秒

5. 服务器心跳检测

服务器连接建立后会定期发送 MAVLink 心跳包。第一阶段先不解析 MAVLink,只要透传接收路径收到服务器数据,就更新:

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 断开通常会上报:

NO CARRIER

模块会退出透传模式。程序应支持完整和分包匹配:

记录断连原因
停止 UART3 -> UART2 的发送
connect_sta = false
执行 AT+QICLOSE=0
进入 RECONNECT_WAIT

收到 NO CARRIER 后通常不需要再次发送 +++,因为模块已经退出透传模式。

6.2 服务器心跳超时

如果超过配置的心跳超时时间没有收到服务器数据:

TRANSPARENT_CONNECTED
    -> SUSPECTED
    -> 暂停飞控数据发送
    -> 严格退出透传
    -> QICLOSE
    -> QIOPEN 重连

6.3 +++ 退出透传

只有在程序仍处于透传模式、但需要主动恢复时才发送 +++。必须满足:

发送前至少 1 秒没有其他 UART 数据
+++ 输入期间没有其他数据
发送后至少 1 秒没有其他数据
等待模块返回 OK

执行期间必须暂停飞控发送线程,否则 +++ 可能被当作普通 TCP 数据发送。

暂停不能只依赖 connect_sta=false。所有 UART2 写路径必须检查统一的发送闸门,必要时使用互斥锁,确保停止当前写操作后再等待 1 秒静默。+++、退出后的 AT 命令和恢复透传必须与飞控发送互斥。

7. Socket 恢复和模块复位

推荐恢复顺序:

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 与业务心跳的关系

AT+QICFG="tcp/keepalive",1,30,25,3

用于 TCP 协议栈探测对端是否仍可达。它不能确认服务器业务程序是否处理了飞控心跳,也不能替代服务器的 MAVLink 心跳。

AT+QICFG="passiveclosed",1 用于处理服务器 FIN/RST 已经到达模块的被动关闭。网络黑洞导致 FIN 没有到达时,仍需依靠 TCP keepalive 或服务器心跳超时。

9. 日志内容

建议在断连日志中记录:

断连原因
server_rx_bytes
server_rx_read_events
age_server_rx
心跳超时次数
当前连接状态
重连退避时间
UART2 收发字节和错误计数
CSQ/CEREG/PDP 状态
AT 最后一条命令、结果和耗时

这些信息可以初步区分:

  • 模块明确报告 TCP 断开;
  • 服务器心跳停止;
  • 网络黑洞导致模块尚未收到 FIN;
  • UART 丢数据或溢出;
  • PDP/注册状态异常;
  • AT 状态机无响应。

10. 内存预算

第一阶段不解析 MAVLink,只增加计时器、状态和计数器:

纯状态字段:约 32~64 字节
加 UART2 发送互斥对象:通常约 100~300 字节,取决于 RT-Thread 配置
Flash:约 1~3 KB

不新增线程,不新增大块动态内存。

如果后续只增加一个 MAVLink HEARTBEAT 识别器,而不是解析所有消息,预计额外增加:

RAM:约 50~100 字节
Flash:约 1~2 KB

11. 实施顺序

  1. 确认服务器实际 MAVLink 心跳周期。
  2. 增加 passiveclosedtcp/keepalive 配置及查询日志。
  3. 增加服务器下行数据计时器和超时状态。
  4. 修正 NO CARRIER 分包解析。
  5. 修正 QIOPEN 重复发送问题。
  6. 实现 QICLOSE 优先、复位兜底的恢复流程。
  7. 实现严格的 +++ 退出保护。
  8. 增加重连退避和断连诊断日志。
  9. 根据现场日志决定是否增加轻量级 MAVLink HEARTBEAT 识别。