Browse Source

对接x1服务接口

origin/hotfix/hlk-flight
root 4 months ago
parent
commit
b95d55fbe4
  1. BIN
      .vs/TermControlAgent/CopilotIndices/17.13.439.2385/CodeChunks.db
  2. BIN
      .vs/TermControlAgent/CopilotIndices/17.13.439.2385/SemanticSymbols.db
  3. 5
      app/api/v1/endpoints/websocket.py
  4. 48
      app/core/websocket/manager.py
  5. 15
      app/utils/system_utils.py
  6. 213
      docs/modify.md

BIN
.vs/TermControlAgent/CopilotIndices/17.13.439.2385/CodeChunks.db

Binary file not shown.

BIN
.vs/TermControlAgent/CopilotIndices/17.13.439.2385/SemanticSymbols.db

Binary file not shown.

5
app/api/v1/endpoints/websocket.py

@ -24,6 +24,7 @@ websocket_manager = WebSocketManager()
# 定义缺失的请求和响应模型 # 定义缺失的请求和响应模型
class SuccessResponse(BaseModel): class SuccessResponse(BaseModel):
"""成功响应模型""" """成功响应模型"""
success: bool = Field(True, description="操作是否成功")
message: str = Field(..., description="响应消息") message: str = Field(..., description="响应消息")
data: Optional[Dict[str, Any]] = Field(None, description="响应数据") data: Optional[Dict[str, Any]] = Field(None, description="响应数据")
timestamp: str = Field(..., description="时间戳") timestamp: str = Field(..., description="时间戳")
@ -57,6 +58,7 @@ async def create_and_connect_client(request: CreateWebSocketClientRequest):
logger.info(f"WebSocket客户端 {request.name} 创建并连接成功") logger.info(f"WebSocket客户端 {request.name} 创建并连接成功")
return SuccessResponse( return SuccessResponse(
success=True,
message=f"WebSocket客户端 {request.name} 创建并连接成功", message=f"WebSocket客户端 {request.name} 创建并连接成功",
data={ data={
"name": request.name, "name": request.name,
@ -91,6 +93,7 @@ async def disconnect_client(name: str):
logger.info(f"WebSocket客户端 {name} 断开成功") logger.info(f"WebSocket客户端 {name} 断开成功")
return SuccessResponse( return SuccessResponse(
success=True,
message=f"WebSocket客户端 {name} 断开成功", message=f"WebSocket客户端 {name} 断开成功",
timestamp=now_iso() timestamp=now_iso()
) )
@ -121,6 +124,7 @@ async def send_message(name: str, message_type: str = "data", data: dict = None,
logger.info(f"消息发送成功: {name} -> {message_type}") logger.info(f"消息发送成功: {name} -> {message_type}")
return SuccessResponse( return SuccessResponse(
success=True,
message=f"消息发送成功", message=f"消息发送成功",
data={"client": name, "type": message_type, "priority": priority}, data={"client": name, "type": message_type, "priority": priority},
timestamp=now_iso() timestamp=now_iso()
@ -149,6 +153,7 @@ async def send_heartbeat(name: str):
logger.info(f"心跳发送成功: {name}") logger.info(f"心跳发送成功: {name}")
return SuccessResponse( return SuccessResponse(
success=True,
message=f"心跳发送成功", message=f"心跳发送成功",
data={"client": name}, data={"client": name},
timestamp=now_iso() timestamp=now_iso()

48
app/core/websocket/manager.py

@ -47,8 +47,26 @@ class WebSocketManager:
# 新增:设备事件推送支持 # 新增:设备事件推送支持
self._device_manager = None # 延迟初始化 self._device_manager = None # 延迟初始化
# 新增:缓存机器码,避免频繁获取
self._service_serial = None
self._init_service_serial()
logger.info("WebSocket管理器初始化完成") logger.info("WebSocket管理器初始化完成")
def _init_service_serial(self):
"""初始化服务序列号(机器码)"""
try:
from app.utils.system_utils import SystemUtils
self._service_serial = SystemUtils.get_machine_code()
if self._service_serial:
logger.info(f"WebSocket管理器机器码初始化成功: {self._service_serial}")
else:
logger.warning("WebSocket管理器机器码获取失败,将使用默认值")
self._service_serial = "unknown"
except Exception as e:
logger.error(f"WebSocket管理器机器码初始化异常: {e}")
self._service_serial = "unknown"
async def _get_device_manager(self): async def _get_device_manager(self):
"""获取设备管理器实例(延迟初始化)""" """获取设备管理器实例(延迟初始化)"""
if self._device_manager is None: if self._device_manager is None:
@ -561,6 +579,30 @@ class WebSocketManager:
logger.error(f"WebSocket管理器移除客户端失败: {name} - {e}") logger.error(f"WebSocket管理器移除客户端失败: {name} - {e}")
return False return False
async def _add_service_serial_to_message(self, message_content: Any) -> Dict[str, Any]:
"""为消息内容添加 ServiceSerial 字段
Args:
message_content: 原始消息内容
Returns:
添加了 ServiceSerial 字段的消息内容字典
"""
# 构建消息数据格式,去除data中的type字段避免冗余
if isinstance(message_content, dict):
# 复制字典避免修改原始数据
result = message_content.copy()
if "type" in result:
result.pop("type")
else:
# 如果message_content不是字典,创建一个新的字典
result = {"data": message_content}
# 添加ServiceSerial字段
result["ServiceSerial"] = self._service_serial
return result
async def send_message(self, client_name: str, message_type: str, data: Any, priority: int = 0) -> bool: async def send_message(self, client_name: str, message_type: str, data: Any, priority: int = 0) -> bool:
"""发送消息到指定客户端""" """发送消息到指定客户端"""
try: try:
@ -572,10 +614,8 @@ class WebSocketManager:
# 所有外部消息都发送到send_channel # 所有外部消息都发送到send_channel
channel_name = f"{client_name}_send" channel_name = f"{client_name}_send"
# 构建消息数据格式,去除data中的type字段避免冗余 # 添加ServiceSerial字段
message_content = data.copy() if isinstance(data, dict) else data message_content = await self._add_service_serial_to_message(data)
if isinstance(message_content, dict) and "type" in message_content:
message_content.pop("type")
message_data = { message_data = {
"payload": { "payload": {

15
app/utils/system_utils.py

@ -44,22 +44,19 @@ class SystemUtils:
def _get_windows_machine_code() -> Optional[str]: def _get_windows_machine_code() -> Optional[str]:
"""获取Windows系统机器码""" """获取Windows系统机器码"""
try: try:
# 使用 wmic csproduct get uuid 命令 # 使用 PowerShell 命令获取 UUID,兼容 Windows 11
result = subprocess.run( result = subprocess.run(
["wmic", "csproduct", "get", "uuid"], ["powershell", "-command", "(Get-CimInstance Win32_ComputerSystemProduct).UUID"],
capture_output=True, capture_output=True,
text=True, text=True,
timeout=10 timeout=10
) )
if result.returncode == 0: if result.returncode == 0:
# 解析输出,跳过标题行 uuid = result.stdout.strip()
lines = result.stdout.strip().split('\n') if uuid and len(uuid) > 0:
if len(lines) >= 2: logger.info(f"Windows机器码获取成功: {uuid}")
uuid = lines[1].strip() return uuid
if uuid and uuid != "UUID":
logger.info(f"Windows机器码获取成功: {uuid}")
return uuid
logger.warning("Windows机器码获取失败,尝试备用方法") logger.warning("Windows机器码获取失败,尝试备用方法")
return SystemUtils._get_windows_machine_code_fallback() return SystemUtils._get_windows_machine_code_fallback()

213
docs/modify.md

@ -1,5 +1,218 @@
# 修改记录 # 修改记录
## 2025-08-15 WebSocket API响应添加success字段
**修改内容:**
`app/api/v1/endpoints/websocket.py` 中的所有WebSocket API端点添加 `success` 字段,确保所有成功响应都包含明确的操作状态标识。
**修改详情:**
### 1. SuccessResponse模型已包含success字段
```python
class SuccessResponse(BaseModel):
"""成功响应模型"""
success: bool = Field(True, description="操作是否成功")
message: str = Field(..., description="响应消息")
data: Optional[Dict[str, Any]] = Field(None, description="响应数据")
timestamp: str = Field(..., description="时间戳")
```
### 2. 为所有WebSocket API端点添加success字段
```python
# create_and_connect_client - 已包含success=True
return SuccessResponse(
success=True,
message=f"WebSocket客户端 {request.name} 创建并连接成功",
data={...},
timestamp=now_iso()
)
# disconnect_client - 添加success=True
return SuccessResponse(
success=True,
message=f"WebSocket客户端 {name} 断开成功",
timestamp=now_iso()
)
# send_message - 添加success=True
return SuccessResponse(
success=True,
message=f"消息发送成功",
data={"client": name, "type": message_type, "priority": priority},
timestamp=now_iso()
)
# send_heartbeat - 添加success=True
return SuccessResponse(
success=True,
message=f"心跳发送成功",
data={"client": name},
timestamp=now_iso()
)
```
**优化效果:**
- ✅ 所有WebSocket API响应都包含明确的success字段
- ✅ 客户端可以统一检查操作是否成功
- ✅ 响应格式更加规范和一致
- ✅ 便于前端处理和错误判断
- ✅ 符合RESTful API设计规范
**技术说明:**
- **统一响应格式**:所有成功响应都包含success=True字段
- **明确状态标识**:客户端可以通过success字段快速判断操作结果
- **向后兼容**:不影响现有的响应数据结构
- **标准化**:符合API设计最佳实践
## 2025-08-15 Windows机器码获取命令更新
**修改内容:**
更新 `app/utils/system_utils.py` 中的 `_get_windows_machine_code` 方法,将获取机器码的命令从 `wmic csproduct get uuid` 更改为 `powershell -command "(Get-CimInstance Win32_ComputerSystemProduct).UUID"`,以兼容 Windows 11 系统。
**修改详情:**
### 原命令(不兼容Windows 11)
```python
# 使用 wmic csproduct get uuid 命令
result = subprocess.run(
["wmic", "csproduct", "get", "uuid"],
capture_output=True,
text=True,
timeout=10
)
# 解析输出,跳过标题行
lines = result.stdout.strip().split('\n')
if len(lines) >= 2:
uuid = lines[1].strip()
if uuid and uuid != "UUID":
logger.info(f"Windows机器码获取成功: {uuid}")
return uuid
```
### 新命令(兼容Windows 11)
```python
# 使用 PowerShell 命令获取 UUID,兼容 Windows 11
result = subprocess.run(
["powershell", "-command", "(Get-CimInstance Win32_ComputerSystemProduct).UUID"],
capture_output=True,
text=True,
timeout=10
)
if result.returncode == 0:
uuid = result.stdout.strip()
if uuid and len(uuid) > 0:
logger.info(f"Windows机器码获取成功: {uuid}")
return uuid
```
**优化效果:**
- ✅ 兼容 Windows 11 系统(wmic 命令已被弃用)
- ✅ 简化输出解析逻辑(PowerShell 直接返回 UUID)
- ✅ 保持相同的错误处理和备用方法机制
- ✅ 不影响现有的 ServiceSerial 功能
**技术说明:**
- **兼容性提升**:Windows 11 不再支持 `wmic` 命令,使用 PowerShell 的 `Get-CimInstance` 替代
- **输出简化**:PowerShell 命令直接返回 UUID 值,无需解析多行输出
- **向后兼容**:保留备用方法机制,确保在异常情况下仍能获取机器码
## 2025-08-15 WebSocket消息添加ServiceSerial字段
**优化内容:**
`app/core/websocket/manager.py``send_message` 方法中添加 `ServiceSerial` 字段,该字段从系统机器码获取,并在类初始化时缓存以避免频繁获取。后续重构将添加ServiceSerial的逻辑提取到单独的方法中。
**实现详情:**
### 1. 初始化时获取机器码
```python
def __init__(self):
# ... 其他初始化代码 ...
# 新增:缓存机器码,避免频繁获取
self._service_serial = None
self._init_service_serial()
def _init_service_serial(self):
"""初始化服务序列号(机器码)"""
try:
from app.utils.system_utils import SystemUtils
self._service_serial = SystemUtils.get_machine_code()
if self._service_serial:
logger.info(f"WebSocket管理器机器码初始化成功: {self._service_serial}")
else:
logger.warning("WebSocket管理器机器码获取失败,将使用默认值")
self._service_serial = "unknown"
except Exception as e:
logger.error(f"WebSocket管理器机器码初始化异常: {e}")
self._service_serial = "unknown"
```
### 2. 提取ServiceSerial添加逻辑到单独方法
```python
async def _add_service_serial_to_message(self, message_content: Any) -> Dict[str, Any]:
"""为消息内容添加 ServiceSerial 字段
Args:
message_content: 原始消息内容
Returns:
添加了 ServiceSerial 字段的消息内容字典
"""
# 构建消息数据格式,去除data中的type字段避免冗余
if isinstance(message_content, dict):
# 复制字典避免修改原始数据
result = message_content.copy()
if "type" in result:
result.pop("type")
else:
# 如果message_content不是字典,创建一个新的字典
result = {"data": message_content}
# 添加ServiceSerial字段
result["ServiceSerial"] = self._service_serial
return result
```
### 3. 发送消息时调用ServiceSerial添加方法
```python
async def send_message(self, client_name: str, message_type: str, data: Any, priority: int = 0) -> bool:
# ... 其他代码 ...
# 添加ServiceSerial字段
message_content = await self._add_service_serial_to_message(data)
```
**优化效果:**
- ✅ 在WebSocket消息中自动添加ServiceSerial字段
- ✅ 机器码在初始化时获取一次并缓存,避免频繁调用
- ✅ 支持字典和非字典类型的消息内容
- ✅ 完善的错误处理,获取失败时使用默认值
- ✅ 详细的日志记录,便于调试和监控
- ✅ **代码重构**:将ServiceSerial添加逻辑提取到单独方法,提高代码可维护性
**技术特点:**
- **性能优化**:机器码只获取一次,避免每次发送消息时都调用系统命令
- **兼容性**:支持Windows和Linux系统的机器码获取
- **容错性**:获取失败时使用"unknown"作为默认值,不影响消息发送
- **灵活性**:支持不同格式的消息内容,自动适配
- **代码质量**:单一职责原则,方法职责清晰,易于测试和维护
**消息格式示例:**
```json
{
"payload": {
"message": {
"device_id": "AMFU6R1813008221",
"status": "device",
"ServiceSerial": "12345678-1234-1234-1234-123456789012"
}
}
}
```
## 2025-08-15 实现系统接口获取机器码功能 ## 2025-08-15 实现系统接口获取机器码功能
**新增内容:** **新增内容:**

Loading…
Cancel
Save