VWED_server/docs/sc/设备处理器相关.md

568 lines
15 KiB
Markdown
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.

# 设备处理器模块文档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. **资源清理**:脚本停止时会自动清理所有注册的设备处理器