处理OTA下发无回执超时
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
from datetime import datetime, time, timedelta
|
from datetime import datetime, timezone, time, timedelta
|
||||||
from typing import Any, List, Literal
|
from typing import Any, List, Literal
|
||||||
|
|
||||||
from services.database_service_base import DatabaseServiceBase
|
from services.database_service_base import DatabaseServiceBase
|
||||||
@@ -8,6 +8,7 @@ from fastapi import HTTPException
|
|||||||
from banban.dao.device import DeviceDAO
|
from banban.dao.device import DeviceDAO
|
||||||
from banban.service.device_setting import device_setting_service
|
from banban.service.device_setting import device_setting_service
|
||||||
from banban.service.ota_firmware import ota_firmware_service
|
from banban.service.ota_firmware import ota_firmware_service
|
||||||
|
from config import settings
|
||||||
from services.device_update_manager import device_firmware_update_manager
|
from services.device_update_manager import device_firmware_update_manager
|
||||||
|
|
||||||
|
|
||||||
@@ -301,6 +302,29 @@ class DeviceService(DatabaseServiceBase):
|
|||||||
latest_parts.extend([0] * (max_len - len(latest_parts)))
|
latest_parts.extend([0] * (max_len - len(latest_parts)))
|
||||||
return latest_parts > current_parts
|
return latest_parts > current_parts
|
||||||
|
|
||||||
|
def _firmware_sent_timed_out(self, updated_at: Any) -> bool:
|
||||||
|
timeout_seconds = max(0, int(settings.ota_sent_timeout_seconds or 0))
|
||||||
|
if timeout_seconds <= 0 or not updated_at:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if isinstance(updated_at, str):
|
||||||
|
text = updated_at.strip()
|
||||||
|
if not text:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
updated_at = datetime.fromisoformat(text.replace("Z", "+00:00"))
|
||||||
|
except ValueError:
|
||||||
|
try:
|
||||||
|
updated_at = datetime.strptime(text, "%Y-%m-%d %H:%M:%S")
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not isinstance(updated_at, datetime):
|
||||||
|
return False
|
||||||
|
|
||||||
|
now = datetime.now(timezone.utc) if updated_at.tzinfo else datetime.now()
|
||||||
|
return (now - updated_at).total_seconds() >= timeout_seconds
|
||||||
|
|
||||||
async def get_firmware_status(
|
async def get_firmware_status(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
@@ -320,6 +344,18 @@ class DeviceService(DatabaseServiceBase):
|
|||||||
progress = update_record.get("progress") if update_record else 0.0
|
progress = update_record.get("progress") if update_record else 0.0
|
||||||
target_version = update_record.get("firmware_version") if update_record else None
|
target_version = update_record.get("firmware_version") if update_record else None
|
||||||
updated_at = update_record.get("updated_at") if update_record else None
|
updated_at = update_record.get("updated_at") if update_record else None
|
||||||
|
if str(update_status or "").strip().lower() == "sent" and self._firmware_sent_timed_out(updated_at):
|
||||||
|
update_status = "failed"
|
||||||
|
progress = 0.0
|
||||||
|
await device_firmware_update_manager.update_firmware_update(
|
||||||
|
device_id=device_id,
|
||||||
|
firmware_version=target_version or latest_version or current_version or "unknown",
|
||||||
|
update_status="failed",
|
||||||
|
progress=0.0,
|
||||||
|
)
|
||||||
|
update_record = await device_firmware_update_manager.get_firmware_update_dict(device_id)
|
||||||
|
if update_record:
|
||||||
|
updated_at = update_record.get("updated_at") or updated_at
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"device_id": device_id,
|
"device_id": device_id,
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ class Settings(BaseSettings):
|
|||||||
talkingq_mqtt_keepalive: int = Field(default=60, validation_alias="TALKINGQ_MQTT_KEEPALIVE")
|
talkingq_mqtt_keepalive: int = Field(default=60, validation_alias="TALKINGQ_MQTT_KEEPALIVE")
|
||||||
talkingq_mqtt_nfc_notice_interval: int = Field(default=600, validation_alias="TALKINGQ_MQTT_NFC_NOTICE_INTERVAL")
|
talkingq_mqtt_nfc_notice_interval: int = Field(default=600, validation_alias="TALKINGQ_MQTT_NFC_NOTICE_INTERVAL")
|
||||||
|
|
||||||
|
ota_sent_timeout_seconds: int = Field(default=300, validation_alias="OTA_SENT_TIMEOUT_SECONDS")
|
||||||
|
|
||||||
admin_api_key: str = Field(default="", validation_alias="ADMIN_API_KEY")
|
admin_api_key: str = Field(default="", validation_alias="ADMIN_API_KEY")
|
||||||
client_api_key: str = Field(default="", validation_alias="CLIENT_API_KEY")
|
client_api_key: str = Field(default="", validation_alias="CLIENT_API_KEY")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user