# 设备处理器模块文档（Python 版本）

## 概述

设备处理器模块提供了基于 VDA5050 协议的设备管理框架，支持 MQTT 通信，用于监听和处理各类设备（AGV小车、门、电梯等）的消息，并自动转发到指定的 topic。

## 核心概念

### 设备类型 (DeviceType)

系统支持以下设备类型：
- `vehicle`: 小车/AGV
- `door`: 门
- `caller`: 呼叫器
- `lift`: 电梯
- `custom`: 自定义设备

### 设备品牌 (DeviceBrand)

系统支持以下品牌：
- `huarui`: 华睿
- `seer`: 仙工
- `hikrobot`: 海康机器人
- `standard`: 标准协议
- `custom`: 自定义品牌

### 指令类型 (CommandType)

根据设备类型不同，支持的指令类型：
- **小车设备**：`order`、`state`、`factsheet`、`instantActions`
- **其他设备**：`instantActions`

## API 方法

### 注册并运行设备处理器

```python
VWED.device.register_and_run(
    device_ids: List[str],
    device_type: str = "vehicle",
    brand_name: str = "huarui",
    command_type: str = None,
    handler: Callable = None,
    description: str = ""
)
```

**说明**：批量注册设备处理器，系统会自动：
1. 根据设备品牌和类型生成 MQTT topics
2. 订阅相应的 topics
3. 开始监听消息
4. 消息到达时自动调用处理函数
5. 自动转发处理结果

**参数**：
- `device_ids`: List[str] - 设备ID列表（必需）
- `device_type`: str - 设备类型，默认 "vehicle"
- `brand_name`: str - 设备品牌，默认 "huarui"
- `command_type`: str - 指令类型（必需），如 "order"、"state"、"instantActions"
- `handler`: Callable - 消息处理函数（必需）
- `description`: str - 设备描述信息

**返回值**：
- List[str] - 成功注册的设备ID列表

**处理函数格式**：

处理函数接收一个 `DeviceMessage` 对象作为参数，并返回一个字典，指示如何处理消息。

```python
def handler(message):
    """
    消息处理函数

    参数:
        message: DeviceMessage对象，包含以下属性：
            - device_id: str - 设备ID
            - device_type: DeviceType - 设备类型
            - topic: str - 接收消息的topic
            - payload: dict - 消息载荷（已解析为字典）
            - timestamp: float - 消息时间戳

    返回值: dict - 处理结果，支持以下字段：
        {
            "forward": bool,              # 是否转发消息（可选，默认True）
            "payload": dict,              # 要转发的消息载荷（可选，默认使用原始消息）
            "response_topic": str,        # 自定义响应topic（可选）
            "response": dict              # 自定义响应消息载荷（可选，需配合response_topic）
        }
    """
    # 处理逻辑
    return {"forward": True}
```

**返回值格式约束**：

| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| forward | bool | 否 | 是否转发消息，默认 True |
| payload | dict | 否 | 转发的消息载荷，默认使用原始消息 |
| response_topic | str | 否 | 自定义响应的 topic |
| response | dict | 否 | 自定义响应的消息载荷，需配合 response_topic |

**注意事项**：
- 返回值必须是字典类型
- `payload` 和 `response` 必须是字典类型
- 如果提供 `response`，必须同时提供 `response_topic`

### 使用示例

#### 示例1：批量注册华瑞小车处理 order 指令

```python
def agv_order_processor(message):
    """处理AGV订单指令"""
    VWED.log.info(f"收到订单: 设备 {message.device_id}")
    VWED.log.info(f"订单内容: {message.payload}")

    # 提取订单信息
    order_id = message.payload.get("orderId")
    nodes = message.payload.get("nodes", [])

    # 可以在这里添加业务逻辑，比如：
    # - 验证订单有效性
    # - 记录到数据库
    # - 通知其他系统

    # 直接透传到设备
    return {
        "forward": True  # 使用原始消息转发
    }

# 注册处理器
VWED.device.register_and_run(
    device_ids=["AGV001", "AGV002", "AGV003"],
    device_type="vehicle",
    brand_name="huarui",
    command_type="order",
    handler=agv_order_processor,
    description="华瑞小车order指令处理器"
)
```

#### 示例2：修改消息后转发

```python
def agv_state_processor(message):
    """处理AGV状态消息，添加额外信息后转发"""
    state_data = message.payload

    # 添加额外的业务信息
    enhanced_state = {
        **state_data,
        "processed_at": VWED.get_current_time(),
        "system_status": "online",
        "battery_warning": state_data.get("batteryState", {}).get("batteryCharge", 100) < 20
    }

    # 转发修改后的消息
    return {
        "forward": True,
        "payload": enhanced_state
    }

VWED.device.register_and_run(
    device_ids=["AGV001", "AGV002"],
    device_type="vehicle",
    brand_name="huarui",
    command_type="state",
    handler=agv_state_processor,
    description="AGV状态处理器（增强版）"
)
```

#### 示例3：不转发，仅记录

```python
def agv_monitor(message):
    """仅监控AGV消息，不转发"""
    # 记录到数据库
    VWED.db.execute_update(
        "INSERT INTO agv_logs (device_id, message, created_at) VALUES (?, ?, ?)",
        [message.device_id, str(message.payload), VWED.get_current_time()]
    )

    # 不转发
    return {"forward": False}

VWED.device.register_and_run(
    device_ids=["AGV001"],
    device_type="vehicle",
    brand_name="huarui",
    command_type="state",
    handler=agv_monitor,
    description="AGV监控（仅记录）"
)
```

#### 示例4：发送自定义响应

```python
def door_controller(message):
    """门控制器，接收指令后返回确认"""
    action = message.payload.get("instantActions", [])

    if action:
        action_type = action[0].get("actionType")

        # 处理开门/关门指令
        if action_type == "openDoor":
            VWED.log.info(f"门 {message.device_id} 正在开启...")
            result = "success"
        elif action_type == "closeDoor":
            VWED.log.info(f"门 {message.device_id} 正在关闭...")
            result = "success"
        else:
            result = "unknown_action"

        # 不转发原始消息，发送自定义响应
        return {
            "forward": False,
            "response_topic": f"devices/door/{message.device_id}/response",
            "response": {
                "device_id": message.device_id,
                "action": action_type,
                "result": result,
                "timestamp": VWED.get_current_time()
            }
        }

    return {"forward": False}

VWED.device.register_and_run(
    device_ids=["DOOR001", "DOOR002"],
    device_type="door",
    brand_name="huarui",
    command_type="instantActions",
    handler=door_controller,
    description="门设备控制器"
)
```

#### 示例5：条件转发

```python
def smart_forwarder(message):
    """根据条件决定是否转发"""
    battery = message.payload.get("batteryState", {}).get("batteryCharge", 100)

    # 电量低于20%时不转发，发送告警
    if battery < 20:
        VWED.log.warning(f"设备 {message.device_id} 电量过低: {battery}%")

        # 发送告警消息到告警topic
        return {
            "forward": False,
            "response_topic": "alerts/battery/low",
            "response": {
                "device_id": message.device_id,
                "battery": battery,
                "alert_level": "critical",
                "timestamp": VWED.get_current_time()
            }
        }

    # 正常转发
    return {"forward": True}

VWED.device.register_and_run(
    device_ids=["AGV001", "AGV002", "AGV003"],
    device_type="vehicle",
    brand_name="huarui",
    command_type="state",
    handler=smart_forwarder,
    description="智能转发器（低电量告警）"
)
```

### 停止设备处理器

```python
VWED.device.stop_handler(device_id: str)
```

**说明**：停止指定设备处理器的运行

**参数**：
- `device_id`: str - 设备ID

**示例**：
```python
# 停止设备处理器
VWED.device.stop_handler("AGV001")
```

### 获取运行中的处理器列表

```python
VWED.device.get_running_handlers() -> Dict[str, Any]
```

**说明**：获取所有正在运行的设备处理器信息

**返回值**：包含所有设备处理器状态的字典

**示例**：
```python
handlers = VWED.device.get_running_handlers()
VWED.log.info(f"运行中的处理器: {handlers}")
```

### 获取设备处理器状态

```python
VWED.device.get_handler_status(device_id: str) -> Dict[str, Any]
```

**说明**：获取指定设备处理器的运行状态

**参数**：
- `device_id`: str - 设备ID

**返回值**：设备处理器状态信息

**示例**：
```python
status = VWED.device.get_handler_status("AGV001")
VWED.log.info(f"设备状态: {status}")
```

### 主动发布MQTT消息

```python
await VWED.device.publish_message(topic: str, payload: Any)
```

**说明**：主动向指定 topic 发布 MQTT 消息（异步方法）

**参数**：
- `topic`: str - MQTT topic
- `payload`: dict - 消息载荷

**示例**：
```python
# 异步发布
await VWED.device.publish_message(
    topic="factory/agv/command",
    payload={"action": "move", "x": 100, "y": 200}
)

# 或使用同步方式
VWED.device.sync_publish_message(
    topic="factory/agv/command",
    payload={"action": "move", "x": 100, "y": 200}
)
```

### 获取支持的设备类型

```python
VWED.device.get_device_types() -> List[str]
```

**说明**：获取系统支持的所有设备类型

**返回值**：设备类型列表

**示例**：
```python
types = VWED.device.get_device_types()
VWED.log.info(f"支持的设备类型: {types}")
# 输出: ['vehicle', 'door', 'caller', 'lift', 'conveyor', 'sensor', 'robot', 'camera', 'scanner', 'custom']
```

### 获取支持的设备品牌

```python
VWED.device.get_device_brands() -> List[str]
```

**说明**：获取系统支持的所有设备品牌

**返回值**：设备品牌列表

**示例**：
```python
brands = VWED.device.get_device_brands()
VWED.log.info(f"支持的设备品牌: {brands}")
# 输出: ['huarui', 'seer', 'quicktron', 'geek', 'mushiny', 'flashhold', 'hikrobot', 'standard', 'custom']
```

## 完整应用示例

### 场景：AGV车队管理系统

```python
# AGV订单处理器
def process_agv_order(message):
    """处理AGV订单"""
    order_data = message.payload
    order_id = order_data.get("orderId")

    # 记录订单到数据库
    VWED.db.execute_update(
        "INSERT INTO agv_orders (device_id, order_id, data, created_at) VALUES (?, ?, ?, ?)",
        [message.device_id, order_id, str(order_data), VWED.get_current_time()]
    )

    VWED.log.info(f"AGV {message.device_id} 收到订单 {order_id}")

    # 透传订单到设备
    return {"forward": True}

# AGV状态监控
def monitor_agv_state(message):
    """监控AGV状态并记录关键信息"""
    state = message.payload
    battery = state.get("batteryState", {}).get("batteryCharge", 100)
    position = state.get("agvPosition", {})
    errors = state.get("errors", [])

    # 更新设备状态到数据库
    VWED.db.execute_update(
        "UPDATE agv_devices SET battery=?, position_x=?, position_y=?, last_update=? WHERE device_id=?",
        [battery, position.get("x"), position.get("y"), VWED.get_current_time(), message.device_id]
    )

    # 处理错误
    if errors:
        for error in errors:
            VWED.log.error(f"AGV {message.device_id} 错误: {error.get('errorDescription')}")
            # 发送告警
            VWED.device.sync_publish_message(
                topic=f"alerts/agv/{message.device_id}/error",
                payload={
                    "device_id": message.device_id,
                    "error": error,
                    "timestamp": VWED.get_current_time()
                }
            )

    # 低电量告警
    if battery < 20:
        VWED.log.warning(f"AGV {message.device_id} 电量低: {battery}%")
        VWED.device.sync_publish_message(
            topic=f"alerts/agv/{message.device_id}/battery",
            payload={
                "device_id": message.device_id,
                "battery": battery,
                "level": "warning",
                "timestamp": VWED.get_current_time()
            }
        )

    # 转发状态
    return {"forward": True}

# 注册华瑞AGV处理器
VWED.device.register_and_run(
    device_ids=["HR_AGV001", "HR_AGV002", "HR_AGV003"],
    device_type="vehicle",
    brand_name="huarui",
    command_type="order",
    handler=process_agv_order,
    description="华瑞AGV订单处理器"
)

VWED.device.register_and_run(
    device_ids=["HR_AGV001", "HR_AGV002", "HR_AGV003"],
    device_type="vehicle",
    brand_name="huarui",
    command_type="state",
    handler=monitor_agv_state,
    description="华瑞AGV状态监控"
)

# 注册仙工AGV处理器
VWED.device.register_and_run(
    device_ids=["SEER_AGV001", "SEER_AGV002"],
    device_type="vehicle",
    brand_name="seer",
    command_type="order",
    handler=process_agv_order,
    description="仙工AGV订单处理器"
)

VWED.device.register_and_run(
    device_ids=["SEER_AGV001", "SEER_AGV002"],
    device_type="vehicle",
    brand_name="seer",
    command_type="state",
    handler=monitor_agv_state,
    description="仙工AGV状态监控"
)

VWED.log.info("AGV车队管理系统已启动")
```

## 常见问题

### 1. 如何处理多个品牌的设备？

分别为每个品牌注册处理器，系统会自动根据品牌生成正确的 MQTT topic。

```python
# 华瑞设备
VWED.device.register_and_run(
    device_ids=["HR_001", "HR_002"],
    brand_name="huarui",
    command_type="order",
    handler=handler_func
)

# 仙工设备
VWED.device.register_and_run(
    device_ids=["SEER_001", "SEER_002"],
    brand_name="seer",
    command_type="order",
    handler=handler_func
)
```

### 2. 一个设备可以注册多个处理器吗？

可以，但需要处理不同的指令类型：

```python
# 处理order指令
VWED.device.register_and_run(
    device_ids=["AGV001"],
    command_type="order",
    handler=order_handler
)

# 处理state指令
VWED.device.register_and_run(
    device_ids=["AGV001"],
    command_type="state",
    handler=state_handler
)
```

### 3. 返回值必须是字典吗？

是的，必须返回字典类型，否则会记录错误日志并忽略该返回值。

### 4. 如何调试消息处理？

使用日志记录消息内容：

```python
def debug_handler(message):
    VWED.log.info(f"收到消息:")
    VWED.log.info(f"  设备ID: {message.device_id}")
    VWED.log.info(f"  Topic: {message.topic}")
    VWED.log.info(f"  载荷: {message.payload}")
    return {"forward": True}
```

## 注意事项

1. **处理函数必须返回字典**：返回值格式必须符合约定
2. **payload 必须是字典类型**：转发和响应的 payload 都必须是字典
3. **批量注册时所有设备使用相同的处理函数**：如果需要不同的处理逻辑，分别注册
4. **处理函数应该快速返回**：避免长时间阻塞，影响其他消息处理
5. **异常处理**：系统会自动捕获异常并记录日志，但建议在处理函数中添加适当的异常处理
6. **资源清理**：脚本停止时会自动清理所有注册的设备处理器
