base_agent/uas/action/actions/builtin_actions.py

385 lines
13 KiB
Python
Raw Normal View History

2026-06-18 03:28:14 +00:00
# -*- 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,
}