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