修复部分识别error

This commit is contained in:
Xuwznln
2025-06-28 10:52:34 +08:00
parent 817e88cfc4
commit 9be6e1069a
7 changed files with 66 additions and 70 deletions

View File

@@ -13,17 +13,17 @@ def register_devices_and_resources(mqtt_client, lab_registry):
""" """
logger.info("[UniLab Register] 开始注册设备和资源...") logger.info("[UniLab Register] 开始注册设备和资源...")
# # 注册设备信息 # 注册设备信息
# for device_info in lab_registry.obtain_registry_device_info(): for device_info in lab_registry.obtain_registry_device_info():
# mqtt_client.publish_registry(device_info["id"], device_info, False) mqtt_client.publish_registry(device_info["id"], device_info, False)
# logger.debug(f"[UniLab Register] 注册设备: {device_info['id']}") logger.debug(f"[UniLab Register] 注册设备: {device_info['id']}")
#
# # 注册资源信息 # 注册资源信息
# for resource_info in lab_registry.obtain_registry_resource_info(): for resource_info in lab_registry.obtain_registry_resource_info():
# mqtt_client.publish_registry(resource_info["id"], resource_info, False) mqtt_client.publish_registry(resource_info["id"], resource_info, False)
# logger.debug(f"[UniLab Register] 注册资源: {resource_info['id']}") logger.debug(f"[UniLab Register] 注册资源: {resource_info['id']}")
#
# time.sleep(10) time.sleep(10)
logger.info("[UniLab Register] 设备和资源注册完成.") logger.info("[UniLab Register] 设备和资源注册完成.")

View File

@@ -40,7 +40,6 @@ class HTTPClient:
Returns: Returns:
Response: API响应对象 Response: API响应对象
""" """
return True
response = requests.post( response = requests.post(
f"{self.remote_addr}/lab/resource/edge/batch_create/?database_process_later={1 if database_process_later else 0}", f"{self.remote_addr}/lab/resource/edge/batch_create/?database_process_later={1 if database_process_later else 0}",
json=resources, json=resources,
@@ -61,7 +60,6 @@ class HTTPClient:
Returns: Returns:
Response: API响应对象 Response: API响应对象
""" """
return True
response = requests.post( response = requests.post(
f"{self.remote_addr}/lab/resource/?database_process_later={1 if database_process_later else 0}", f"{self.remote_addr}/lab/resource/?database_process_later={1 if database_process_later else 0}",
json=resources, json=resources,

View File

@@ -7,6 +7,7 @@ Web页面模块
import json import json
import os import os
import sys import sys
import traceback
from pathlib import Path from pathlib import Path
from typing import Dict from typing import Dict
@@ -17,7 +18,7 @@ from jinja2 import Environment, FileSystemLoader
from unilabos.config.config import BasicConfig from unilabos.config.config import BasicConfig
from unilabos.registry.registry import lab_registry from unilabos.registry.registry import lab_registry
from unilabos.ros.msgs.message_converter import msg_converter_manager from unilabos.ros.msgs.message_converter import msg_converter_manager
from unilabos.utils.log import error from unilabos.utils.log import error, debug
from unilabos.utils.type_check import TypeEncoder from unilabos.utils.type_check import TypeEncoder
from unilabos.app.web.utils.device_utils import get_registry_info from unilabos.app.web.utils.device_utils import get_registry_info
from unilabos.app.web.utils.host_utils import get_host_node_info from unilabos.app.web.utils.host_utils import get_host_node_info
@@ -123,6 +124,7 @@ def setup_web_pages(router: APIRouter) -> None:
return html return html
except Exception as e: except Exception as e:
debug(traceback.format_exc())
error(f"生成状态页面时出错: {str(e)}") error(f"生成状态页面时出错: {str(e)}")
raise HTTPException(status_code=500, detail=f"Error generating status page: {str(e)}") raise HTTPException(status_code=500, detail=f"Error generating status page: {str(e)}")

View File

@@ -4899,7 +4899,7 @@ liquid_handler.biomek:
none_keys: none_keys:
default: [] default: []
description: '参数: none_keys' description: '参数: none_keys'
type: string type: array
protocol_author: protocol_author:
description: '参数: protocol_author' description: '参数: protocol_author'
type: string type: string
@@ -5287,7 +5287,7 @@ liquid_handler.biomek:
none_keys: none_keys:
default: [] default: []
description: '参数: none_keys' description: '参数: none_keys'
type: string type: array
offsets: offsets:
description: '参数: offsets' description: '参数: offsets'
type: string type: string

View File

@@ -402,7 +402,7 @@ virtual_column:
properties: properties:
config: config:
description: '参数: config' description: '参数: config'
type: string type: object
device_id: device_id:
description: '参数: device_id' description: '参数: device_id'
type: string type: string
@@ -1370,7 +1370,7 @@ virtual_heatchill:
properties: properties:
config: config:
description: '参数: config' description: '参数: config'
type: string type: object
device_id: device_id:
description: '参数: device_id' description: '参数: device_id'
type: string type: string
@@ -1893,7 +1893,7 @@ virtual_multiway_valve:
module: unilabos.devices.virtual.virtual_multiway_valve:VirtualMultiwayValve module: unilabos.devices.virtual.virtual_multiway_valve:VirtualMultiwayValve
status_types: status_types:
current_position: int current_position: int
get_available_ports: typing:Dict get_available_ports: dict
get_available_positions: list get_available_positions: list
get_current_port: str get_current_port: str
get_current_position: int get_current_position: int
@@ -2372,7 +2372,7 @@ virtual_pump:
properties: properties:
config: config:
description: '参数: config' description: '参数: config'
type: string type: object
device_id: device_id:
description: '参数: device_id' description: '参数: device_id'
type: string type: string
@@ -3026,8 +3026,7 @@ virtual_solenoid_valve:
auto-close: auto-close:
feedback: {} feedback: {}
goal: {} goal: {}
goal_default: goal_default: {}
kwargs: null
handles: [] handles: []
result: {} result: {}
schema: schema:
@@ -3036,12 +3035,8 @@ virtual_solenoid_valve:
feedback: {} feedback: {}
goal: goal:
description: UniLabJsonCommand close 的参数schema description: UniLabJsonCommand close 的参数schema
properties: properties: {}
kwargs: required: []
description: '参数: kwargs'
type: string
required:
- kwargs
type: object type: object
result: {} result: {}
required: required:
@@ -3136,8 +3131,7 @@ virtual_solenoid_valve:
auto-open: auto-open:
feedback: {} feedback: {}
goal: {} goal: {}
goal_default: goal_default: {}
kwargs: null
handles: [] handles: []
result: {} result: {}
schema: schema:
@@ -3146,12 +3140,8 @@ virtual_solenoid_valve:
feedback: {} feedback: {}
goal: goal:
description: UniLabJsonCommand open 的参数schema description: UniLabJsonCommand open 的参数schema
properties: properties: {}
kwargs: required: []
description: '参数: kwargs'
type: string
required:
- kwargs
type: object type: object
result: {} result: {}
required: required:
@@ -3185,7 +3175,6 @@ virtual_solenoid_valve:
goal: {} goal: {}
goal_default: goal_default:
command: null command: null
kwargs: null
handles: [] handles: []
result: {} result: {}
schema: schema:
@@ -3198,12 +3187,8 @@ virtual_solenoid_valve:
command: command:
description: '参数: command' description: '参数: command'
type: string type: string
kwargs:
description: '参数: kwargs'
type: string
required: required:
- command - command
- kwargs
type: object type: object
result: {} result: {}
required: required:
@@ -3216,7 +3201,6 @@ virtual_solenoid_valve:
goal: {} goal: {}
goal_default: goal_default:
command: null command: null
kwargs: null
handles: [] handles: []
result: {} result: {}
schema: schema:
@@ -3229,11 +3213,7 @@ virtual_solenoid_valve:
command: command:
description: '参数: command' description: '参数: command'
type: string type: string
kwargs: required: []
description: '参数: kwargs'
type: string
required:
- kwargs
type: object type: object
result: {} result: {}
required: required:
@@ -3852,7 +3832,7 @@ virtual_stirrer:
properties: properties:
config: config:
description: '参数: config' description: '参数: config'
type: string type: object
device_id: device_id:
description: '参数: device_id' description: '参数: device_id'
type: string type: string

View File

@@ -459,6 +459,8 @@ class HostNode(BaseROS2DeviceNode):
self.devices_instances[device_id] = d self.devices_instances[device_id] = d
# noinspection PyProtectedMember # noinspection PyProtectedMember
for action_name, action_value_mapping in d._ros_node._action_value_mappings.items(): for action_name, action_value_mapping in d._ros_node._action_value_mappings.items():
if action_name.startswith("auto-"):
continue
action_id = f"/devices/{device_id}/{action_name}" action_id = f"/devices/{device_id}/{action_name}"
if action_id not in self._action_clients: if action_id not in self._action_clients:
action_type = action_value_mapping["type"] action_type = action_value_mapping["type"]

View File

@@ -216,15 +216,16 @@ class ImportManager:
f"{module_path} 失败(将使用静态分析," f"{module_path} 失败(将使用静态分析,"
f"建议修复导入错误,以实现更好的注册表识别效果!): {e}" f"建议修复导入错误,以实现更好的注册表识别效果!): {e}"
) )
use_dynamic = False
# 尝试静态分析 if not use_dynamic:
static_info = None # 尝试静态分析
try: static_info = None
static_info = self._get_static_class_info(module_path) try:
result["static_analysis_success"] = True static_info = self._get_static_class_info(module_path)
logger.debug(f"[ImportManager] 静态分析类 {module_path} 成功") result["static_analysis_success"] = True
except Exception as e: logger.debug(f"[ImportManager] 静态分析类 {module_path} 成功")
logger.warning(f"[ImportManager] 静态分析类 {module_path} 失败: {e}") except Exception as e:
logger.warning(f"[ImportManager] 静态分析类 {module_path} 失败: {e}")
# 合并信息(优先使用动态导入的信息) # 合并信息(优先使用动态导入的信息)
if dynamic_info: if dynamic_info:
@@ -351,15 +352,32 @@ class ImportManager:
return result return result
def _analyze_method_signature(self, method) -> Dict[str, Any]: def _analyze_method_signature(self, method) -> Dict[str, Any]:
"""分析方法签名""" """
signature = inspect.signature(method) 分析方法签名,提取具体的命名参数信息
注意:此方法会跳过*args和**kwargs只提取具体的命名参数
这样可以确保通过**dict方式传参时的准确性
示例用法:
method_info = self._analyze_method_signature(some_method)
params = {"param1": "value1", "param2": "value2"}
result = some_method(**params) # 安全的参数传递
"""
signature = inspect.signature(method)
args = [] args = []
num_required = 0 num_required = 0
for param_name, param in signature.parameters.items(): for param_name, param in signature.parameters.items():
# 跳过self参数
if param_name == "self": if param_name == "self":
continue continue
# 跳过*args和**kwargs参数
if param.kind == param.VAR_POSITIONAL: # *args
continue
if param.kind == param.VAR_KEYWORD: # **kwargs
continue
is_required = param.default == inspect.Parameter.empty is_required = param.default == inspect.Parameter.empty
if is_required: if is_required:
num_required += 1 num_required += 1
@@ -392,10 +410,15 @@ class ImportManager:
"""将类型注解转换为字符串""" """将类型注解转换为字符串"""
if annotation == inspect.Parameter.empty: if annotation == inspect.Parameter.empty:
return "Any" # 如果没有注解返回Any return "Any" # 如果没有注解返回Any
if annotation is None: if annotation is None:
return "None" # 明确的None类型 return "None" # 明确的None类型
annotation_str = str(annotation)
# 处理typing模块的复杂类型
if "typing." in annotation_str:
# 简化typing类型显示
return (
annotation_str.replace("typing.", "") if getattr(annotation, "_name", None) is None else annotation._name.lower()
)
# 如果是类型对象 # 如果是类型对象
if hasattr(annotation, "__name__"): if hasattr(annotation, "__name__"):
# 如果是内置类型 # 如果是内置类型
@@ -404,22 +427,13 @@ class ImportManager:
else: else:
# 如果是自定义类,返回完整路径 # 如果是自定义类,返回完整路径
return f"{annotation.__module__}:{annotation.__name__}" return f"{annotation.__module__}:{annotation.__name__}"
# 如果是typing模块的类型 # 如果是typing模块的类型
elif hasattr(annotation, "_name"): elif hasattr(annotation, "_name"):
return annotation._name return annotation._name
# 如果是字符串形式的类型注解 # 如果是字符串形式的类型注解
elif isinstance(annotation, str): elif isinstance(annotation, str):
return annotation return annotation
# 其他情况,尝试转换为字符串
else: else:
annotation_str = str(annotation)
# 处理typing模块的复杂类型
if "typing." in annotation_str:
# 简化typing类型显示
return annotation_str.replace("typing.", "")
return annotation_str return annotation_str
def _is_property_method(self, node: ast.FunctionDef) -> bool: def _is_property_method(self, node: ast.FunctionDef) -> bool: