云平台开发笔记
mavlink_id & mavlink_password
Device添加mavlink_id和mavlink_password字段。在/users路由完成数据交互相关的表单。在users.html添加相关表单
后端 mavlink_server_with_user.py:824-880 现在在 /users 返回值中为每台设备带上 mavlink_id/mavlink_password,同时 / device_info_fix (mavlink_server_with_user.py:890-910) 支持读取这两个字段、校验 mavlink_id 为整数并写入数据库,保证 前端获得现有值后可保存修改。
templates/users.html:488-506 的“绑定的设备”表格新增两列展示 MAVLink 凭证,并在“修改”按钮上以 data-* 属性附带当前的 吊舱及 MAVLink 信息。
点击“修改”时,editDeviceInfo (templates/users.html:360-390) 会将这些值写进弹窗表单(设备 ID 只读,新增两个输入 框),并在提交时通过 AJAX 一并提交;按钮事件处理也更新为从 data-device-id 等属性读取 (templates/users.html:413- 423),因此弹窗中现在能正确预填 mavlink_id / mavlink_password。
TODO 在绑定/注册设备流程中填写 MAVLink 凭证,可在 /bind-device 界面沿用同样的字段
平台接入airlink
- 在 mavlink_server_with_user.py:16-138 新增 airlink 直连配置:支持 AIRLINK_HOST/PORT 环境变量、心跳打包 (build_airlink_heartbeat) 及后台线程管理 (ensure_airlink_stream、airlink_stream_worker),平台会以设备的 mavlink_id/ mavlink_password 和管控平台身份连接本机 14550 端口,持续接收 TCP 数据流。
- /share 页面和登录流程会校验并启动对应的 airlink 流。share_index 现在在渲染前确保设备凭证有效并拉起连接 (mavlink_server_with_user.py:165-178);login 在绑定设备校验后调用 ensure_airlink_stream,无凭证时直接返回提示 (mavlink_server_with_user.py:455-507)。handle_token 事件也会触发连接,确保任意使用 token 订阅的客户端都能把数据拉 进来(mavlink_server_with_user.py:1044-1055)。
- 将原 @socketio.on(‘mavlink_data’) 的解析逻辑抽成 process_mavlink_payload(mavlink_server_with_user.py:1090-1258), 既供兼容旧的 Socket.IO 上传,也供新的 airlink 线程复用。解析结果会同时广播到用户名房间、设备房间以及分享房间,超级 管理员房间仍然全部覆盖。新增的 TCP 背景线程调用同一个处理函数,从而把 airlink 的二进制流实时推送到前端。
- 由于从 airlink 直连,确保每台设备都配置了唯一的 mavlink_id/mavlink_password,并在 UI(users.html)里正确维护即可。 启动时需要先运行 airlink/tcp_server,再运行 Flask,登录设备账户(或访问分享链接)即可触发后台连接并看到不再依赖 Socket.IO 上传的 MAVLink 数据。
不记得本地代理是没有把消息转发到云上的!!本代代理通过USB接收mavlink并转发到5760,同时通过连接服务器,服务器的mavlink转发到本地代理!!
• airlink_stream_worker 在 mavlink_server_with_user.py:90-128,核心是为某个设备维护一条到 Go airlink 中继的 TCP 管道, 并把原始字节流交给解析函数:
- mavlink_server_with_user.py:110-123 外层 while 循环只要没有收到 stop_event,就会反复尝试 socket.create_connection((AIRLINK_HOST, AIRLINK_PORT)),建联成功后先发认证帧,然后持续 recv(AIRLINK_BUFFER_SIZE)。
- 每次收到数据块,如果长度大于 0,就调用 process_mavlink_payload(device_key, owner_username, chunk) 做 MAVLink 解析与 Socket.IO 广播;若 recv 返回空或抛出异常就 break/进入异常分支。
- except 分支里记录 airlink 连接 … 异常 并 sleep 3 秒后重试,确保网络抖动时能自愈。
- finally 块保证 socket 被关闭,外层循环退出(收到 stop_event)后会在 airlink_streams 全局字典里 pop(device_key) 清理 线程状态。
整体来看,这个 worker 就是“管理端到 airlink 的一条专线”:负责认证、保持连接、不断搬运原始数据流,遇到错误自动重连,收 到 stop_event 时退出。
- emit_mavlink_data (mavlink_server_with_user.py:1126): 接收某条解析好的数据字典、设备 key 和可选的 owner/super_admin 列表。它统一构造 {‘data’: send_data, ‘device_id’: device_key} 负载并通过 socketio.emit 发到各个房间:设备拥有者、全 部超级管理员、按 device_key 和 share{device_key} 命名的房间。这个 helper 让广播逻辑集中,避免在不同消息类型里重复写 emit 代码。
- process_mavlink_payload (mavlink_server_with_user.py:1139): 后台 TCP 线程或 Socket.IO 入口收到 airlink 的原始字节 流后,都通过它解析 MAVLink。流程:创建 MAVLink(None) 实例,尝试 parse_buffer(raw_data);解析成功会遍历返回的消息列 表,每种消息(GPS、姿态、SYS_STATUS 等)更新对应 send_data_* 字典。为了提速,这里在函数顶部拉取一次 super_admins, 每解析出一条消息就调用 emit_mavlink_data 立即广播。它还负责写入路径点、更新 home position 等后端状态。
- device_key: 不是函数,而是我们对设备的统一标识字符串。例如数据库里的 device.device_id(可能是序列号),在 airlink 流里作为线程/缓存的 key:airlink_streams 字典按 device_key 保存 stop_event,GPS 轨迹、home_position、 battery_current 等缓存也都用它作为下标;同时 Socket.IO 房间 room=device_key 可以让前端订阅某台设备的实时数据。
- handle_mavlink_data (mavlink_server_with_user.py:1310): 这是 Socket.IO 事件 @socketio.on(‘mavlink_data’) 的处理器, 用于收管理平台自身通过 Socket.IO 发来的 MAVLink 流(带 token)。它先用 JWT 解出 user_info,取出 device_id 和发送者 用户名,然后直接调用 process_mavlink_payload(device_id, sender_username, data) 重用同一套解析/广播逻辑。这保证无论 数据来自 airlink 的 TCP 还是前端 socket 反向推送,都走相同的处理路径。
这些函数和变量串起来的流程是:airlink_stream_worker/handle_mavlink_data 获取原始字节 → process_mavlink_payload 解析并 调用 emit_mavlink_data → 前端房间按 device_key 收到实时更新。
• 已实现后端航点读取/清除的基础流程(基于 MAVLink 请求/响应),并增加了缓存与并发控制:
- 新增缓存结构 mission_cache:按 device_id 存储期望航点数、已收集项、事件和时间戳,确保线程安全。
- process_mavlink_payload 现在会捕获 MISSION_COUNT、MISSION_ITEM/INT、MISSION_ACK,填充缓存并在收齐时触发事件。
- 新函数 build_mavlink_clear_packets:构造 MISSION_CLEAR_ALL。
- API:
- /drone/api/waypoints/clear:向设备发送清航点包(sysid=1),失败会重试一次。
- /drone/api/waypoints/read:完整读取流程:
- 清理旧缓存、建立事件;
- 发送 MISSION_REQUEST_LIST,等待 MISSION_COUNT(默认超时 5s,可传 timeout);
- 顺序发送 MISSION_REQUEST_INT 逐项请求,等待全部 MISSION_ITEM_INT/ITEM 收齐或超时;
- 返回 waypoints 列表(含 command/frame/lat/lon/alt/seq)。
- 缺陷/注意:
- 读取使用 sysid=1,若飞控 sysid 非 1,请调整。
- 未对 mission_type 分类,默认 mission。
- 超时简化处理:收不齐会返回失败提示。
- 清理机制:超过 30s 的缓存会被清理。
- 前端按钮目前仅做本地生成/清空,需改为调用新接口才能真实读/清;请按需调整前端 AJAX 至 /drone/api/waypoints/read 和 /drone/api/waypoints/clear。
文件:mavlink_server_with_user.py。请重启后端后测试。