44 KiB
44 KiB
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小车注册和处理
#!/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 门设备即时动作示例
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 通用设备即时动作示例
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 基本小车命令处理
#!/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协调处理
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 基本门禁控制
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 门禁状态监控
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 基本呼叫处理
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 呼叫器多级响应
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 智能楼宇综合管理
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 设备状态监控
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 设备处理器动态管理
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 设备处理器调试
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设备处理器的完整使用示例,包括:
主要功能
- 设备类型支持 - 小车、门禁、呼叫器、电梯、传感器等
- 注册即运行 - 一次注册,持续监听和处理MQTT消息
- 自动转发 - 处理完成后自动发送到指定topic
- 动态管理 - 支持运行时启停、重启设备处理器
- 状态监控 - 实时监控设备状态和处理统计
关键特点
- 分离式设计 - 注册和处理逻辑分离,保持代码清晰
- 消息驱动 - MQTT消息自动触发处理,无需手动调用
- 错误处理 - 完善的异常处理和重试机制
- 扩展性强 - 支持自定义设备类型和处理逻辑
- 易于调试 - 详细的日志记录和调试功能
使用建议
- 根据实际设备类型选择合适的device_type
- 合理设置listen_topics和forward_topics
- 在处理函数中添加充分的错误处理
- 使用VWED.log记录关键操作日志
- 利用VWED.data缓存必要的状态信息
通过这些示例,您可以快速掌握VWED设备处理器的使用方法,实现复杂的设备逻辑处理和MQTT消息转发。