modify: aibox_sophon_adapter plugins
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
路由导出 — aibox_sophon_adapter
|
||||
"""
|
||||
from .board_ping import board_ping
|
||||
from .list_devices import list_devices
|
||||
from .get_device import get_device
|
||||
from .get_offline_devices import get_offline_devices
|
||||
|
||||
__all__ = [
|
||||
"board_ping",
|
||||
"list_devices",
|
||||
"get_device",
|
||||
"get_offline_devices",
|
||||
]
|
||||
@@ -0,0 +1,94 @@
|
||||
"""
|
||||
AI Box Sophon Adapter — MQTT 心跳上报处理器
|
||||
|
||||
监听 MQTT 主题 /board_ping(通过 MQTT Bridge 路由到 chongming/aibox_sophon_adapter/board_ping),
|
||||
解析设备心跳数据并更新数据库记录。
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from chongming_worker import rpc_method
|
||||
from ..models.board_models import BoardPingRequest
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@rpc_method(
|
||||
subject="aibox_sophon_adapter.board_ping",
|
||||
method="MQTT",
|
||||
summary="AI Box 设备心跳上报",
|
||||
request_model=BoardPingRequest,
|
||||
)
|
||||
async def board_ping(request: BoardPingRequest, worker_id: str = "") -> dict:
|
||||
"""
|
||||
处理设备心跳上报
|
||||
|
||||
设备通过 MQTT 主题 /board_ping 定期(默认 5 秒)上报系统状态。
|
||||
收到心跳后更新数据库中的设备记录,标记为在线。
|
||||
"""
|
||||
from ..global_var import db, heartbeat_timeout
|
||||
|
||||
board_id = request.BoardId
|
||||
|
||||
try:
|
||||
async with db.get_session() as session:
|
||||
from ..models.orm import BoardHeartbeat
|
||||
from sqlalchemy import select
|
||||
|
||||
stmt = select(BoardHeartbeat).where(BoardHeartbeat.board_id == board_id)
|
||||
result = await session.execute(stmt)
|
||||
record: BoardHeartbeat | None = result.scalar_one_or_none()
|
||||
|
||||
now = datetime.now()
|
||||
ping_json = request.model_dump_json()
|
||||
|
||||
if record is None:
|
||||
# 新设备,创建记录
|
||||
record = BoardHeartbeat(
|
||||
board_id=board_id,
|
||||
board_ip=request.BoardIp,
|
||||
board_platform=request.BoardPlatform,
|
||||
board_temp=request.BoardTemp,
|
||||
board_type=request.BoardType,
|
||||
status=request.Status,
|
||||
version=request.Version,
|
||||
system_info=request.System,
|
||||
grant_code=request.GrantCode,
|
||||
grant_desc=request.GrantDesc,
|
||||
last_ping_time=now,
|
||||
ping_data=ping_json,
|
||||
is_online=True,
|
||||
)
|
||||
session.add(record)
|
||||
logger.info(f"[Heartbeat] 新设备上线: {board_id} (IP: {request.BoardIp})")
|
||||
else:
|
||||
# 已有设备,更新心跳
|
||||
record.board_ip = request.BoardIp
|
||||
record.board_platform = request.BoardPlatform
|
||||
record.board_temp = request.BoardTemp
|
||||
record.board_type = request.BoardType
|
||||
record.status = request.Status
|
||||
record.version = request.Version
|
||||
record.system_info = request.System
|
||||
record.grant_code = request.GrantCode
|
||||
record.grant_desc = request.GrantDesc
|
||||
record.last_ping_time = now
|
||||
record.ping_data = ping_json
|
||||
record.is_online = True
|
||||
record.updated_at = now
|
||||
|
||||
await session.commit()
|
||||
|
||||
logger.debug(
|
||||
f"[Heartbeat] {board_id}: temp={request.BoardTemp}, "
|
||||
f"disk={request.HostDisk.Used}/{request.HostDisk.Total} kB, "
|
||||
f"mem={request.HostMemory[0]:.1f} kB ({request.HostMemory[1]*100:.1f}%), "
|
||||
f"medias={len(request.Medias)}, tasks={len(request.Tasks)}"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[Heartbeat] 处理心跳失败 (board_id={board_id}): {e}")
|
||||
return {"error": str(e)}
|
||||
|
||||
return {"received": True, "board_id": board_id}
|
||||
@@ -0,0 +1,63 @@
|
||||
"""
|
||||
查询单个设备详情 — GET /aibox/get_device?board_id=xxx
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from chongming_worker import rpc_method
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@rpc_method(
|
||||
subject="aibox_sophon_adapter.get_device",
|
||||
method="GET",
|
||||
summary="查询单个设备详情",
|
||||
)
|
||||
async def get_device(board_id: str, worker_id: str = "") -> dict:
|
||||
"""根据 BoardId 查询设备的完整心跳数据和在线状态"""
|
||||
from ..global_var import db, heartbeat_timeout
|
||||
|
||||
try:
|
||||
async with db.get_session() as session:
|
||||
from ..models.orm import BoardHeartbeat
|
||||
from sqlalchemy import select
|
||||
|
||||
stmt = select(BoardHeartbeat).where(BoardHeartbeat.board_id == board_id)
|
||||
result = await session.execute(stmt)
|
||||
record: BoardHeartbeat | None = result.scalar_one_or_none()
|
||||
|
||||
if record is None:
|
||||
return {"error": f"设备不存在: {board_id}"}
|
||||
|
||||
now = datetime.now()
|
||||
elapsed = (now - record.last_ping_time).total_seconds()
|
||||
is_online = elapsed <= heartbeat_timeout
|
||||
|
||||
ping_data = {}
|
||||
try:
|
||||
ping_data = json.loads(record.ping_data) if record.ping_data else {}
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
return {
|
||||
"board_id": record.board_id,
|
||||
"board_ip": record.board_ip,
|
||||
"board_platform": record.board_platform,
|
||||
"board_type": record.board_type,
|
||||
"board_temp": record.board_temp,
|
||||
"status": record.status,
|
||||
"version": record.version,
|
||||
"system_info": record.system_info,
|
||||
"grant_code": record.grant_code,
|
||||
"grant_desc": record.grant_desc,
|
||||
"is_online": is_online,
|
||||
"last_ping_time": record.last_ping_time.isoformat() if record.last_ping_time else None,
|
||||
"elapsed_seconds": round(elapsed, 1),
|
||||
"ping_data": ping_data,
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[get_device] 查询失败 (board_id={board_id}): {e}")
|
||||
return {"error": str(e)}
|
||||
@@ -0,0 +1,54 @@
|
||||
"""
|
||||
查询离线/异常设备 — GET /aibox/get_offline_devices
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from chongming_worker import rpc_method
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@rpc_method(
|
||||
subject="aibox_sophon_adapter.get_offline_devices",
|
||||
method="GET",
|
||||
summary="查询离线/异常设备列表",
|
||||
)
|
||||
async def get_offline_devices(worker_id: str = "") -> dict:
|
||||
"""返回所有超过心跳超时时间未上报的设备列表"""
|
||||
from ..global_var import db, heartbeat_timeout
|
||||
|
||||
offline_devices = []
|
||||
try:
|
||||
async with db.get_session() as session:
|
||||
from ..models.orm import BoardHeartbeat
|
||||
from sqlalchemy import select
|
||||
|
||||
stmt = select(BoardHeartbeat).order_by(BoardHeartbeat.last_ping_time.desc())
|
||||
result = await session.execute(stmt)
|
||||
records = result.scalars().all()
|
||||
|
||||
now = datetime.now()
|
||||
for record in records:
|
||||
elapsed = (now - record.last_ping_time).total_seconds()
|
||||
is_online = elapsed <= heartbeat_timeout
|
||||
|
||||
if not is_online:
|
||||
offline_devices.append({
|
||||
"board_id": record.board_id,
|
||||
"board_ip": record.board_ip,
|
||||
"board_platform": record.board_platform,
|
||||
"board_type": record.board_type,
|
||||
"status": record.status,
|
||||
"version": record.version,
|
||||
"last_ping_time": record.last_ping_time.isoformat() if record.last_ping_time else None,
|
||||
"elapsed_seconds": round(elapsed, 1),
|
||||
"is_online": False,
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[get_offline_devices] 查询失败: {e}")
|
||||
return {"offline_devices": [], "total": 0, "error": str(e)}
|
||||
|
||||
return {"offline_devices": offline_devices, "total": len(offline_devices)}
|
||||
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
查询所有设备状态 — GET /aibox/list_devices
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from chongming_worker import rpc_method
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@rpc_method(
|
||||
subject="aibox_sophon_adapter.list_devices",
|
||||
method="GET",
|
||||
summary="查询所有设备状态",
|
||||
)
|
||||
async def list_devices(worker_id: str = "") -> dict:
|
||||
"""返回所有已上报过心跳的设备及其在线状态"""
|
||||
from ..global_var import db, heartbeat_timeout
|
||||
|
||||
devices = []
|
||||
try:
|
||||
async with db.get_session() as session:
|
||||
from ..models.orm import BoardHeartbeat
|
||||
from sqlalchemy import select
|
||||
|
||||
stmt = select(BoardHeartbeat).order_by(BoardHeartbeat.updated_at.desc())
|
||||
result = await session.execute(stmt)
|
||||
records = result.scalars().all()
|
||||
|
||||
now = datetime.now()
|
||||
for record in records:
|
||||
# 检查是否超时
|
||||
elapsed = (now - record.last_ping_time).total_seconds()
|
||||
is_online = elapsed <= heartbeat_timeout
|
||||
|
||||
ping_data = {}
|
||||
try:
|
||||
ping_data = json.loads(record.ping_data) if record.ping_data else {}
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
devices.append({
|
||||
"board_id": record.board_id,
|
||||
"board_ip": record.board_ip,
|
||||
"board_platform": record.board_platform,
|
||||
"board_type": record.board_type,
|
||||
"board_temp": record.board_temp,
|
||||
"status": record.status,
|
||||
"version": record.version,
|
||||
"system_info": record.system_info,
|
||||
"grant_code": record.grant_code,
|
||||
"grant_desc": record.grant_desc,
|
||||
"is_online": is_online,
|
||||
"last_ping_time": record.last_ping_time.isoformat() if record.last_ping_time else None,
|
||||
"elapsed_seconds": round(elapsed, 1),
|
||||
"host_disk": ping_data.get("HostDisk", {}),
|
||||
"host_memory": ping_data.get("HostMemory", []),
|
||||
"medias_count": len(ping_data.get("Medias", [])),
|
||||
"tasks_count": len(ping_data.get("Tasks", [])),
|
||||
"tpu": ping_data.get("Tpu", []),
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[list_devices] 查询失败: {e}")
|
||||
return {"devices": [], "total": 0, "error": str(e)}
|
||||
|
||||
return {"devices": devices, "total": len(devices)}
|
||||
Reference in New Issue
Block a user