【系统集成 16-20】第 18/25 课

🤖 第18课:远程监控

📌 远程监控概述

远程监控让运维人员随时掌握机器人状态,及时发现和处理异常:

📊 监控维度

维度指标告警阈值
硬件电量、温度、CPU、内存电量<20%紧急
导航位置、状态、被困被困>2分钟
任务完成率、延迟延迟>10分钟
网络延迟、丢包丢包>30%
安全碰撞、急停立即告警

📌 遥测数据采集

import json, time, random

class TelemetryCollector:
    """遥测数据采集器"""
    def __init__(self):
        self.metrics = {
            "battery": 95.0,
            "cpu_usage": 25.0,
            "memory_usage": 40.0,
            "temperature": 42.0,
            "nav_status": "idle",
            "position": {"x": 0, "y": 0, "floor": 1},
            "tasks_completed": 0,
            "uptime": 3600,
        }
        self.alert_rules = {
            "battery_low": {"metric": "battery", "threshold": 20, "operator": "<", "level": "critical"},
            "battery_medium": {"metric": "battery", "threshold": 40, "operator": "<", "level": "warning"},
            "cpu_high": {"metric": "cpu_usage", "threshold": 80, "operator": ">", "level": "warning"},
            "temp_high": {"metric": "temperature", "threshold": 60, "operator": ">", "level": "critical"},
            "memory_high": {"metric": "memory_usage", "threshold": 85, "operator": ">", "level": "warning"},
        }
        self.history = []

    def update(self):
        """模拟指标更新"""
        self.metrics["battery"] = max(0, self.metrics["battery"] - random.uniform(0.1, 0.5))
        self.metrics["cpu_usage"] = min(100, max(5, self.metrics["cpu_usage"] + random.uniform(-5, 5)))
        self.metrics["memory_usage"] = min(100, max(20, self.metrics["memory_usage"] + random.uniform(-2, 2)))
        self.metrics["temperature"] = max(30, min(70, self.metrics["temperature"] + random.uniform(-2, 2)))
        self.metrics["uptime"] += 1
        self.history.append(dict(self.metrics))

    def check_alerts(self):
        """检查告警"""
        alerts = []
        for rule_name, rule in self.alert_rules.items():
            value = self.metrics[rule["metric"]]
            threshold = rule["threshold"]
            triggered = value < threshold if rule["operator"] == "<" else value > threshold
            if triggered:
                alerts.append({
                    "rule": rule_name,
                    "metric": rule["metric"],
                    "value": value,
                    "threshold": threshold,
                    "level": rule["level"],
                })
        return alerts

    def get_snapshot(self):
        return dict(self.metrics)

telemetry = TelemetryCollector()
print("远程监控 - 遥测数据采集")
print("=" * 55)

random.seed(42)
for step in range(20):
    telemetry.update()
    alerts = telemetry.check_alerts()
    if alerts or step % 5 == 0:
        snap = telemetry.get_snapshot()
        print(f"\n步骤{step}: 电量{snap['battery']:.1f}% CPU{snap['cpu_usage']:.1f}% 温度{snap['temperature']:.1f}°C")
        for alert in alerts:
            icon = "🔴" if alert["level"] == "critical" else "🟡"
            print(f"  {icon} {alert['rule']}: {alert['metric']}={alert['value']:.1f} (阈值{alert['threshold']})")

print("\n✅ 遥测采集验证通过")
✅ 验证通过 远程监控 - 遥测数据采集 ======================================================= 步骤0: 电量94.6% CPU20.3% 温度40.9°C 步骤5: 电量93.3% CPU17.2% 温度36.1°C 步骤10: 电量91.2% CPU18.0% 温度35.1°C 步骤15: 电量89.9% CPU22.0% 温度33.7°C ✅ 遥测采集验证通过

📌 远程控制

class RemoteController:
    """远程控制器"""
    def __init__(self):
        self.commands = []
        self.robot_state = "idle"
        self.position = [0, 0]
        self.authorized = False

    def authenticate(self, token):
        """认证"""
        self.authorized = token == "admin_token_123"
        return self.authorized

    def send_command(self, cmd_type, params=None):
        """发送远程命令"""
        if not self.authorized:
            return {"success": False, "error": "未认证"}

        cmd = {"type": cmd_type, "params": params or {}, "timestamp": time.time()}
        self.commands.append(cmd)

        if cmd_type == "goto":
            target = params.get("target", (0,0))
            self.robot_state = "navigating"
            self.position = list(target)
            return {"success": True, "message": f"导航到{target}"}
        elif cmd_type == "stop":
            self.robot_state = "idle"
            return {"success": True, "message": "已停止"}
        elif cmd_type == "return_home":
            self.robot_state = "returning"
            self.position = [0, 0]
            return {"success": True, "message": "返回充电桩"}
        elif cmd_type == "restart":
            self.robot_state = "idle"
            return {"success": True, "message": "重启完成"}
        elif cmd_type == "screenshot":
            return {"success": True, "message": "截图已保存"}
        return {"success": False, "error": "未知命令"}

import time
ctrl = RemoteController()
print("远程控制模拟")
print("=" * 55)

ctrl.authenticate("admin_token_123")
commands = [
    ("goto", {"target": (5, 3)}),
    ("stop", {}),
    ("goto", {"target": (10, 8)}),
    ("screenshot", {}),
    ("return_home", {}),
    ("restart", {}),
]
for cmd_type, params in commands:
    result = ctrl.send_command(cmd_type, params)
    print(f"  {'✅' if result['success'] else '❌'} {cmd_type}: {result['message']}")

print(f"\n命令历史: {len(ctrl.commands)}条")
print("✅ 远程控制验证通过")
✅ 验证通过 远程控制模拟 ======================================================= ✅ goto: 导航到(5, 3) ✅ stop: 已停止 ✅ goto: 导航到(10, 8) ✅ screenshot: 截图已保存 ✅ return_home: 返回充电桩 ✅ restart: 重启完成 命令历史: 6条 ✅ 远程控制验证通过

📌 告警管理

class AlertManager:
    """告警管理器"""
    def __init__(self):
        self.alerts = []
        self.escalation_rules = {
            "critical": {"notify": ["管理员","主管"], "timeout": 300, "action": "自动处理"},
            "warning": {"notify": ["管理员"], "timeout": 1800, "action": "记录日志"},
            "info": {"notify": [], "timeout": 3600, "action": "记录日志"},
        }
        self.auto_actions = {
            "battery_low": "自动返回充电",
            "temp_high": "降低运行频率",
            "stuck": "尝试脱困",
            "network_lost": "切换离线模式",
        }

    def create_alert(self, alert_type, level, message, auto_handle=True):
        """创建告警"""
        alert = {
            "type": alert_type, "level": level, "message": message,
            "timestamp": time.time(), "handled": False, "auto_handled": False
        }
        self.alerts.append(alert)

        rule = self.escalation_rules.get(level, self.escalation_rules["info"])
        print(f"  {'🔴' if level=='critical' else '🟡' if level=='warning' else 'ℹ️'} [{level}] {message}")
        print(f"    通知: {', '.join(rule['notify'])}")

        if auto_handle and alert_type in self.auto_actions:
            action = self.auto_actions[alert_type]
            alert["auto_handled"] = True
            print(f"    自动处理: {action}")
        
        return alert

import time
am = AlertManager()
print("告警管理模拟")
print("=" * 55)

am.create_alert("battery_low", "critical", "电量仅剩15%,即将关机")
am.create_alert("temp_high", "warning", "CPU温度达到65°C")
am.create_alert("stuck", "critical", "机器人被困,无法移动")
am.create_alert("network_lost", "warning", "网络连接丢失")
am.create_alert("task_delay", "info", "任务T003预计延迟5分钟")

handled = sum(1 for a in am.alerts if a["auto_handled"])
print(f"\n告警统计: 总计{len(am.alerts)}个, 自动处理{handled}个")
print("✅ 告警管理验证通过")
✅ 验证通过 告警管理模拟 ======================================================= 🔴 [critical] 电量仅剩15%,即将关机 通知: 管理员, 主管 自动处理: 自动返回充电 🟡 [warning] CPU温度达到65°C 通知: 管理员 自动处理: 降低运行频率 🔴 [critical] 机器人被困,无法移动 通知: 管理员, 主管 自动处理: 尝试脱困 🟡 [warning] 网络连接丢失 通知: 管理员 自动处理: 切换离线模式 ℹ️ [info] 任务T003预计延迟5分钟 通知: 告警统计: 总计5个, 自动处理4个 ✅ 告警管理验证通过

📌 监控架构

🏗️ 典型监控架构

机器人 → 采集Agent → MQTT/Kafka → 时序数据库
                                         ↓
                              Grafana仪表盘 ← 告警引擎
                              远程控制台   ← 日志服务
💡 推荐技术栈:MQTT消息传输 + InfluxDB时序存储 + Grafana可视化 + Prometheus告警。

📌 练习

📝 练习 1

实现实时视频流:模拟WebRTC视频传输,支持远程查看机器人摄像头画面。

📝 练习 2

设计告警降噪:对相同告警去重和聚合,避免告警风暴。

📝 练习 3

实现预测性维护:基于历史数据预测电池衰减、电机寿命,提前预警。

📌 成就

🏆 本课成就

◀ 上一课 📚 目录 下一课 ▶