PingWatch 网络设备离线监控系统
- FastAPI 后端 + Vue 3 前端 - Docker Compose 一键部署 - Casdoor OAuth 认证集成 - LogHive 集中式日志 - 设备批量 CSV 导入/导出 - WebSocket 实时状态推送 - 企业微信告警通知 - fping 高性能并发 Ping 检测 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
"""WebSocket 实时推送"""
|
||||
import json
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
|
||||
|
||||
logger = logging.getLogger("pingwatch.ws")
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class ConnectionManager:
|
||||
"""WebSocket 连接管理器"""
|
||||
|
||||
def __init__(self):
|
||||
self._connections: set[WebSocket] = set()
|
||||
|
||||
async def connect(self, ws: WebSocket):
|
||||
await ws.accept()
|
||||
self._connections.add(ws)
|
||||
|
||||
def disconnect(self, ws: WebSocket):
|
||||
self._connections.discard(ws)
|
||||
|
||||
async def broadcast(self, message: dict):
|
||||
"""向所有客户端广播消息"""
|
||||
dead = set()
|
||||
for ws in self._connections:
|
||||
try:
|
||||
await ws.send_json(message)
|
||||
except Exception:
|
||||
dead.add(ws)
|
||||
self._connections -= dead
|
||||
|
||||
@property
|
||||
def count(self) -> int:
|
||||
return len(self._connections)
|
||||
|
||||
|
||||
manager = ConnectionManager()
|
||||
|
||||
|
||||
@router.websocket("/ws")
|
||||
async def websocket_endpoint(ws: WebSocket):
|
||||
"""WebSocket 端点,用于前端实时接收状态更新"""
|
||||
await manager.connect(ws)
|
||||
try:
|
||||
while True:
|
||||
# 保持连接,接收心跳 pong
|
||||
data = await ws.receive_text()
|
||||
if data == "ping":
|
||||
await ws.send_text("pong")
|
||||
except WebSocketDisconnect:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.error(f"WebSocket 异常: {e}")
|
||||
finally:
|
||||
manager.disconnect(ws)
|
||||
|
||||
|
||||
async def broadcast_status_change(device_id: int, status: str, name: str):
|
||||
"""广播设备状态变化"""
|
||||
await manager.broadcast({
|
||||
"type": "device_status_change",
|
||||
"device_id": device_id,
|
||||
"status": status,
|
||||
"name": name,
|
||||
"timestamp": asyncio.get_event_loop().time(),
|
||||
})
|
||||
Reference in New Issue
Block a user