VWED_server/docs/device_handler_examples.md

1426 lines
44 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.

# VWED设备处理器使用示例文档
## 概述
本文档详细说明了在VWED在线脚本中如何使用更新后的设备处理器功能特别是对VDA5050协议的支持。
**核心特点:**
- **消息透传模式**: 消息直接透传,不进行编解码处理,保持原始数据格式
- **内置MQTT服务**: 集成自己的MQTT客户端自主管理连接和重连
- **多设备类型支持**: 支持vehicle、door、caller、lift、sensor、robot等设备类型
- **多品牌支持**: 支持huarui、seer、quicktron、geek等主流设备品牌
- **注册即运行**: 调用 `VWED.device.register_and_run()` 后立即开始监听MQTT消息
- **自动处理**: 消息到达时自动调用您定义的处理函数
- **自动转发**: 处理完成后自动发送到指定topic
- **持续运行**: 一次注册,持续处理消息直到手动停止
- **脚本ID自动关联**: `script_id` 参数由系统在热加载时自动传入,无需用户手动提供
---
## 1. VDA5050协议小车设备示例
### 1.1 VDA5050小车注册和处理
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def boot():
"""VDA5050小车处理脚本启动函数"""
# 注册华睿小车处理器(消息透传模式)
VWED.device.register_and_run(
device_id="huarui_agv_001",
device_type="vehicle",
listen_topics=["vda5050/v2/huarui_agv_001/state", "vda5050/v2/huarui_agv_001/factsheet"],
forward_topics=["fleet/huarui_agv_001/status"],
handler=vda5050_vehicle_handler,
device_brand="huarui",
protocol_type="vda5050", # 协议类型
description="华睿小车处理器"
)
def vda5050_vehicle_handler(message):
"""VDA5050小车消息处理器"""
device_id = message.device_id
payload = message.payload
VWED.log.sync_info(f"收到VDA5050小车 {device_id} 消息: {payload}")
# 根据消息内容处理(消息透传,保持原始格式)
# 可以根据实际消息格式调整解析逻辑
message_type = payload.get('message_type', payload.get('command_type', 'unknown'))
if message_type == 'state_response' or 'driving' in payload:
# 处理状态响应
driving = payload.get('driving', False)
paused = payload.get('paused', False)
operating_mode = payload.get('operating_mode', 'unknown')
battery_state = payload.get('battery_state', {})
agv_position = payload.get('agv_position', {})
VWED.log.sync_info(f"小车状态 - 运行: {driving}, 暂停: {paused}, 模式: {operating_mode}")
VWED.log.sync_info(f"电池状态: {battery_state}")
VWED.log.sync_info(f"位置: {agv_position}")
# 检查低电量警告
battery_charge = battery_state.get('batteryCharge', 100)
if battery_charge < 20:
VWED.log.sync_warning(f"小车 {device_id} 电量不足: {battery_charge}%")
# 发送低电量警报
alert = {
"type": "low_battery_alert",
"device_id": device_id,
"battery_level": battery_charge,
"timestamp": VWED.util.now()
}
return {
"forward": True,
"topics": ["fleet/alerts", "fleet/huarui_agv_001/status"],
"payload": [alert, payload]
}
elif message_type == 'factsheet_response' or 'manufacturer' in payload:
# 处理设备信息响应
manufacturer = payload.get('manufacturer', '')
serial_number = payload.get('serial_number', '')
type_spec = payload.get('type_specification', {})
VWED.log.sync_info(f"设备信息 - 制造商: {manufacturer}, 序列号: {serial_number}")
# 存储设备信息到缓存
VWED.data.set(f"device_info_{device_id}", {
"manufacturer": manufacturer,
"serial_number": serial_number,
"type_specification": type_spec,
"updated_at": VWED.util.now()
})
# 默认转发消息
return {
"forward": True,
"payload": {
"device_id": device_id,
"original_data": payload,
"processed_at": VWED.util.now()
}
}
# VDA5050指令发送示例
def send_vda5050_order_example():
"""发送VDA5050订单指令示例"""
# 构建订单数据
order_data = {
"order_id": f"order_{int(VWED.util.timestamp())}",
"nodes": [
{
"nodeId": "pickup_station",
"sequenceId": 1,
"nodePosition": {"x": 10.5, "y": 20.3, "theta": 0.0, "mapId": "warehouse_map"},
"actions": [
{
"actionType": "pick",
"actionId": "pick_001",
"actionDescription": "Pick up cargo",
"blockingType": "HARD",
"actionParameters": [
{"key": "load_type", "value": "box"},
{"key": "weight", "value": "5"}
]
}
]
},
{
"nodeId": "delivery_station",
"sequenceId": 2,
"nodePosition": {"x": 30.0, "y": 45.0, "theta": 1.57, "mapId": "warehouse_map"},
"actions": [
{
"actionType": "drop",
"actionId": "drop_001",
"actionDescription": "Drop cargo",
"blockingType": "HARD"
}
]
}
],
"edges": [
{
"edgeId": "edge_pickup_to_delivery",
"sequenceId": 1,
"startNodeId": "pickup_station",
"endNodeId": "delivery_station",
"maxSpeed": 1.5,
"actions": []
}
]
}
# 发送订单
VWED.device.send_order("huarui_agv_001", order_data)
VWED.log.sync_info("订单已发送")
def send_emergency_stop():
"""发送紧急停止指令"""
emergency_actions = [
{
"actionType": "cancelOrder",
"actionId": f"emergency_stop_{int(VWED.util.timestamp())}",
"actionDescription": "Emergency stop - cancel current order",
"blockingType": "HARD"
}
]
VWED.device.send_instant_action("huarui_agv_001", emergency_actions)
VWED.log.sync_warning("紧急停止指令已发送")
def request_vehicle_state():
"""请求小车状态"""
VWED.device.request_state("huarui_agv_001")
VWED.log.sync_info("状态查询请求已发送")
```
### 1.2 门设备即时动作示例
```python
def boot():
"""门设备VDA5050即时动作处理"""
# 注册门设备处理器
VWED.device.register_and_run(
device_id="door_001",
device_type="door",
listen_topics=["door/door_001/status"],
forward_topics=["facility/door_001/events"],
handler=door_instant_action_handler,
device_brand="standard",
protocol_type="vda5050",
description="门设备处理器"
)
def door_instant_action_handler(message):
"""门设备即时动作处理器"""
device_id = message.device_id
payload = message.payload
VWED.log.sync_info(f"收到门设备 {device_id} 消息: {payload}")
door_status = payload.get('door_status', 'unknown')
if door_status == 'access_requested':
# 处理门禁访问请求
card_id = payload.get('card_id')
# 验证访问权限
if is_authorized_card(card_id):
# 发送开门指令
open_actions = [
{
"actionType": "open",
"actionId": f"open_{int(VWED.util.timestamp())}",
"actionDescription": f"Open door for card {card_id}",
"blockingType": "SOFT",
"actionParameters": [
{"key": "duration", "value": "5"}, # 开门5秒
{"key": "card_id", "value": card_id}
]
}
]
VWED.device.send_instant_action("door_001", open_actions, "door/door_001/control")
VWED.log.sync_info(f"已授权开门: {card_id}")
return {
"forward": True,
"payload": {
"event": "access_granted",
"card_id": card_id,
"timestamp": VWED.util.now()
}
}
else:
VWED.log.sync_warning(f"未授权访问被拒绝: {card_id}")
return {
"forward": True,
"payload": {
"event": "access_denied",
"card_id": card_id,
"reason": "unauthorized",
"timestamp": VWED.util.now()
}
}
return {"forward": True, "payload": payload}
def is_authorized_card(card_id):
"""检查卡片是否有权限"""
authorized_cards = VWED.data.get("authorized_cards", ["CARD001", "CARD002", "CARD003"])
return card_id in authorized_cards
```
### 1.3 通用设备即时动作示例
```python
def boot():
"""传感器设备即时动作处理"""
# 注册传感器设备
VWED.device.register_and_run(
device_id="temp_sensor_001",
device_type="sensor",
listen_topics=["sensors/temperature/001/data"],
forward_topics=["environmental/alerts"],
handler=sensor_instant_action_handler,
device_brand="standard",
protocol_type="vda5050",
description="温度传感器处理器"
)
def sensor_instant_action_handler(message):
"""传感器即时动作处理器"""
device_id = message.device_id
payload = message.payload
temperature = payload.get('temperature', 0)
VWED.log.sync_info(f"传感器 {device_id} 温度: {temperature}°C")
if temperature > 35:
# 温度过高,发送冷却指令
cooling_actions = [
{
"actionType": "cooling_control",
"actionId": f"cool_{int(VWED.util.timestamp())}",
"actionDescription": "Activate cooling system",
"blockingType": "SOFT",
"actionParameters": [
{"key": "target_temp", "value": "25"},
{"key": "priority", "value": "high"}
]
}
]
VWED.device.send_instant_action("temp_sensor_001", cooling_actions, "hvac/control")
return {
"forward": True,
"payload": {
"alert_type": "temperature_high",
"temperature": temperature,
"action_taken": "cooling_activated",
"timestamp": VWED.util.now()
}
}
return {"forward": False} # 正常温度不转发
```
---
## 2. 传统协议小车设备示例
### 1.1 基本小车命令处理
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def boot():
"""脚本启动函数"""
# 注册并运行AGV设备处理器
VWED.device.register_and_run(
device_id="agv_001",
device_type="vehicle",
listen_topics=["factory/agv/command"],
forward_topics=["factory/agv/execute"],
handler=agv_command_processor,
device_brand="standard",
protocol_type="vda5050",
description="AGV命令处理器 - 添加安全检查"
)
def agv_command_processor(message):
"""AGV命令处理逻辑 - 消息到达时自动执行"""
# 记录接收到的消息
VWED.log.sync_info(f"收到AGV命令: {message.payload}")
command = message.payload.get("command")
if command == "move":
# 添加安全检查逻辑
x = message.payload.get("x", 0)
y = message.payload.get("y", 0)
speed = message.payload.get("speed", 100)
# 限制最大速度
safe_speed = min(speed, 50)
# 检查坐标范围
if x < 0 or x > 1000 or y < 0 or y > 800:
VWED.log.sync_warning(f"AGV坐标超出安全范围: x={x}, y={y}")
return {
"forward": False, # 不转发
"response": {
"status": "error",
"message": "坐标超出安全范围"
},
"response_topic": "factory/agv/response"
}
# 构建安全的移动命令
safe_command = {
"command": "move_safe",
"x": x,
"y": y,
"speed": safe_speed,
"safety_check": True,
"timestamp": VWED.util.now(),
"processed_by": "agv_001_processor"
}
VWED.log.sync_info(f"AGV安全命令已生成: 速度限制 {speed} -> {safe_speed}")
return {
"forward": True,
"payload": safe_command
}
elif command == "stop":
# 紧急停止 - 直接转发
emergency_stop = {
"command": "emergency_stop",
"reason": message.payload.get("reason", "manual_stop"),
"timestamp": VWED.util.now()
}
return {
"forward": True,
"payload": emergency_stop
}
else:
# 未知命令 - 记录并拒绝
VWED.log.sync_warning(f"未知AGV命令: {command}")
return {
"forward": False,
"response": {
"status": "error",
"message": f"不支持的命令: {command}"
},
"response_topic": "factory/agv/response"
}
```
**MQTT消息流转示例:**
```
输入topic: factory/agv/command
输入消息: {"command": "move", "x": 100, "y": 200, "speed": 80}
处理后输出topic: factory/agv/execute
输出消息: {"command": "move_safe", "x": 100, "y": 200, "speed": 50, "safety_check": true, "timestamp": "2024-01-01T12:00:00", "processed_by": "agv_001_processor"}
```
### 1.2 多AGV协调处理
```python
def boot():
"""多AGV统一处理"""
# 注册AGV车队控制器
VWED.device.register_and_run(
device_id="agv_fleet_controller",
device_type="vehicle",
listen_topics=["factory/agv/+/command"], # 监听所有AGV命令
forward_topics=["factory/agv/coordination"],
handler=agv_fleet_coordinator,
device_brand="standard",
protocol_type="vda5050",
description="AGV车队协调器"
)
def agv_fleet_coordinator(message):
"""AGV车队协调逻辑"""
# 解析AGV ID
topic_parts = message.topic.split("/")
agv_id = topic_parts[2] if len(topic_parts) > 2 else "unknown"
command = message.payload.get("command")
if command == "move":
# 检查路径冲突
x = message.payload.get("x")
y = message.payload.get("y")
# 获取其他AGV位置从缓存中
other_agvs = VWED.data.get("agv_positions", {})
# 简单的冲突检测
conflict_detected = False
for other_id, other_pos in other_agvs.items():
if other_id != agv_id:
distance = ((x - other_pos["x"])**2 + (y - other_pos["y"])**2)**0.5
if distance < 50: # 50cm安全距离
conflict_detected = True
break
if conflict_detected:
# 发送等待指令
wait_command = {
"command": "wait",
"reason": "path_conflict",
"retry_after": 3, # 3秒后重试
"timestamp": VWED.util.now()
}
VWED.log.sync_warning(f"AGV {agv_id} 路径冲突,指令等待")
return {
"forward": True,
"topics": [f"factory/agv/{agv_id}/execute"],
"payload": wait_command
}
else:
# 更新AGV位置缓存
other_agvs[agv_id] = {"x": x, "y": y, "timestamp": VWED.util.now()}
VWED.data.set("agv_positions", other_agvs)
# 转发原始命令
return {
"forward": True,
"topics": [f"factory/agv/{agv_id}/execute"],
"payload": message.payload
}
# 默认转发
return {
"forward": True,
"topics": [f"factory/agv/{agv_id}/execute"],
"payload": message.payload
}
```
---
## 2. 门禁(Door)设备处理示例
### 2.1 基本门禁控制
```python
def boot():
"""门禁系统处理器"""
VWED.device.register_and_run(
device_id="door_main_entrance",
device_type="door",
listen_topics=["building/door/access_request"],
forward_topics=["building/door/control"],
handler=door_access_controller,
device_brand="standard",
protocol_type="vda5050",
description="主入口门禁控制器"
)
def door_access_controller(message):
"""门禁访问控制逻辑"""
# 获取访问请求信息
card_id = message.payload.get("card_id")
door_id = message.payload.get("door_id", "main_entrance")
request_time = message.payload.get("timestamp", VWED.util.now())
VWED.log.sync_info(f"门禁访问请求: 卡号={card_id}, 门={door_id}")
# 权限验证逻辑
if not card_id:
return {
"forward": False,
"response": {"status": "error", "message": "缺少卡号"},
"response_topic": "building/door/response"
}
# 检查黑名单
blacklist = VWED.data.get("door_blacklist", [])
if card_id in blacklist:
VWED.log.sync_warning(f"黑名单卡号访问被拒绝: {card_id}")
return {
"forward": False,
"response": {
"status": "denied",
"reason": "blacklist",
"card_id": card_id,
"timestamp": request_time
},
"response_topic": "building/door/response"
}
# 检查白名单
whitelist = VWED.data.get("door_whitelist", [
"CARD001", "CARD002", "CARD003" # 默认白名单
])
if card_id in whitelist:
# 授权开门
open_command = {
"action": "open",
"door_id": door_id,
"card_id": card_id,
"authorized_by": "door_main_entrance",
"open_duration": 5, # 开门5秒
"timestamp": request_time
}
# 记录访问日志
access_log = VWED.data.get("door_access_log", [])
access_log.append({
"card_id": card_id,
"door_id": door_id,
"status": "granted",
"timestamp": request_time
})
# 只保留最近100条记录
if len(access_log) > 100:
access_log = access_log[-100:]
VWED.data.set("door_access_log", access_log)
VWED.log.sync_info(f"门禁访问已授权: {card_id}")
return {
"forward": True,
"payload": open_command
}
else:
# 未授权卡号
VWED.log.sync_warning(f"未授权卡号访问被拒绝: {card_id}")
return {
"forward": False,
"response": {
"status": "denied",
"reason": "unauthorized",
"card_id": card_id,
"timestamp": request_time
},
"response_topic": "building/door/response"
}
```
### 2.2 门禁状态监控
```python
def boot():
"""门禁状态监控"""
# 监控门禁状态
VWED.device.register_and_run(
device_id="door_status_monitor",
device_type="door",
listen_topics=["building/door/+/status"],
forward_topics=["building/security/alerts"],
handler=door_status_monitor,
device_brand="standard",
protocol_type="vda5050",
description="门禁状态监控器"
)
def door_status_monitor(message):
"""门禁状态监控逻辑"""
# 解析门ID
topic_parts = message.topic.split("/")
door_id = topic_parts[2] if len(topic_parts) > 2 else "unknown"
status = message.payload.get("status")
timestamp = message.payload.get("timestamp", VWED.util.now())
# 更新门状态缓存
door_states = VWED.data.get("door_states", {})
door_states[door_id] = {
"status": status,
"timestamp": timestamp,
"last_update": VWED.util.now()
}
VWED.data.set("door_states", door_states)
# 异常状态检测
if status == "forced_open":
# 门被强制打开 - 发送安全警报
alert = {
"type": "security_alert",
"level": "high",
"door_id": door_id,
"event": "forced_open",
"message": f"门 {door_id} 被强制打开",
"timestamp": timestamp,
"requires_action": True
}
VWED.log.sync_error(f"安全警报: 门 {door_id} 被强制打开")
return {
"forward": True,
"payload": alert
}
elif status == "open_timeout":
# 门打开超时 - 发送提醒
alert = {
"type": "maintenance_alert",
"level": "medium",
"door_id": door_id,
"event": "open_timeout",
"message": f"门 {door_id} 打开时间过长",
"timestamp": timestamp,
"requires_action": False
}
VWED.log.sync_warning(f"维护提醒: 门 {door_id} 打开时间过长")
return {
"forward": True,
"payload": alert
}
# 正常状态 - 不转发
return {"forward": False}
```
---
## 3. 呼叫器(Caller)设备处理示例
### 3.1 基本呼叫处理
```python
def boot():
"""呼叫器处理系统"""
VWED.device.register_and_run(
device_id="caller_lobby_01",
device_type="caller",
listen_topics=["building/caller/signal"],
forward_topics=["building/caller/response", "building/notification/broadcast"],
handler=caller_signal_processor,
device_brand="standard",
protocol_type="vda5050",
description="大厅呼叫器信号处理器"
)
def caller_signal_processor(message):
"""呼叫器信号处理逻辑"""
caller_id = message.payload.get("caller_id")
signal_type = message.payload.get("signal_type")
location = message.payload.get("location", "unknown")
priority = message.payload.get("priority", "normal")
VWED.log.sync_info(f"收到呼叫信号: {caller_id} - {signal_type} ({priority})")
# 根据信号类型处理
if signal_type == "emergency":
# 紧急呼叫 - 立即响应
emergency_response = {
"type": "emergency_response",
"caller_id": caller_id,
"location": location,
"status": "received",
"response_time": "immediate",
"assigned_staff": "security_team",
"message": "紧急响应团队已派遣",
"timestamp": VWED.util.now()
}
# 广播紧急通知
emergency_broadcast = {
"type": "emergency_broadcast",
"level": "critical",
"message": f"紧急呼叫: {location} ({caller_id})",
"location": location,
"caller_id": caller_id,
"timestamp": VWED.util.now()
}
VWED.log.sync_error(f"紧急呼叫处理: {caller_id} 位置: {location}")
return {
"forward": True,
"topics": ["building/caller/response", "building/notification/broadcast"],
"payload": [emergency_response, emergency_broadcast]
}
elif signal_type == "service":
# 服务请求 - 分配服务人员
service_response = {
"type": "service_response",
"caller_id": caller_id,
"location": location,
"status": "queued",
"estimated_time": "5-10 minutes",
"queue_position": get_queue_position(location),
"message": "服务请求已接收,请稍候",
"timestamp": VWED.util.now()
}
VWED.log.sync_info(f"服务请求处理: {caller_id}")
return {
"forward": True,
"topics": ["building/caller/response"],
"payload": service_response
}
elif signal_type == "information":
# 信息查询 - 提供自动回复
info_response = {
"type": "information_response",
"caller_id": caller_id,
"location": location,
"status": "completed",
"information": get_location_info(location),
"timestamp": VWED.util.now()
}
return {
"forward": True,
"topics": ["building/caller/response"],
"payload": info_response
}
else:
# 未知信号类型
error_response = {
"type": "error_response",
"caller_id": caller_id,
"status": "error",
"message": f"不支持的信号类型: {signal_type}",
"timestamp": VWED.util.now()
}
return {
"forward": True,
"topics": ["building/caller/response"],
"payload": error_response
}
def get_queue_position(location):
"""获取队列位置"""
queue = VWED.data.get(f"service_queue_{location}", [])
return len(queue) + 1
def get_location_info(location):
"""获取位置信息"""
location_data = {
"lobby": "大厅 - 营业时间: 8:00-18:00, 电话: 123-456-7890",
"elevator": "电梯区域 - 共6部电梯, 楼层: B1-F20",
"parking": "停车场 - 地下3层, 收费标准: 5元/小时"
}
return location_data.get(location, "暂无相关信息")
```
### 3.2 呼叫器多级响应
```python
def boot():
"""多级呼叫响应系统"""
VWED.device.register_and_run(
device_id="caller_escalation_manager",
device_type="caller",
listen_topics=["building/caller/+/urgent"],
forward_topics=["building/staff/notification"],
handler=caller_escalation_handler,
device_brand="standard",
protocol_type="vda5050",
description="呼叫升级管理器"
)
def caller_escalation_handler(message):
"""呼叫升级处理逻辑"""
# 解析呼叫器ID
topic_parts = message.topic.split("/")
caller_id = topic_parts[2] if len(topic_parts) > 2 else "unknown"
urgency_level = message.payload.get("urgency", "medium")
repeat_count = message.payload.get("repeat_count", 1)
last_response_time = message.payload.get("last_response_time")
# 升级逻辑
if repeat_count >= 3:
# 第3次重复呼叫 - 升级到管理层
escalation = {
"type": "management_escalation",
"caller_id": caller_id,
"urgency": "high",
"repeat_count": repeat_count,
"reason": "multiple_unattended_calls",
"notify_roles": ["supervisor", "manager"],
"message": f"呼叫器 {caller_id} 连续{repeat_count}次呼叫未响应",
"timestamp": VWED.util.now()
}
VWED.log.sync_warning(f"呼叫升级到管理层: {caller_id} ({repeat_count}次)")
return {
"forward": True,
"payload": escalation
}
elif repeat_count == 2:
# 第2次重复呼叫 - 通知高级员工
notification = {
"type": "senior_staff_notification",
"caller_id": caller_id,
"urgency": "medium",
"repeat_count": repeat_count,
"notify_roles": ["senior_staff"],
"message": f"呼叫器 {caller_id} 重复呼叫,请优先处理",
"timestamp": VWED.util.now()
}
return {
"forward": True,
"payload": notification
}
else:
# 首次呼叫 - 正常通知
notification = {
"type": "normal_notification",
"caller_id": caller_id,
"urgency": urgency_level,
"notify_roles": ["staff"],
"message": f"呼叫器 {caller_id} 请求服务",
"timestamp": VWED.util.now()
}
return {
"forward": True,
"payload": notification
}
```
---
## 4. 综合设备处理示例
### 4.1 智能楼宇综合管理
```python
def boot():
"""智能楼宇综合管理系统"""
# 环境监控
VWED.device.register_and_run(
device_id="environmental_monitor",
device_type="sensor",
listen_topics=["building/sensors/+/data"],
forward_topics=["building/hvac/control", "building/alerts"],
handler=environmental_processor,
description="环境监控处理器"
)
# 电梯调度
VWED.device.register_and_run(
device_id="elevator_scheduler",
device_type="lift",
listen_topics=["building/elevator/call"],
forward_topics=["building/elevator/+/command"],
handler=elevator_scheduler,
description="电梯调度器"
)
# 安全系统集成
VWED.device.register_and_run(
device_id="security_integrator",
device_type="custom",
listen_topics=["building/security/+/event"],
forward_topics=["building/security/response"],
handler=security_event_processor,
description="安全系统集成器"
)
def environmental_processor(message):
"""环境数据处理"""
# 解析传感器ID
topic_parts = message.topic.split("/")
sensor_id = topic_parts[2] if len(topic_parts) > 2 else "unknown"
temperature = message.payload.get("temperature")
humidity = message.payload.get("humidity")
air_quality = message.payload.get("air_quality")
controls = []
alerts = []
# 温度控制
if temperature is not None:
if temperature > 26:
controls.append({
"device": "hvac",
"action": "cool",
"target_temp": 24,
"reason": f"温度过高: {temperature}°C"
})
elif temperature < 20:
controls.append({
"device": "hvac",
"action": "heat",
"target_temp": 22,
"reason": f"温度过低: {temperature}°C"
})
# 湿度控制
if humidity is not None:
if humidity > 70:
controls.append({
"device": "dehumidifier",
"action": "on",
"target_humidity": 60,
"reason": f"湿度过高: {humidity}%"
})
# 空气质量监控
if air_quality is not None and air_quality < 50:
alerts.append({
"type": "air_quality_alert",
"level": "medium",
"sensor_id": sensor_id,
"value": air_quality,
"message": "空气质量较差,建议开启新风系统"
})
# 返回控制指令和警报
responses = []
if controls:
responses.append(("building/hvac/control", {"controls": controls, "timestamp": VWED.util.now()}))
if alerts:
responses.append(("building/alerts", {"alerts": alerts, "timestamp": VWED.util.now()}))
if responses:
return {
"forward": True,
"topics": [topic for topic, _ in responses],
"payload": [payload for _, payload in responses]
}
return {"forward": False}
def elevator_scheduler(message):
"""电梯调度逻辑"""
floor_from = message.payload.get("from_floor")
floor_to = message.payload.get("to_floor")
priority = message.payload.get("priority", "normal")
# 获取电梯状态
elevator_status = VWED.data.get("elevator_status", {
"elevator_1": {"current_floor": 1, "status": "idle"},
"elevator_2": {"current_floor": 10, "status": "busy"},
"elevator_3": {"current_floor": 5, "status": "idle"}
})
# 选择最佳电梯
best_elevator = None
min_distance = float('inf')
for elevator_id, status in elevator_status.items():
if status["status"] == "idle":
distance = abs(status["current_floor"] - floor_from)
if distance < min_distance:
min_distance = distance
best_elevator = elevator_id
if best_elevator:
# 分配电梯
command = {
"elevator_id": best_elevator,
"action": "goto",
"from_floor": floor_from,
"to_floor": floor_to,
"priority": priority,
"estimated_time": min_distance * 3, # 假设每层3秒
"timestamp": VWED.util.now()
}
# 更新电梯状态
elevator_status[best_elevator]["status"] = "busy"
VWED.data.set("elevator_status", elevator_status)
return {
"forward": True,
"topics": [f"building/elevator/{best_elevator}/command"],
"payload": command
}
else:
# 无空闲电梯 - 加入队列
queue = VWED.data.get("elevator_queue", [])
queue.append({
"from_floor": floor_from,
"to_floor": floor_to,
"priority": priority,
"request_time": VWED.util.now()
})
VWED.data.set("elevator_queue", queue)
return {
"forward": False,
"response": {
"status": "queued",
"position": len(queue),
"estimated_wait": len(queue) * 30 # 每个请求30秒
},
"response_topic": "building/elevator/response"
}
def security_event_processor(message):
"""安全事件处理"""
event_type = message.payload.get("event_type")
location = message.payload.get("location")
severity = message.payload.get("severity", "medium")
if event_type == "intrusion_detected":
# 入侵检测 - 立即响应
response = {
"action": "lockdown",
"location": location,
"alert_level": "high",
"notify_security": True,
"timestamp": VWED.util.now()
}
return {
"forward": True,
"payload": response
}
elif event_type == "fire_alarm":
# 火警 - 疏散程序
response = {
"action": "evacuation",
"location": location,
"alert_level": "critical",
"notify_fire_dept": True,
"timestamp": VWED.util.now()
}
return {
"forward": True,
"payload": response
}
# 其他事件正常处理
return {
"forward": True,
"payload": message.payload
}
```
---
## 5. 设备处理器管理功能
### 5.1 设备状态监控
```python
def boot():
"""设备管理和监控"""
# 注册设备状态监控
VWED.device.register_and_run(
device_id="device_status_monitor",
device_type="custom",
listen_topics=["system/device/+/heartbeat"],
forward_topics=["system/alerts"],
handler=device_heartbeat_monitor,
description="设备心跳监控器"
)
# 定时检查设备状态
VWED.timer.interval(
seconds=60, # 每分钟检查一次
handler=check_device_status
)
def device_heartbeat_monitor(message):
"""设备心跳监控"""
device_id = message.payload.get("device_id")
status = message.payload.get("status")
timestamp = message.payload.get("timestamp", VWED.util.now())
# 更新设备心跳记录
heartbeats = VWED.data.get("device_heartbeats", {})
heartbeats[device_id] = {
"status": status,
"last_heartbeat": timestamp,
"updated_at": VWED.util.now()
}
VWED.data.set("device_heartbeats", heartbeats)
# 如果设备状态异常,发送警报
if status in ["error", "offline", "malfunction"]:
alert = {
"type": "device_alert",
"device_id": device_id,
"status": status,
"message": f"设备 {device_id} 状态异常: {status}",
"timestamp": timestamp,
"requires_attention": True
}
return {
"forward": True,
"payload": alert
}
return {"forward": False}
def check_device_status():
"""定时检查设备状态"""
current_time = VWED.util.timestamp()
heartbeats = VWED.data.get("device_heartbeats", {})
for device_id, info in heartbeats.items():
last_heartbeat = info.get("last_heartbeat")
if last_heartbeat:
# 检查是否超过5分钟没有心跳
if current_time - last_heartbeat > 300: # 5分钟
VWED.log.sync_warning(f"设备 {device_id} 心跳超时")
# 发送超时警报
VWED.device.sync_publish_message(
topic="system/alerts",
payload={
"type": "device_timeout",
"device_id": device_id,
"last_seen": last_heartbeat,
"timeout_duration": current_time - last_heartbeat,
"timestamp": VWED.util.now()
}
)
```
### 5.2 设备处理器动态管理
```python
def boot():
"""动态设备管理"""
# 设备管理控制器
VWED.device.register_and_run(
device_id="device_manager",
device_type="custom",
listen_topics=["system/device/control"],
forward_topics=["system/device/response"],
handler=device_management_handler,
description="设备动态管理控制器"
)
def device_management_handler(message):
"""设备管理控制处理"""
action = message.payload.get("action")
device_id = message.payload.get("device_id")
if action == "status":
# 获取设备状态
status = VWED.device.get_handler_status(device_id)
return {
"forward": True,
"payload": {
"action": "status_response",
"device_id": device_id,
"status": status,
"timestamp": VWED.util.now()
}
}
elif action == "stop":
# 停止设备处理器
try:
VWED.device.stop_handler(device_id)
return {
"forward": True,
"payload": {
"action": "stop_response",
"device_id": device_id,
"status": "stopped",
"timestamp": VWED.util.now()
}
}
except Exception as e:
return {
"forward": True,
"payload": {
"action": "stop_response",
"device_id": device_id,
"status": "error",
"error": str(e),
"timestamp": VWED.util.now()
}
}
elif action == "restart":
# 重启设备处理器
try:
VWED.device.restart_handler(device_id)
return {
"forward": True,
"payload": {
"action": "restart_response",
"device_id": device_id,
"status": "restarted",
"timestamp": VWED.util.now()
}
}
except Exception as e:
return {
"forward": True,
"payload": {
"action": "restart_response",
"device_id": device_id,
"status": "error",
"error": str(e),
"timestamp": VWED.util.now()
}
}
elif action == "list":
# 获取所有设备列表
handlers = VWED.device.get_running_handlers()
return {
"forward": True,
"payload": {
"action": "list_response",
"handlers": handlers,
"timestamp": VWED.util.now()
}
}
else:
return {
"forward": True,
"payload": {
"action": "error_response",
"message": f"不支持的操作: {action}",
"timestamp": VWED.util.now()
}
}
```
---
## 6. 调试和故障排除
### 6.1 设备处理器调试
```python
def boot():
"""设备处理器调试模式"""
# 启用调试模式
debug_mode = True
if debug_mode:
# 注册调试设备处理器
VWED.device.register_and_run(
device_id="debug_processor",
device_type="custom",
listen_topics=["debug/+/+"], # 监听所有调试消息
forward_topics=[],
handler=debug_message_handler,
description="调试消息处理器"
)
def debug_message_handler(message):
"""调试消息处理"""
# 详细记录消息信息
VWED.log.sync_info(f"调试消息 - Topic: {message.topic}")
VWED.log.sync_info(f"调试消息 - Payload: {message.payload}")
VWED.log.sync_info(f"调试消息 - Device: {message.device_id}")
VWED.log.sync_info(f"调试消息 - Type: {message.device_type}")
VWED.log.sync_info(f"调试消息 - Timestamp: {message.timestamp}")
# 保存调试日志
debug_logs = VWED.data.get("debug_logs", [])
debug_logs.append({
"topic": message.topic,
"payload": message.payload,
"device_id": message.device_id,
"device_type": message.device_type.value if hasattr(message.device_type, 'value') else str(message.device_type),
"timestamp": message.timestamp,
"processed_at": VWED.util.now()
})
# 只保留最近50条调试日志
if len(debug_logs) > 50:
debug_logs = debug_logs[-50:]
VWED.data.set("debug_logs", debug_logs)
# 不转发调试消息
return {"forward": False}
def get_debug_statistics():
"""获取调试统计信息"""
handlers = VWED.device.get_running_handlers()
debug_logs = VWED.data.get("debug_logs", [])
return {
"total_handlers": handlers.get("device_count", 0),
"running_handlers": handlers.get("running_devices", 0),
"debug_log_count": len(debug_logs),
"last_debug_time": debug_logs[-1]["processed_at"] if debug_logs else None
}
```
---
## 总结
本文档提供了VWED设备处理器的完整使用示例包括
### 主要功能
1. **设备类型支持** - 小车、门禁、呼叫器、电梯、传感器等
2. **注册即运行** - 一次注册持续监听和处理MQTT消息
3. **自动转发** - 处理完成后自动发送到指定topic
4. **动态管理** - 支持运行时启停、重启设备处理器
5. **状态监控** - 实时监控设备状态和处理统计
### 关键特点
- **分离式设计** - 注册和处理逻辑分离,保持代码清晰
- **消息驱动** - MQTT消息自动触发处理无需手动调用
- **错误处理** - 完善的异常处理和重试机制
- **扩展性强** - 支持自定义设备类型和处理逻辑
- **易于调试** - 详细的日志记录和调试功能
### 使用建议
1. 根据实际设备类型选择合适的device_type
2. 合理设置listen_topics和forward_topics
3. 在处理函数中添加充分的错误处理
4. 使用VWED.log记录关键操作日志
5. 利用VWED.data缓存必要的状态信息
通过这些示例您可以快速掌握VWED设备处理器的使用方法实现复杂的设备逻辑处理和MQTT消息转发。