fix: support MQTT location refresh
This commit is contained in:
@@ -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}")
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user