Compare commits

...

3 Commits

Author SHA1 Message Date
Xuwznln
be0a73eb19 修复静态方法识别get status,注册表支持python类型 2025-06-28 12:18:30 +08:00
Xuwznln
9be6e1069a 修复部分识别error 2025-06-28 10:52:34 +08:00
Xuwznln
817e88cfc4 修复不启用注册表补充就无法启动的bug 2025-06-28 01:32:10 +08:00
18 changed files with 145 additions and 1112 deletions

View File

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

View File

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

View File

@@ -7,6 +7,7 @@ Web页面模块
import json
import os
import sys
import traceback
from pathlib import Path
from typing import Dict
@@ -17,7 +18,7 @@ from jinja2 import Environment, FileSystemLoader
from unilabos.config.config import BasicConfig
from unilabos.registry.registry import lab_registry
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.app.web.utils.device_utils import get_registry_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
except Exception as e:
debug(traceback.format_exc())
error(f"生成状态页面时出错: {str(e)}")
raise HTTPException(status_code=500, detail=f"Error generating status page: {str(e)}")

View File

@@ -22,32 +22,6 @@ hplc.agilent:
title: check_status 命令参数
type: object
type: UniLabJsonCommand
auto-execute_command_from_outer:
feedback: {}
goal: {}
goal_default:
command: null
handles: []
result: {}
schema:
description: UniLabJsonCommand execute_command_from_outer 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand execute_command_from_outer 的参数schema
properties:
command:
description: '参数: command'
type: string
required:
- command
type: object
result: {}
required:
- goal
title: execute_command_from_outer 命令参数
type: object
type: UniLabJsonCommand
auto-extract_data_from_txt:
feedback: {}
goal: {}
@@ -74,35 +48,6 @@ hplc.agilent:
title: extract_data_from_txt 命令参数
type: object
type: UniLabJsonCommand
auto-get_data_file:
feedback: {}
goal: {}
goal_default:
after_time: null
mat_index: null
handles: []
result: {}
schema:
description: UniLabJsonCommand get_data_file 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_data_file 的参数schema
properties:
after_time:
description: '参数: after_time'
type: string
mat_index:
description: '参数: mat_index'
type: string
required: []
type: object
result: {}
required:
- goal
title: get_data_file 命令参数
type: object
type: UniLabJsonCommand
auto-start_sequence:
feedback: {}
goal: {}
@@ -237,10 +182,10 @@ hplc.agilent:
module: unilabos.devices.hplc.AgilentHPLC:HPLCDriver
status_types:
could_run: bool
data_file: tuple
device_status: str
driver_init_ok: bool
finish_status: str
get_data_file: tuple
is_running: bool
status_text: str
success: bool
@@ -467,8 +412,7 @@ raman_home_made:
type: object
type: SendCmd
module: unilabos.devices.raman_uv.home_made_raman:RamanObj
status_types:
status: String
status_types: {}
type: python
description: Raman spectroscopy device
handles: []

View File

@@ -1,30 +1,9 @@
hotel.thermo_orbitor_rs2_hotel:
class:
action_value_mappings:
auto-get_rotation:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_rotation 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_rotation 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_rotation 命令参数
type: object
type: UniLabJsonCommand
action_value_mappings: {}
module: unilabos.devices.resource_container.container:HotelContainer
status_types:
get_rotation: String
rotation: String
type: python
description: Thermo Orbitor RS2 Hotel
handles: []

View File

@@ -4831,8 +4831,7 @@ liquid_handler:
type: object
type: LiquidHandlerTransfer
module: unilabos.devices.liquid_handling.liquid_handler_abstract:LiquidHandlerAbstract
status_types:
name: String
status_types: {}
type: python
description: Liquid handler device controlled by pylabrobot
handles:
@@ -4899,7 +4898,7 @@ liquid_handler.biomek:
none_keys:
default: []
description: '参数: none_keys'
type: string
type: array
protocol_author:
description: '参数: protocol_author'
type: string
@@ -5287,7 +5286,7 @@ liquid_handler.biomek:
none_keys:
default: []
description: '参数: none_keys'
type: string
type: array
offsets:
description: '参数: offsets'
type: string

View File

@@ -22,27 +22,6 @@ mock_chiller:
title: emergency_stop 命令参数
type: object
type: UniLabJsonCommand
auto-get_status_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status_info 命令参数
type: object
type: UniLabJsonCommand
auto-heat_chill_start:
feedback: {}
goal: {}
@@ -250,11 +229,11 @@ mock_chiller:
module: unilabos.devices.mock.mock_chiller:MockChiller
status_types:
current_temperature: float
get_status_info: dict
is_cooling: bool
is_heating: bool
purpose: str
status: str
status_info: dict
target_temperature: float
vessel: str
type: python
@@ -359,27 +338,6 @@ mock_filter:
title: filter 命令参数
type: object
type: UniLabJsonCommand
auto-get_status_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status_info 命令参数
type: object
type: UniLabJsonCommand
auto-replace_filter:
feedback: {}
goal: {}
@@ -595,11 +553,11 @@ mock_filter:
filtered_volume: float
filtrate_vessel: str
flow_rate: float
get_status_info: dict
is_filtering: bool
pressure_drop: float
progress: float
status: str
status_info: dict
stir: bool
stir_speed: float
target_volume: float
@@ -651,27 +609,6 @@ mock_heater:
title: emergency_stop 命令参数
type: object
type: UniLabJsonCommand
auto-get_status_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status_info 命令参数
type: object
type: UniLabJsonCommand
auto-heat_chill:
feedback: {}
goal: {}
@@ -1055,12 +992,12 @@ mock_heater:
module: unilabos.devices.mock.mock_heater:MockHeater
status_types:
current_temperature: float
get_status_info: dict
heating_power: float
is_heating: bool
max_temperature: float
purpose: str
status: str
status_info: dict
stir: bool
stir_speed: float
target_temperature: float
@@ -1111,27 +1048,6 @@ mock_pump:
title: emergency_stop 命令参数
type: object
type: UniLabJsonCommand
auto-get_status_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status_info 命令参数
type: object
type: UniLabJsonCommand
auto-pause_pump:
feedback: {}
goal: {}
@@ -1513,7 +1429,6 @@ mock_pump:
current_device: str
flow_rate: float
from_vessel: str
get_status_info: dict
is_solid: bool
is_viscous: bool
max_flow_rate: float
@@ -1524,6 +1439,7 @@ mock_pump:
rinsing_solvent: str
rinsing_volume: float
status: str
status_info: dict
target_flow_rate: float
time_remaining: float
time_spent: float
@@ -1577,27 +1493,6 @@ mock_rotavap:
title: emergency_stop 命令参数
type: object
type: UniLabJsonCommand
auto-get_status_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status_info 命令参数
type: object
type: UniLabJsonCommand
auto-set_pump_time:
feedback: {}
goal: {}
@@ -2085,14 +1980,13 @@ mock_rotavap:
type: EmptyIn
module: unilabos.devices.mock.mock_rotavap:MockRotavap
status_types:
get_status_info: dict
pump_state: str
pump_time: float
rotate_speed: float
rotate_state: str
rotate_time: float
status: str
success: String
status_info: dict
target_temperature: float
temperature: float
vacuum_level: float
@@ -2121,27 +2015,6 @@ mock_rotavap:
mock_separator:
class:
action_value_mappings:
auto-get_status_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status_info 命令参数
type: object
type: UniLabJsonCommand
auto-separate:
feedback: {}
goal: {}
@@ -2578,7 +2451,6 @@ mock_separator:
status_types:
current_device: str
from_vessel: str
get_status_info: dict
product_phase: str
purpose: str
repeats: int
@@ -2589,6 +2461,7 @@ mock_separator:
solvent: str
solvent_volume: float
status: str
status_info: dict
stir_speed: float
stir_time: float
through: str
@@ -2643,27 +2516,6 @@ mock_solenoid_valve:
title: close_valve 命令参数
type: object
type: UniLabJsonCommand
auto-get_valve_status:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_valve_status 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_valve_status 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_valve_status 命令参数
type: object
type: UniLabJsonCommand
auto-is_closed:
feedback: {}
goal: {}
@@ -2871,7 +2723,6 @@ mock_solenoid_valve:
type: StrSingleInput
module: unilabos.devices.mock.mock_solenoid_valve:MockSolenoidValve
status_types:
get_valve_status: str
status: str
valve_status: str
type: python
@@ -2920,27 +2771,6 @@ mock_stirrer:
title: emergency_stop 命令参数
type: object
type: UniLabJsonCommand
auto-get_status_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status_info 命令参数
type: object
type: UniLabJsonCommand
auto-heating_control:
feedback: {}
goal: {}
@@ -3288,12 +3118,12 @@ mock_stirrer:
type: EmptyIn
module: unilabos.devices.mock.mock_stirrer:MockStirrer
status_types:
get_status_info: dict
heating_power: float
heating_state: str
max_stir_speed: float
max_temperature: float
status: str
status_info: dict
stir_speed: float
stir_state: str
target_stir_speed: float
@@ -3324,27 +3154,6 @@ mock_stirrer:
mock_stirrer_new:
class:
action_value_mappings:
auto-get_status_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status_info 命令参数
type: object
type: UniLabJsonCommand
auto-start_stir:
feedback: {}
goal: {}
@@ -3629,12 +3438,12 @@ mock_stirrer_new:
type: StopStir
module: unilabos.devices.mock.mock_stirrer_new:MockStirrer_new
status_types:
get_status_info: dict
max_stir_speed: float
progress: float
purpose: str
settling_time: float
status: str
status_info: dict
stir_speed: float
stir_state: str
stir_time: float
@@ -3686,27 +3495,6 @@ mock_vacuum:
title: emergency_stop 命令参数
type: object
type: UniLabJsonCommand
auto-get_status_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status_info 命令参数
type: object
type: UniLabJsonCommand
auto-pause_vacuum:
feedback: {}
goal: {}
@@ -4134,13 +3922,13 @@ mock_vacuum:
type: EmptyIn
module: unilabos.devices.mock.mock_vacuum:MockVacuum
status_types:
get_status_info: dict
max_pump_speed: float
power_state: str
pump_efficiency: float
pump_speed: float
pump_state: str
status: str
status_info: dict
target_vacuum: float
vacuum_level: float
type: python

View File

@@ -174,9 +174,7 @@ rotavap.one:
type: object
type: SendCmd
module: unilabos.devices.rotavap.rotavap_one:RotavapOne
status_types:
pump_time: Float64
rotate_time: Float64
status_types: {}
type: python
description: Rotavap device
handles: []
@@ -453,9 +451,7 @@ separator.homemade:
type: object
type: SendCmd
module: unilabos.devices.separator.homemade_grbl_conductivity:SeparatorController
status_types:
sensordata: Float64
status: String
status_types: {}
type: python
description: Separator device with homemade grbl controller
handles: []

View File

@@ -22,27 +22,6 @@ solenoid_valve:
title: close 命令参数
type: object
type: UniLabJsonCommand
auto-get_valve_position:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_valve_position 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_valve_position 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_valve_position 命令参数
type: object
type: UniLabJsonCommand
auto-is_closed:
feedback: {}
goal: {}
@@ -224,7 +203,6 @@ solenoid_valve:
type: StrSingleInput
module: unilabos.devices.pump_and_valve.solenoid_valve:SolenoidValve
status_types:
get_valve_position: str
status: str
valve_position: str
type: python
@@ -273,27 +251,6 @@ solenoid_valve.mock:
title: close 命令参数
type: object
type: UniLabJsonCommand
auto-get_valve_position:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_valve_position 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_valve_position 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_valve_position 命令参数
type: object
type: UniLabJsonCommand
auto-is_closed:
feedback: {}
goal: {}
@@ -455,7 +412,6 @@ solenoid_valve.mock:
type: EmptyIn
module: unilabos.devices.pump_and_valve.solenoid_valve_mock:SolenoidValveMock
status_types:
get_valve_position: str
status: str
valve_position: str
type: python
@@ -514,174 +470,6 @@ syringe_pump_with_valve.runze:
title: close 命令参数
type: object
type: UniLabJsonCommand
auto-get_max_velocity:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_max_velocity 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_max_velocity 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_max_velocity 命令参数
type: object
type: UniLabJsonCommand
auto-get_plunger_position:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_plunger_position 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_plunger_position 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_plunger_position 命令参数
type: object
type: UniLabJsonCommand
auto-get_position:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_position 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_position 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_position 命令参数
type: object
type: UniLabJsonCommand
auto-get_status:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status 命令参数
type: object
type: UniLabJsonCommand
auto-get_valve_position:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_valve_position 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_valve_position 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_valve_position 命令参数
type: object
type: UniLabJsonCommand
auto-get_velocity_end:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_velocity_end 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_velocity_end 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_velocity_end 命令参数
type: object
type: UniLabJsonCommand
auto-get_velocity_grade:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_velocity_grade 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_velocity_grade 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_velocity_grade 命令参数
type: object
type: UniLabJsonCommand
auto-get_velocity_init:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_velocity_init 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_velocity_init 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_velocity_init 命令参数
type: object
type: UniLabJsonCommand
auto-initialize:
feedback: {}
goal: {}
@@ -703,27 +491,6 @@ syringe_pump_with_valve.runze:
title: initialize 命令参数
type: object
type: UniLabJsonCommand
auto-list:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand list 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand list 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: list 命令参数
type: object
type: UniLabJsonCommand
auto-pull_plunger:
feedback: {}
goal: {}
@@ -1089,19 +856,15 @@ syringe_pump_with_valve.runze:
write: send_command
module: unilabos.devices.pump_and_valve.runze_backbone:RunzeSyringePump
status_types:
get_max_velocity: String
get_plunger_position: String
get_position: String
get_status: String
get_valve_position: str
get_velocity_end: String
get_velocity_grade: String
get_velocity_init: String
max_velocity: float
mode: int
plunger_position: String
position: float
status: str
valve_position: str
velocity_end: String
velocity_grade: String
velocity_init: String
type: python
description: Runze Syringe pump with valve
handles: []

View File

@@ -494,8 +494,6 @@ linear_motion.grbl:
type: SingleJointPosition
module: unilabos.devices.cnc.grbl_sync:GrblCNC
status_types:
get_position: String
get_status: String
position: unilabos.messages:Point3D
spindle_speed: float
status: str

View File

@@ -245,48 +245,6 @@ heaterstirrer.dalong:
title: close 命令参数
type: object
type: UniLabJsonCommand
auto-get_status:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status 命令参数
type: object
type: UniLabJsonCommand
auto-get_temp:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_temp 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_temp 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_temp 命令参数
type: object
type: UniLabJsonCommand
auto-heatchill:
feedback: {}
goal: {}
@@ -614,8 +572,6 @@ heaterstirrer.dalong:
type: SendCmd
module: unilabos.devices.heaterstirrer.dalong:HeaterStirrer_DaLong
status_types:
get_status: str
get_temp: String
status: str
stir_speed: float
temp: float
@@ -849,7 +805,6 @@ tempsensor:
module: unilabos.devices.temperature.sensor_node:TempSensorNode
status_types:
value: float
warning: Float64
type: python
description: Temperature sensor
handles: []

View File

@@ -22,27 +22,6 @@ gas_source.mock:
title: close 命令参数
type: object
type: UniLabJsonCommand
auto-get_status:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status 命令参数
type: object
type: UniLabJsonCommand
auto-is_closed:
feedback: {}
goal: {}
@@ -247,7 +226,6 @@ gas_source.mock:
type: StrSingleInput
module: unilabos.devices.pump_and_valve.vacuum_pump_mock:VacuumPumpMock
status_types:
get_status: str
status: str
type: python
description: Mock gas source
@@ -301,27 +279,6 @@ vacuum_pump.mock:
title: close 命令参数
type: object
type: UniLabJsonCommand
auto-get_status:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status 命令参数
type: object
type: UniLabJsonCommand
auto-is_closed:
feedback: {}
goal: {}
@@ -526,7 +483,6 @@ vacuum_pump.mock:
type: StrSingleInput
module: unilabos.devices.pump_and_valve.vacuum_pump_mock:VacuumPumpMock
status_types:
get_status: str
status: str
type: python
description: Mock vacuum pump

View File

@@ -402,7 +402,7 @@ virtual_column:
properties:
config:
description: '参数: config'
type: string
type: object
device_id:
description: '参数: device_id'
type: string
@@ -721,27 +721,6 @@ virtual_gas_source:
title: close 命令参数
type: object
type: UniLabJsonCommand
auto-get_status:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status 命令参数
type: object
type: UniLabJsonCommand
auto-initialize:
feedback: {}
goal: {}
@@ -967,7 +946,6 @@ virtual_gas_source:
type: StrSingleInput
module: unilabos.devices.virtual.virtual_gas_source:VirtualGasSource
status_types:
get_status: str
status: str
type: python
description: Virtual gas source
@@ -1370,7 +1348,7 @@ virtual_heatchill:
properties:
config:
description: '参数: config'
type: string
type: object
device_id:
description: '参数: device_id'
type: string
@@ -1409,153 +1387,6 @@ virtual_multiway_valve:
title: close 命令参数
type: object
type: UniLabJsonCommand
auto-get_available_ports:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_available_ports 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_available_ports 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_available_ports 命令参数
type: object
type: UniLabJsonCommand
auto-get_available_positions:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_available_positions 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_available_positions 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_available_positions 命令参数
type: object
type: UniLabJsonCommand
auto-get_current_port:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_current_port 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_current_port 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_current_port 命令参数
type: object
type: UniLabJsonCommand
auto-get_current_position:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_current_position 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_current_position 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_current_position 命令参数
type: object
type: UniLabJsonCommand
auto-get_flow_path:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_flow_path 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_flow_path 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_flow_path 命令参数
type: object
type: UniLabJsonCommand
auto-get_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_info 命令参数
type: object
type: UniLabJsonCommand
auto-get_valve_position:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_valve_position 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_valve_position 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_valve_position 命令参数
type: object
type: UniLabJsonCommand
auto-is_at_port:
feedback: {}
goal: {}
@@ -1892,17 +1723,15 @@ virtual_multiway_valve:
type: SendCmd
module: unilabos.devices.virtual.virtual_multiway_valve:VirtualMultiwayValve
status_types:
available_ports: dict
available_positions: list
current_port: str
current_position: int
get_available_ports: typing:Dict
get_available_positions: list
get_current_port: str
get_current_position: int
get_flow_path: str
get_info: dict
get_valve_position: int
max_positions: Int32
flow_path: str
info: dict
status: str
target_position: int
valve_position: int
valve_state: str
type: python
description: Virtual 8-Way Valve for flow direction control
@@ -2345,7 +2174,6 @@ virtual_pump:
current_volume: float
from_vessel: str
max_volume: float
position: Float64
progress: float
status: str
to_vessel: str
@@ -2372,7 +2200,7 @@ virtual_pump:
properties:
config:
description: '参数: config'
type: string
type: object
device_id:
description: '参数: device_id'
type: string
@@ -3026,8 +2854,7 @@ virtual_solenoid_valve:
auto-close:
feedback: {}
goal: {}
goal_default:
kwargs: null
goal_default: {}
handles: []
result: {}
schema:
@@ -3036,12 +2863,8 @@ virtual_solenoid_valve:
feedback: {}
goal:
description: UniLabJsonCommand close 的参数schema
properties:
kwargs:
description: '参数: kwargs'
type: string
required:
- kwargs
properties: {}
required: []
type: object
result: {}
required:
@@ -3049,48 +2872,6 @@ virtual_solenoid_valve:
title: close 命令参数
type: object
type: UniLabJsonCommandAsync
auto-get_state:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_state 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_state 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_state 命令参数
type: object
type: UniLabJsonCommand
auto-get_valve_position:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_valve_position 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_valve_position 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_valve_position 命令参数
type: object
type: UniLabJsonCommand
auto-initialize:
feedback: {}
goal: {}
@@ -3136,8 +2917,7 @@ virtual_solenoid_valve:
auto-open:
feedback: {}
goal: {}
goal_default:
kwargs: null
goal_default: {}
handles: []
result: {}
schema:
@@ -3146,12 +2926,8 @@ virtual_solenoid_valve:
feedback: {}
goal:
description: UniLabJsonCommand open 的参数schema
properties:
kwargs:
description: '参数: kwargs'
type: string
required:
- kwargs
properties: {}
required: []
type: object
result: {}
required:
@@ -3185,7 +2961,6 @@ virtual_solenoid_valve:
goal: {}
goal_default:
command: null
kwargs: null
handles: []
result: {}
schema:
@@ -3198,12 +2973,8 @@ virtual_solenoid_valve:
command:
description: '参数: command'
type: string
kwargs:
description: '参数: kwargs'
type: string
required:
- command
- kwargs
type: object
result: {}
required:
@@ -3216,7 +2987,6 @@ virtual_solenoid_valve:
goal: {}
goal_default:
command: null
kwargs: null
handles: []
result: {}
schema:
@@ -3229,11 +2999,7 @@ virtual_solenoid_valve:
command:
description: '参数: command'
type: string
kwargs:
description: '参数: kwargs'
type: string
required:
- kwargs
required: []
type: object
result: {}
required:
@@ -3452,10 +3218,10 @@ virtual_solenoid_valve:
type: SendCmd
module: unilabos.devices.virtual.virtual_solenoid_valve:VirtualSolenoidValve
status_types:
get_state: dict
get_valve_position: str
is_open: bool
state: dict
status: str
valve_position: str
valve_state: str
type: python
description: Virtual Solenoid Valve for simple on/off flow control
@@ -3852,7 +3618,7 @@ virtual_stirrer:
properties:
config:
description: '参数: config'
type: string
type: object
device_id:
description: '参数: device_id'
type: string
@@ -4001,111 +3767,6 @@ virtual_transfer_pump:
title: fill_syringe 命令参数
type: object
type: UniLabJsonCommandAsync
auto-get_current_volume:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_current_volume 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_current_volume 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_current_volume 命令参数
type: object
type: UniLabJsonCommand
auto-get_position:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_position 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_position 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_position 命令参数
type: object
type: UniLabJsonCommand
auto-get_pump_info:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_pump_info 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_pump_info 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_pump_info 命令参数
type: object
type: UniLabJsonCommand
auto-get_remaining_capacity:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_remaining_capacity 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_remaining_capacity 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_remaining_capacity 命令参数
type: object
type: UniLabJsonCommand
auto-get_status:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status 命令参数
type: object
type: UniLabJsonCommand
auto-initialize:
feedback: {}
goal: {}
@@ -4515,14 +4176,10 @@ virtual_transfer_pump:
module: unilabos.devices.virtual.virtual_transferpump:VirtualTransferPump
status_types:
current_volume: float
get_current_volume: float
get_position: float
get_pump_info: dict
get_remaining_capacity: float
get_status: str
max_velocity: float
max_volume: Float64
position: float
pump_info: dict
remaining_capacity: float
status: str
transfer_rate: float
type: python
@@ -4606,27 +4263,6 @@ virtual_vacuum_pump:
title: close 命令参数
type: object
type: UniLabJsonCommand
auto-get_status:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_status 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_status 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_status 命令参数
type: object
type: UniLabJsonCommand
auto-initialize:
feedback: {}
goal: {}
@@ -4852,7 +4488,6 @@ virtual_vacuum_pump:
type: StrSingleInput
module: unilabos.devices.virtual.virtual_vacuum_pump:VirtualVacuumPump
status_types:
get_status: str
status: str
type: python
description: Virtual vacuum pump

View File

@@ -99,27 +99,6 @@ zhida_hplc:
title: connect 命令参数
type: object
type: UniLabJsonCommand
auto-get_methods:
feedback: {}
goal: {}
goal_default: {}
handles: []
result: {}
schema:
description: UniLabJsonCommand get_methods 的参数schema
properties:
feedback: {}
goal:
description: UniLabJsonCommand get_methods 的参数schema
properties: {}
required: []
type: object
result: {}
required:
- goal
title: get_methods 命令参数
type: object
type: UniLabJsonCommand
auto-start:
feedback: {}
goal: {}
@@ -226,7 +205,7 @@ zhida_hplc:
type: StrSingleInput
module: unilabos.devices.zhida_hplc.zhida:ZhidaClient
status_types:
get_methods: dict
methods: dict
status: dict
type: python
description: Zhida HPLC

View File

@@ -7,7 +7,7 @@ from typing import Any, Dict, List
import yaml
from unilabos.ros.msgs.message_converter import msg_converter_manager, ros_action_to_json_schema
from unilabos.ros.msgs.message_converter import msg_converter_manager, ros_action_to_json_schema, String
from unilabos.utils import logger
from unilabos.utils.decorator import singleton
from unilabos.utils.import_manager import get_enhanced_class_info
@@ -180,6 +180,13 @@ class Registry:
if not type_name or type_name == "":
logger.warning(f"[UniLab Registry] 设备 {device_id}{field_name} 类型为空,跳过替换")
return type_name
convert_manager = { # 将python基本对象转为ros2基本对象
"str": "String",
"bool": "Bool",
"int": "Int64",
"float": "Float64",
}
type_name = convert_manager.get(type_name, type_name) # 替换为ROS2类型
if ":" in type_name:
type_class = msg_converter_manager.get_class(type_name)
else:
@@ -297,37 +304,42 @@ class Registry:
device_config["class"]["action_value_mappings"] = {}
enhanced_info = {}
if complete_registry:
device_config["class"]["status_types"].clear()
enhanced_info = get_enhanced_class_info(device_config["class"]["module"], use_dynamic=True)
device_config["class"]["status_types"].update(
{k: v["return_type"] for k, v in enhanced_info["status_methods"].items()}
)
device_config["class"]["status_types"].update(
{k: v["return_type"] for k, v in enhanced_info["status_methods"].items()}
)
for status_name, status_type in device_config["class"]["status_types"].items():
if status_type in ["Any", "None"]:
status_type = "String" # 替换成ROS的String便于显示
device_config["class"]["status_types"][status_name] = status_type
target_type = self._replace_type_with_class(status_type, device_id, f"状态 {status_name}")
if target_type in [dict]: # 对于字典和对象的返回类型,要处理成字符串,直接进行转换
target_type = String
status_str_type_mapping[status_type] = target_type
device_config["class"]["status_types"] = dict(
sorted(device_config["class"]["status_types"].items())
)
# 处理动作值映射
device_config["class"]["action_value_mappings"].update(
{
f"auto-{k}": {
"type": "UniLabJsonCommandAsync" if v["is_async"] else "UniLabJsonCommand",
"goal": {},
"feedback": {},
"result": {},
"schema": self._generate_unilab_json_command_schema(v["args"], k),
"goal_default": {i["name"]: i["default"] for i in v["args"]},
"handles": [],
if complete_registry:
device_config["class"]["action_value_mappings"] = {k:v for k, v in device_config["class"]["action_value_mappings"].items() if not k.startswith("auto-")}
# 处理动作值映射
device_config["class"]["action_value_mappings"].update(
{
f"auto-{k}": {
"type": "UniLabJsonCommandAsync" if v["is_async"] else "UniLabJsonCommand",
"goal": {},
"feedback": {},
"result": {},
"schema": self._generate_unilab_json_command_schema(v["args"], k),
"goal_default": {i["name"]: i["default"] for i in v["args"]},
"handles": [],
}
for k, v in enhanced_info["action_methods"].items()
}
for k, v in enhanced_info["action_methods"].items()
}
)
device_config["init_param_schema"] = self._generate_unilab_json_command_schema(
enhanced_info["init_params"], "__init__"
)
)
device_config["init_param_schema"] = self._generate_unilab_json_command_schema(
enhanced_info["init_params"], "__init__"
)
device_config.pop("schema", None)
device_config["class"]["action_value_mappings"] = dict(
sorted(device_config["class"]["action_value_mappings"].items())

View File

@@ -168,7 +168,10 @@ class PropertyPublisher:
self.print_publish = print_publish
self._value = None
self.publisher_ = node.create_publisher(msg_type, f"{name}", 10)
try:
self.publisher_ = node.create_publisher(msg_type, f"{name}", 10)
except AttributeError as ex:
logger.error(f"创建发布者失败,可能由于注册表有误,类型: {msg_type},错误: {ex}\n{traceback.format_exc()}")
self.timer = node.create_timer(self.timer_period, self.publish_property)
self.__loop = get_event_loop()
str_msg_type = str(msg_type)[8:-2]

View File

@@ -459,6 +459,8 @@ class HostNode(BaseROS2DeviceNode):
self.devices_instances[device_id] = d
# noinspection PyProtectedMember
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}"
if action_id not in self._action_clients:
action_type = action_value_mapping["type"]

View File

@@ -216,15 +216,16 @@ class ImportManager:
f"{module_path} 失败(将使用静态分析,"
f"建议修复导入错误,以实现更好的注册表识别效果!): {e}"
)
# 尝试静态分析
static_info = None
try:
static_info = self._get_static_class_info(module_path)
result["static_analysis_success"] = True
logger.debug(f"[ImportManager] 静态分析类 {module_path} 成功")
except Exception as e:
logger.warning(f"[ImportManager] 静态分析类 {module_path} 失败: {e}")
use_dynamic = False
if not use_dynamic:
# 尝试静态分析
static_info = None
try:
static_info = self._get_static_class_info(module_path)
result["static_analysis_success"] = True
logger.debug(f"[ImportManager] 静态分析类 {module_path} 成功")
except Exception as e:
logger.warning(f"[ImportManager] 静态分析类 {module_path} 失败: {e}")
# 合并信息(优先使用动态导入的信息)
if dynamic_info:
@@ -292,9 +293,12 @@ class ImportManager:
elif inspect.ismethod(method) or inspect.isfunction(method):
if name.startswith("get_"):
actual_name = name[4:] # 去掉get_前缀
if actual_name in result["status_methods"]:
continue
# get_ 开头的方法归类为status
method_info = self._analyze_method_signature(method)
result["status_methods"][name] = method_info
result["status_methods"][actual_name] = method_info
elif not name.startswith("_"):
# 其他非_开头的方法归类为action
method_info = self._analyze_method_signature(method)
@@ -345,21 +349,43 @@ class ImportManager:
elif self._is_property_method(node):
# @property 装饰的方法
result["status_methods"][method_name] = method_info
elif method_name.startswith("get_"):
# get_ 开头的方法归类为status
actual_name = method_name[4:] # 去掉get_前缀
if actual_name not in result["status_methods"]:
result["status_methods"][actual_name] = method_info
else:
# set_ 开头或其他非_开头的方法
# 其他非_开头的方法归类为action
result["action_methods"][method_name] = method_info
return result
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 = []
num_required = 0
for param_name, param in signature.parameters.items():
# 跳过self参数
if param_name == "self":
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
if is_required:
num_required += 1
@@ -392,10 +418,17 @@ class ImportManager:
"""将类型注解转换为字符串"""
if annotation == inspect.Parameter.empty:
return "Any" # 如果没有注解返回Any
if annotation is 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__"):
# 如果是内置类型
@@ -404,22 +437,13 @@ class ImportManager:
else:
# 如果是自定义类,返回完整路径
return f"{annotation.__module__}:{annotation.__name__}"
# 如果是typing模块的类型
elif hasattr(annotation, "_name"):
return annotation._name
# 如果是字符串形式的类型注解
elif isinstance(annotation, str):
return annotation
# 其他情况,尝试转换为字符串
else:
annotation_str = str(annotation)
# 处理typing模块的复杂类型
if "typing." in annotation_str:
# 简化typing类型显示
return annotation_str.replace("typing.", "")
return annotation_str
def _is_property_method(self, node: ast.FunctionDef) -> bool: