mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2026-02-17 05:05:12 +00:00
Compare commits
20 Commits
5610c28b67
...
a1783f489e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1783f489e | ||
|
|
a8f6527de9 | ||
|
|
54cfaf15f3 | ||
|
|
1c9d2ee98a | ||
|
|
3fe8f4ca44 | ||
|
|
2476821dcc | ||
|
|
7b426ed5ae | ||
|
|
9bbae96447 | ||
|
|
10aabb7592 | ||
|
|
a5397ffe12 | ||
|
|
196e0f7e2b | ||
|
|
a632fd495e | ||
|
|
a8cc02a126 | ||
|
|
ad2e1432c6 | ||
|
|
c3b9583eac | ||
|
|
5c47cd0c8a | ||
|
|
63ab1af45d | ||
|
|
a8419dc0c3 | ||
|
|
34f05f2e25 | ||
|
|
0dc2488f02 |
@@ -127,7 +127,7 @@ add_action_files(
|
||||
```bash
|
||||
mamba remove --force ros-humble-unilabos-msgs
|
||||
mamba config set safety_checks disabled # 如果没有提升版本号,会触发md5与网络上md5不一致,是正常现象,因此通过本指令关闭md5检查
|
||||
mamba install xxx.conda2 --offline
|
||||
mamba install xxx.conda --offline
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
60
test/experiments/dispensing_station_bioyond.json
Normal file
60
test/experiments/dispensing_station_bioyond.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "dispensing_station_bioyond",
|
||||
"name": "dispensing_station_bioyond",
|
||||
"children": [
|
||||
"Bioyond_Dispensing_Deck"
|
||||
],
|
||||
"parent": null,
|
||||
"type": "device",
|
||||
"class": "dispensing_station.bioyond",
|
||||
"config": {
|
||||
"config": {
|
||||
"api_key": "DE9BDDA0",
|
||||
"api_host": "http://192.168.1.200:44388"
|
||||
},
|
||||
"deck": {
|
||||
"data": {
|
||||
"_resource_child_name": "Bioyond_Dispensing_Deck",
|
||||
"_resource_type": "unilabos.resources.bioyond.decks:BIOYOND_PolymerPreparationStation_Deck"
|
||||
}
|
||||
},
|
||||
"station_config": {
|
||||
"station_type": "dispensing_station",
|
||||
"enable_dispensing_station": true,
|
||||
"enable_reaction_station": false,
|
||||
"station_name": "DispensingStation_001",
|
||||
"description": "Bioyond配液工作站"
|
||||
},
|
||||
"protocol_type": []
|
||||
},
|
||||
"data": {}
|
||||
},
|
||||
{
|
||||
"id": "Bioyond_Dispensing_Deck",
|
||||
"name": "Bioyond_Dispensing_Deck",
|
||||
"sample_id": null,
|
||||
"children": [],
|
||||
"parent": "dispensing_station_bioyond",
|
||||
"type": "deck",
|
||||
"class": "BIOYOND_PolymerPreparationStation_Deck",
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"type": "BIOYOND_PolymerPreparationStation_Deck",
|
||||
"setup": true,
|
||||
"rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"type": "Rotation"
|
||||
}
|
||||
},
|
||||
"data": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
69
test/experiments/reaction_station_bioyond.json
Normal file
69
test/experiments/reaction_station_bioyond.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "reaction_station_bioyond",
|
||||
"name": "reaction_station_bioyond",
|
||||
"parent": null,
|
||||
"children": [
|
||||
"Bioyond_Deck"
|
||||
],
|
||||
"type": "device",
|
||||
"class": "reaction_station.bioyond",
|
||||
"config": {
|
||||
"bioyond_config": {
|
||||
"api_key": "DE9BDDA0",
|
||||
"api_host": "http://192.168.1.200:44402",
|
||||
"workflow_mappings": {
|
||||
"reactor_taken_out": "3a16081e-4788-ca37-eff4-ceed8d7019d1",
|
||||
"reactor_taken_in": "3a160df6-76b3-0957-9eb0-cb496d5721c6",
|
||||
"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",
|
||||
"Drip_back": "3a162cf9-6aac-565a-ddd7-682ba1796a4a"
|
||||
},
|
||||
"material_type_mappings": {
|
||||
"烧杯": "BIOYOND_PolymerStation_1FlaskCarrier",
|
||||
"试剂瓶": "BIOYOND_PolymerStation_1BottleCarrier",
|
||||
"样品板": "BIOYOND_PolymerStation_6VialCarrier"
|
||||
}
|
||||
},
|
||||
"deck": {
|
||||
"data": {
|
||||
"_resource_child_name": "Bioyond_Deck",
|
||||
"_resource_type": "unilabos.resources.bioyond.decks:BIOYOND_PolymerReactionStation_Deck"
|
||||
}
|
||||
},
|
||||
"protocol_type": []
|
||||
},
|
||||
"data": {}
|
||||
},
|
||||
{
|
||||
"id": "Bioyond_Deck",
|
||||
"name": "Bioyond_Deck",
|
||||
"sample_id": null,
|
||||
"children": [
|
||||
],
|
||||
"parent": "reaction_station_bioyond",
|
||||
"type": "deck",
|
||||
"class": "BIOYOND_PolymerReactionStation_Deck",
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"type": "BIOYOND_PolymerReactionStation_Deck",
|
||||
"setup": true,
|
||||
"rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"type": "Rotation"
|
||||
}
|
||||
},
|
||||
"data": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -173,6 +173,134 @@ class BioyondV1RPC(BaseRequest):
|
||||
return {}
|
||||
return response.get("data", {})
|
||||
|
||||
def validate_workflow_parameters(self, workflows: List[Dict[str, Any]]) -> Dict[str, Any]:
|
||||
"""验证工作流参数格式
|
||||
|
||||
Args:
|
||||
workflows (List[Dict[str, Any]]): 工作流列表
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 验证结果
|
||||
"""
|
||||
try:
|
||||
validation_errors = []
|
||||
|
||||
for i, workflow in enumerate(workflows):
|
||||
workflow_errors = []
|
||||
|
||||
# 检查基本结构
|
||||
if not isinstance(workflow, dict):
|
||||
workflow_errors.append("工作流必须是字典类型")
|
||||
continue
|
||||
|
||||
if "id" not in workflow:
|
||||
workflow_errors.append("缺少必要的 'id' 字段")
|
||||
|
||||
# 检查 stepParameters(如果存在)
|
||||
if "stepParameters" in workflow:
|
||||
step_params = workflow["stepParameters"]
|
||||
|
||||
if not isinstance(step_params, dict):
|
||||
workflow_errors.append("stepParameters 必须是字典类型")
|
||||
else:
|
||||
# 验证参数结构
|
||||
for step_id, modules in step_params.items():
|
||||
if not isinstance(modules, dict):
|
||||
workflow_errors.append(f"步骤 {step_id} 的模块配置必须是字典类型")
|
||||
continue
|
||||
|
||||
for module_name, params in modules.items():
|
||||
if not isinstance(params, list):
|
||||
workflow_errors.append(f"步骤 {step_id} 模块 {module_name} 的参数必须是列表类型")
|
||||
continue
|
||||
|
||||
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")
|
||||
|
||||
if workflow_errors:
|
||||
validation_errors.append({
|
||||
"workflow_index": i,
|
||||
"workflow_id": workflow.get("id", "unknown"),
|
||||
"errors": workflow_errors
|
||||
})
|
||||
|
||||
if validation_errors:
|
||||
return {
|
||||
"valid": False,
|
||||
"errors": validation_errors,
|
||||
"message": f"发现 {len(validation_errors)} 个工作流存在验证错误"
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"valid": True,
|
||||
"message": f"所有 {len(workflows)} 个工作流验证通过"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
"valid": False,
|
||||
"errors": [{"general_error": str(e)}],
|
||||
"message": f"验证过程中发生异常: {str(e)}"
|
||||
}
|
||||
|
||||
def get_workflow_parameter_template(self) -> Dict[str, Any]:
|
||||
"""获取工作流参数模板
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 参数模板和说明
|
||||
"""
|
||||
return {
|
||||
"template": {
|
||||
"name": "拼接后的长工作流的名称",
|
||||
"workflows": [
|
||||
{
|
||||
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||
"stepParameters": {
|
||||
"步骤ID (UUID)": {
|
||||
"模块名称": [
|
||||
{
|
||||
"key": "参数键名",
|
||||
"value": "参数值或变量引用 {{index-m-n}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameter_descriptions": {
|
||||
"name": "拼接后的长工作流名称",
|
||||
"workflows": "待合并的子工作流列表",
|
||||
"id": "子工作流 ID,对应工作流列表中 workflows 数组中每个对象的 id 字段",
|
||||
"stepParameters": "步骤参数配置,如果子工作流没有参数则不需要填写"
|
||||
},
|
||||
"common_modules": {
|
||||
"反应模块-开始搅拌": {
|
||||
"description": "反应模块搅拌控制",
|
||||
"common_parameters": ["temperature"]
|
||||
},
|
||||
"通量-配置": {
|
||||
"description": "通量配置模块",
|
||||
"common_parameters": ["cutoff", "assignMaterialName"]
|
||||
},
|
||||
"烧杯溶液放置位-烧杯吸液分液": {
|
||||
"description": "烧杯液体处理模块",
|
||||
"common_parameters": ["titrationType", "assignMaterialName", "volume"]
|
||||
}
|
||||
},
|
||||
"variable_reference_format": {
|
||||
"format": "{{index-m-n}}",
|
||||
"description": {
|
||||
"index": "该步骤所在子工作流的拼接顺序(从 1 开始)",
|
||||
"m": "拼接前该步骤在子工作流内部的 m 值",
|
||||
"n": "拼接前该步骤在子工作流内部的 n 值"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 工作流步骤查询接口
|
||||
def workflow_step_query(self, json_str: str) -> dict:
|
||||
try:
|
||||
@@ -259,6 +387,32 @@ class BioyondV1RPC(BaseRequest):
|
||||
return {}
|
||||
return response.get("data", {})
|
||||
|
||||
def material_id_query(self, json_str: str) -> dict:
|
||||
"""
|
||||
查询物料id
|
||||
json_str 格式为JSON字符串:
|
||||
'{"material123"}'
|
||||
"""
|
||||
params = json_str
|
||||
|
||||
response = self.post(
|
||||
url=f'{self.host}/api/lims/storage/workflow-sample-locations',
|
||||
params={
|
||||
"apiKey": self.api_key,
|
||||
"requestTime": self.get_current_time_iso8601(),
|
||||
"data": params
|
||||
})
|
||||
|
||||
if not response:
|
||||
return {}
|
||||
|
||||
if response['code'] != 1:
|
||||
print(f"material_id_query error: {response.get('message')}")
|
||||
return {}
|
||||
|
||||
print(f"material_id_query data: {response['data']}")
|
||||
return response.get("data", {})
|
||||
|
||||
# 任务取出接口
|
||||
def order_takeout(self, json_str: str) -> int:
|
||||
try:
|
||||
@@ -465,6 +619,88 @@ class BioyondV1RPC(BaseRequest):
|
||||
return {}
|
||||
return response.get("data", {})
|
||||
|
||||
# 合并工作流并设置参数 API
|
||||
def merge_workflow_with_parameters(self, json_str: str) -> dict:
|
||||
"""合并工作流并设置参数
|
||||
|
||||
调用 Bioyond API: /api/lims/workflow/merge-workflow-with-parameters
|
||||
|
||||
Args:
|
||||
json_str (str): JSON 字符串,包含工作流合并配置数据
|
||||
|
||||
Returns:
|
||||
dict: API 响应结果,包含 code、message 和 timestamp
|
||||
"""
|
||||
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.post(
|
||||
url=f'{self.host}/api/lims/workflow/merge-workflow-with-parameters',
|
||||
params={
|
||||
"apiKey": self.api_key,
|
||||
"requestTime": self.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 merge_sequence_workflow(self, json_str: str) -> dict:
|
||||
try:
|
||||
@@ -1056,3 +1292,660 @@ class BioyondV1RPC(BaseRequest):
|
||||
|
||||
def get_logger(self):
|
||||
return self._logger
|
||||
|
||||
# ==================== 配液站特有方法 ====================
|
||||
|
||||
def sample_waste_removal(self, order_id: str) -> dict:
|
||||
"""
|
||||
样品/废料取出接口
|
||||
|
||||
参数:
|
||||
- order_id: 订单ID
|
||||
|
||||
返回: 取出结果
|
||||
"""
|
||||
params = {"orderId": order_id}
|
||||
|
||||
response = self.post(
|
||||
url=f'{self.host}/api/lims/order/take-out',
|
||||
params={
|
||||
"apiKey": self.api_key,
|
||||
"requestTime": self.get_current_time_iso8601(),
|
||||
"data": params
|
||||
})
|
||||
|
||||
if not response:
|
||||
return {}
|
||||
|
||||
if response['code'] != 1:
|
||||
self._logger.error(f"样品废料取出错误: {response.get('message', '')}")
|
||||
return {}
|
||||
|
||||
return response.get("data", {})
|
||||
|
||||
def dispensing_material_inbound(self, material_id: str, location_id: str) -> dict:
|
||||
"""
|
||||
配液站物料入库接口
|
||||
|
||||
参数:
|
||||
- material_id: 物料ID
|
||||
- location_id: 库位ID
|
||||
|
||||
返回: 入库结果
|
||||
"""
|
||||
params = {
|
||||
"materialId": material_id,
|
||||
"locationId": location_id
|
||||
}
|
||||
|
||||
response = self.post(
|
||||
url=f'{self.host}/api/lims/storage/inbound',
|
||||
params={
|
||||
"apiKey": self.api_key,
|
||||
"requestTime": self.get_current_time_iso8601(),
|
||||
"data": params
|
||||
})
|
||||
|
||||
if not response:
|
||||
return {}
|
||||
|
||||
if response['code'] != 1:
|
||||
self._logger.error(f"配液站物料入库错误: {response.get('message', '')}")
|
||||
return {}
|
||||
|
||||
return response.get("data", {})
|
||||
|
||||
def dispensing_material_outbound(self, material_id: str, location_id: str, quantity: int) -> dict:
|
||||
"""
|
||||
配液站物料出库接口
|
||||
|
||||
参数:
|
||||
- material_id: 物料ID
|
||||
- location_id: 库位ID
|
||||
- quantity: 出库数量
|
||||
|
||||
返回: 出库结果
|
||||
"""
|
||||
params = {
|
||||
"materialId": material_id,
|
||||
"locationId": location_id,
|
||||
"quantity": quantity
|
||||
}
|
||||
|
||||
response = self.post(
|
||||
url=f'{self.host}/api/lims/storage/outbound',
|
||||
params={
|
||||
"apiKey": self.api_key,
|
||||
"requestTime": self.get_current_time_iso8601(),
|
||||
"data": params
|
||||
})
|
||||
|
||||
if not response:
|
||||
return {}
|
||||
|
||||
if response['code'] != 1:
|
||||
self._logger.error(f"配液站物料出库错误: {response.get('message', '')}")
|
||||
return {}
|
||||
|
||||
return response.get("data", {})
|
||||
|
||||
def create_90_10_vial_feeding_task(self,
|
||||
order_name: str = None,
|
||||
speed: str = None,
|
||||
temperature: str = None,
|
||||
delay_time: str = None,
|
||||
percent_90_1_assign_material_name: str = None,
|
||||
percent_90_1_target_weigh: str = None,
|
||||
percent_90_2_assign_material_name: str = None,
|
||||
percent_90_2_target_weigh: str = None,
|
||||
percent_90_3_assign_material_name: str = None,
|
||||
percent_90_3_target_weigh: str = None,
|
||||
percent_10_1_assign_material_name: str = None,
|
||||
percent_10_1_target_weigh: str = None,
|
||||
percent_10_1_volume: str = None,
|
||||
percent_10_1_liquid_material_name: str = None,
|
||||
percent_10_2_assign_material_name: str = None,
|
||||
percent_10_2_target_weigh: str = None,
|
||||
percent_10_2_volume: str = None,
|
||||
percent_10_2_liquid_material_name: str = None,
|
||||
percent_10_3_assign_material_name: str = None,
|
||||
percent_10_3_target_weigh: str = None,
|
||||
percent_10_3_volume: str = None,
|
||||
percent_10_3_liquid_material_name: str = None,
|
||||
hold_m_name: str = None) -> dict:
|
||||
"""
|
||||
创建90%10%小瓶投料任务
|
||||
|
||||
参数说明:
|
||||
- order_name: 任务名称,如果为None则使用默认名称
|
||||
- speed: 搅拌速度,如果为None则使用默认值400
|
||||
- temperature: 温度,如果为None则使用默认值40
|
||||
- delay_time: 延迟时间,如果为None则使用默认值600
|
||||
- percent_90_1_assign_material_name: 90%_1物料名称
|
||||
- percent_90_1_target_weigh: 90%_1目标重量
|
||||
- percent_90_2_assign_material_name: 90%_2物料名称
|
||||
- percent_90_2_target_weigh: 90%_2目标重量
|
||||
- percent_90_3_assign_material_name: 90%_3物料名称
|
||||
- percent_90_3_target_weigh: 90%_3目标重量
|
||||
- percent_10_1_assign_material_name: 10%_1固体物料名称
|
||||
- percent_10_1_target_weigh: 10%_1固体目标重量
|
||||
- percent_10_1_volume: 10%_1液体体积
|
||||
- percent_10_1_liquid_material_name: 10%_1液体物料名称
|
||||
- percent_10_2_assign_material_name: 10%_2固体物料名称
|
||||
- percent_10_2_target_weigh: 10%_2固体目标重量
|
||||
- percent_10_2_volume: 10%_2液体体积
|
||||
- percent_10_2_liquid_material_name: 10%_2液体物料名称
|
||||
- percent_10_3_assign_material_name: 10%_3固体物料名称
|
||||
- percent_10_3_target_weigh: 10%_3固体目标重量
|
||||
- percent_10_3_volume: 10%_3液体体积
|
||||
- percent_10_3_liquid_material_name: 10%_3液体物料名称
|
||||
- hold_m_name: 库位名称,如"C01",用于查找对应的holdMId
|
||||
|
||||
返回: 任务创建结果
|
||||
"""
|
||||
# 设置默认值
|
||||
if order_name is None:
|
||||
order_name = f"90%10%小瓶投料任务_{self.get_current_time_iso8601()}"
|
||||
if speed is None:
|
||||
speed = "400"
|
||||
if temperature is None:
|
||||
temperature = "20"
|
||||
if delay_time is None:
|
||||
delay_time = "600"
|
||||
|
||||
# 获取工作流ID
|
||||
workflow_id = "3a19310d-16b9-9d81-b109-0748e953694b" # 90%10%小瓶投料工作流ID
|
||||
|
||||
# 查询holdMId
|
||||
holdMId = None
|
||||
if hold_m_name:
|
||||
holdMId_response = self.material_id_query(hold_m_name)
|
||||
if holdMId_response:
|
||||
holdMId = holdMId_response
|
||||
|
||||
# 构建订单数据
|
||||
order_data = [{
|
||||
"code": order_name,
|
||||
"Name": "90%10%小瓶投料任务",
|
||||
"workflowName": "90%10%小瓶投料",
|
||||
"borderNumber": 1,
|
||||
"paramValues": {
|
||||
workflow_id: [
|
||||
# 搅拌速度
|
||||
{"m": 3, "n": 2, "key": "speed", "value": speed},
|
||||
# 温度
|
||||
{"m": 3, "n": 2, "key": "temperature", "value": temperature},
|
||||
# 延迟时间
|
||||
{"m": 3, "n": 2, "key": "delayTime", "value": delay_time},
|
||||
# 90%_1固体物料
|
||||
{"m": 3, "n": 2, "key": "90%_1_assignMaterialName", "value": percent_90_1_assign_material_name},
|
||||
{"m": 3, "n": 2, "key": "90%_1_targetWeigh", "value": percent_90_1_target_weigh},
|
||||
# 90%_2固体物料
|
||||
{"m": 3, "n": 2, "key": "90%_2_assignMaterialName", "value": percent_90_2_assign_material_name},
|
||||
{"m": 3, "n": 2, "key": "90%_2_targetWeigh", "value": percent_90_2_target_weigh},
|
||||
# 90%_3固体物料
|
||||
{"m": 3, "n": 2, "key": "90%_3_assignMaterialName", "value": percent_90_3_assign_material_name},
|
||||
{"m": 3, "n": 2, "key": "90%_3_targetWeigh", "value": percent_90_3_target_weigh},
|
||||
# 10%_1液体物料
|
||||
{"m": 3, "n": 2, "key": "10%_1_assignMaterialName", "value": percent_10_1_assign_material_name},
|
||||
{"m": 3, "n": 2, "key": "10%_1_targetWeigh", "value": percent_10_1_target_weigh},
|
||||
{"m": 3, "n": 2, "key": "10%_1_volume", "value": percent_10_1_volume},
|
||||
{"m": 3, "n": 2, "key": "10%_1_liquidMaterialName", "value": percent_10_1_liquid_material_name},
|
||||
# 10%_2液体物料
|
||||
{"m": 3, "n": 2, "key": "10%_2_assignMaterialName", "value": percent_10_2_assign_material_name},
|
||||
{"m": 3, "n": 2, "key": "10%_2_targetWeigh", "value": percent_10_2_target_weigh},
|
||||
{"m": 3, "n": 2, "key": "10%_2_volume", "value": percent_10_2_volume},
|
||||
{"m": 3, "n": 2, "key": "10%_2_liquidMaterialName", "value": percent_10_2_liquid_material_name},
|
||||
# 10%_3液体物料
|
||||
{"m": 3, "n": 2, "key": "10%_3_assignMaterialName", "value": percent_10_3_assign_material_name},
|
||||
{"m": 3, "n": 2, "key": "10%_3_targetWeigh", "value": percent_10_3_target_weigh},
|
||||
{"m": 3, "n": 2, "key": "10%_3_volume", "value": percent_10_3_volume},
|
||||
{"m": 3, "n": 2, "key": "10%_3_liquidMaterialName", "value": percent_10_3_liquid_material_name}
|
||||
]
|
||||
},
|
||||
"ExtendProperties": f"{{{holdMId}:null}}" if holdMId else "{}"
|
||||
}]
|
||||
|
||||
try:
|
||||
# 调用create_order方法创建任务
|
||||
result = self.create_order(json.dumps(order_data, ensure_ascii=False))
|
||||
self._logger.info(f"90%10%小瓶投料任务创建成功: {result}")
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"90%10%小瓶投料任务创建异常: {str(e)}"
|
||||
self._logger.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def create_diamine_solution_task(self,
|
||||
order_name: str = None,
|
||||
material_name: str = None,
|
||||
target_weigh: str = None,
|
||||
volume: str = None,
|
||||
liquid_material_name: str = "NMP",
|
||||
speed: str = None,
|
||||
temperature: str = None,
|
||||
delay_time: str = None,
|
||||
hold_m_name: str = None) -> dict:
|
||||
"""
|
||||
创建二胺溶液配置任务
|
||||
|
||||
参数说明:
|
||||
- order_name: 任务名称,如果为None则使用默认名称
|
||||
- material_name: 固体物料名称,必填
|
||||
- target_weigh: 固体目标重量,必填
|
||||
- volume: 液体体积,必填
|
||||
- liquid_material_name: 液体物料名称,默认为NMP
|
||||
- speed: 搅拌速度,如果为None则使用默认值400
|
||||
- temperature: 温度,如果为None则使用默认值25
|
||||
- delay_time: 延迟时间,如果为None则使用默认值600
|
||||
- hold_m_name: 库位名称,如"ODA-1",用于查找对应的holdMId
|
||||
|
||||
返回: 任务创建结果
|
||||
"""
|
||||
# 验证必填参数
|
||||
if not material_name or not target_weigh or not volume:
|
||||
return {
|
||||
"status": "error",
|
||||
"message": "material_name、target_weigh和volume为必填参数"
|
||||
}
|
||||
|
||||
# 设置默认值
|
||||
if order_name is None:
|
||||
order_name = f"二胺溶液配置任务_{self.get_current_time_iso8601()}"
|
||||
if speed is None:
|
||||
speed = "400"
|
||||
if temperature is None:
|
||||
temperature = "25"
|
||||
if delay_time is None:
|
||||
delay_time = "600"
|
||||
|
||||
# 获取工作流ID
|
||||
workflow_id = "1"
|
||||
|
||||
# 查询holdMId
|
||||
holdMId = None
|
||||
if hold_m_name:
|
||||
try:
|
||||
material_query_params = json.dumps({"materialName": hold_m_name})
|
||||
material_response = self.material_id_query(material_query_params)
|
||||
if material_response and material_response.get("code") == 1:
|
||||
data = material_response.get("data", [])
|
||||
if data:
|
||||
holdMId = data[0].get("id")
|
||||
self._logger.info(f"查询到holdMId: {holdMId} for {hold_m_name}")
|
||||
else:
|
||||
self._logger.warning(f"未找到物料: {hold_m_name}")
|
||||
else:
|
||||
self._logger.error(f"查询物料ID失败: {material_response}")
|
||||
except Exception as e:
|
||||
self._logger.error(f"查询holdMId时发生错误: {e}")
|
||||
|
||||
# 构建order_data
|
||||
order_data = {
|
||||
"workflowId": workflow_id,
|
||||
"orderName": order_name,
|
||||
"params": {
|
||||
"1": speed, # 搅拌速度
|
||||
"2": temperature, # 温度
|
||||
"3": delay_time, # 延迟时间
|
||||
"4": material_name, # 固体物料名称
|
||||
"5": target_weigh, # 固体目标重量
|
||||
"6": volume, # 液体体积
|
||||
"7": liquid_material_name # 液体物料名称
|
||||
}
|
||||
}
|
||||
|
||||
if holdMId:
|
||||
order_data["holdMId"] = holdMId
|
||||
|
||||
try:
|
||||
# 使用create_order方法创建任务
|
||||
order_params = json.dumps(order_data)
|
||||
response = self.create_order(order_params)
|
||||
return response
|
||||
except Exception as e:
|
||||
self._logger.error(f"创建二胺溶液配置任务时发生错误: {e}")
|
||||
return {"status": "error", "message": f"创建任务失败: {str(e)}"}
|
||||
|
||||
def create_batch_90_10_vial_feeding_task(self, json_str: str) -> dict:
|
||||
"""
|
||||
创建批量90%10%小瓶投料任务
|
||||
|
||||
接受JSON输入,支持多个90%10%小瓶投料任务的批量创建
|
||||
|
||||
JSON格式示例:
|
||||
{
|
||||
"batch_name": "批量90%10%小瓶投料任务_20240101",
|
||||
"tasks": [
|
||||
{
|
||||
"order_name": "小瓶投料任务1",
|
||||
"hold_m_name": "C01",
|
||||
"percent_90_1_assign_material_name": "物料A",
|
||||
"percent_90_1_target_weigh": "10.5",
|
||||
"percent_10_1_assign_material_name": "物料B",
|
||||
"percent_10_1_target_weigh": "5.2",
|
||||
"percent_10_1_volume": "50.0",
|
||||
"percent_10_1_liquid_material_name": "NMP",
|
||||
"speed": "400",
|
||||
"temperature": "40",
|
||||
"delay_time": "600"
|
||||
}
|
||||
],
|
||||
"global_settings": {
|
||||
"speed": "400",
|
||||
"temperature": "40",
|
||||
"delay_time": "600"
|
||||
}
|
||||
}
|
||||
|
||||
参数说明:
|
||||
- batch_name: 批量任务名称,可选
|
||||
- tasks: 任务列表,每个任务包含90%10%小瓶投料参数
|
||||
- global_settings: 全局默认设置,当单个任务未指定参数时使用
|
||||
|
||||
返回: 批量任务创建结果
|
||||
"""
|
||||
try:
|
||||
# 解析JSON输入
|
||||
data = json.loads(json_str)
|
||||
|
||||
# 获取批量任务参数
|
||||
batch_name = data.get("batch_name", f"批量90%10%小瓶投料任务_{self.get_current_time_iso8601()}")
|
||||
tasks = data.get("tasks", [])
|
||||
global_settings = data.get("global_settings", {})
|
||||
|
||||
if not tasks:
|
||||
return {
|
||||
"status": "error",
|
||||
"message": "任务列表不能为空"
|
||||
}
|
||||
|
||||
# 批量创建结果
|
||||
batch_results = {
|
||||
"batch_name": batch_name,
|
||||
"total_tasks": len(tasks),
|
||||
"successful_tasks": 0,
|
||||
"failed_tasks": 0,
|
||||
"task_results": []
|
||||
}
|
||||
|
||||
self._logger.info(f"开始创建批量90%10%小瓶投料任务: {batch_name}, 包含 {len(tasks)} 个子任务")
|
||||
|
||||
# 逐个创建任务
|
||||
for i, task in enumerate(tasks):
|
||||
try:
|
||||
# 合并全局设置和任务特定设置
|
||||
task_params = {**global_settings, **task}
|
||||
|
||||
# 验证必填参数 - hold_m_name是必须的
|
||||
if not task_params.get("hold_m_name"):
|
||||
error_msg = f"任务 {i+1} 缺少必填参数: hold_m_name"
|
||||
self._logger.error(error_msg)
|
||||
batch_results["task_results"].append({
|
||||
"task_index": i + 1,
|
||||
"status": "error",
|
||||
"message": error_msg
|
||||
})
|
||||
batch_results["failed_tasks"] += 1
|
||||
continue
|
||||
|
||||
# 设置任务名称
|
||||
if not task_params.get("order_name"):
|
||||
task_params["order_name"] = f"{batch_name}_任务{i+1}"
|
||||
|
||||
# 调用单个90%10%小瓶投料任务创建方法
|
||||
task_result = self.create_90_10_vial_feeding_task(
|
||||
order_name=task_params.get("order_name"),
|
||||
speed=task_params.get("speed"),
|
||||
temperature=task_params.get("temperature"),
|
||||
delay_time=task_params.get("delay_time"),
|
||||
percent_90_1_assign_material_name=task_params.get("percent_90_1_assign_material_name"),
|
||||
percent_90_1_target_weigh=task_params.get("percent_90_1_target_weigh"),
|
||||
percent_90_2_assign_material_name=task_params.get("percent_90_2_assign_material_name"),
|
||||
percent_90_2_target_weigh=task_params.get("percent_90_2_target_weigh"),
|
||||
percent_90_3_assign_material_name=task_params.get("percent_90_3_assign_material_name"),
|
||||
percent_90_3_target_weigh=task_params.get("percent_90_3_target_weigh"),
|
||||
percent_10_1_assign_material_name=task_params.get("percent_10_1_assign_material_name"),
|
||||
percent_10_1_target_weigh=task_params.get("percent_10_1_target_weigh"),
|
||||
percent_10_1_volume=task_params.get("percent_10_1_volume"),
|
||||
percent_10_1_liquid_material_name=task_params.get("percent_10_1_liquid_material_name"),
|
||||
percent_10_2_assign_material_name=task_params.get("percent_10_2_assign_material_name"),
|
||||
percent_10_2_target_weigh=task_params.get("percent_10_2_target_weigh"),
|
||||
percent_10_2_volume=task_params.get("percent_10_2_volume"),
|
||||
percent_10_2_liquid_material_name=task_params.get("percent_10_2_liquid_material_name"),
|
||||
percent_10_3_assign_material_name=task_params.get("percent_10_3_assign_material_name"),
|
||||
percent_10_3_target_weigh=task_params.get("percent_10_3_target_weigh"),
|
||||
percent_10_3_volume=task_params.get("percent_10_3_volume"),
|
||||
percent_10_3_liquid_material_name=task_params.get("percent_10_3_liquid_material_name"),
|
||||
hold_m_name=task_params.get("hold_m_name")
|
||||
)
|
||||
|
||||
# 记录任务结果
|
||||
if isinstance(task_result, dict) and task_result.get("status") != "error":
|
||||
batch_results["successful_tasks"] += 1
|
||||
batch_results["task_results"].append({
|
||||
"task_index": i + 1,
|
||||
"task_name": task_params.get("order_name"),
|
||||
"status": "success",
|
||||
"result": task_result
|
||||
})
|
||||
self._logger.info(f"任务 {i+1} 创建成功: {task_params.get('order_name')}")
|
||||
else:
|
||||
batch_results["failed_tasks"] += 1
|
||||
batch_results["task_results"].append({
|
||||
"task_index": i + 1,
|
||||
"task_name": task_params.get("order_name"),
|
||||
"status": "error",
|
||||
"message": str(task_result)
|
||||
})
|
||||
self._logger.error(f"任务 {i+1} 创建失败: {task_result}")
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"任务 {i+1} 处理时发生异常: {str(e)}"
|
||||
self._logger.error(error_msg)
|
||||
batch_results["failed_tasks"] += 1
|
||||
batch_results["task_results"].append({
|
||||
"task_index": i + 1,
|
||||
"status": "error",
|
||||
"message": error_msg
|
||||
})
|
||||
|
||||
# 设置批量任务整体状态
|
||||
if batch_results["failed_tasks"] == 0:
|
||||
batch_results["status"] = "success"
|
||||
batch_results["message"] = f"批量90%10%小瓶投料任务全部创建成功,共 {batch_results['successful_tasks']} 个任务"
|
||||
elif batch_results["successful_tasks"] == 0:
|
||||
batch_results["status"] = "error"
|
||||
batch_results["message"] = f"批量90%10%小瓶投料任务全部创建失败,共 {batch_results['failed_tasks']} 个任务"
|
||||
else:
|
||||
batch_results["status"] = "partial_success"
|
||||
batch_results["message"] = f"批量90%10%小瓶投料任务部分成功,成功 {batch_results['successful_tasks']} 个,失败 {batch_results['failed_tasks']} 个"
|
||||
|
||||
self._logger.info(f"批量90%10%小瓶投料任务完成: {batch_results['message']}")
|
||||
return batch_results
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
error_msg = f"JSON解析失败: {str(e)}"
|
||||
self._logger.error(error_msg)
|
||||
return {"status": "error", "message": error_msg}
|
||||
except Exception as e:
|
||||
error_msg = f"创建批量90%10%小瓶投料任务时发生错误: {str(e)}"
|
||||
self._logger.error(error_msg)
|
||||
return {"status": "error", "message": error_msg}
|
||||
|
||||
def create_batch_diamine_solution_task(self, json_str: str) -> dict:
|
||||
"""
|
||||
创建批量二胺溶液配制任务
|
||||
|
||||
接受JSON输入,支持多个二胺溶液配制任务的批量创建
|
||||
|
||||
JSON格式示例:
|
||||
{
|
||||
"batch_name": "批量二胺溶液配制任务_20240101",
|
||||
"tasks": [
|
||||
{
|
||||
"order_name": "二胺溶液配制任务1",
|
||||
"material_name": "物料A",
|
||||
"target_weigh": "10.5",
|
||||
"volume": "50.0",
|
||||
"liquid_material_name": "NMP",
|
||||
"speed": "400",
|
||||
"temperature": "25",
|
||||
"delay_time": "600",
|
||||
"hold_m_name": "A01"
|
||||
},
|
||||
{
|
||||
"order_name": "二胺溶液配制任务2",
|
||||
"material_name": "物料B",
|
||||
"target_weigh": "15.2",
|
||||
"volume": "75.0",
|
||||
"liquid_material_name": "DMF",
|
||||
"speed": "350",
|
||||
"temperature": "30",
|
||||
"delay_time": "800",
|
||||
"hold_m_name": "B02"
|
||||
}
|
||||
],
|
||||
"global_settings": {
|
||||
"speed": "400",
|
||||
"temperature": "25",
|
||||
"delay_time": "600",
|
||||
"liquid_material_name": "NMP"
|
||||
}
|
||||
}
|
||||
|
||||
参数说明:
|
||||
- batch_name: 批量任务名称,可选
|
||||
- tasks: 任务列表,每个任务包含二胺溶液配制参数
|
||||
- global_settings: 全局默认设置,当单个任务未指定参数时使用
|
||||
|
||||
每个任务参数:
|
||||
- order_name: 任务名称
|
||||
- material_name: 物料名称,必填
|
||||
- target_weigh: 目标重量,必填
|
||||
- volume: 体积,必填
|
||||
- liquid_material_name: 液体物料名称,可选
|
||||
- speed: 搅拌速度,可选
|
||||
- temperature: 温度,可选
|
||||
- delay_time: 延迟时间,可选
|
||||
- hold_m_name: 库位名称,可选
|
||||
|
||||
返回: 批量任务创建结果
|
||||
"""
|
||||
try:
|
||||
# 解析JSON输入
|
||||
data = json.loads(json_str)
|
||||
|
||||
# 获取批量任务参数
|
||||
batch_name = data.get("batch_name", f"批量二胺溶液配制任务_{self.get_current_time_iso8601()}")
|
||||
tasks = data.get("tasks", [])
|
||||
global_settings = data.get("global_settings", {})
|
||||
|
||||
if not tasks:
|
||||
return {
|
||||
"status": "error",
|
||||
"message": "任务列表不能为空"
|
||||
}
|
||||
|
||||
# 批量创建结果
|
||||
batch_results = {
|
||||
"batch_name": batch_name,
|
||||
"total_tasks": len(tasks),
|
||||
"successful_tasks": 0,
|
||||
"failed_tasks": 0,
|
||||
"task_results": []
|
||||
}
|
||||
|
||||
self._logger.info(f"开始创建批量二胺溶液配制任务: {batch_name}, 包含 {len(tasks)} 个子任务")
|
||||
|
||||
# 逐个创建任务
|
||||
for i, task in enumerate(tasks):
|
||||
try:
|
||||
# 合并全局设置和任务特定设置
|
||||
task_params = {**global_settings, **task}
|
||||
|
||||
# 验证必填参数
|
||||
required_params = ["material_name", "target_weigh", "volume"]
|
||||
missing_params = [param for param in required_params if not task_params.get(param)]
|
||||
|
||||
if missing_params:
|
||||
error_msg = f"任务 {i+1} 缺少必填参数: {', '.join(missing_params)}"
|
||||
self._logger.error(error_msg)
|
||||
batch_results["task_results"].append({
|
||||
"task_index": i + 1,
|
||||
"status": "error",
|
||||
"message": error_msg
|
||||
})
|
||||
batch_results["failed_tasks"] += 1
|
||||
continue
|
||||
|
||||
# 设置任务名称
|
||||
if not task_params.get("order_name"):
|
||||
task_params["order_name"] = f"{batch_name}_任务{i+1}"
|
||||
|
||||
# 调用单个二胺溶液配制任务创建方法
|
||||
task_result = self.create_diamine_solution_task(
|
||||
order_name=task_params.get("order_name"),
|
||||
material_name=task_params.get("material_name"),
|
||||
target_weigh=task_params.get("target_weigh"),
|
||||
volume=task_params.get("volume"),
|
||||
liquid_material_name=task_params.get("liquid_material_name", "NMP"),
|
||||
speed=task_params.get("speed"),
|
||||
temperature=task_params.get("temperature"),
|
||||
delay_time=task_params.get("delay_time"),
|
||||
hold_m_name=task_params.get("hold_m_name")
|
||||
)
|
||||
|
||||
# 记录任务结果
|
||||
if isinstance(task_result, dict) and task_result.get("status") != "error":
|
||||
batch_results["successful_tasks"] += 1
|
||||
batch_results["task_results"].append({
|
||||
"task_index": i + 1,
|
||||
"task_name": task_params.get("order_name"),
|
||||
"status": "success",
|
||||
"result": task_result
|
||||
})
|
||||
self._logger.info(f"任务 {i+1} 创建成功: {task_params.get('order_name')}")
|
||||
else:
|
||||
batch_results["failed_tasks"] += 1
|
||||
batch_results["task_results"].append({
|
||||
"task_index": i + 1,
|
||||
"task_name": task_params.get("order_name"),
|
||||
"status": "error",
|
||||
"message": str(task_result)
|
||||
})
|
||||
self._logger.error(f"任务 {i+1} 创建失败: {task_result}")
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"滴定液任务 {i+1} 处理时发生异常: {str(e)}"
|
||||
self._logger.error(error_msg)
|
||||
batch_results["failed_tasks"] += 1
|
||||
batch_results["task_results"].append({
|
||||
"task_index": i + 1,
|
||||
"status": "error",
|
||||
"message": error_msg
|
||||
})
|
||||
|
||||
# 设置批量任务整体状态
|
||||
if batch_results["failed_tasks"] == 0:
|
||||
batch_results["status"] = "success"
|
||||
batch_results["message"] = f"批量滴定液任务全部创建成功,共 {batch_results['successful_tasks']} 个任务"
|
||||
elif batch_results["successful_tasks"] == 0:
|
||||
batch_results["status"] = "error"
|
||||
batch_results["message"] = f"批量滴定液任务全部创建失败,共 {batch_results['failed_tasks']} 个任务"
|
||||
else:
|
||||
batch_results["status"] = "partial_success"
|
||||
batch_results["message"] = f"批量滴定液任务部分成功,成功 {batch_results['successful_tasks']} 个,失败 {batch_results['failed_tasks']} 个"
|
||||
|
||||
self._logger.info(f"批量滴定液任务完成: {batch_results['message']}")
|
||||
return batch_results
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
error_msg = f"JSON解析失败: {str(e)}"
|
||||
self._logger.error(error_msg)
|
||||
return {"status": "error", "message": error_msg}
|
||||
except Exception as e:
|
||||
error_msg = f"创建批量滴定液任务时发生错误: {str(e)}"
|
||||
self._logger.error(error_msg)
|
||||
return {"status": "error", "message": error_msg}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
506
unilabos/registry/devices/dispensing_station_bioyond.yaml
Normal file
506
unilabos/registry/devices/dispensing_station_bioyond.yaml
Normal file
@@ -0,0 +1,506 @@
|
||||
dispensing_station.bioyond:
|
||||
category:
|
||||
- work_station
|
||||
- dispensing_station_bioyond
|
||||
class:
|
||||
action_value_mappings:
|
||||
bioyond_sync:
|
||||
feedback: {}
|
||||
goal:
|
||||
force_sync: force_sync
|
||||
sync_type: sync_type
|
||||
goal_default:
|
||||
force_sync: false
|
||||
sync_type: full
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 从Bioyond系统同步物料
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
force_sync:
|
||||
description: 是否强制同步
|
||||
type: boolean
|
||||
sync_type:
|
||||
description: 同步类型
|
||||
enum:
|
||||
- full
|
||||
- incremental
|
||||
type: string
|
||||
required:
|
||||
- sync_type
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: bioyond_sync参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
bioyond_update:
|
||||
feedback: {}
|
||||
goal:
|
||||
material_ids: material_ids
|
||||
sync_all: sync_all
|
||||
goal_default:
|
||||
material_ids: []
|
||||
sync_all: true
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 将本地物料变更同步到Bioyond
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
material_ids:
|
||||
description: 要同步的物料ID列表
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
sync_all:
|
||||
description: 是否同步所有物料
|
||||
type: boolean
|
||||
required:
|
||||
- sync_all
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: bioyond_update参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
create_90_10_vial_feeding_task:
|
||||
feedback: {}
|
||||
goal:
|
||||
delay_time: delay_time
|
||||
order_name: order_name
|
||||
percent_10_1_assign_material_name: percent_10_1_assign_material_name
|
||||
percent_10_1_liquid_material_name: percent_10_1_liquid_material_name
|
||||
percent_10_1_target_weigh: percent_10_1_target_weigh
|
||||
percent_10_1_volume: percent_10_1_volume
|
||||
percent_10_2_assign_material_name: percent_10_2_assign_material_name
|
||||
percent_10_2_liquid_material_name: percent_10_2_liquid_material_name
|
||||
percent_10_2_target_weigh: percent_10_2_target_weigh
|
||||
percent_10_2_volume: percent_10_2_volume
|
||||
percent_90_1_assign_material_name: percent_90_1_assign_material_name
|
||||
percent_90_1_target_weigh: percent_90_1_target_weigh
|
||||
percent_90_2_assign_material_name: percent_90_2_assign_material_name
|
||||
percent_90_2_target_weigh: percent_90_2_target_weigh
|
||||
percent_90_3_assign_material_name: percent_90_3_assign_material_name
|
||||
percent_90_3_target_weigh: percent_90_3_target_weigh
|
||||
speed: speed
|
||||
temperature: temperature
|
||||
goal_default:
|
||||
delay_time: '600'
|
||||
order_name: ''
|
||||
percent_10_1_assign_material_name: ''
|
||||
percent_10_1_liquid_material_name: ''
|
||||
percent_10_1_target_weigh: ''
|
||||
percent_10_1_volume: ''
|
||||
percent_10_2_assign_material_name: ''
|
||||
percent_10_2_liquid_material_name: ''
|
||||
percent_10_2_target_weigh: ''
|
||||
percent_10_2_volume: ''
|
||||
percent_90_1_assign_material_name: ''
|
||||
percent_90_1_target_weigh: ''
|
||||
percent_90_2_assign_material_name: ''
|
||||
percent_90_2_target_weigh: ''
|
||||
percent_90_3_assign_material_name: ''
|
||||
percent_90_3_target_weigh: ''
|
||||
speed: '400'
|
||||
temperature: '20'
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 创建90%/10%小瓶投料任务
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
delay_time:
|
||||
default: '600'
|
||||
description: 延迟时间(s)
|
||||
type: string
|
||||
order_name:
|
||||
description: 任务名称
|
||||
type: string
|
||||
percent_10_1_assign_material_name:
|
||||
description: 10%组分1物料名称
|
||||
type: string
|
||||
percent_10_1_liquid_material_name:
|
||||
description: 10%组分1液体物料名称
|
||||
type: string
|
||||
percent_10_1_target_weigh:
|
||||
description: 10%组分1目标重量(g)
|
||||
type: string
|
||||
percent_10_1_volume:
|
||||
description: 10%组分1液体体积(mL)
|
||||
type: string
|
||||
percent_10_2_assign_material_name:
|
||||
description: 10%组分2物料名称
|
||||
type: string
|
||||
percent_10_2_liquid_material_name:
|
||||
description: 10%组分2液体物料名称
|
||||
type: string
|
||||
percent_10_2_target_weigh:
|
||||
description: 10%组分2目标重量(g)
|
||||
type: string
|
||||
percent_10_2_volume:
|
||||
description: 10%组分2液体体积(mL)
|
||||
type: string
|
||||
percent_90_1_assign_material_name:
|
||||
description: 90%组分1物料名称
|
||||
type: string
|
||||
percent_90_1_target_weigh:
|
||||
description: 90%组分1目标重量(g)
|
||||
type: string
|
||||
percent_90_2_assign_material_name:
|
||||
description: 90%组分2物料名称
|
||||
type: string
|
||||
percent_90_2_target_weigh:
|
||||
description: 90%组分2目标重量(g)
|
||||
type: string
|
||||
percent_90_3_assign_material_name:
|
||||
description: 90%组分3物料名称
|
||||
type: string
|
||||
percent_90_3_target_weigh:
|
||||
description: 90%组分3目标重量(g)
|
||||
type: string
|
||||
speed:
|
||||
default: '400'
|
||||
description: 搅拌速度(rpm)
|
||||
type: string
|
||||
temperature:
|
||||
default: '20'
|
||||
description: 温度(°C)
|
||||
type: string
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: create_90_10_vial_feeding_task参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
create_batch_90_10_vial_feeding_task:
|
||||
feedback: {}
|
||||
goal:
|
||||
batch_data: batch_data
|
||||
goal_default:
|
||||
batch_data: '{}'
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 创建批量90%10%小瓶投料任务
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
batch_data:
|
||||
description: 批量90%10%小瓶投料任务数据(JSON格式),包含batch_name、tasks列表和global_settings
|
||||
type: string
|
||||
required:
|
||||
- batch_data
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: create_batch_90_10_vial_feeding_task参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
create_batch_diamine_solution_task:
|
||||
feedback: {}
|
||||
goal:
|
||||
batch_data: batch_data
|
||||
goal_default:
|
||||
batch_data: '{}'
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 创建批量二胺溶液配制任务
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
batch_data:
|
||||
description: 批量二胺溶液配制任务数据(JSON格式),包含batch_name、tasks列表和global_settings
|
||||
type: string
|
||||
required:
|
||||
- batch_data
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: create_batch_diamine_solution_task参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
create_diamine_solution_task:
|
||||
feedback: {}
|
||||
goal:
|
||||
delay_time: delay_time
|
||||
hold_m_name: hold_m_name
|
||||
liquid_material_name: liquid_material_name
|
||||
material_name: material_name
|
||||
order_name: order_name
|
||||
speed: speed
|
||||
target_weigh: target_weigh
|
||||
temperature: temperature
|
||||
volume: volume
|
||||
goal_default:
|
||||
delay_time: '600'
|
||||
hold_m_name: ''
|
||||
liquid_material_name: NMP
|
||||
material_name: ''
|
||||
order_name: ''
|
||||
speed: '400'
|
||||
target_weigh: ''
|
||||
temperature: '20'
|
||||
volume: ''
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 创建二胺溶液配制任务
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
delay_time:
|
||||
default: '600'
|
||||
description: 延迟时间(s)
|
||||
type: string
|
||||
hold_m_name:
|
||||
description: 库位名称(如ODA-1)
|
||||
type: string
|
||||
liquid_material_name:
|
||||
default: NMP
|
||||
description: 液体物料名称
|
||||
type: string
|
||||
material_name:
|
||||
description: 固体物料名称
|
||||
type: string
|
||||
order_name:
|
||||
description: 任务名称
|
||||
type: string
|
||||
speed:
|
||||
default: '400'
|
||||
description: 搅拌速度(rpm)
|
||||
type: string
|
||||
target_weigh:
|
||||
description: 固体目标重量(g)
|
||||
type: string
|
||||
temperature:
|
||||
default: '20'
|
||||
description: 温度(°C)
|
||||
type: string
|
||||
volume:
|
||||
description: 液体体积(mL)
|
||||
type: string
|
||||
required:
|
||||
- material_name
|
||||
- target_weigh
|
||||
- volume
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: create_diamine_solution_task参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
create_resource:
|
||||
feedback: {}
|
||||
goal:
|
||||
resource_config: resource_config
|
||||
resource_type: resource_type
|
||||
goal_default:
|
||||
resource_config: {}
|
||||
resource_type: ''
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 创建资源操作
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
resource_config:
|
||||
description: 资源配置
|
||||
type: object
|
||||
resource_type:
|
||||
description: 资源类型
|
||||
type: string
|
||||
required:
|
||||
- resource_type
|
||||
- resource_config
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: create_resource参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
dispensing_material_inbound:
|
||||
feedback: {}
|
||||
goal:
|
||||
location: location
|
||||
material_id: material_id
|
||||
goal_default:
|
||||
location: ''
|
||||
material_id: ''
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 配液站物料入库操作
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
location:
|
||||
description: 存储位置
|
||||
type: string
|
||||
material_id:
|
||||
description: 物料ID
|
||||
type: string
|
||||
required:
|
||||
- material_id
|
||||
- location
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: dispensing_material_inbound参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
dispensing_material_outbound:
|
||||
feedback: {}
|
||||
goal:
|
||||
material_id: material_id
|
||||
quantity: quantity
|
||||
goal_default:
|
||||
material_id: ''
|
||||
quantity: 0.0
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 配液站物料出库操作
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
material_id:
|
||||
description: 物料ID
|
||||
type: string
|
||||
quantity:
|
||||
description: 出库数量
|
||||
type: number
|
||||
required:
|
||||
- material_id
|
||||
- quantity
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: dispensing_material_outbound参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
sample_waste_removal:
|
||||
feedback: {}
|
||||
goal:
|
||||
sample_id: sample_id
|
||||
waste_type: waste_type
|
||||
goal_default:
|
||||
sample_id: ''
|
||||
waste_type: general
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 样品废料移除操作
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
sample_id:
|
||||
description: 样品ID
|
||||
type: string
|
||||
waste_type:
|
||||
description: 废料类型
|
||||
enum:
|
||||
- general
|
||||
- hazardous
|
||||
- organic
|
||||
- inorganic
|
||||
type: string
|
||||
required:
|
||||
- sample_id
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: sample_waste_removal参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
module: unilabos.devices.workstation.bioyond_studio.station:BioyondWorkstation
|
||||
protocol_type: []
|
||||
status_types:
|
||||
bioyond_status: dict
|
||||
enable_dispensing_station: bool
|
||||
enable_reaction_station: bool
|
||||
station_type: str
|
||||
type: python
|
||||
config_info: []
|
||||
description: Bioyond配液站 - 专门用于物料配制和管理的工作站
|
||||
handles: []
|
||||
icon: 配液站.webp
|
||||
init_param_schema:
|
||||
config:
|
||||
properties:
|
||||
bioyond_config:
|
||||
description: Bioyond API配置
|
||||
properties:
|
||||
api_host:
|
||||
description: Bioyond API主机地址
|
||||
type: string
|
||||
api_key:
|
||||
description: Bioyond API密钥
|
||||
type: string
|
||||
material_type_mappings:
|
||||
description: 物料类型映射配置
|
||||
type: object
|
||||
workflow_mappings:
|
||||
description: 工作流映射配置
|
||||
type: object
|
||||
type: object
|
||||
deck:
|
||||
description: Deck配置
|
||||
type: object
|
||||
station_config:
|
||||
description: 配液站配置
|
||||
properties:
|
||||
description:
|
||||
description: 配液站描述
|
||||
type: string
|
||||
enable_dispensing_station:
|
||||
default: true
|
||||
description: 启用配液站功能
|
||||
type: boolean
|
||||
enable_reaction_station:
|
||||
default: false
|
||||
description: 禁用反应站功能
|
||||
type: boolean
|
||||
station_name:
|
||||
description: 配液站名称
|
||||
type: string
|
||||
station_type:
|
||||
default: dispensing_station
|
||||
description: 站点类型 - 配液站
|
||||
enum:
|
||||
- dispensing_station
|
||||
type: string
|
||||
type: object
|
||||
required: []
|
||||
type: object
|
||||
data:
|
||||
properties: {}
|
||||
required: []
|
||||
type: object
|
||||
version: 1.0.0
|
||||
384
unilabos/registry/devices/reaction_station_bioyond.yaml
Normal file
384
unilabos/registry/devices/reaction_station_bioyond.yaml
Normal file
@@ -0,0 +1,384 @@
|
||||
reaction_station.bioyond:
|
||||
category:
|
||||
- work_station
|
||||
- reaction_station_bioyond
|
||||
class:
|
||||
action_value_mappings:
|
||||
bioyond_sync:
|
||||
feedback: {}
|
||||
goal:
|
||||
force_sync: force_sync
|
||||
sync_type: sync_type
|
||||
goal_default:
|
||||
force_sync: false
|
||||
sync_type: full
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 从Bioyond系统同步物料
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
force_sync:
|
||||
description: 是否强制同步
|
||||
type: boolean
|
||||
sync_type:
|
||||
description: 同步类型
|
||||
enum:
|
||||
- full
|
||||
- incremental
|
||||
type: string
|
||||
required:
|
||||
- sync_type
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: bioyond_sync参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
bioyond_update:
|
||||
feedback: {}
|
||||
goal:
|
||||
material_ids: material_ids
|
||||
sync_all: sync_all
|
||||
goal_default:
|
||||
material_ids: []
|
||||
sync_all: true
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 将本地物料变更同步到Bioyond
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
material_ids:
|
||||
description: 要同步的物料ID列表
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
sync_all:
|
||||
description: 是否同步所有物料
|
||||
type: boolean
|
||||
required:
|
||||
- sync_all
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: bioyond_update参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
reaction_station_drip_back:
|
||||
feedback: {}
|
||||
goal:
|
||||
assign_material_name: assign_material_name
|
||||
time: time
|
||||
torque_variation: torque_variation
|
||||
volume: volume
|
||||
goal_default:
|
||||
assign_material_name: ''
|
||||
time: ''
|
||||
torque_variation: ''
|
||||
volume: ''
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 反应站滴回操作
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
assign_material_name:
|
||||
description: 溶剂名称
|
||||
type: string
|
||||
time:
|
||||
description: 观察时间(单位min)
|
||||
type: string
|
||||
torque_variation:
|
||||
description: 是否观察1否2是
|
||||
type: string
|
||||
volume:
|
||||
description: 投料体积
|
||||
type: string
|
||||
required:
|
||||
- volume
|
||||
- assign_material_name
|
||||
- time
|
||||
- torque_variation
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: reaction_station_drip_back参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
reaction_station_liquid_feed:
|
||||
feedback: {}
|
||||
goal:
|
||||
assign_material_name: assign_material_name
|
||||
time: time
|
||||
titration_type: titration_type
|
||||
torque_variation: torque_variation
|
||||
volume: volume
|
||||
goal_default:
|
||||
assign_material_name: ''
|
||||
time: ''
|
||||
titration_type: ''
|
||||
torque_variation: ''
|
||||
volume: ''
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 反应站液体进料操作
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
assign_material_name:
|
||||
description: 溶剂名称
|
||||
type: string
|
||||
time:
|
||||
description: 观察时间(单位min)
|
||||
type: string
|
||||
titration_type:
|
||||
description: 滴定类型1否2是
|
||||
type: string
|
||||
torque_variation:
|
||||
description: 是否观察1否2是
|
||||
type: string
|
||||
volume:
|
||||
description: 投料体积
|
||||
type: string
|
||||
required:
|
||||
- titration_type
|
||||
- volume
|
||||
- assign_material_name
|
||||
- time
|
||||
- torque_variation
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: reaction_station_liquid_feed参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
reaction_station_process_execute:
|
||||
feedback: {}
|
||||
goal:
|
||||
task_name: task_name
|
||||
workflow_name: workflow_name
|
||||
goal_default:
|
||||
task_name: ''
|
||||
workflow_name: ''
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 反应站流程执行
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
task_name:
|
||||
description: 任务名称
|
||||
type: string
|
||||
workflow_name:
|
||||
description: 工作流名称
|
||||
type: string
|
||||
required:
|
||||
- workflow_name
|
||||
- task_name
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: reaction_station_process_execute参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
reaction_station_reactor_taken_out:
|
||||
feedback: {}
|
||||
goal:
|
||||
order_id: order_id
|
||||
preintake_id: preintake_id
|
||||
goal_default:
|
||||
order_id: ''
|
||||
preintake_id: ''
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 反应站反应器取出操作 - 通过订单ID和预取样ID进行精确控制
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
order_id:
|
||||
description: 订单ID,用于标识要取出的订单
|
||||
type: string
|
||||
preintake_id:
|
||||
description: 预取样ID,用于标识具体的取样任务
|
||||
type: string
|
||||
required: []
|
||||
type: object
|
||||
result:
|
||||
properties:
|
||||
code:
|
||||
description: 操作结果代码(1表示成功,0表示失败)
|
||||
type: integer
|
||||
return_info:
|
||||
description: 操作结果详细信息
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- goal
|
||||
title: reaction_station_reactor_taken_out参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
reaction_station_solid_feed_vial:
|
||||
feedback: {}
|
||||
goal:
|
||||
assign_material_name: assign_material_name
|
||||
material_id: material_id
|
||||
time: time
|
||||
torque_variation: torque_variation
|
||||
goal_default:
|
||||
assign_material_name: ''
|
||||
material_id: ''
|
||||
time: ''
|
||||
torque_variation: ''
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 反应站固体进料操作
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
assign_material_name:
|
||||
description: 固体名称_粉末加样模块-投料
|
||||
type: string
|
||||
material_id:
|
||||
description: 固体投料类型_粉末加样模块-投料
|
||||
type: string
|
||||
time:
|
||||
description: 观察时间_反应模块-观察搅拌结果
|
||||
type: string
|
||||
torque_variation:
|
||||
description: 是否观察1否2是_反应模块-观察搅拌结果
|
||||
type: string
|
||||
required:
|
||||
- assign_material_name
|
||||
- material_id
|
||||
- time
|
||||
- torque_variation
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: reaction_station_solid_feed_vial参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
reaction_station_take_in:
|
||||
feedback: {}
|
||||
goal:
|
||||
assign_material_name: assign_material_name
|
||||
cutoff: cutoff
|
||||
temperature: temperature
|
||||
goal_default:
|
||||
assign_material_name: ''
|
||||
cutoff: ''
|
||||
temperature: ''
|
||||
handles: {}
|
||||
result: {}
|
||||
schema:
|
||||
description: 反应站取入操作
|
||||
properties:
|
||||
feedback: {}
|
||||
goal:
|
||||
properties:
|
||||
assign_material_name:
|
||||
description: 物料名称
|
||||
type: string
|
||||
cutoff:
|
||||
description: 截止参数
|
||||
type: string
|
||||
temperature:
|
||||
description: 温度
|
||||
type: string
|
||||
required:
|
||||
- cutoff
|
||||
- temperature
|
||||
- assign_material_name
|
||||
type: object
|
||||
result: {}
|
||||
required:
|
||||
- goal
|
||||
title: reaction_station_take_in参数
|
||||
type: object
|
||||
type: UniLabJsonCommand
|
||||
module: unilabos.devices.workstation.bioyond_studio.station:BioyondWorkstation
|
||||
protocol_type: []
|
||||
status_types:
|
||||
bioyond_status: dict
|
||||
enable_dispensing_station: bool
|
||||
enable_reaction_station: bool
|
||||
station_type: str
|
||||
type: python
|
||||
config_info: []
|
||||
description: Bioyond反应站 - 专门用于化学反应操作的工作站
|
||||
handles: []
|
||||
icon: 反应站.webp
|
||||
init_param_schema:
|
||||
config:
|
||||
properties:
|
||||
bioyond_config:
|
||||
description: Bioyond API配置
|
||||
properties:
|
||||
api_host:
|
||||
description: Bioyond API主机地址
|
||||
type: string
|
||||
api_key:
|
||||
description: Bioyond API密钥
|
||||
type: string
|
||||
material_type_mappings:
|
||||
description: 物料类型映射配置
|
||||
type: object
|
||||
workflow_mappings:
|
||||
description: 工作流映射配置
|
||||
type: object
|
||||
type: object
|
||||
deck:
|
||||
description: Deck配置
|
||||
type: object
|
||||
station_config:
|
||||
description: 反应站配置
|
||||
properties:
|
||||
description:
|
||||
description: 反应站描述
|
||||
type: string
|
||||
enable_dispensing_station:
|
||||
default: false
|
||||
description: 禁用配液站功能
|
||||
type: boolean
|
||||
enable_reaction_station:
|
||||
default: true
|
||||
description: 启用反应站功能
|
||||
type: boolean
|
||||
station_name:
|
||||
description: 反应站名称
|
||||
type: string
|
||||
station_type:
|
||||
default: reaction_station
|
||||
description: 站点类型 - 反应站
|
||||
enum:
|
||||
- reaction_station
|
||||
type: string
|
||||
type: object
|
||||
required: []
|
||||
type: object
|
||||
data:
|
||||
properties: {}
|
||||
required: []
|
||||
type: object
|
||||
version: 1.0.0
|
||||
@@ -6,8 +6,8 @@ from typing import List, Tuple, Any, Dict, Literal, Optional, cast, TYPE_CHECKIN
|
||||
from unilabos.utils.log import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# from unilabos.devices.workstation.workstation_base import WorkstationBase
|
||||
from pylabrobot.resources import Resource as PLRResource, corning_6_wellplate_16point8ml_flat
|
||||
from unilabos.devices.workstation.workstation_base import WorkstationBase
|
||||
from pylabrobot.resources import Resource as PLRResource
|
||||
|
||||
|
||||
class ResourceDictPositionSize(BaseModel):
|
||||
@@ -372,49 +372,79 @@ class ResourceTreeSet(object):
|
||||
- PLR 资源实例列表
|
||||
- 每个资源对应的 name_to_uuid 映射字典列表
|
||||
"""
|
||||
from unilabos.resources.graphio import resource_ulab_to_plr
|
||||
from pylabrobot.resources import Resource as PLRResource
|
||||
from pylabrobot.utils.object_parsing import find_subclass
|
||||
import inspect
|
||||
|
||||
# 类型映射
|
||||
TYPE_MAP = {"plate": "plate", "well": "well", "container": "tip_spot", "deck": "deck", "tip_rack": "tip_rack"}
|
||||
|
||||
def collect_node_data(node: ResourceDictInstance, name_to_uuid: dict, all_states: dict):
|
||||
"""一次遍历收集 name_to_uuid 和 all_states"""
|
||||
name_to_uuid[node.res_content.name] = node.res_content.uuid
|
||||
all_states[node.res_content.name] = node.res_content.data
|
||||
for child in node.children:
|
||||
collect_node_data(child, name_to_uuid, all_states)
|
||||
|
||||
def node_to_plr_dict(node: ResourceDictInstance, has_model: bool):
|
||||
"""转换节点为 PLR 字典格式"""
|
||||
res = node.res_content
|
||||
plr_type = TYPE_MAP.get(res.type, "tip_spot")
|
||||
if res.type not in TYPE_MAP:
|
||||
logger.warning(f"未知类型 {res.type},使用默认类型 tip_spot")
|
||||
|
||||
d = {
|
||||
"name": res.name,
|
||||
"type": plr_type,
|
||||
"size_x": res.config.get("size_x", 0),
|
||||
"size_y": res.config.get("size_y", 0),
|
||||
"size_z": res.config.get("size_z", 0),
|
||||
"location": {
|
||||
"x": res.position.position.x,
|
||||
"y": res.position.position.y,
|
||||
"z": res.position.position.z,
|
||||
"type": "Coordinate",
|
||||
},
|
||||
"rotation": {"x": 0, "y": 0, "z": 0, "type": "Rotation"},
|
||||
"category": plr_type,
|
||||
"children": [node_to_plr_dict(child, has_model) for child in node.children],
|
||||
"parent_name": res.parent_name,
|
||||
**res.config,
|
||||
}
|
||||
if has_model:
|
||||
d["model"] = res.config.get("model", None)
|
||||
return d
|
||||
|
||||
plr_resources = []
|
||||
name_to_uuid_maps = []
|
||||
|
||||
def build_name_to_uuid_map(node: ResourceDictInstance, result: Dict[str, str]):
|
||||
"""递归构建 name 到 uuid 的映射"""
|
||||
result[node.res_content.name] = node.res_content.uuid
|
||||
for child in node.children:
|
||||
build_name_to_uuid_map(child, result)
|
||||
tracker = DeviceNodeResourceTracker()
|
||||
|
||||
for tree in self.trees:
|
||||
# 构建 name_to_uuid 映射
|
||||
name_to_uuid = {}
|
||||
build_name_to_uuid_map(tree.root_node, name_to_uuid)
|
||||
name_to_uuid: Dict[str, str] = {}
|
||||
all_states: Dict[str, Any] = {}
|
||||
collect_node_data(tree.root_node, name_to_uuid, all_states)
|
||||
|
||||
# 使用 get_nested_dict 获取字典表示
|
||||
resource_dict = tree.root_node.get_nested_dict()
|
||||
|
||||
# 判断是否包含 model(Deck 下没有 model)
|
||||
plr_model = tree.root_node.res_content.type != "deck"
|
||||
has_model = tree.root_node.res_content.type != "deck"
|
||||
plr_dict = node_to_plr_dict(tree.root_node, has_model)
|
||||
|
||||
try:
|
||||
# 使用 resource_ulab_to_plr 创建 PLR 资源实例
|
||||
plr_resource = resource_ulab_to_plr(resource_dict, plr_model=plr_model)
|
||||
sub_cls = find_subclass(plr_dict["type"], PLRResource)
|
||||
if sub_cls is None:
|
||||
raise ValueError(f"无法找到类型 {plr_dict['type']} 对应的 PLR 资源类")
|
||||
|
||||
# 设置 unilabos_uuid 属性到资源及其所有子节点
|
||||
def set_uuid_recursive(plr_res: "PLRResource", node: ResourceDictInstance):
|
||||
"""递归设置 PLR 资源的 unilabos_uuid 属性"""
|
||||
setattr(plr_res, "unilabos_uuid", node.res_content.uuid)
|
||||
# 匹配子节点(通过 name)
|
||||
for plr_child in plr_res.children:
|
||||
matching_node = next(
|
||||
(child for child in node.children if child.res_content.name == plr_child.name),
|
||||
None,
|
||||
)
|
||||
if matching_node:
|
||||
set_uuid_recursive(plr_child, matching_node)
|
||||
spec = inspect.signature(sub_cls)
|
||||
if "category" not in spec.parameters:
|
||||
plr_dict.pop("category", None)
|
||||
|
||||
set_uuid_recursive(plr_resource, tree.root_node)
|
||||
plr_resource = sub_cls.deserialize(plr_dict, allow_marshal=True)
|
||||
plr_resource.load_all_state(all_states)
|
||||
|
||||
# 使用 DeviceNodeResourceTracker 设置 UUID
|
||||
tracker.loop_set_uuid(plr_resource, name_to_uuid)
|
||||
|
||||
plr_resources.append(plr_resource)
|
||||
name_to_uuid_maps.append(name_to_uuid)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"转换 PLR 资源失败: {e}")
|
||||
import traceback
|
||||
@@ -685,9 +715,7 @@ class DeviceNodeResourceTracker(object):
|
||||
res_list = []
|
||||
for r in self.resources:
|
||||
if isinstance(query_resource, dict):
|
||||
res_list.extend(
|
||||
self.loop_find_resource(r, object, identifier_key, query_resource[identifier_key])
|
||||
)
|
||||
res_list.extend(self.loop_find_resource(r, object, identifier_key, query_resource[identifier_key]))
|
||||
else:
|
||||
res_list.extend(
|
||||
self.loop_find_resource(
|
||||
@@ -735,134 +763,84 @@ class DeviceNodeResourceTracker(object):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import os
|
||||
from pylabrobot.resources import corning_6_wellplate_16point8ml_flat
|
||||
|
||||
a = corning_6_wellplate_16point8ml_flat("a").serialize()
|
||||
# 尝试导入 pylabrobot,如果失败则尝试从本地 pylabrobot_repo 导入
|
||||
try:
|
||||
from pylabrobot.resources import Resource, Coordinate
|
||||
except ImportError:
|
||||
# 尝试添加本地 pylabrobot_repo 路径
|
||||
# __file__ is unilabos/ros/nodes/resource_tracker.py
|
||||
# We need to go up 4 levels to get to project root
|
||||
current_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
pylabrobot_path = os.path.join(current_dir, "pylabrobot_repo")
|
||||
if os.path.exists(pylabrobot_path):
|
||||
sys.path.insert(0, pylabrobot_path)
|
||||
try:
|
||||
from pylabrobot.resources import Resource, Coordinate
|
||||
except ImportError:
|
||||
print("pylabrobot 未安装,且无法从本地 pylabrobot_repo 导入")
|
||||
print("如需运行测试,请先安装: pip install pylabrobot")
|
||||
exit(0)
|
||||
else:
|
||||
print("pylabrobot 未安装,跳过测试")
|
||||
print("如需运行测试,请先安装: pip install pylabrobot")
|
||||
exit(0)
|
||||
# 测试 from_plr_resources 和 to_plr_resources 的往返转换
|
||||
print("=" * 60)
|
||||
print("测试 PLR 资源转换往返")
|
||||
print("=" * 60)
|
||||
|
||||
# 创建一个简单的测试资源
|
||||
def create_test_resource(name: str):
|
||||
"""创建一个简单的测试用资源"""
|
||||
# 创建父资源
|
||||
parent = Resource(name=name, size_x=100.0, size_y=100.0, size_z=50.0, category="container")
|
||||
# 1. 创建一个 PLR 资源并设置 UUID
|
||||
original_plate = corning_6_wellplate_16point8ml_flat("test_plate")
|
||||
|
||||
# 添加一些子资源
|
||||
for i in range(3):
|
||||
child = Resource(name=f"{name}_child_{i}", size_x=20.0, size_y=20.0, size_z=10.0, category="container")
|
||||
child.location = Coordinate(x=i * 30, y=0, z=0)
|
||||
parent.assign_child_resource(child, location=child.location)
|
||||
# 使用 DeviceNodeResourceTracker 设置 UUID
|
||||
tracker = DeviceNodeResourceTracker()
|
||||
name_to_uuid = {}
|
||||
|
||||
return parent
|
||||
# 递归生成 name_to_uuid 映射
|
||||
def build_uuid_map(resource):
|
||||
name_to_uuid[resource.name] = str(uuid.uuid4())
|
||||
for child in resource.children:
|
||||
build_uuid_map(child)
|
||||
|
||||
print("=" * 80)
|
||||
print("测试 1: 基本序列化和反序列化")
|
||||
print("=" * 80)
|
||||
build_uuid_map(original_plate)
|
||||
|
||||
# 创建原始 PLR 资源
|
||||
original_resource = create_test_resource("test_resource")
|
||||
print(f"\n1. 创建原始 PLR 资源: {original_resource.name}")
|
||||
print(f" 子节点数量: {len(original_resource.children)}")
|
||||
# 使用 tracker 的 loop_set_uuid 方法设置 UUID
|
||||
tracker.loop_set_uuid(original_plate, name_to_uuid)
|
||||
|
||||
# 手动设置 unilabos_uuid(模拟实际使用场景)
|
||||
def set_test_uuid(res: "PLRResource", prefix="uuid"):
|
||||
"""递归设置测试用的 uuid"""
|
||||
import uuid as uuid_module
|
||||
print(f"\n1. 原始 PLR 资源: {original_plate.name}")
|
||||
print(f" - UUID: {getattr(original_plate, 'unilabos_uuid', 'N/A')}")
|
||||
print(f" - 子节点数量: {len(original_plate.children)}")
|
||||
if original_plate.children:
|
||||
print(f" - 第一个子节点: {original_plate.children[0].name}")
|
||||
print(f" - 第一个子节点 UUID: {getattr(original_plate.children[0], 'unilabos_uuid', 'N/A')}")
|
||||
|
||||
setattr(res, "unilabos_uuid", f"{prefix}-{uuid_module.uuid4()}")
|
||||
for i, child in enumerate(res.children):
|
||||
set_test_uuid(child, f"{prefix}-{i}")
|
||||
# 2. 将 PLR 资源转换为 ResourceTreeSet
|
||||
resource_tree_set = ResourceTreeSet.from_plr_resources([original_plate])
|
||||
print(f"\n2. 转换为 ResourceTreeSet:")
|
||||
print(f" - 树的数量: {len(resource_tree_set.trees)}")
|
||||
print(f" - 根节点: {resource_tree_set.root_nodes[0].res_content.name}")
|
||||
print(f" - 所有节点数量: {len(resource_tree_set.all_nodes)}")
|
||||
|
||||
set_test_uuid(original_resource, "root")
|
||||
print(f" 根节点 UUID: {getattr(original_resource, 'unilabos_uuid', 'None')}")
|
||||
|
||||
# 转换为 ResourceTreeSet (from_plr_resources)
|
||||
print("\n2. 使用 from_plr_resources 转换为 ResourceTreeSet")
|
||||
resource_tree_set = ResourceTreeSet.from_plr_resources([original_resource])
|
||||
print(f" 树的数量: {len(resource_tree_set.trees)}")
|
||||
print(f" 根节点名称: {resource_tree_set.root_nodes[0].res_content.name}")
|
||||
print(f" 根节点 UUID: {resource_tree_set.root_nodes[0].res_content.uuid}")
|
||||
print(f" 总节点数: {len(resource_tree_set.all_nodes)}")
|
||||
|
||||
# 转换回 PLR 资源 (to_plr_resources)
|
||||
print("\n3. 使用 to_plr_resources 转换回 PLR 资源")
|
||||
try:
|
||||
# 3. 将 ResourceTreeSet 转换回 PLR 资源
|
||||
plr_resources, name_to_uuid_maps = resource_tree_set.to_plr_resources()
|
||||
except ModuleNotFoundError as e:
|
||||
print(f" ❌ 缺少依赖模块: {e}")
|
||||
print(" 提示: to_plr_resources 方法实现完成,但需要安装额外的依赖(如 networkx)")
|
||||
print("\n测试部分完成!from_plr_resources 已验证正常工作。")
|
||||
exit(0)
|
||||
print(f" PLR 资源数量: {len(plr_resources)}")
|
||||
print(f" name_to_uuid 映射数量: {len(name_to_uuid_maps)}")
|
||||
converted_plate = plr_resources[0]
|
||||
print(f"\n3. 转换回 PLR 资源: {converted_plate.name}")
|
||||
print(f" - 子节点数量: {len(converted_plate.children)}")
|
||||
if converted_plate.children:
|
||||
print(f" - 第一个子节点: {converted_plate.children[0].name}")
|
||||
|
||||
restored_resource = plr_resources[0]
|
||||
# 4. 验证 UUID 映射
|
||||
name_to_uuid = name_to_uuid_maps[0]
|
||||
print(f"\n4. UUID 映射:")
|
||||
print(f" - 映射条目数: {len(name_to_uuid)}")
|
||||
print(f" - 示例映射: {list(name_to_uuid.items())[:3]}")
|
||||
|
||||
print(f" 恢复的资源名称: {restored_resource.name}")
|
||||
print(f" 恢复的资源子节点数: {len(restored_resource.children)}")
|
||||
print(f" 恢复的资源 UUID: {getattr(restored_resource, 'unilabos_uuid', 'None')}")
|
||||
print(f" name_to_uuid 映射条目数: {len(name_to_uuid)}")
|
||||
# 5. 验证 unilabos_uuid 属性
|
||||
print(f"\n5. 验证 unilabos_uuid 设置:")
|
||||
if hasattr(converted_plate, "unilabos_uuid"):
|
||||
print(f" - 根节点 UUID: {getattr(converted_plate, 'unilabos_uuid')}")
|
||||
if converted_plate.children and hasattr(converted_plate.children[0], "unilabos_uuid"):
|
||||
print(f" - 第一个子节点 UUID: {getattr(converted_plate.children[0], 'unilabos_uuid')}")
|
||||
else:
|
||||
print(" - 警告: unilabos_uuid 未设置")
|
||||
|
||||
# 验证 UUID 映射
|
||||
print("\n4. 验证 UUID 映射")
|
||||
original_uuid = getattr(original_resource, "unilabos_uuid", None)
|
||||
restored_uuid = getattr(restored_resource, "unilabos_uuid", None)
|
||||
print(f" 原始根节点 UUID: {original_uuid}")
|
||||
print(f" 恢复后根节点 UUID: {restored_uuid}")
|
||||
print(f" UUID 匹配: {original_uuid == restored_uuid}")
|
||||
# 6. 验证 UUID 保持不变
|
||||
print(f"\n6. 验证 UUID 在往返过程中保持不变:")
|
||||
original_uuid = getattr(original_plate, "unilabos_uuid")
|
||||
converted_uuid = getattr(converted_plate, "unilabos_uuid")
|
||||
print(f" - 原始 UUID: {original_uuid}")
|
||||
print(f" - 转换后 UUID: {converted_uuid}")
|
||||
print(f" - UUID 保持不变: {original_uuid == converted_uuid}")
|
||||
|
||||
# 验证 name_to_uuid 映射完整性
|
||||
def count_all_nodes(res: "PLRResource") -> int:
|
||||
"""递归统计节点总数"""
|
||||
return 1 + sum(count_all_nodes(child) for child in res.children)
|
||||
# 7. 再次往返转换,验证稳定性
|
||||
resource_tree_set_2 = ResourceTreeSet.from_plr_resources([converted_plate])
|
||||
plr_resources_2, name_to_uuid_maps_2 = resource_tree_set_2.to_plr_resources()
|
||||
print(f"\n7. 第二次往返转换:")
|
||||
print(f" - 资源名称: {plr_resources_2[0].name}")
|
||||
print(f" - 子节点数量: {len(plr_resources_2[0].children)}")
|
||||
print(f" - UUID 依然保持: {getattr(plr_resources_2[0], 'unilabos_uuid') == original_uuid}")
|
||||
|
||||
original_node_count = count_all_nodes(original_resource)
|
||||
restored_node_count = count_all_nodes(restored_resource)
|
||||
mapping_count = len(name_to_uuid)
|
||||
|
||||
print(f"\n 原始资源节点总数: {original_node_count}")
|
||||
print(f" 恢复资源节点总数: {restored_node_count}")
|
||||
print(f" 映射字典条目数: {mapping_count}")
|
||||
print(f" 节点数量匹配: {original_node_count == restored_node_count == mapping_count}")
|
||||
|
||||
# 验证子节点的 UUID
|
||||
print("\n5. 验证子节点 UUID (前3个)")
|
||||
for i, (original_child, restored_child) in enumerate(
|
||||
zip(original_resource.children[:3], restored_resource.children[:3])
|
||||
):
|
||||
orig_uuid = getattr(original_child, "unilabos_uuid", None)
|
||||
rest_uuid = getattr(restored_child, "unilabos_uuid", None)
|
||||
print(f" 子节点 {i}: {original_child.name}")
|
||||
print(f" 原始 UUID: {orig_uuid}")
|
||||
print(f" 恢复 UUID: {rest_uuid}")
|
||||
print(f" 匹配: {orig_uuid == rest_uuid}")
|
||||
|
||||
# 测试 name_to_uuid 映射的正确性
|
||||
print("\n6. 验证 name_to_uuid 映射内容 (前5个)")
|
||||
for i, (name, uuid_val) in enumerate(list(name_to_uuid.items())[:5]):
|
||||
print(f" {name} -> {uuid_val}")
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
print("测试完成!")
|
||||
print("=" * 80)
|
||||
print("\n" + "=" * 60)
|
||||
print("✅ 测试完成! 所有转换正常工作")
|
||||
print("=" * 60)
|
||||
|
||||
@@ -150,7 +150,7 @@ class PyLabRobotCreator(DeviceClassCreator[T]):
|
||||
target_type = import_manager.get_class(type_path)
|
||||
contain_model = not issubclass(target_type, Deck)
|
||||
resource, target_type = self._process_resource_mapping(resource, target_type)
|
||||
resource_instance: Resource = resource_ulab_to_plr(resource, contain_model)
|
||||
resource_instance: Resource = resource_ulab_to_plr(resource, contain_model) # 带state
|
||||
states[prefix_path] = resource_instance.serialize_all_state()
|
||||
# 使用 prefix_path 作为 key 存储资源状态
|
||||
if to_dict:
|
||||
@@ -159,7 +159,7 @@ class PyLabRobotCreator(DeviceClassCreator[T]):
|
||||
return serialized
|
||||
else:
|
||||
self.resource_tracker.add_resource(resource_instance)
|
||||
# 立即设置UUID
|
||||
# 立即设置UUID,state已经在resource_ulab_to_plr中处理过了
|
||||
if name_to_uuid:
|
||||
self.resource_tracker.loop_set_uuid(resource_instance, name_to_uuid)
|
||||
return resource_instance
|
||||
@@ -244,7 +244,7 @@ class PyLabRobotCreator(DeviceClassCreator[T]):
|
||||
v[kk] = vv
|
||||
self.device_instance.load_all_state(v)
|
||||
self.resource_tracker.add_resource(self.device_instance)
|
||||
self.post_create()
|
||||
self.post_create() # 对应DeviceClassCreator进行调用
|
||||
return self.device_instance # type: ignore
|
||||
except Exception as e:
|
||||
# 先静默继续,尝试另外一种创建方法
|
||||
@@ -265,7 +265,7 @@ class PyLabRobotCreator(DeviceClassCreator[T]):
|
||||
data[param_name]["_resource_type"] = self.device_cls.__module__ + ":" + arg_value
|
||||
logger.debug(f"自动补充 _resource_type: {data[param_name]['_resource_type']}")
|
||||
processed_data = self._process_resource_references(data, to_dict=False, name_to_uuid=name_to_uuid)
|
||||
self.device_instance = super(PyLabRobotCreator, self).create_instance(processed_data)
|
||||
self.device_instance = super(PyLabRobotCreator, self).create_instance(processed_data) # 补全变量后直接调用,调用的自身的attach_resource
|
||||
except Exception as e:
|
||||
logger.error(f"PyLabRobot创建实例失败: {e}")
|
||||
logger.error(f"PyLabRobot创建实例堆栈: {traceback.format_exc()}")
|
||||
|
||||
@@ -105,8 +105,12 @@ set(action_files
|
||||
"action/PostProcessTriggerPostPro.action"
|
||||
|
||||
"action/ReactionStationDripBack.action"
|
||||
"action/ReactionStationLiquidFeed.action"
|
||||
"action/ReactionStationLiquidFeedBeaker.action"
|
||||
"action/ReactionStationLiquidFeedSolvents.action"
|
||||
"action/ReactionStationLiquidFeedTitration.action"
|
||||
"action/ReactionStationLiquidFeedVialsNonTitration.action"
|
||||
"action/ReactionStationProExecu.action"
|
||||
"action/ReactionStationReactorTakenOut.action"
|
||||
"action/ReactionStationReaTackIn.action"
|
||||
"action/ReactionStationSolidFeedVial.action"
|
||||
)
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
# Goal - 滴回去
|
||||
# Goal - 滴回去操作参数
|
||||
string volume # 投料体积
|
||||
string assign_material_name # 溶剂名称
|
||||
string time # 观察时间(单位min)
|
||||
string torque_variation #是否观察1否2是
|
||||
string torque_variation # 是否观察1否2是
|
||||
---
|
||||
# Result - 操作结果
|
||||
bool success # 操作是否成功
|
||||
string return_info # 结果消息
|
||||
|
||||
int32 code # 操作结果代码(1表示成功,0表示失败)
|
||||
---
|
||||
# Feedback - 实时反馈
|
||||
string feedback # 操作过程中的反馈信息
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# Goal - 液体投料
|
||||
string titration_type # 滴定类型1否2是
|
||||
string volume # 投料体积
|
||||
string assign_material_name # 溶剂名称
|
||||
string time # 观察时间(单位min)
|
||||
string torque_variation #是否观察1否2是
|
||||
---
|
||||
# Result - 操作结果
|
||||
string return_info # 结果消息
|
||||
---
|
||||
# Feedback - 实时反馈
|
||||
15
unilabos_msgs/action/ReactionStationLiquidFeedBeaker.action
Normal file
15
unilabos_msgs/action/ReactionStationLiquidFeedBeaker.action
Normal file
@@ -0,0 +1,15 @@
|
||||
# Goal - 液体投料-烧杯操作参数
|
||||
string volume # 投料体积
|
||||
string assign_material_name # 溶剂名称
|
||||
string titration_type # 滴定类型1否2是
|
||||
string time # 观察时间(单位min)
|
||||
string torque_variation # 是否观察1否2是
|
||||
string temperature # 温度设置
|
||||
---
|
||||
# Result - 操作结果
|
||||
bool success # 操作是否成功
|
||||
string return_info # 结果消息
|
||||
int32 code # 操作结果代码(1表示成功,0表示失败)
|
||||
---
|
||||
# Feedback - 实时反馈
|
||||
string feedback # 操作过程中的反馈信息
|
||||
@@ -0,0 +1,15 @@
|
||||
# Goal - 液体投料-溶剂操作参数
|
||||
string volume # 投料体积
|
||||
string assign_material_name # 溶剂名称
|
||||
string titration_type # 滴定类型1否2是
|
||||
string time # 观察时间(单位min)
|
||||
string torque_variation # 是否观察1否2是
|
||||
string temperature # 温度设置
|
||||
---
|
||||
# Result - 操作结果
|
||||
bool success # 操作是否成功
|
||||
string return_info # 结果消息
|
||||
int32 code # 操作结果代码(1表示成功,0表示失败)
|
||||
---
|
||||
# Feedback - 实时反馈
|
||||
string feedback # 操作过程中的反馈信息
|
||||
@@ -0,0 +1,15 @@
|
||||
# Goal - 液体投料滴定操作参数
|
||||
string volume_formula # 投料体积公式
|
||||
string assign_material_name # 溶剂名称
|
||||
string titration_type # 滴定类型1否2是
|
||||
string time # 观察时间(单位min)
|
||||
string torque_variation # 是否观察1否2是
|
||||
string temperature # 温度设置
|
||||
---
|
||||
# Result - 操作结果
|
||||
bool success # 操作是否成功
|
||||
string return_info # 结果消息
|
||||
int32 code # 操作结果代码(1表示成功,0表示失败)
|
||||
---
|
||||
# Feedback - 实时反馈
|
||||
string feedback # 操作过程中的反馈信息
|
||||
@@ -0,0 +1,15 @@
|
||||
# Goal - 液体投料-小瓶非滴定操作参数
|
||||
string volume_formula # 投料体积公式
|
||||
string assign_material_name # 溶剂名称
|
||||
string titration_type # 滴定类型1否2是
|
||||
string time # 观察时间(单位min)
|
||||
string torque_variation # 是否观察1否2是
|
||||
string temperature # 温度设置
|
||||
---
|
||||
# Result - 操作结果
|
||||
bool success # 操作是否成功
|
||||
string return_info # 结果消息
|
||||
int32 code # 操作结果代码(1表示成功,0表示失败)
|
||||
---
|
||||
# Feedback - 实时反馈
|
||||
string feedback # 操作过程中的反馈信息
|
||||
@@ -1,8 +1,11 @@
|
||||
# Goal - 合并工作流+执行
|
||||
# Goal - 合并工作流+执行参数
|
||||
string workflow_name # 工作流名称
|
||||
string task_name # 任务名称
|
||||
---
|
||||
# Result - 操作结果
|
||||
bool success # 操作是否成功
|
||||
string return_info # 结果消息
|
||||
int32 code # 操作结果代码(1表示成功,0表示失败)
|
||||
---
|
||||
# Feedback - 实时反馈
|
||||
string feedback # 操作过程中的反馈信息
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# Goal - 通量-配置
|
||||
string cutoff # 黏度_通量-配置
|
||||
string temperature # 温度_通量-配置
|
||||
string assign_material_name # 分液类型_通量-配置
|
||||
# Goal - 反应器放入操作参数
|
||||
string cutoff # 黏度设置
|
||||
string temperature # 温度设置
|
||||
string assign_material_name # 分液类型
|
||||
---
|
||||
# Result - 操作结果
|
||||
bool success # 操作是否成功
|
||||
string return_info # 结果消息
|
||||
int32 code # 操作结果代码(1表示成功,0表示失败)
|
||||
---
|
||||
# Feedback - 实时反馈
|
||||
string feedback # 操作过程中的反馈信息
|
||||
|
||||
12
unilabos_msgs/action/ReactionStationReactorTakenOut.action
Normal file
12
unilabos_msgs/action/ReactionStationReactorTakenOut.action
Normal file
@@ -0,0 +1,12 @@
|
||||
# Goal - 反应器取出操作参数
|
||||
# 反应器取出操作不需要任何参数
|
||||
---
|
||||
# Result - 操作结果
|
||||
# 反应器取出操作的结果
|
||||
bool success # 要求必须包含success,以便回传执行结果
|
||||
string return_info # 要求必须包含return_info,以便回传执行结果
|
||||
int32 code # 操作结果代码(1表示成功,0表示失败)
|
||||
---
|
||||
# Feedback - 实时反馈
|
||||
# 反应器取出操作的反馈
|
||||
string feedback # 操作过程中的反馈信息
|
||||
@@ -1,10 +1,13 @@
|
||||
# Goal - 固体投料-小瓶
|
||||
string assign_material_name # 固体名称_粉末加样模块-投料
|
||||
string material_id # 固体投料类型_粉末加样模块-投料
|
||||
string time # 观察时间_反应模块-观察搅拌结果
|
||||
string torque_variation #是否观察1否2是_反应模块-观察搅拌结果
|
||||
# Goal - 固体投料-小瓶操作参数
|
||||
string assign_material_name # 固体名称
|
||||
string material_id # 固体投料类型
|
||||
string time # 观察时间(单位min)
|
||||
string torque_variation # 是否观察1否2是
|
||||
---
|
||||
# Result - 操作结果
|
||||
bool success # 操作是否成功
|
||||
string return_info # 结果消息
|
||||
int32 code # 操作结果代码(1表示成功,0表示失败)
|
||||
---
|
||||
# Feedback - 实时反馈
|
||||
string feedback # 操作过程中的反馈信息
|
||||
|
||||
Reference in New Issue
Block a user