Files
code-test-drone/utils/pod_bridge/pod_serial.py
T
keita 477ad5f5de 新增pod_bridge吊舱桥接中间件(树莓派4B部署)
- pod_bridge: 协议G版编解码/地理位置引导律/PX4网关/串口链路/闭环主循环
- 含三项安全修复: position_time_ms拆分、表2-2锁定门控、run()异常护栏
- 测试92条全绿; 附树莓派4B(Ubuntu 24.04)部署注意事项与最小依赖清单
2026-09-23 14:38:23 +08:00

69 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""pod_serial.py —— 吊舱串口链路(pyserial 8N1 + FrameParser 分帧)。
文档:波特率 115200、无校验、8N1。本模块只做字节搬运与分帧,不理解帧语义:
* poll() —— 非阻塞读取已到达字节(timeout=0 + in_waiting),喂 FrameParser,
返回本次解析出的帧列表(粘包/半帧由 FrameParser 处理);
* send() —— 写入一帧已编码字节;
* close() —— 关闭串口。
非阻塞轮询设计便于与 asyncio 桥接主循环单线程协作(无需读线程)。PodLink 为
duck-typed 接口,桥接层据此工作,测试可注入内存 FakePod,无需硬件。
"""
import logging
from typing import List, Protocol, runtime_checkable
from .protocol import FrameParser
logger = logging.getLogger(__name__)
@runtime_checkable
class PodLink(Protocol):
"""吊舱链路接口(PodSerial 实机实现 / 测试 FakePod 均满足)。"""
def poll(self) -> List[object]:
"""返回本次解析出的帧列表(Telemetry / TargetGeo 等)。"""
...
def send(self, data: bytes) -> None:
"""写入一帧已编码字节。"""
...
def close(self) -> None:
...
class PodSerial:
"""实机串口实现。pyserial 惰性导入:未装 pyserial 也能 import 本模块并用 mock。"""
def __init__(self, port: str, baudrate: int = 115200,
parser: FrameParser | None = None) -> None:
if not port:
raise ValueError("吊舱串口未配置: pod_serial.port 为空")
import serial # 惰性导入
self._ser = serial.Serial(
port=port, baudrate=baudrate,
bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=0, write_timeout=1.0,
)
self._parser = parser or FrameParser()
logger.info("[PodSerial] 打开 %s @%d 8N1", port, baudrate)
def poll(self) -> List[object]:
waiting = self._ser.in_waiting
if waiting <= 0:
return []
return self._parser.feed(self._ser.read(waiting))
def send(self, data: bytes) -> None:
self._ser.write(data)
def close(self) -> None:
try:
self._ser.close()
logger.info("[PodSerial] 串口已关闭")
except Exception as exc:
logger.warning("[PodSerial] 关闭异常: %s", exc)