Files
banban/talkingq-url/api/mqtt_router.py
2026-04-26 20:07:41 +08:00

127 lines
4.9 KiB
Python

import logging
from typing import Optional
from fastapi import APIRouter, HTTPException, Query
from services.offline_audio_cache import offline_audio_cache
from api.mqtt_models import (
GPSQueryRequest,
VolumeRequest,
OTARequest,
NFCNoticeRequest,
NFCListenRequest,
NFCUnreadRequest,
NFCBindRequest,
CommandResponse,
DeviceResponseData,
DeviceStatusResponse,
)
from handlers.mqtt_handler import TalkingQMQTTService
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/mqtt", tags=["MQTT 服务"])
async def _get_service() -> TalkingQMQTTService:
service = await TalkingQMQTTService.get_instance()
if service is None:
raise HTTPException(status_code=503, detail="MQTT 服务未初始化")
return service
@router.post("/gps", response_model=CommandResponse, summary="GPS位置查询")
async def query_gps(req: GPSQueryRequest):
service = await _get_service()
msg_id = await service.send_gps_query(req.device_id)
return CommandResponse(msg_id=msg_id, device_id=req.device_id)
@router.post("/volume", response_model=CommandResponse, summary="音量调节")
async def set_volume(req: VolumeRequest):
service = await _get_service()
msg_id = await service.send_volume_command(req.device_id, req.level)
return CommandResponse(msg_id=msg_id, device_id=req.device_id)
@router.post("/ota", response_model=CommandResponse, summary="OTA升级")
async def start_ota(req: OTARequest):
service = await _get_service()
msg_id = await service.send_ota_command(req.device_id, req.url, req.version)
return CommandResponse(msg_id=msg_id, device_id=req.device_id)
@router.post("/nfc/notice", response_model=CommandResponse, summary="NFC留言下发提示")
async def send_nfc_notice(req: NFCNoticeRequest):
service = await _get_service()
msg_id = await service.send_nfc_notice(req.device_id, req.url)
return CommandResponse(msg_id=msg_id, device_id=req.device_id)
@router.post("/nfc/listen", response_model=CommandResponse, summary="NFC收听留言")
async def nfc_listen(req: NFCListenRequest):
service = await _get_service()
topic = f"device/{req.device_id}/event"
payload = {
"msg_id": "005",
"params": {"uuid": req.uuid}
}
await service._publish(topic, payload)
return CommandResponse(msg_id="005", device_id=req.device_id)
@router.post("/nfc/unread", response_model=CommandResponse, summary="设置NFC未读留言")
async def set_nfc_unread(req: NFCUnreadRequest):
await offline_audio_cache.add_audio_url(req.device_id, req.url)
return CommandResponse(msg_id="", device_id=req.device_id, message="已设置未读留言")
@router.delete("/nfc/unread/{device_id}", response_model=CommandResponse, summary="清除NFC未读留言定时推送")
async def clear_nfc_unread(device_id: str):
await offline_audio_cache.clear_audio_urls(device_id)
return CommandResponse(msg_id="", device_id=device_id, message="已清除未读留言")
@router.post("/nfc/bind", response_model=CommandResponse, summary="NFC绑定卡片")
async def bind_nfc(req: NFCBindRequest):
service = await _get_service()
msg_id = await service.send_bind_nfc_command(req.device_id, req.uuid)
return CommandResponse(msg_id=msg_id, device_id=req.device_id)
# @router.get("/nfc/unread", summary="查询所有未读留言设备列表")
# async def get_nfc_unread_devices():
# service = await _get_service()
# devices = service.get_nfc_unread_devices()
# return {"count": len(devices), "devices": devices}
# @router.get("/device/{device_id}/status", response_model=DeviceStatusResponse, summary="查询设备在线状态")
# async def get_device_status(device_id: str):
# service = await _get_service()
# online = service.is_device_online(device_id)
# last_seen = service.get_device_last_seen(device_id)
# return DeviceStatusResponse(device_id=device_id, online=online, last_seen=last_seen)
# @router.get("/device/{device_id}/responses", summary="查询设备上报记录")
# async def get_device_responses(
# device_id: str,
# msg_id: Optional[str] = Query(None, description="按msg_id过滤"),
# limit: int = Query(20, ge=1, le=100, description="返回条数"),
# ):
# service = await _get_service()
# responses = service.get_device_responses(device_id, msg_id=msg_id, limit=limit)
# return {"device_id": device_id, "count": len(responses), "responses": responses}
# @router.get("/device/{device_id}/wait_response", summary="等待设备响应(同步阻塞)")
# async def wait_device_response(
# device_id: str,
# msg_id: str = Query(..., description="等待的消息ID"),
# timeout: float = Query(10.0, ge=1.0, le=60.0, description="超时时间(秒)"),
# ):
# service = await _get_service()
# response = service.wait_for_response(device_id, msg_id, timeout=timeout)
# if response is None:
# raise HTTPException(status_code=408, detail=f"等待设备 {device_id} 的 msg_id={msg_id} 响应超时")
# return response