118 lines
3.6 KiB
Python
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
|