Files
banban/talkingq-url/banban/dao/device.py
2026-05-05 16:31:39 +08:00

118 lines
3.6 KiB
Python

from collections.abc import Mapping
from typing import Any, List
from sqlalchemy import text
from banban.dao import BaseDAO
class DeviceDAO(BaseDAO):
async def ensure_device_access(self, *, device_id: str, user_id: int) -> None:
from fastapi import HTTPException, status
result = await self.execute(
text(
"""
SELECT 1
FROM device_bindings
WHERE device_id = :device_id
AND owner_user_id = :user_id
AND status = 1
LIMIT 1
"""
),
{"device_id": device_id, "user_id": user_id},
)
row = result.mappings().first()
if row is None:
raise HTTPException(status_code=404, detail="device not found")
async def list_device_messages(
self,
*,
device_id: str,
cursor: int | None,
limit: int,
) -> List[Mapping[str, Any]]:
params = {"device_id": device_id, "limit": limit + 1}
where = "ch.device_id = :device_id"
if cursor is not None:
where += " AND cm.id < :cursor"
params["cursor"] = cursor
result = await self.execute(
text(
f"""
SELECT
cm.id,
ch.id AS conversation_id,
ch.role_key,
cm.is_user,
cm.content,
cm.timestamp,
cm.created_at
FROM conversation_messages AS cm
JOIN conversation_histories AS ch
ON ch.id = cm.conversation_id
WHERE {where}
ORDER BY cm.id DESC
LIMIT :limit
"""
),
params,
)
return result.mappings().all()
async def get_device_status(
self,
*,
device_id: str,
user_id: int,
) -> Mapping[str, Any]:
from fastapi import HTTPException
result = await self.execute(
text(
"""
SELECT
db.device_id,
db.child_id,
c.child_name,
ds.power,
ds.volume,
ds.`signal` AS signal_strength,
ds.`version` AS version,
ds.updated_at AS settings_updated_at,
cl.coord_type,
cl.lat,
cl.lng,
cl.accuracy_m,
cl.altitude_m,
cl.speed_mps,
cl.heading_deg,
cl.source,
cl.battery_pct,
cl.device_time,
cl.server_time,
cl.updated_at AS location_updated_at
FROM device_bindings AS db
LEFT JOIN children AS c
ON c.child_id = db.child_id
AND c.status = 1
LEFT JOIN device_settings AS ds
ON ds.device_id = db.device_id
LEFT JOIN child_location_current AS cl
ON cl.child_id = db.child_id
AND cl.device_id = db.device_id
WHERE db.device_id = :device_id
AND db.owner_user_id = :user_id
AND db.status = 1
LIMIT 1
"""
),
{"device_id": device_id, "user_id": user_id},
)
row = result.mappings().first()
if row is None:
raise HTTPException(status_code=404, detail="device not found")
return row