本项目是摩天云 MQTT–MAVLink 串口桥(motian-mavlink-bridge)。它连接飞控串口与摩天云 MQTT Broker:被动解析串口上的 MAVLink 帧,按平台 Base JSON 协议上报遥测,并把平台下行指令翻译成 VKFly MAVLink 帧写回串口。详细协议说明见 README.md,实施方案见 doc/实施方案.md。
X | None 等语法),Linux 部署。paho-mqtt>=2,<3、pyserial>=3.5,<4、pymavlink>=2.4.50,<3(见 pyproject.toml)。VKFly 由 msg_definitions Git 子模块的 XML 生成。unittest,不使用 pytest。motian_bridge/
cli.py 生产入口,创建 paho-mqtt / pyserial 实例并注入 Bridge
bridge.py Bridge 核心:MQTT 收发、串口读写线程、Base JSON 编解码、handler 注册、参数表自动同步
config.py Config 冻结 dataclass,含校验;密钥从环境变量读取
aircraft.py Aircraft:按飞控聚合身份、最新观测、电池与参数表(ParamTable)
telemetry.py MAVLink 帧解析与上报节流,内部持有一个 Aircraft(仅串口线程使用)
commands.py 平台业务指令 -> VKFly MAVLink 帧的 handler
dialects/v20/VKFly.py ⚠️ 生成文件,禁止手工修改
tests/ unittest 用例(依赖 FakeMqtt/FakeSerial,test_commands 复用 test_bridge 的辅助函数)
tools/ local_mqtt_broker.py,本地 aMQTT 测试 Broker(非生产依赖)
doc/ 平台接口规范、实施方案、qa.md(待平台澄清问题)
config.example.json 配置模板
python3 -m venv .venv
.venv/bin/python -m pip install -e . # 安装(可编辑模式)
cp config.example.json config.local.json # 再按需修改真实参数
# 跑全部测试(必须是 -s tests,用例间有相互导入)
.venv/bin/python -m unittest discover -s tests -v
# 启动桥接服务
export MOTIAN_MQTT_PASSWORD='由部署环境提供'
.venv/bin/motian-mavlink-bridge --config config.local.json --debug
# 本地联调:先起本地 Broker(需先 pip install "amqtt>=0.12,<0.13")
.venv/bin/python tools/local_mqtt_broker.py
Bridge 只接收抽象的 MQTT client 与 serial_factory,具体实现由 cli.py 提供,便于测试用 fake 替换。保持这一模式。_serial_loop)独占 Telemetry 解析器与其内部的 Aircraft 状态;MQTT 回调线程负责下发。跨线程共享用 threading.Lock / threading.Event,不要引入全局可变状态。Aircraft 的 latest/batteries/params 都只允许串口线程写入,Telemetry 保留 source/latest/params/batteries 兼容属性。Config 冻结 dataclass,并在 __post_init__ 里做校验(非法值直接抛 ValueError)。密钥、密码只从环境变量读取(mqtt_password_env),绝不写进 JSON 或代码。LOG = logging.getLogger(__name__)。判断类型用 type(x) is int 这类精确判断(避免 bool 被当作 int 接受)。FlightCommandHandlers.install() 里 register_handler(data_type, handler),handler 返回时通过 bridge.publish_report(data_type, data) 上报。未实现/未确认的指令只记日志并丢弃,绝不伪造成功 ACK。Add platform command forwarding callbacks)。DataType=526 + 大写 HEX Data,发到 /PUBLISH/<SystemID>;结构化上报发到 /RECEIVE/<SystemID>。字段名是 DataType(没有尾随空格)。DataType/UAVType/Data/SystemID/TimeStamp,且设备标识须与本机配置一致;Data 必须是非空、偶数长度 HEX,不超过 max_command_bytes。_target() 会抛错保护)。不要修改 motian_bridge/dialects/v20/VKFly.py——它是生成文件。XML 变更后重新生成:
.venv/bin/python -m pymavlink.tools.mavgen --lang Python --wire-protocol 2.0 \
--output motian_bridge/dialects/v20/VKFly.py \
msg_definitions/msg_definitions/VKFly.xml
Telemetry 中 VKFly.MAVLINK_IGNORE_CRC = 0 是安全底线,不要为调试方便关闭 CRC 校验。
不要提交 config.local.json、.venv/、*.pdf(见 .gitignore);
不要降低 TLS 强度(mqtt_ca_file 校验、证书配置等保持开启)。
tests/ 下的 unittest 用例;提交前必须通过:
.venv/bin/python -m unittest discover -s tests -vFakeMqtt / FakeSerial(见 tests/test_bridge.py);涉及真实帧编解码时用 VKFly.MAVLink 构造帧,参照 tests/test_telemetry.py。ValidationTests。Telemetry(可能换了一架飞控),旧状态必须丢弃,不要跨重连复用遥测。Telemetry 逐字节喂给 parse_char,每次只返回一条消息;分块读取不影响帧边界,不要改成整块喂入。STATUSTEXT 的文本需绕过生成的 Python 解码器、手动按 char[50] 读 UTF-8(生成代码按 ASCII 处理会丢字符),改动这里前先看 telemetry.py 注释。--debug 可看到 missing/stale 日志)。参数同步由 request_params_on_start(默认开)控制,超时/重试见 param_request_timeout、param_request_max_attempts;#281 与自动同步共用 commands.py 的 request_params(),改动需同步更新 test_commands.ParameterSyncTests。#274 的 true 表示解锁,不是物理离地;DataType 258 的 IsFlying 也按解锁解释。commands.py 的 TODO_PARAMS)以及 #2050 Data=true 的“接管”语义,均保留 TODO,不要擅自映射或发送;需先澄清可记入 doc/qa.md。