modify: 接口转发

This commit is contained in:
2026-08-11 14:47:19 +08:00
parent 74d115d2bb
commit 3e1c568d04
2 changed files with 34 additions and 26 deletions
+12 -12
View File
@@ -56,12 +56,12 @@ async def edge_app_controller(payload: dict, topic: str) -> dict | None:
)
if command is None:
return _reply(-1, "缺少 command 字段")
return None
handler = _COMMANDS.get(str(command))
if handler is None:
logger.warning(f"[EdgeAppController] 未知命令: {command}")
return _reply(-2, f"未知命令: {command}")
return None
try:
data = await handler(payload)
@@ -73,7 +73,7 @@ async def edge_app_controller(payload: dict, topic: str) -> dict | None:
return data
except Exception as e:
logger.error(f"[EdgeAppController] 命令 {command} 执行失败: {e}")
return _reply(-3, f"命令执行异常: {e}")
return None
# ============================================================
@@ -124,15 +124,15 @@ async def _cmd_alg_media_fetch(payload: dict) -> dict | None:
board_id = payload.get("BoardId")
if not board_id:
return _reply(-4, "缺少 BoardId 参数")
return None
print(f"[alg_media_fetch]Processing for board: {board_id}")
print(f"[alg_media_fetch]Expected payload: {payload}")
if db is None:
return _reply(-5, "数据库未初始化")
return None
if internal_mqtt is None:
return _reply(-5, "internal_mqtt 未初始化")
return None
async with db.get_session() as session:
from .models.orm import BoardHeartbeat
@@ -144,7 +144,7 @@ async def _cmd_alg_media_fetch(payload: dict) -> dict | None:
if record is None:
print(f"[alg_media_fetch]Board {board_id} not found in database.")
return _reply(-4, f"设备 {board_id} 不在数据库中")
return None
# 内部请求-响应主题由 [workers.config.internal_mqtt] 配置,与盒子侧约定一致
# (盒子只设根主题 box,子路径固定 aibox_sophon/...,回复主题固定为 ..._reply)。
@@ -161,7 +161,7 @@ async def _cmd_alg_media_fetch(payload: dict) -> dict | None:
print(f"[alg_media_fetch]Response from internal_mqtt: {resp}")
if resp is None:
return _reply(-5, "获取算法媒体信息失败(内部请求无响应)")
return None
return resp
async def _cmd_alg_task_fetch(payload: dict) -> dict | None:
@@ -180,15 +180,15 @@ async def _cmd_alg_task_fetch(payload: dict) -> dict | None:
board_id = payload.get("BoardId")
if not board_id:
return _reply(-4, "缺少 BoardId 参数")
return None
print(f"[alg_task_fetch]Processing for board: {board_id}")
print(f"[alg_task_fetch]Expected payload: {payload}")
if db is None:
return _reply(-5, "数据库未初始化")
return None
if internal_mqtt is None:
return _reply(-5, "internal_mqtt 未初始化")
return None
async with db.get_session() as session:
from .models.orm import BoardHeartbeat
@@ -200,7 +200,7 @@ async def _cmd_alg_task_fetch(payload: dict) -> dict | None:
if record is None:
print(f"[alg_task_fetch]Board {board_id} not found in database.")
return _reply(-4, f"设备 {board_id} 不在数据库中")
return None
resp = await internal_mqtt.request(
+22 -14
View File
@@ -38,31 +38,37 @@ logger = logging.getLogger(__name__)
router = APIRouter(prefix="/aibox_sophon_adapter", tags=["aibox_sophon_adapter"])
class _FileStream(httpx.AsyncByteStream):
class _FileStream:
"""
异步文件流 — 用于流式上传视频,避免一次性将整个文件读入内存。
文件流 — 用于流式上传视频,避免一次性将整个文件读入内存。
以 1MB 分块异步读取文件,供 httpx multipart 上传使用。
注意: httpx 0.28 的 multipart 上传(FileField)要求文件对象提供同步的
read()/seek() 方法,httpx 内部以 64KB 分块同步读取;AsyncByteStream 只能
作为整个请求体 content= 使用,无法与 multipart 字段共存。因此这里提供
同步文件接口,配合同步上下文管理器 with 使用(本地磁盘小分块读取,
内存占用依然有界)。
"""
_CHUNK_SIZE = 1024 * 1024
def __init__(self, file_path: str):
self._file_path = file_path
self._file = None
async def __aenter__(self) -> "_FileStream":
self._file = await aiofiles.open(self._file_path, "rb")
def __enter__(self) -> "_FileStream":
self._file = open(self._file_path, "rb")
return self
async def __aexit__(self, exc_type, exc, tb) -> None:
def __exit__(self, exc_type, exc, tb) -> None:
if self._file is not None:
await self._file.close()
self._file.close()
self._file = None
async def __aiter__(self):
assert self._file is not None, "必须在 async with 上下文内使用"
while chunk := await self._file.read(self._CHUNK_SIZE):
yield chunk
def read(self, size: int = -1) -> bytes:
assert self._file is not None, "必须在 with 上下文内使用"
return self._file.read(size)
def seek(self, offset: int, whence: int = 0) -> int:
assert self._file is not None, "必须在 with 上下文内使用"
return self._file.seek(offset, whence)
# ============================================================
@@ -206,7 +212,9 @@ async def _upload_video_to_external(
video_path = os.path.join(video_dir_path, video_files[0])
try:
async with _FileStream(video_path) as video_stream:
# httpx 0.28 的 multipart 以同步 read() 流式读取文件(64KB 分块),
# 因此这里用同步 with 打开文件流
with _FileStream(video_path) as video_stream:
resp = await http_client.post(
video_url,
data={