""" Beacons Router - 蓝牙信标管理接口 API endpoints for managing Bluetooth beacon configuration. """ import math from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.schemas import ( APIResponse, BeaconConfigCreate, BeaconConfigResponse, BeaconConfigUpdate, PaginatedList, ) from app.services import beacon_service router = APIRouter(prefix="/api/beacons", tags=["Beacons / 蓝牙信标"]) @router.get( "", response_model=APIResponse[PaginatedList[BeaconConfigResponse]], summary="获取信标列表 / List beacons", ) async def list_beacons( status: str | None = Query(default=None, description="状态筛选 (active/inactive)"), search: str | None = Query(default=None, description="搜索 MAC/名称/区域"), page: int = Query(default=1, ge=1), page_size: int = Query(default=20, ge=1, le=100), db: AsyncSession = Depends(get_db), ): records, total = await beacon_service.get_beacons( db, page=page, page_size=page_size, status_filter=status, search=search ) return APIResponse( data=PaginatedList( items=[BeaconConfigResponse.model_validate(r) for r in records], total=total, page=page, page_size=page_size, total_pages=math.ceil(total / page_size) if total else 0, ) ) @router.get( "/{beacon_id}", response_model=APIResponse[BeaconConfigResponse], summary="获取信标详情 / Get beacon", ) async def get_beacon(beacon_id: int, db: AsyncSession = Depends(get_db)): beacon = await beacon_service.get_beacon(db, beacon_id) if beacon is None: raise HTTPException(status_code=404, detail="Beacon not found") return APIResponse(data=BeaconConfigResponse.model_validate(beacon)) @router.post( "", response_model=APIResponse[BeaconConfigResponse], status_code=201, summary="添加信标 / Create beacon", ) async def create_beacon(body: BeaconConfigCreate, db: AsyncSession = Depends(get_db)): existing = await beacon_service.get_beacon_by_mac(db, body.beacon_mac) if existing: raise HTTPException(status_code=400, detail=f"Beacon MAC {body.beacon_mac} already exists") beacon = await beacon_service.create_beacon(db, body) await db.commit() return APIResponse(message="Beacon created", data=BeaconConfigResponse.model_validate(beacon)) @router.put( "/{beacon_id}", response_model=APIResponse[BeaconConfigResponse], summary="更新信标 / Update beacon", ) async def update_beacon( beacon_id: int, body: BeaconConfigUpdate, db: AsyncSession = Depends(get_db) ): beacon = await beacon_service.update_beacon(db, beacon_id, body) if beacon is None: raise HTTPException(status_code=404, detail="Beacon not found") await db.commit() return APIResponse(message="Beacon updated", data=BeaconConfigResponse.model_validate(beacon)) @router.delete( "/{beacon_id}", response_model=APIResponse, summary="删除信标 / Delete beacon", ) async def delete_beacon(beacon_id: int, db: AsyncSession = Depends(get_db)): success = await beacon_service.delete_beacon(db, beacon_id) if not success: raise HTTPException(status_code=404, detail="Beacon not found") await db.commit() return APIResponse(message="Beacon deleted")