合入小程序修改,新增告警功能

This commit is contained in:
HycJack
2026-05-09 09:46:06 +08:00
parent 46cc5272f3
commit be4d276557
10 changed files with 800 additions and 28 deletions

View File

@@ -0,0 +1,129 @@
from __future__ import annotations
from dataclasses import dataclass
from sqlalchemy import text
from services.database_service_base import DatabaseServiceBase
from utils.logger import session_logger
class DeviceIdentityInitializationError(ValueError):
pass
@dataclass(frozen=True)
class DeviceIdentityInitializationResult:
imei: str
device_id: str
serial_number: str
activated: bool
class DeviceIdentityInitializer(DatabaseServiceBase):
def __init__(self):
super().__init__(service_name="device_identity_initializer")
async def initialize_by_imei(self, imei: str) -> DeviceIdentityInitializationResult:
normalized_imei = str(imei or "").strip()
if not normalized_imei:
raise DeviceIdentityInitializationError("imei is required")
db_session = await self.get_session()
try:
mapping_result = await db_session.execute(
text(
"""
SELECT imei, device_id, serial_number, status
FROM device_imei_mapping
WHERE imei = :imei
LIMIT 1
"""
),
{"imei": normalized_imei},
)
mapping = mapping_result.mappings().first()
if mapping is None:
raise DeviceIdentityInitializationError("imei mapping not found")
device_id = str(mapping["device_id"]).strip()
serial_number = str(mapping["serial_number"]).strip()
if not device_id or not serial_number:
raise DeviceIdentityInitializationError("imei mapping is incomplete")
device_auth_result = await db_session.execute(
text(
"""
SELECT device_id, serial_number
FROM device_auth
WHERE device_id = :device_id
LIMIT 1
"""
),
{"device_id": device_id},
)
device_auth = device_auth_result.mappings().first()
if device_auth is None:
await db_session.execute(
text(
"""
INSERT INTO device_auth (device_id, serial_number, is_active)
VALUES (:device_id, :serial_number, 1)
"""
),
{"device_id": device_id, "serial_number": serial_number},
)
elif str(device_auth["serial_number"]) != serial_number:
raise DeviceIdentityInitializationError("device_auth serial_number conflict")
else:
await db_session.execute(
text(
"""
UPDATE device_auth
SET is_active = 1
WHERE device_id = :device_id
"""
),
{"device_id": device_id},
)
await db_session.execute(
text(
"""
UPDATE device_imei_mapping
SET status = 'activated',
activated_at = COALESCE(activated_at, CURRENT_TIMESTAMP)
WHERE imei = :imei
"""
),
{"imei": normalized_imei},
)
await db_session.commit()
session_logger.info(
device_id,
"device_identity_initializer",
f"IMEI identity initialized: imei={normalized_imei}",
)
return DeviceIdentityInitializationResult(
imei=normalized_imei,
device_id=device_id,
serial_number=serial_number,
activated=str(mapping["status"]) == "activated",
)
except DeviceIdentityInitializationError:
await db_session.rollback()
raise
except Exception as exc:
await db_session.rollback()
session_logger.error(
normalized_imei,
"device_identity_initializer",
f"initialize identity failed: {exc}",
)
raise
finally:
await db_session.close()
device_identity_initializer = DeviceIdentityInitializer()

View File

@@ -1,6 +1,8 @@
from typing import Dict, Optional
import time
from sqlalchemy import select, update, insert, delete
from collections.abc import Mapping
from sqlalchemy import select, update, insert, delete, text
from database.models import DeviceFirmwareUpdate
from services.database_service_base import DatabaseServiceBase
from utils.logger import session_logger
@@ -13,7 +15,31 @@ class DeviceFirmwareUpdateManager(DatabaseServiceBase):
self.cache_timestamps = {} # 记录缓存更新时间
self.max_cache_size = 1000 # 最大缓存条目数
async def create_firmware_update(self, device_id: str, firmware_version: str, update_status: str = "success"):
async def _get_serial_number(self, db_session, device_id: str) -> str:
result = await db_session.execute(
text("SELECT serial_number FROM device_auth WHERE device_id = :device_id LIMIT 1"),
{"device_id": device_id},
)
row = result.mappings().first()
if row and row.get("serial_number"):
return str(row["serial_number"])
return ""
def _row_to_dict(self, row) -> dict:
if row is None:
return {}
if isinstance(row, Mapping):
return dict(row)
return {
"device_id": row.device_id,
"firmware_version": row.firmware_version,
"update_status": row.update_status,
"progress": row.progress,
"created_at": row.created_at,
"updated_at": row.updated_at,
}
async def create_firmware_update(self, device_id: str, firmware_version: str, update_status: str = "success", progress: float = 0.0):
"""新增固件更新记录"""
await self._init_database()
db_session = await self.get_session()
@@ -29,16 +55,18 @@ class DeviceFirmwareUpdateManager(DatabaseServiceBase):
.values(
firmware_version=firmware_version,
update_status=update_status,
progress=0.0
progress=progress
)
)
await db_session.execute(update_stmt)
else:
serial_number = await self._get_serial_number(db_session, device_id)
insert_stmt = insert(DeviceFirmwareUpdate).values(
device_id=device_id,
serial_number=serial_number,
firmware_version=firmware_version,
update_status=update_status,
progress=0.0
progress=progress
)
await db_session.execute(insert_stmt)
@@ -48,7 +76,7 @@ class DeviceFirmwareUpdateManager(DatabaseServiceBase):
"device_id": device_id,
"firmware_version": firmware_version,
"update_status": update_status,
"progress": 0.0
"progress": progress
})
return True
@@ -79,7 +107,13 @@ class DeviceFirmwareUpdateManager(DatabaseServiceBase):
finally:
await db_session.close()
async def update_firmware_update(self, device_id: str, firmware_version: str, update_status: str) -> bool:
async def update_firmware_update(
self,
device_id: str,
firmware_version: str,
update_status: str,
progress: Optional[float] = None,
) -> bool:
"""更新设备固件信息(支持部分字段更新)"""
await self._init_database()
db_session = await self.get_session()
@@ -88,6 +122,8 @@ class DeviceFirmwareUpdateManager(DatabaseServiceBase):
"firmware_version": firmware_version,
"update_status": update_status
}
if progress is not None:
update_values["progress"] = progress
query = select(DeviceFirmwareUpdate).where(DeviceFirmwareUpdate.device_id == device_id)
result = await db_session.execute(query)
@@ -101,10 +137,13 @@ class DeviceFirmwareUpdateManager(DatabaseServiceBase):
)
await db_session.execute(update_stmt)
else:
serial_number = await self._get_serial_number(db_session, device_id)
insert_stmt = insert(DeviceFirmwareUpdate).values(
device_id=device_id,
serial_number=serial_number,
firmware_version=firmware_version,
update_status=update_status
update_status=update_status,
progress=progress if progress is not None else 0.0,
)
await db_session.execute(insert_stmt)
@@ -131,8 +170,12 @@ class DeviceFirmwareUpdateManager(DatabaseServiceBase):
await db_session.execute(update_stmt)
await db_session.commit()
if device_id in self.update_cache:
self.update_cache[device_id].progress = progress
cached_update = self.update_cache.get(device_id)
if isinstance(cached_update, dict):
cached_update["progress"] = progress
elif cached_update is not None:
cached_update.progress = progress
if cached_update is not None:
self.cache_timestamps[device_id] = time.time()
session_logger.info(device_id, "firmware_update", f"更新进度已更新: {progress:.1f}%")
@@ -184,8 +227,10 @@ class DeviceFirmwareUpdateManager(DatabaseServiceBase):
)
await db_session.execute(update_stmt)
else:
serial_number = await self._get_serial_number(db_session, device_id)
insert_stmt = insert(DeviceFirmwareUpdate).values(
device_id=device_id,
serial_number=serial_number,
firmware_version=firmware_version,
update_status="success" # 默认状态为成功
)
@@ -264,4 +309,10 @@ class DeviceFirmwareUpdateManager(DatabaseServiceBase):
if device_id in self.cache_timestamps:
del self.cache_timestamps[device_id]
device_firmware_update_manager = DeviceFirmwareUpdateManager()
async def get_firmware_update_dict(self, device_id: str) -> Optional[dict]:
record = await self.get_firmware_update(device_id)
if record is None:
return None
return self._row_to_dict(record)
device_firmware_update_manager = DeviceFirmwareUpdateManager()