Files
moss-ai/app/backend-python/services/device_operation_service.py

218 lines
7.5 KiB
Python
Raw Normal View History

2025-12-15 22:05:56 +08:00
"""
设备操作记录服务
负责保存和管理设备操作记录
"""
import logging
import time
import random
import json
from typing import Dict, Any, Optional, List
from datetime import datetime
from database import insert, query, DatabaseConnectionError
logger = logging.getLogger(__name__)
class DeviceOperationService:
"""设备操作记录服务类"""
@staticmethod
def save_operation_record(operation_record: Dict[str, Any]) -> bool:
"""
保存设备操作记录到数据库
Args:
operation_record: 操作记录字典包含以下字段
- system_user_id: int
- context_id: Optional[str]
- device_type: str
- device_name: Optional[str]
- action: str
- parameters: Optional[Dict]
- success: bool
- response: Optional[str]
- error_message: Optional[str]
- execution_time: Optional[int]
- timestamp: str (ISO格式)
Returns:
bool: 保存是否成功
"""
try:
# 生成操作ID
op_id = int(time.time() * 1000000) + random.randint(1000, 9999)
# 提取字段
system_user_id = operation_record.get('system_user_id', 1000000001)
context_id = operation_record.get('context_id')
device_type = operation_record.get('device_type')
device_name = operation_record.get('device_name')
action = operation_record.get('action')
parameters = operation_record.get('parameters')
success = operation_record.get('success', False)
response = operation_record.get('response')
error_message = operation_record.get('error_message')
execution_time = operation_record.get('execution_time')
# 转换参数为JSON
parameters_json = json.dumps(parameters, ensure_ascii=False) if parameters else None
# SQL插入语句
sql = """
INSERT INTO device_operations
(id, system_user_id, context_id, device_type, device_name, action,
parameters, success, response, error_message, execution_time, created_at)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW())
"""
params = (
op_id,
system_user_id,
context_id,
device_type,
device_name,
action,
parameters_json,
success,
response[:1000] if response else None, # 限制长度
error_message[:500] if error_message else None, # 限制长度
execution_time
)
# 执行插入
insert(sql, params)
status_emoji = "" if success else ""
logger.info(
f"{status_emoji} 保存设备操作记录: user={system_user_id}, "
f"device={device_type}, action={action}, success={success}"
)
return True
except DatabaseConnectionError as e:
logger.error(f"❌ 数据库连接失败,无法保存操作记录: {e}")
return False
except Exception as e:
logger.error(f"❌ 保存设备操作记录失败: {e}", exc_info=True)
return False
@staticmethod
def get_recent_operations(
system_user_id: int,
limit: int = 50,
device_type: Optional[str] = None
) -> List[Dict[str, Any]]:
"""
获取最近的操作记录
Args:
system_user_id: 用户ID
limit: 返回记录数量限制
device_type: 可选过滤设备类型
Returns:
操作记录列表
"""
try:
if device_type:
sql = """
SELECT * FROM device_operations
WHERE system_user_id = %s AND device_type = %s
ORDER BY created_at DESC
LIMIT %s
"""
params = (system_user_id, device_type, limit)
else:
sql = """
SELECT * FROM device_operations
WHERE system_user_id = %s
ORDER BY created_at DESC
LIMIT %s
"""
params = (system_user_id, limit)
results = query(sql, params)
# 转换时间戳为字符串
for record in results:
if 'created_at' in record and isinstance(record['created_at'], datetime):
record['created_at'] = record['created_at'].isoformat()
# 解析parameters JSON
if 'parameters' in record and record['parameters']:
try:
record['parameters'] = json.loads(record['parameters'])
except:
pass
return results
except Exception as e:
logger.error(f"❌ 查询操作记录失败: {e}")
return []
@staticmethod
def get_operation_statistics(
system_user_id: int,
days: int = 7
) -> Dict[str, Any]:
"""
获取操作统计信息
Args:
system_user_id: 用户ID
days: 统计最近多少天
Returns:
统计信息字典
"""
try:
sql = """
SELECT
device_type,
COUNT(*) as total_count,
SUM(CASE WHEN success = TRUE THEN 1 ELSE 0 END) as success_count,
SUM(CASE WHEN success = FALSE THEN 1 ELSE 0 END) as failure_count,
AVG(execution_time) as avg_execution_time
FROM device_operations
WHERE system_user_id = %s
AND created_at >= DATE_SUB(NOW(), INTERVAL %s DAY)
GROUP BY device_type
"""
results = query(sql, (system_user_id, days))
# 转换结果
statistics = {
"period_days": days,
"devices": {}
}
for row in results:
device_type = row['device_type']
statistics["devices"][device_type] = {
"total": int(row['total_count']),
"success": int(row['success_count']),
"failure": int(row['failure_count']),
"success_rate": round(row['success_count'] / row['total_count'] * 100, 2) if row['total_count'] > 0 else 0,
"avg_execution_time_ms": round(float(row['avg_execution_time']), 2) if row['avg_execution_time'] else 0
}
return statistics
except Exception as e:
logger.error(f"❌ 查询操作统计失败: {e}")
return {"error": str(e)}
# 全局服务实例
_device_operation_service = None
def get_device_operation_service() -> DeviceOperationService:
"""获取设备操作服务单例"""
global _device_operation_service
if _device_operation_service is None:
_device_operation_service = DeviceOperationService()
return _device_operation_service