mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-14 13:14:39 +00:00
Fix/update resource (#112)
* cancel upload_registry * Refactor Bioyond workstation and experiment workflow -fix (#111) * refactor(bioyond_studio): 优化材料缓存加载和参数验证逻辑 改进材料缓存加载逻辑以支持多种材料类型和详细材料处理 更新工作流参数验证中的字段名从key/value改为Key/DisplayValue 移除未使用的merge_workflow_with_parameters方法 添加get_station_info方法获取工作站基础信息 清理实验文件中的注释代码和更新导入路径 * fix: 修复资源移除时的父资源检查问题 在BaseROS2DeviceNode中,移除资源前添加对父资源是否为None的检查,避免空指针异常 同时更新Bottle和BottleCarrier类以支持**kwargs参数 修正测试文件中Liquid_feeding_beaker的大小写拼写错误 * correct return message --------- Co-authored-by: ZiWei <131428629+ZiWei09@users.noreply.github.com>
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
"type": "device",
|
||||
"class": "reaction_station.bioyond",
|
||||
"config": {
|
||||
"bioyond_config": {
|
||||
"config": {
|
||||
"api_key": "DE9BDDA0",
|
||||
"api_host": "http://192.168.1.200:44402",
|
||||
"workflow_mappings": {
|
||||
@@ -19,8 +19,8 @@
|
||||
"Solid_feeding_vials": "3a160877-87e7-7699-7bc6-ec72b05eb5e6",
|
||||
"Liquid_feeding_vials(non-titration)": "3a167d99-6158-c6f0-15b5-eb030f7d8e47",
|
||||
"Liquid_feeding_solvents": "3a160824-0665-01ed-285a-51ef817a9046",
|
||||
"Liquid_feeding(titration)": "3a160824-0665-01ed-285a-51ef817a9046",
|
||||
"Liquid_feeding_beaker": "3a16087e-124f-8ddb-8ec1-c2dff09ca784",
|
||||
"Liquid_feeding(titration)": "3a16082a-96ac-0449-446a-4ed39f3365b6",
|
||||
"liquid_feeding_beaker": "3a16087e-124f-8ddb-8ec1-c2dff09ca784",
|
||||
"Drip_back": "3a162cf9-6aac-565a-ddd7-682ba1796a4a"
|
||||
},
|
||||
"material_type_mappings": {
|
||||
|
||||
@@ -356,7 +356,7 @@ def main():
|
||||
|
||||
if BasicConfig.upload_registry:
|
||||
# 设备注册到服务端 - 需要 ak 和 sk
|
||||
if args_dict.get("ak") and args_dict.get("sk"):
|
||||
if BasicConfig.ak and BasicConfig.sk:
|
||||
print_status("开始注册设备到服务端...", "info")
|
||||
try:
|
||||
register_devices_and_resources(lab_registry)
|
||||
|
||||
@@ -334,8 +334,8 @@ class BioyondV1RPC(BaseRequest):
|
||||
for j, param in enumerate(params):
|
||||
if not isinstance(param, dict):
|
||||
workflow_errors.append(f"步骤 {step_id} 模块 {module_name} 参数 {j} 必须是字典类型")
|
||||
elif "key" not in param or "value" not in param:
|
||||
workflow_errors.append(f"步骤 {step_id} 模块 {module_name} 参数 {j} 必须包含 key 和 value")
|
||||
elif "Key" not in param or "DisplayValue" not in param:
|
||||
workflow_errors.append(f"步骤 {step_id} 模块 {module_name} 参数 {j} 必须包含 Key 和 DisplayValue")
|
||||
|
||||
if workflow_errors:
|
||||
validation_errors.append({
|
||||
@@ -703,20 +703,35 @@ class BioyondV1RPC(BaseRequest):
|
||||
"""预加载材料列表到缓存中"""
|
||||
try:
|
||||
print("正在加载材料列表缓存...")
|
||||
stock_query = '{"typeMode": 2, "includeDetail": true}'
|
||||
stock_result = self.stock_material(stock_query)
|
||||
|
||||
# 加载所有类型的材料:耗材(0)、样品(1)、试剂(2)
|
||||
material_types = [1, 2]
|
||||
|
||||
for type_mode in material_types:
|
||||
print(f"正在加载类型 {type_mode} 的材料...")
|
||||
stock_query = f'{{"typeMode": {type_mode}, "includeDetail": true}}'
|
||||
stock_result = self.stock_material(stock_query)
|
||||
|
||||
if isinstance(stock_result, str):
|
||||
stock_data = json.loads(stock_result)
|
||||
else:
|
||||
stock_data = stock_result
|
||||
if isinstance(stock_result, str):
|
||||
stock_data = json.loads(stock_result)
|
||||
else:
|
||||
stock_data = stock_result
|
||||
|
||||
materials = stock_data
|
||||
for material in materials:
|
||||
material_name = material.get("name")
|
||||
material_id = material.get("id")
|
||||
if material_name and material_id:
|
||||
self.material_cache[material_name] = material_id
|
||||
materials = stock_data
|
||||
for material in materials:
|
||||
material_name = material.get("name")
|
||||
material_id = material.get("id")
|
||||
if material_name and material_id:
|
||||
self.material_cache[material_name] = material_id
|
||||
|
||||
# 处理样品板等容器中的detail材料
|
||||
detail_materials = material.get("detail", [])
|
||||
for detail_material in detail_materials:
|
||||
detail_name = detail_material.get("name")
|
||||
detail_id = detail_material.get("detailMaterialId")
|
||||
if detail_name and detail_id:
|
||||
self.material_cache[detail_name] = detail_id
|
||||
print(f"加载detail材料: {detail_name} -> ID: {detail_id}")
|
||||
|
||||
print(f"材料列表缓存加载完成,共加载 {len(self.material_cache)} 个材料")
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"""
|
||||
|
||||
import json
|
||||
from reaction_station import BioyondReactionStation
|
||||
from config import API_CONFIG, WORKFLOW_MAPPINGS, DECK_CONFIG, MATERIAL_TYPE_MAPPINGS
|
||||
from unilabos.devices.workstation.bioyond_studio.reaction_station import BioyondReactionStation
|
||||
from unilabos.devices.workstation.bioyond_studio.config import API_CONFIG, WORKFLOW_MAPPINGS, DECK_CONFIG, MATERIAL_TYPE_MAPPINGS
|
||||
|
||||
|
||||
def run_experiment():
|
||||
@@ -45,7 +45,7 @@ def run_experiment():
|
||||
assign_material_name="ODA",
|
||||
time="0",
|
||||
torque_variation="1",
|
||||
titrationType="1",
|
||||
titration_type="1",
|
||||
temperature=-10
|
||||
)
|
||||
|
||||
@@ -56,14 +56,14 @@ def run_experiment():
|
||||
assign_material_name="MPDA",
|
||||
time="5",
|
||||
torque_variation="2",
|
||||
titrationType="1",
|
||||
titration_type="1",
|
||||
temperature=0
|
||||
)
|
||||
|
||||
# 4. 液体投料-小瓶非滴定
|
||||
print("4. 添加液体投料-小瓶非滴定,带参数...")
|
||||
Bioyond.liquid_feeding_vials_non_titration(
|
||||
volumeFormula="639.5",
|
||||
volume_formula="639.5",
|
||||
assign_material_name="SIDA",
|
||||
titration_type="1",
|
||||
time="0",
|
||||
@@ -91,7 +91,7 @@ def run_experiment():
|
||||
assign_material_name="BTDA1",
|
||||
temperature=-10.00
|
||||
)
|
||||
#二杆,样品版90
|
||||
|
||||
print("7. 添加固体进料小瓶,带参数...")
|
||||
Bioyond.solid_feeding_vials(
|
||||
material_id="3",
|
||||
@@ -100,7 +100,7 @@ def run_experiment():
|
||||
assign_material_name="BTDA2",
|
||||
temperature=25.00
|
||||
)
|
||||
#二杆,样品版90
|
||||
|
||||
print("8. 添加固体进料小瓶,带参数...")
|
||||
Bioyond.solid_feeding_vials(
|
||||
material_id="3",
|
||||
@@ -196,8 +196,8 @@ def run_experiment():
|
||||
print("\n4. 执行process_and_execute_workflow...")
|
||||
|
||||
result = Bioyond.process_and_execute_workflow(
|
||||
workflow_name="test3_8",
|
||||
task_name="实验3_8"
|
||||
workflow_name="test3",
|
||||
task_name="实验3"
|
||||
)
|
||||
|
||||
# 显示执行结果
|
||||
@@ -207,9 +207,9 @@ def run_experiment():
|
||||
result_dict = json.loads(result)
|
||||
if result_dict.get("success"):
|
||||
print("任务创建成功!")
|
||||
print(f"- 工作流: {result_dict.get('workflow', {}).get('name')}")
|
||||
print(f"- 工作流ID: {result_dict.get('workflow', {}).get('id')}")
|
||||
print(f"- 任务结果: {result_dict.get('task')}")
|
||||
# print(f"- 工作流: {result_dict.get('workflow', {}).get('name')}")
|
||||
# print(f"- 工作流ID: {result_dict.get('workflow', {}).get('id')}")
|
||||
# print(f"- 任务结果: {result_dict.get('task')}")
|
||||
else:
|
||||
print(f"任务创建失败: {result_dict.get('error')}")
|
||||
except:
|
||||
@@ -229,166 +229,166 @@ def run_experiment():
|
||||
return Bioyond
|
||||
|
||||
|
||||
def prepare_materials(bioyond):
|
||||
"""准备实验材料(可选)"""
|
||||
# def prepare_materials(bioyond):
|
||||
# """准备实验材料(可选)"""
|
||||
|
||||
# 样品板材料数据定义
|
||||
material_data_yp_1 = {
|
||||
"typeId": "3a142339-80de-8f25-6093-1b1b1b6c322e",
|
||||
"name": "样品板-1",
|
||||
"unit": "个",
|
||||
"quantity": 1,
|
||||
"details": [
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "BPDA-DD-1",
|
||||
"quantity": 1,
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "PEPA",
|
||||
"quantity": 1,
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "BPDA-DD-2",
|
||||
"quantity": 1,
|
||||
"x": 1,
|
||||
"y": 3,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "BPDA-1",
|
||||
"quantity": 1,
|
||||
"x": 2,
|
||||
"y": 1,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "PMDA",
|
||||
"quantity": 1,
|
||||
"x": 2,
|
||||
"y": 2,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "BPDA-2",
|
||||
"quantity": 1,
|
||||
"x": 2,
|
||||
"y": 3,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
}
|
||||
],
|
||||
"Parameters": "{}"
|
||||
}
|
||||
# # 样品板材料数据定义
|
||||
# material_data_yp_1 = {
|
||||
# "typeId": "3a142339-80de-8f25-6093-1b1b1b6c322e",
|
||||
# "name": "样品板-1",
|
||||
# "unit": "个",
|
||||
# "quantity": 1,
|
||||
# "details": [
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "BPDA-DD-1",
|
||||
# "quantity": 1,
|
||||
# "x": 1,
|
||||
# "y": 1,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "PEPA",
|
||||
# "quantity": 1,
|
||||
# "x": 1,
|
||||
# "y": 2,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "BPDA-DD-2",
|
||||
# "quantity": 1,
|
||||
# "x": 1,
|
||||
# "y": 3,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "BPDA-1",
|
||||
# "quantity": 1,
|
||||
# "x": 2,
|
||||
# "y": 1,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "PMDA",
|
||||
# "quantity": 1,
|
||||
# "x": 2,
|
||||
# "y": 2,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "BPDA-2",
|
||||
# "quantity": 1,
|
||||
# "x": 2,
|
||||
# "y": 3,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# }
|
||||
# ],
|
||||
# "Parameters": "{}"
|
||||
# }
|
||||
|
||||
material_data_yp_2 = {
|
||||
"typeId": "3a142339-80de-8f25-6093-1b1b1b6c322e",
|
||||
"name": "样品板-2",
|
||||
"unit": "个",
|
||||
"quantity": 1,
|
||||
"details": [
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "BPDA-DD",
|
||||
"quantity": 1,
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "SIDA",
|
||||
"quantity": 1,
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "BTDA-1",
|
||||
"quantity": 1,
|
||||
"x": 2,
|
||||
"y": 1,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "BTDA-2",
|
||||
"quantity": 1,
|
||||
"x": 2,
|
||||
"y": 2,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
"name": "BTDA-3",
|
||||
"quantity": 1,
|
||||
"x": 2,
|
||||
"y": 3,
|
||||
"Parameters": "{\"molecular\": 1}"
|
||||
}
|
||||
],
|
||||
"Parameters": "{}"
|
||||
}
|
||||
# material_data_yp_2 = {
|
||||
# "typeId": "3a142339-80de-8f25-6093-1b1b1b6c322e",
|
||||
# "name": "样品板-2",
|
||||
# "unit": "个",
|
||||
# "quantity": 1,
|
||||
# "details": [
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "BPDA-DD",
|
||||
# "quantity": 1,
|
||||
# "x": 1,
|
||||
# "y": 1,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "SIDA",
|
||||
# "quantity": 1,
|
||||
# "x": 1,
|
||||
# "y": 2,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "BTDA-1",
|
||||
# "quantity": 1,
|
||||
# "x": 2,
|
||||
# "y": 1,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "BTDA-2",
|
||||
# "quantity": 1,
|
||||
# "x": 2,
|
||||
# "y": 2,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233a-84a3-088d-6676-7cb4acd57c64",
|
||||
# "name": "BTDA-3",
|
||||
# "quantity": 1,
|
||||
# "x": 2,
|
||||
# "y": 3,
|
||||
# "Parameters": "{\"molecular\": 1}"
|
||||
# }
|
||||
# ],
|
||||
# "Parameters": "{}"
|
||||
# }
|
||||
|
||||
# 烧杯材料数据定义
|
||||
beaker_materials = [
|
||||
{
|
||||
"typeId": "3a14233b-f0a9-ba84-eaa9-0d4718b361b6",
|
||||
"name": "PDA-1",
|
||||
"unit": "微升",
|
||||
"quantity": 1,
|
||||
"parameters": "{\"DeviceMaterialType\":\"NMP\"}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233b-f0a9-ba84-eaa9-0d4718b361b6",
|
||||
"name": "TFDB",
|
||||
"unit": "微升",
|
||||
"quantity": 1,
|
||||
"parameters": "{\"DeviceMaterialType\":\"NMP\"}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233b-f0a9-ba84-eaa9-0d4718b361b6",
|
||||
"name": "ODA",
|
||||
"unit": "微升",
|
||||
"quantity": 1,
|
||||
"parameters": "{\"DeviceMaterialType\":\"NMP\"}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233b-f0a9-ba84-eaa9-0d4718b361b6",
|
||||
"name": "MPDA",
|
||||
"unit": "微升",
|
||||
"quantity": 1,
|
||||
"parameters": "{\"DeviceMaterialType\":\"NMP\"}"
|
||||
},
|
||||
{
|
||||
"typeId": "3a14233b-f0a9-ba84-eaa9-0d4718b361b6",
|
||||
"name": "PDA-2",
|
||||
"unit": "微升",
|
||||
"quantity": 1,
|
||||
"parameters": "{\"DeviceMaterialType\":\"NMP\"}"
|
||||
}
|
||||
]
|
||||
# # 烧杯材料数据定义
|
||||
# beaker_materials = [
|
||||
# {
|
||||
# "typeId": "3a14233b-f0a9-ba84-eaa9-0d4718b361b6",
|
||||
# "name": "PDA-1",
|
||||
# "unit": "微升",
|
||||
# "quantity": 1,
|
||||
# "parameters": "{\"DeviceMaterialType\":\"NMP\"}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233b-f0a9-ba84-eaa9-0d4718b361b6",
|
||||
# "name": "TFDB",
|
||||
# "unit": "微升",
|
||||
# "quantity": 1,
|
||||
# "parameters": "{\"DeviceMaterialType\":\"NMP\"}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233b-f0a9-ba84-eaa9-0d4718b361b6",
|
||||
# "name": "ODA",
|
||||
# "unit": "微升",
|
||||
# "quantity": 1,
|
||||
# "parameters": "{\"DeviceMaterialType\":\"NMP\"}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233b-f0a9-ba84-eaa9-0d4718b361b6",
|
||||
# "name": "MPDA",
|
||||
# "unit": "微升",
|
||||
# "quantity": 1,
|
||||
# "parameters": "{\"DeviceMaterialType\":\"NMP\"}"
|
||||
# },
|
||||
# {
|
||||
# "typeId": "3a14233b-f0a9-ba84-eaa9-0d4718b361b6",
|
||||
# "name": "PDA-2",
|
||||
# "unit": "微升",
|
||||
# "quantity": 1,
|
||||
# "parameters": "{\"DeviceMaterialType\":\"NMP\"}"
|
||||
# }
|
||||
# ]
|
||||
|
||||
# 如果需要,可以在这里调用add_material方法添加材料
|
||||
# 例如:
|
||||
# result = bioyond.add_material(json.dumps(material_data_yp_1))
|
||||
# print(f"添加材料结果: {result}")
|
||||
# # 如果需要,可以在这里调用add_material方法添加材料
|
||||
# # 例如:
|
||||
# # result = bioyond.add_material(json.dumps(material_data_yp_1))
|
||||
# # print(f"添加材料结果: {result}")
|
||||
|
||||
return {
|
||||
"sample_plates": [material_data_yp_1, material_data_yp_2],
|
||||
"beakers": beaker_materials
|
||||
}
|
||||
# return {
|
||||
# "sample_plates": [material_data_yp_1, material_data_yp_2],
|
||||
# "beakers": beaker_materials
|
||||
# }
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -245,79 +245,7 @@ class BioyondWorkstation(WorkstationBase):
|
||||
}
|
||||
|
||||
# ==================== 工作流合并与参数设置 API ====================
|
||||
|
||||
def merge_workflow_with_parameters(self, json_str: str) -> dict:
|
||||
"""合并工作流并设置参数"""
|
||||
try:
|
||||
# 解析输入的 JSON 数据
|
||||
data = json.loads(json_str)
|
||||
|
||||
# 构造 API 请求参数
|
||||
params = {
|
||||
"name": data.get("name", ""),
|
||||
"workflows": data.get("workflows", [])
|
||||
}
|
||||
|
||||
# 验证必要参数
|
||||
if not params["name"]:
|
||||
return {
|
||||
"code": 0,
|
||||
"message": "工作流名称不能为空",
|
||||
"timestamp": int(datetime.now().timestamp() * 1000)
|
||||
}
|
||||
|
||||
if not params["workflows"]:
|
||||
return {
|
||||
"code": 0,
|
||||
"message": "工作流列表不能为空",
|
||||
"timestamp": int(datetime.now().timestamp() * 1000)
|
||||
}
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
return {
|
||||
"code": 0,
|
||||
"message": f"JSON 解析错误: {str(e)}",
|
||||
"timestamp": int(datetime.now().timestamp() * 1000)
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"code": 0,
|
||||
"message": f"参数处理错误: {str(e)}",
|
||||
"timestamp": int(datetime.now().timestamp() * 1000)
|
||||
}
|
||||
|
||||
# 发送 POST 请求到 Bioyond API
|
||||
try:
|
||||
response = self.hardware_interface.post(
|
||||
url=f'{self.hardware_interface.host}/api/lims/workflow/merge-workflow-with-parameters',
|
||||
params={
|
||||
"apiKey": self.hardware_interface.api_key,
|
||||
"requestTime": self.hardware_interface.get_current_time_iso8601(),
|
||||
"data": params,
|
||||
})
|
||||
|
||||
# 处理响应
|
||||
if not response:
|
||||
return {
|
||||
"code": 0,
|
||||
"message": "API 请求失败,未收到响应",
|
||||
"timestamp": int(datetime.now().timestamp() * 1000)
|
||||
}
|
||||
|
||||
# 返回完整的响应结果
|
||||
return {
|
||||
"code": response.get("code", 0),
|
||||
"message": response.get("message", ""),
|
||||
"timestamp": response.get("timestamp", int(datetime.now().timestamp() * 1000))
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
"code": 0,
|
||||
"message": f"API 请求异常: {str(e)}",
|
||||
"timestamp": int(datetime.now().timestamp() * 1000)
|
||||
}
|
||||
|
||||
|
||||
def append_to_workflow_sequence(self, web_workflow_name: str) -> bool:
|
||||
# 检查是否为JSON格式的字符串
|
||||
actual_workflow_name = web_workflow_name
|
||||
@@ -391,6 +319,23 @@ class BioyondWorkstation(WorkstationBase):
|
||||
# ==================== 基础物料管理接口 ====================
|
||||
|
||||
# ============ 工作站状态管理 ============
|
||||
def get_station_info(self) -> Dict[str, Any]:
|
||||
"""获取工作站基础信息
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 工作站基础信息,包括设备ID、状态等
|
||||
"""
|
||||
return {
|
||||
"device_id": getattr(self._ros_node, 'device_id', 'unknown'),
|
||||
"station_type": "BioyondWorkstation",
|
||||
"workflow_status": self.current_workflow_status.value if hasattr(self, 'current_workflow_status') else "unknown",
|
||||
"is_busy": getattr(self, 'is_busy', False),
|
||||
"deck_info": {
|
||||
"name": self.deck.name if self.deck and hasattr(self.deck, 'name') else "unknown",
|
||||
"children_count": len(self.deck.children) if self.deck and hasattr(self.deck, 'children') else 0
|
||||
} if self.deck else None,
|
||||
"hardware_interface": type(self.hardware_interface).__name__ if self.hardware_interface else None
|
||||
}
|
||||
|
||||
def get_workstation_status(self) -> Dict[str, Any]:
|
||||
"""获取工作站状态
|
||||
|
||||
@@ -32,6 +32,7 @@ class Bottle(Well):
|
||||
barcode: Optional[str] = "",
|
||||
category: str = "container",
|
||||
model: Optional[str] = None,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(
|
||||
name=name,
|
||||
@@ -427,6 +428,7 @@ class BottleCarrier(ItemizedCarrier):
|
||||
sites: Optional[Dict[Union[int, str], ResourceHolder]] = None,
|
||||
category: str = "bottle_carrier",
|
||||
model: Optional[str] = None,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(
|
||||
name=name,
|
||||
|
||||
@@ -582,6 +582,7 @@ class BaseROS2DeviceNode(Node, Generic[T]):
|
||||
- update: 更新现有资源
|
||||
- remove: 从资源树中移除资源
|
||||
"""
|
||||
from pylabrobot.resources.resource import Resource as ResourcePLR
|
||||
try:
|
||||
data = json.loads(req.command)
|
||||
results = []
|
||||
@@ -662,22 +663,23 @@ class BaseROS2DeviceNode(Node, Generic[T]):
|
||||
)
|
||||
found_plr_resources = []
|
||||
other_plr_resources = []
|
||||
for res_list in found_resources:
|
||||
for res in res_list:
|
||||
if issubclass(res.__class__, ResourcePLR):
|
||||
found_plr_resources.append(res)
|
||||
for found_resource in found_resources:
|
||||
for resource in found_resource:
|
||||
if issubclass(resource.__class__, ResourcePLR):
|
||||
found_plr_resources.append(resource)
|
||||
else:
|
||||
other_plr_resources.append(res)
|
||||
other_plr_resources.append(resource)
|
||||
func = getattr(self.driver_instance, "resource_tree_remove", None)
|
||||
if callable(func):
|
||||
func(found_plr_resources)
|
||||
for plr_resource in found_plr_resources:
|
||||
plr_resource.parent.unassign_child_resource(plr_resource)
|
||||
if plr_resource.parent is not None:
|
||||
plr_resource.parent.unassign_child_resource(plr_resource)
|
||||
self.resource_tracker.remove_resource(plr_resource)
|
||||
self.lab_logger().info(f"移除物料 {plr_resource} 及其子节点")
|
||||
for res in other_plr_resources:
|
||||
self.resource_tracker.remove_resource(res)
|
||||
self.lab_logger().info(f"移除物料 {res} 及其子节点")
|
||||
for other_plr_resource in other_plr_resources:
|
||||
self.resource_tracker.remove_resource(other_plr_resource)
|
||||
self.lab_logger().info(f"移除物料 {other_plr_resource} 及其子节点")
|
||||
results.append({"success": True, "action": "remove"})
|
||||
except Exception as e:
|
||||
error_msg = f"Error processing {action} operation: {str(e)}"
|
||||
|
||||
Reference in New Issue
Block a user