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.
project/Src/command_center/communication
topfive 368b9eca39
功能实现1.0
9 months ago
..
__pycache__ 功能实现1.0 9 months ago
1.md 6 9 months ago
README.md 6 9 months ago
__init__.py 后端实现 9 months ago
communication_manager.py 后端实现 9 months ago
database_handler.py 后端实现 9 months ago
drone_connection_manager.py 后端实现 9 months ago
mavlink_handler.py 后端实现 9 months ago
message_queue.py 后端实现 9 months ago

README.md

我会帮你实现通信模块。首先,我们需要创建通信模块的目录结构和相关文件。让我们先看看是否已经有相关的目录:

Ran tool

我们需要创建一个新的通信模块。我会创建以下文件:

  1. communication/ 目录
  2. mavlink_handler.py - MAVLink通信处理
  3. database_handler.py - 数据库操作
  4. message_queue.py - 消息队列管理
  5. __init__.py - 模块初始化文件

我已经完成了通信模块的实现,这个模块包含以下主要组件:

  1. MavlinkHandler - MAVLink通信处理器

    • 负责建立和维护MAVLink连接
    • 处理MAVLink消息的发送和接收
    • 支持消息回调注册
    • 使用线程进行异步消息处理
  2. DatabaseHandler - 数据库处理器:

    • 负责MySQL数据库的连接和管理
    • 提供数据库表的创建和管理
    • 支持MAVLink消息的存储和查询
    • 管理无人机状态信息的存储和更新
  3. MessageQueue - 消息队列:

    • 提供线程安全的消息队列实现
    • 支持消息的异步处理
    • 提供回调机制
    • 包含消息时间戳
  4. CommunicationManager - 通信管理器:

    • 协调MAVLink和数据库组件
    • 处理消息的路由和分发
    • 管理无人机状态更新
    • 提供统一的接口访问通信功能

要使用这个通信模块,你需要:

  1. 安装必要的依赖:
pip install pymavlink mysql-connector-python
  1. 配置数据库连接:
db_config = {
    'host': 'localhost',
    'user': 'your_username',
    'password': 'your_password',
    'database': 'drone_control'
}
  1. 初始化通信管理器:
from command_center.communication import CommunicationManager

# 创建通信管理器实例
comm_manager = CommunicationManager(
    mavlink_connection="udp:127.0.0.1:14550",  # MAVLink连接字符串
    db_config=db_config
)

# 启动通信管理器
if comm_manager.start():
    print("通信管理器启动成功")
    
    # 获取无人机状态
    drone_status = comm_manager.get_drone_status("drone_1")
    print(f"无人机状态: {drone_status}")
    
    # 获取消息队列
    message_queue = comm_manager.get_message_queue()
    
    # 注册消息回调
    def on_message():
        msg = message_queue.get()
        if msg:
            print(f"收到消息: {msg}")
    
    message_queue.register_callback(on_message)

这个通信模块提供了完整的MAVLink通信和数据库集成功能可以

  1. 接收和处理MAVLink消息
  2. 将消息存储到MySQL数据库
  3. 实时更新无人机状态
  4. 提供消息队列和回调机制
  5. 支持多线程异步处理

你可以根据需要扩展这个模块,比如:

  1. 添加更多的MAVLink消息处理
  2. 实现更复杂的数据库查询
  3. 添加消息过滤和转换功能
  4. 实现消息重传机制
  5. 添加错误处理和恢复机制

需要我详细解释某个部分或者添加其他功能吗?

我来详细描述一下当前通信模块的工作流程:

  1. 初始化阶段

    • 创建 CommunicationManager 实例,传入 MAVLink 连接字符串和数据库配置
    • 初始化三个核心组件:
      • MavlinkHandler:负责 MAVLink 通信
      • DatabaseHandler:负责数据库操作
      • MessageQueue:负责消息队列管理
  2. 启动阶段(调用 start() 方法):

    • 首先连接数据库
    • 创建必要的数据库表(mavlink_messagesdrone_status
    • 建立 MAVLink 连接
    • 注册三个关键消息的回调函数:
      • HEARTBEAT:心跳消息
      • GLOBAL_POSITION_INT:位置信息
      • SYS_STATUS:系统状态
    • 启动 MAVLink 消息接收线程
    • 启动消息处理线程
  3. 消息接收流程

    MAVLink设备 -> MavlinkHandler -> MessageQueue -> CommunicationManager -> DatabaseHandler
    
    • MavlinkHandler 通过 _receive_loop 持续监听 MAVLink 消息
    • 收到消息后,调用 _handle_message 处理
    • 消息被放入 MessageQueue 队列
    • 同时触发注册的回调函数
  4. 消息处理流程

    MessageQueue -> CommunicationManager._process_messages -> 数据库存储/状态更新
    
    • CommunicationManager_process_messages 线程从队列获取消息
    • 对消息进行分类处理:
      • 保存到数据库的 mavlink_messages
      • 根据消息类型更新 drone_status
      • 位置消息:更新经纬度和高度
      • 状态消息:更新电池电量和系统状态
  5. 数据库操作

    • 所有 MAVLink 消息都被保存到 mavlink_messages
    • 无人机状态信息被保存到 drone_status
    • 支持按时间范围和消息类型查询历史消息
    • 支持获取最新的无人机状态
  6. 消息回调机制

    • 支持注册消息回调函数
    • 当收到特定类型的消息时,自动触发对应的回调
    • 回调函数可以处理消息并执行自定义逻辑
  7. 错误处理

    • 连接失败时的重试机制
    • 消息处理异常的错误捕获
    • 数据库操作的异常处理和回滚
  8. 停止流程(调用 stop() 方法):

    • 停止消息处理线程
    • 停止 MAVLink 连接
    • 断开数据库连接
    • 清理资源

这个通信模块的设计特点:

  1. 异步处理:使用多线程实现消息的异步接收和处理
  2. 数据持久化:所有消息都被保存到数据库,便于后续分析
  3. 状态管理:实时维护无人机的最新状态
  4. 可扩展性:通过回调机制支持自定义消息处理
  5. 错误恢复:包含完整的错误处理机制

使用示例:

# 初始化
comm_manager = CommunicationManager(
    mavlink_connection="udp:127.0.0.1:14550",
    db_config={
        'host': 'localhost',
        'user': 'root',
        'password': 'password',
        'database': 'drone_control'
    }
)

# 启动通信
comm_manager.start()

# 获取无人机状态
drone_status = comm_manager.get_drone_status("drone_1")

# 注册消息回调
def on_message():
    msg = comm_manager.get_message_queue().get()
    if msg:
        print(f"收到消息: {msg}")

comm_manager.get_message_queue().register_callback(on_message)

这个通信模块提供了一个完整的解决方案,可以:

  1. 实时接收和处理 MAVLink 消息
  2. 将消息持久化到数据库
  3. 维护无人机的最新状态
  4. 支持自定义消息处理
  5. 提供错误恢复机制

让我详细解释一下与无人机建立连接的过程。在当前的实现中,连接建立主要发生在 MavlinkHandler 类中,通过 connect() 方法实现。让我们看看具体的连接流程:

  1. 连接初始化
# 在 MavlinkHandler 类中
def __init__(self, connection_string: str = "udp:127.0.0.1:14550"):
    self.connection_string = connection_string
    self.connection = None
    # ... 其他初始化代码
  1. 建立连接
def connect(self) -> bool:
    """建立MAVLink连接"""
    try:
        # 创建MAVLink连接
        self.connection = mavutil.mavlink_connection(self.connection_string)
        # 等待心跳包,确认连接成功
        self.connection.wait_heartbeat()
        print(f"MAVLink连接成功: {self.connection_string}")
        return True
    except Exception as e:
        print(f"MAVLink连接失败: {str(e)}")
        return False

连接建立的关键点:

  1. 连接字符串格式

    • 支持多种连接方式:
      • UDP: "udp:IP:PORT" (例如: "udp:127.0.0.1:14550")
      • TCP: "tcp:IP:PORT"
      • 串口: "serial:PORT,BAUDRATE" (例如: "serial:/dev/ttyUSB0,57600")
      • 蓝牙: "bluetooth:ADDRESS"
  2. 连接验证

    • 通过 wait_heartbeat() 等待无人机发送心跳包
    • 心跳包是MAVLink协议中的基础消息用于确认连接状态
    • 如果在一定时间内没有收到心跳包,连接会失败
  3. 连接状态管理

    • 连接成功后,connection 对象会被保存
    • 用于后续的消息发送和接收
    • 连接失败时会返回 False,上层可以处理错误

要使用这个连接功能,你需要:

  1. 确定连接方式

    • 如果无人机使用地面站软件如QGroundControl通常使用UDP连接
    • 如果直接连接飞控,可能需要使用串口连接
    • 连接字符串需要根据实际情况配置
  2. 配置连接参数

# UDP连接示例
mavlink_connection = "udp:127.0.0.1:14550"  # 本地UDP连接

# 串口连接示例
mavlink_connection = "serial:/dev/ttyUSB0,57600"  # Linux系统
# 或
mavlink_connection = "serial:COM3,57600"  # Windows系统
  1. 建立连接
# 创建通信管理器
comm_manager = CommunicationManager(
    mavlink_connection="udp:127.0.0.1:14550",  # 根据实际情况修改
    db_config={
        'host': 'localhost',
        'user': 'root',
        'password': 'password',
        'database': 'drone_control'
    }
)

# 启动连接
if comm_manager.start():
    print("连接成功")
else:
    print("连接失败,请检查连接参数")
  1. 连接后的操作

    • 发送命令:使用 send_message 方法
    • 接收消息:通过消息队列或回调函数
    • 监控状态:通过数据库查询
  2. 错误处理

    • 连接失败时会有错误提示
    • 可以设置重试机制
    • 可以添加连接状态监控

建议的连接使用流程:

  1. 准备阶段
def setup_connection():
    # 配置连接参数
    connection_config = {
        'mavlink': {
            'type': 'udp',  # 或 'serial', 'tcp' 等
            'address': '127.0.0.1',
            'port': 14550,
            'baudrate': 57600  # 串口连接时需要
        },
        'database': {
            'host': 'localhost',
            'user': 'root',
            'password': 'password',
            'database': 'drone_control'
        }
    }
    
    # 构建连接字符串
    if connection_config['mavlink']['type'] == 'udp':
        connection_string = f"udp:{connection_config['mavlink']['address']}:{connection_config['mavlink']['port']}"
    elif connection_config['mavlink']['type'] == 'serial':
        connection_string = f"serial:{connection_config['mavlink']['address']},{connection_config['mavlink']['baudrate']}"
    
    return connection_string, connection_config['database']
  1. 连接建立
def establish_connection():
    connection_string, db_config = setup_connection()
    
    # 创建通信管理器
    comm_manager = CommunicationManager(connection_string, db_config)
    
    # 尝试连接
    max_retries = 3
    retry_count = 0
    
    while retry_count < max_retries:
        if comm_manager.start():
            print("连接成功")
            return comm_manager
        else:
            retry_count += 1
            print(f"连接失败,第{retry_count}次重试...")
            time.sleep(2)  # 等待2秒后重试
    
    print("连接失败,达到最大重试次数")
    return None
  1. 连接监控
def monitor_connection(comm_manager):
    def heartbeat_callback(msg):
        print(f"收到心跳包: {msg.to_dict()}")
    
    # 注册心跳回调
    comm_manager.mavlink.register_callback('HEARTBEAT', heartbeat_callback)
    
    # 定期检查连接状态
    while True:
        if not comm_manager.mavlink.connection:
            print("连接断开,尝试重连...")
            if not comm_manager.mavlink.connect():
                print("重连失败")
                break
        time.sleep(1)

这个连接模块提供了灵活的连接方式,可以根据不同的无人机和飞控配置选择合适的连接参数。同时,它也包含了错误处理和重试机制,确保连接的可靠性。

需要注意的是:

  1. 确保无人机和地面站软件如QGroundControl使用相同的端口
  2. 串口连接时需要正确的端口号和波特率
  3. 防火墙设置可能会影响UDP/TCP连接
  4. 建议在连接前先测试基本的MAVLink通信

你可以根据实际需求调整连接参数和错误处理策略。需要我详细解释某个部分吗?

MAVLink 消息的格式是标准化的二进制协议格式。让我详细解释一下 MAVLink 消息的格式和结构:

  1. MAVLink 消息基本结构
+-------------------+------------------+------------------+------------------+------------------+
| 起始标记 (0xFE)   | 载荷长度 (1字节) | 序列号 (1字节)   | 系统ID (1字节)   | 组件ID (1字节)   |
+-------------------+------------------+------------------+------------------+------------------+
| 消息ID (1字节)    | 载荷数据 (N字节) | CRC校验 (2字节)  |
+-------------------+------------------+------------------+
  1. 消息字段说明

    • 起始标记 (0xFE):标识消息开始
    • 载荷长度消息载荷的长度不包括头部和CRC
    • 序列号:用于检测消息丢失
    • 系统ID发送系统的ID如无人机ID
    • 组件ID发送组件的ID如飞控、相机等
    • 消息ID:标识消息类型
    • 载荷数据:实际的消息内容
    • CRC校验:用于验证消息完整性
  2. 常见消息类型

# 心跳消息 (HEARTBEAT)
{
    'type': 'HEARTBEAT',
    'system_status': 0,  # 系统状态
    'base_mode': 0,      # 基础模式
    'custom_mode': 0,    # 自定义模式
    'mavlink_version': 3 # MAVLink版本
}

# 位置消息 (GLOBAL_POSITION_INT)
{
    'type': 'GLOBAL_POSITION_INT',
    'time_boot_ms': 0,    # 启动时间
    'lat': 0,             # 纬度 (度 * 1e7)
    'lon': 0,             # 经度 (度 * 1e7)
    'alt': 0,             # 高度 (毫米)
    'relative_alt': 0,    # 相对高度 (毫米)
    'vx': 0,              # X方向速度 (厘米/秒)
    'vy': 0,              # Y方向速度 (厘米/秒)
    'vz': 0,              # Z方向速度 (厘米/秒)
    'hdg': 0              # 航向 (度 * 100)
}

# 系统状态消息 (SYS_STATUS)
{
    'type': 'SYS_STATUS',
    'onboard_control_sensors_present': 0,  # 存在的传感器
    'onboard_control_sensors_enabled': 0,  # 启用的传感器
    'onboard_control_sensors_health': 0,   # 传感器健康状态
    'load': 0,                             # 处理器负载
    'voltage_battery': 0,                  # 电池电压
    'current_battery': 0,                  # 电池电流
    'battery_remaining': 0,                # 剩余电量百分比
    'drop_rate_comm': 0,                   # 通信丢包率
    'errors_comm': 0,                      # 通信错误
    'errors_count1': 0,                    # 错误计数1
    'errors_count2': 0,                    # 错误计数2
    'errors_count3': 0,                    # 错误计数3
    'errors_count4': 0                     # 错误计数4
}
  1. 消息处理示例
# 在 MavlinkHandler 类中处理消息
def _handle_message(self, msg):
    """处理接收到的MAVLink消息"""
    msg_type = msg.get_type()
    msg_data = msg.to_dict()
    
    # 根据消息类型处理
    if msg_type == 'HEARTBEAT':
        self._handle_heartbeat(msg_data)
    elif msg_type == 'GLOBAL_POSITION_INT':
        self._handle_position(msg_data)
    elif msg_type == 'SYS_STATUS':
        self._handle_system_status(msg_data)
    
    # 将消息放入队列
    self.message_queue.put({
        'type': msg_type,
        'data': msg_data,
        'timestamp': datetime.now()
    })
  1. 消息发送示例
# 发送命令消息
def send_command(self, command_type: str, **kwargs):
    """发送MAVLink命令"""
    try:
        # 构建命令消息
        msg = self.connection.mav.command_long_send(
            self.connection.target_system,    # 目标系统ID
            self.connection.target_component, # 目标组件ID
            command_type,                     # 命令类型
            0,                               # 确认
            *kwargs.values()                 # 命令参数
        )
        return True
    except Exception as e:
        print(f"发送命令失败: {str(e)}")
        return False
  1. 消息转换和存储
# 在 DatabaseHandler 中存储消息
def save_mavlink_message(self, msg_type: str, msg_data: Dict) -> bool:
    """保存MAVLink消息到数据库"""
    query = """
    INSERT INTO mavlink_messages 
    (message_type, message_data, timestamp) 
    VALUES (%s, %s, %s)
    """
    params = (
        msg_type,
        json.dumps(msg_data),  # 将消息数据转换为JSON格式存储
        datetime.now()
    )
    return self.execute_update(query, params)
  1. 消息查询示例
# 查询特定类型的消息
def get_messages_by_type(self, msg_type: str, 
                        start_time: Optional[datetime] = None,
                        end_time: Optional[datetime] = None) -> List[Dict]:
    """获取特定类型的MAVLink消息"""
    query = """
    SELECT * FROM mavlink_messages 
    WHERE message_type = %s
    """
    params = [msg_type]
    
    if start_time:
        query += " AND timestamp >= %s"
        params.append(start_time)
    if end_time:
        query += " AND timestamp <= %s"
        params.append(end_time)
        
    query += " ORDER BY timestamp DESC"
    return self.execute_query(query, tuple(params))

MAVLink 消息的特点:

  1. 二进制格式:高效的数据传输
  2. 固定头部:便于消息识别和解析
  3. 可变载荷:支持不同类型的数据
  4. CRC校验:确保数据完整性
  5. 系统/组件ID:支持多设备通信
  6. 序列号:支持消息顺序和丢失检测

在实际使用中,我们不需要直接处理二进制格式,因为 pymavlink 库已经帮我们处理了消息的编码和解码。我们只需要关注消息的内容和类型即可。

需要我详细解释某个具体的消息类型或处理过程吗?