base_agent/uas/action/actions/builtin_actions.py

385 lines
13 KiB
Python
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.

# -*- coding: utf-8 -*-
"""
内置 Action 处理器实现
─────────────────────────────────────────────────────────────────
每个处理函数签名:
def handler(action: Action, ctx: ActionContext) -> Any
处理函数内部通过 ctx.emit_event() 产生一个或多个 Event 对象
─────────────────────────────────────────────────────────────────
"""
import logging
import random
import time
from uas.action.action_context import ActionContext
from uas.action.action_model import Action
from uas.event.event_model import make_event
# 复用 Event 模块
from uas.event.event_type import EventType
logger = logging.getLogger(__name__)
# ─────────────────────────────────────────────────────────────────
# 控制类 Action 处理器
# ─────────────────────────────────────────────────────────────────
def handle_pause(action: Action, ctx: ActionContext) -> dict:
"""
暂停处理器
产生事件DEVICE_STATUS_CHANGED
"""
ctx.report_progress(10, "发送暂停指令...")
time.sleep(0.1) # 模拟指令发送延迟
ctx.check_cancel()
ctx.report_progress(80, "等待设备响应...")
time.sleep(0.1)
# 产生状态变更事件
ctx.emit_event(make_event(
EventType.DEVICE_STATUS_CHANGED,
source = action.source,
message = f"设备已暂停",
prev_state = "running",
curr_state = "paused",
action_id = action.action_id,
))
ctx.report_progress(100, "暂停完成")
logger.info(f"⏸ 暂停完成: {action.source}")
return {"status": "paused", "device": action.source}
def handle_resume(action: Action, ctx: ActionContext) -> dict:
"""
继续处理器
产生事件DEVICE_STATUS_CHANGED
"""
ctx.report_progress(20, "发送继续指令...")
time.sleep(0.1)
ctx.check_cancel()
ctx.emit_event(make_event(
EventType.DEVICE_STATUS_CHANGED,
source = action.source,
message = "设备已恢复运行",
prev_state = "paused",
curr_state = "running",
action_id = action.action_id,
))
ctx.report_progress(100, "继续完成")
logger.info(f"▶️ 继续完成: {action.source}")
return {"status": "running", "device": action.source}
def handle_stop(action: Action, ctx: ActionContext) -> dict:
"""
停止处理器
产生事件DEVICE_STATUS_CHANGED + SYSTEM_WARNING若强制停止
"""
force = action.params.get("force", False)
ctx.report_progress(10, "准备停止...")
if force:
# 强制停止:产生警告事件
ctx.emit_event(make_event(
EventType.SYSTEM_WARNING,
source = action.source,
message = "强制停止指令已执行",
level = "warning",
))
ctx.report_progress(60, "执行停止序列...")
time.sleep(0.2)
ctx.check_cancel()
ctx.emit_event(make_event(
EventType.DEVICE_STATUS_CHANGED,
source = action.source,
message = "设备已停止",
prev_state = "running",
curr_state = "stopped",
force = force,
))
ctx.report_progress(100, "停止完成")
logger.info(f"⏹ 停止完成: {action.source} force={force}")
return {"status": "stopped", "force": force}
def handle_reset(action: Action, ctx: ActionContext) -> dict:
"""
重置处理器
产生事件DEVICE_RESET + DEVICE_STATUS_CHANGED
"""
ctx.report_progress(10, "开始重置...")
time.sleep(0.1)
ctx.emit_event(make_event(
EventType.DEVICE_RESET,
source = action.source,
message = "设备重置开始",
))
ctx.report_progress(50, "重置中...")
time.sleep(0.2)
ctx.check_cancel()
ctx.emit_event(make_event(
EventType.DEVICE_STATUS_CHANGED,
source = action.source,
message = "设备重置完成",
curr_state = "idle",
))
ctx.report_progress(100, "重置完成")
logger.info(f"🔄 重置完成: {action.source}")
return {"status": "reset_done"}
# ─────────────────────────────────────────────────────────────────
# 感知类 Action 处理器
# ─────────────────────────────────────────────────────────────────
def handle_capture_photo(action: Action, ctx: ActionContext) -> dict:
"""
拍照处理器
产生事件DEVICE_DATA_RECEIVED含图像元数据
"""
resolution = action.params.get("resolution", "1080P")
fmt = action.params.get("format", "jpg")
camera_id = action.source
ctx.report_progress(20, f"初始化相机 {camera_id}...")
time.sleep(0.05)
ctx.check_cancel()
ctx.report_progress(60, "曝光采集...")
time.sleep(0.1)
# 模拟图像数据
photo_meta = {
"camera_id": camera_id,
"resolution": resolution,
"format": fmt,
"file_path": f"/data/photos/{camera_id}_{int(time.time())}.{fmt}",
"size_kb": random.randint(500, 5000),
"exposure_ms": random.randint(10, 100),
}
# 产生数据到达事件
ctx.emit_event(make_event(
EventType.DEVICE_DATA_RECEIVED,
source = camera_id,
message = f"拍照完成 [{resolution}]",
data_type = "image",
**photo_meta,
))
ctx.report_progress(100, "拍照完成")
logger.info(f"📷 拍照完成: {camera_id} {resolution} -> {photo_meta['file_path']}")
return photo_meta
def handle_recognize_target(action: Action, ctx: ActionContext) -> dict:
"""
目标识别处理器
产生事件:
- DEVICE_DATA_RECEIVED识别结果
- EQUIPMENT_ALARM若发现威胁目标
"""
model = action.params.get("model", "yolov8")
confidence = action.params.get("confidence", 0.85)
image_path = action.params.get("image_path", "")
ctx.report_progress(10, f"加载模型 {model}...")
time.sleep(0.1)
ctx.check_cancel()
ctx.report_progress(40, "推理中...")
time.sleep(0.2)
ctx.check_cancel()
# 模拟识别结果
targets = [
{"id": f"T{i:03d}", "label": random.choice(["aircraft", "vehicle", "person"]),
"confidence": round(random.uniform(0.7, 0.99), 3),
"bbox": [random.randint(0, 640) for _ in range(4)]}
for i in range(random.randint(0, 3))
]
ctx.report_progress(80, f"发现 {len(targets)} 个目标...")
# 产生识别结果事件
ctx.emit_event(make_event(
EventType.DEVICE_DATA_RECEIVED,
source = action.source,
message = f"目标识别完成,发现 {len(targets)} 个目标",
data_type = "recognition",
model = model,
targets = targets,
image_path = image_path,
))
# 若发现高威胁目标,额外产生告警事件
threat_targets = [t for t in targets if t["label"] == "aircraft"
and t["confidence"] > 0.9]
if threat_targets:
ctx.emit_event(make_event(
EventType.EQUIPMENT_ALARM,
source = action.source,
message = f"发现 {len(threat_targets)} 个高威胁目标!",
level = "critical",
targets = threat_targets,
))
logger.warning(f"🚨 发现威胁目标: {threat_targets}")
ctx.report_progress(100, "识别完成")
logger.info(f"🎯 目标识别完成: {len(targets)} 个目标")
return {"targets": targets, "model": model}
def handle_scan_environment(action: Action, ctx: ActionContext) -> dict:
"""
环境扫描处理器
产生事件DEVICE_DATA_RECEIVED扫描数据+ DEVICE_WARNING若发现异常
"""
scan_range = action.params.get("range_m", 100)
sensor = action.source
ctx.report_progress(10, "初始化传感器...")
time.sleep(0.05)
scan_data = []
steps = 5
for i in range(steps):
ctx.check_cancel()
time.sleep(0.05)
ctx.report_progress(
int((i + 1) / steps * 80),
f"扫描中 {int((i+1)/steps*100)}%..."
)
scan_data.append({
"angle": i * (360 // steps),
"distance": random.uniform(5, scan_range),
"intensity": random.uniform(0.1, 1.0),
})
# 产生扫描数据事件
ctx.emit_event(make_event(
EventType.DEVICE_DATA_RECEIVED,
source = sensor,
message = f"环境扫描完成,范围 {scan_range}m",
data_type = "lidar_scan",
points = len(scan_data),
scan_data = scan_data,
))
# 检测到近距离障碍物
close_obstacles = [d for d in scan_data if d["distance"] < 10]
if close_obstacles:
ctx.emit_event(make_event(
EventType.DEVICE_WARNING,
source = sensor,
message = f"检测到 {len(close_obstacles)} 个近距离障碍物",
obstacles = close_obstacles,
))
ctx.report_progress(100, "扫描完成")
return {"scan_points": len(scan_data), "range_m": scan_range}
# ─────────────────────────────────────────────────────────────────
# 系统类 Action 处理器
# ─────────────────────────────────────────────────────────────────
def handle_system_diagnose(action: Action, ctx: ActionContext) -> dict:
"""
系统诊断处理器
产生事件SYSTEM_WARNING若发现问题或 DEVICE_STATUS_CHANGED
"""
checks = ["CPU", "内存", "存储", "网络", "传感器"]
results = {}
for i, check in enumerate(checks):
ctx.check_cancel()
time.sleep(0.05)
ctx.report_progress(int((i + 1) / len(checks) * 90), f"检查 {check}...")
status = random.choice(["normal", "normal", "normal", "warning"])
results[check] = status
if status == "warning":
ctx.emit_event(make_event(
EventType.SYSTEM_WARNING,
source = action.source,
message = f"诊断发现 {check} 异常",
component = check,
level = "warning",
))
# 产生诊断完成事件
ctx.emit_event(make_event(
EventType.DEVICE_STATUS_CHANGED,
source = action.source,
message = "系统诊断完成",
curr_state = "diagnosed",
results = results,
))
ctx.report_progress(100, "诊断完成")
warnings = [k for k, v in results.items() if v == "warning"]
logger.info(f"🔧 系统诊断完成: {results} warnings={warnings}")
return {"results": results, "warnings": warnings}
def handle_system_calibrate(action: Action, ctx: ActionContext) -> dict:
"""
设备校准处理器
产生事件DEVICE_CALIBRATED
"""
sensor_ids = action.params.get("sensors", ["all"])
ctx.report_progress(10, "开始校准...")
for i, sid in enumerate(sensor_ids):
ctx.check_cancel()
time.sleep(0.1)
ctx.report_progress(
int((i + 1) / len(sensor_ids) * 90),
f"校准传感器 {sid}..."
)
ctx.emit_event(make_event(
EventType.DEVICE_CALIBRATED,
source = action.source,
message = f"校准完成,传感器: {sensor_ids}",
sensors = sensor_ids,
accuracy = round(random.uniform(0.95, 0.999), 4),
))
ctx.report_progress(100, "校准完成")
logger.info(f"📐 校准完成: {action.source} sensors={sensor_ids}")
return {"calibrated": sensor_ids}
# ─────────────────────────────────────────────────────────────────
# 处理器映射表(供 ActionRegistry 使用)
# ─────────────────────────────────────────────────────────────────
from uas.action.action_type import ActionType
BUILTIN_HANDLERS = {
ActionType.PAUSE: handle_pause,
ActionType.RESUME: handle_resume,
ActionType.STOP: handle_stop,
ActionType.RESET: handle_reset,
ActionType.CAPTURE_PHOTO: handle_capture_photo,
ActionType.RECOGNIZE_TARGET: handle_recognize_target,
ActionType.SCAN_ENVIRONMENT: handle_scan_environment,
ActionType.SYSTEM_DIAGNOSE: handle_system_diagnose,
ActionType.SYSTEM_CALIBRATE: handle_system_calibrate,
}