fix: support MQTT location refresh

This commit is contained in:
stu2not
2026-05-15 15:34:59 +08:00
parent 02410e2922
commit 3164d81bb0
2 changed files with 36 additions and 29 deletions

View File

@@ -1,7 +1,6 @@
import logging
from collections.abc import Mapping
from datetime import datetime, time
from services.connection_manager import connection_manager
from fastapi import APIRouter, Depends, HTTPException, Query, Request
from pydantic import BaseModel, Field
from sqlalchemy import text
@@ -573,15 +572,12 @@ async def get_current_device_location(
service = await TalkingQMQTTService.get_instance()
if service is None:
raise HTTPException(status_code=503, detail="MQTT 服务未初始化")
query_started_at = datetime.now()
await service.send_gps_query(device_id)
try:
# 每隔1s 获取一次GPS数据最多3次
# 先判断设备是否在线不在线直接提示设备没有在线通过websocket判断
target_websocket = await connection_manager.get_connection(device_id)
if not target_websocket or target_websocket.client_state.name != "CONNECTED":
raise HTTPException(status_code=408, detail="设备未在线")
i=0
while i<1:
# MQTT 设备没有 WebSocket 连接时,也可以通过 GPS 回包刷新定位。
row = None
for _ in range(3):
try:
row = await location_service.get_device_current_location(
device_id=device_id,
@@ -590,12 +586,10 @@ async def get_current_device_location(
except Exception as e:
await asyncio.sleep(1)
continue
if row is None:
await asyncio.sleep(1)
else:
if row["updated_at"] is not None \
and (datetime.now() - row['updated_at']) <= timedelta(seconds=10):
if row is not None and row["updated_at"] is not None:
updated_at = row["updated_at"]
if updated_at >= query_started_at - timedelta(seconds=1):
logger.info(
"device current location fetched",
extra={
@@ -607,22 +601,13 @@ async def get_current_device_location(
},
)
return _row_to_current_location_response(row)
i+=1
await asyncio.sleep(1)
if row is None:
raise HTTPException(status_code=408, detail="GPS数据上报超时")
logger.info(
"device location reported",
extra={
"event": "device_location_report",
"request_id": getattr(request.state, "request_id", None),
"device_id": device_id,
"child_id": int(row["child_id"]),
"lat": float(row["lat"]),
"lng": float(row["lng"]),
},
)
raise HTTPException(status_code=408, detail="GPS数据未刷新")
except Exception as e:
raise HTTPException(status_code=408, detail=f"GPS数据上报失败: {e}")

View File

@@ -109,7 +109,7 @@ class LocationService(DatabaseServiceBase):
altitude_m: float | None = None,
speed_mps: float | None = None,
heading_deg: int | None = None,
source: int | None = None,
source: int | str | None = None,
battery_pct: int | None = None,
device_time: datetime | None = None,
) -> Mapping[str, Any] | None:
@@ -129,6 +129,8 @@ class LocationService(DatabaseServiceBase):
battery_pct: int | None
device_time: datetime
source_value = self._normalize_location_source(source)
db_session = await self.get_session()
try:
dao = LocationDAO(db_session)
@@ -144,7 +146,7 @@ class LocationService(DatabaseServiceBase):
altitude_m=altitude_m,
speed_mps=speed_mps,
heading_deg=heading_deg,
source=source if source is not None else 0,
source=source_value,
battery_pct=battery_pct,
device_time=device_time or datetime.now(),
)
@@ -156,5 +158,25 @@ class LocationService(DatabaseServiceBase):
finally:
await db_session.close()
@staticmethod
def _normalize_location_source(source: int | str | None) -> int:
if source is None:
return 0
if isinstance(source, int):
return source
text = str(source).strip().lower()
if not text:
return 0
if text.isdigit():
return int(text)
return {
"gps": 1,
"wifi": 2,
"cell": 3,
"base_station": 3,
"manual": 4,
"mock": 9,
}.get(text, 0)
# 创建全局 LocationService 实例
location_service = LocationService()