diff --git a/fix_datatype.py b/fix_datatype.py new file mode 100644 index 0000000..67147d2 --- /dev/null +++ b/fix_datatype.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import re + +filepath = r'd:\UniLab\Uni-Lab-OS\unilabos\device_comms\modbus_plc\modbus.py' + +with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + +# Replace the DataType placeholder with actual enum +find_pattern = r'# DataType will be accessed via client instance.*?DataType = None # Placeholder.*?\n' +replacement = '''# Define DataType enum for pymodbus 2.5.3 compatibility +class DataType(Enum): + INT16 = "int16" + UINT16 = "uint16" + INT32 = "int32" + UINT32 = "uint32" + INT64 = "int64" + UINT64 = "uint64" + FLOAT32 = "float32" + FLOAT64 = "float64" + STRING = "string" + BOOL = "bool" + +''' + +new_content = re.sub(find_pattern, replacement, content, flags=re.DOTALL) + +with open(filepath, 'w', encoding='utf-8') as f: + f.write(new_content) + +print('File updated successfully!') diff --git a/unilabos/device_comms/modbus_plc/client.py b/unilabos/device_comms/modbus_plc/client.py index c239b9d..4b46746 100644 --- a/unilabos/device_comms/modbus_plc/client.py +++ b/unilabos/device_comms/modbus_plc/client.py @@ -4,8 +4,7 @@ import traceback from typing import Any, Union, List, Dict, Callable, Optional, Tuple from pydantic import BaseModel -from pymodbus.client import ModbusSerialClient, ModbusTcpClient -from pymodbus.framer import FramerType +from pymodbus.client.sync import ModbusSerialClient, ModbusTcpClient from typing import TypedDict from unilabos.device_comms.modbus_plc.modbus import DeviceType, HoldRegister, Coil, InputRegister, DiscreteInputs, DataType, WorderOrder @@ -403,7 +402,7 @@ class TCPClient(BaseClient): class RTUClient(BaseClient): def __init__(self, port: str, baudrate: int, timeout: int): super().__init__() - self._set_client(ModbusSerialClient(framer=FramerType.RTU, port=port, baudrate=baudrate, timeout=timeout)) + self._set_client(ModbusSerialClient(method='rtu', port=port, baudrate=baudrate, timeout=timeout)) self._connect() if __name__ == '__main__': diff --git a/unilabos/device_comms/modbus_plc/modbus.py b/unilabos/device_comms/modbus_plc/modbus.py index 028477e..7e384d7 100644 --- a/unilabos/device_comms/modbus_plc/modbus.py +++ b/unilabos/device_comms/modbus_plc/modbus.py @@ -1,12 +1,26 @@ # coding=utf-8 from enum import Enum from abc import ABC, abstractmethod +from typing import Tuple, Union, Optional, TYPE_CHECKING +from pymodbus.payload import BinaryPayloadDecoder, BinaryPayloadBuilder +from pymodbus.constants import Endian -from pymodbus.client import ModbusBaseSyncClient -from pymodbus.client.mixin import ModbusClientMixin -from typing import Tuple, Union, Optional +if TYPE_CHECKING: + from pymodbus.client.sync import ModbusSerialClient, ModbusTcpClient + +# Define DataType enum for pymodbus 2.5.3 compatibility +class DataType(Enum): + INT16 = "int16" + UINT16 = "uint16" + INT32 = "int32" + UINT32 = "uint32" + INT64 = "int64" + UINT64 = "uint64" + FLOAT32 = "float32" + FLOAT64 = "float64" + STRING = "string" + BOOL = "bool" -DataType = ModbusClientMixin.DATATYPE class WorderOrder(Enum): BIG = "big" @@ -19,8 +33,96 @@ class DeviceType(Enum): INPUT_REGISTER = 'input_register' +def _convert_from_registers(registers, data_type: DataType, word_order: str = 'big'): + """Convert registers to a value using BinaryPayloadDecoder. + + Args: + registers: List of register values + data_type: DataType enum specifying the target data type + word_order: 'big' or 'little' endian + + Returns: + Converted value + """ + # Determine byte and word order based on word_order parameter + if word_order == 'little': + byte_order = Endian.Little + word_order_enum = Endian.Little + else: + byte_order = Endian.Big + word_order_enum = Endian.Big + + decoder = BinaryPayloadDecoder.fromRegisters(registers, byteorder=byte_order, wordorder=word_order_enum) + + if data_type == DataType.INT16: + return decoder.decode_16bit_int() + elif data_type == DataType.UINT16: + return decoder.decode_16bit_uint() + elif data_type == DataType.INT32: + return decoder.decode_32bit_int() + elif data_type == DataType.UINT32: + return decoder.decode_32bit_uint() + elif data_type == DataType.INT64: + return decoder.decode_64bit_int() + elif data_type == DataType.UINT64: + return decoder.decode_64bit_uint() + elif data_type == DataType.FLOAT32: + return decoder.decode_32bit_float() + elif data_type == DataType.FLOAT64: + return decoder.decode_64bit_float() + elif data_type == DataType.STRING: + return decoder.decode_string(len(registers) * 2) + else: + raise ValueError(f"Unsupported data type: {data_type}") + + +def _convert_to_registers(value, data_type: DataType, word_order: str = 'little'): + """Convert a value to registers using BinaryPayloadBuilder. + + Args: + value: Value to convert + data_type: DataType enum specifying the source data type + word_order: 'big' or 'little' endian + + Returns: + List of register values + """ + # Determine byte and word order based on word_order parameter + if word_order == 'little': + byte_order = Endian.Little + word_order_enum = Endian.Little + else: + byte_order = Endian.Big + word_order_enum = Endian.Big + + builder = BinaryPayloadBuilder(byteorder=byte_order, wordorder=word_order_enum) + + if data_type == DataType.INT16: + builder.add_16bit_int(value) + elif data_type == DataType.UINT16: + builder.add_16bit_uint(value) + elif data_type == DataType.INT32: + builder.add_32bit_int(value) + elif data_type == DataType.UINT32: + builder.add_32bit_uint(value) + elif data_type == DataType.INT64: + builder.add_64bit_int(value) + elif data_type == DataType.UINT64: + builder.add_64bit_uint(value) + elif data_type == DataType.FLOAT32: + builder.add_32bit_float(value) + elif data_type == DataType.FLOAT64: + builder.add_64bit_float(value) + elif data_type == DataType.STRING: + builder.add_string(value) + else: + raise ValueError(f"Unsupported data type: {data_type}") + + return builder.to_registers() + + class Base(ABC): - def __init__(self, client: ModbusBaseSyncClient, name: str, address: int, typ: DeviceType, data_type: DataType): + def __init__(self, client, name: str, address: int, typ: DeviceType, data_type): self._address: int = address self._client = client self._name = name @@ -58,7 +160,11 @@ class Coil(Base): count = value, slave = slave) - return resp.bits, resp.isError() + # 检查是否读取出错 + if resp.isError(): + return [], True + + return resp.bits, False def write(self,value: Union[int, float, bool, str, list[bool], list[int], list[float]], data_type: Optional[DataType ]= None, word_order: WorderOrder = WorderOrder.LITTLE, slave = 1) -> bool: if isinstance(value, list): @@ -91,8 +197,18 @@ class DiscreteInputs(Base): count = value, slave = slave) + # 检查是否读取出错 + if resp.isError(): + # 根据数据类型返回默认值 + if data_type in [DataType.FLOAT32, DataType.FLOAT64]: + return 0.0, True + elif data_type == DataType.STRING: + return "", True + else: + return 0, True + # noinspection PyTypeChecker - return self._client.convert_from_registers(resp.registers, data_type, word_order=word_order.value), resp.isError() + return _convert_from_registers(resp.registers, data_type, word_order=word_order.value), False def write(self,value: Union[int, float, bool, str, list[bool], list[int], list[float]], data_type: Optional[DataType ]= None, word_order: WorderOrder = WorderOrder.LITTLE, slave = 1) -> bool: raise ValueError('discrete inputs only support read') @@ -112,8 +228,19 @@ class HoldRegister(Base): address = self.address, count = value, slave = slave) + + # 检查是否读取出错 + if resp.isError(): + # 根据数据类型返回默认值 + if data_type in [DataType.FLOAT32, DataType.FLOAT64]: + return 0.0, True + elif data_type == DataType.STRING: + return "", True + else: + return 0, True + # noinspection PyTypeChecker - return self._client.convert_from_registers(resp.registers, data_type, word_order=word_order.value), resp.isError() + return _convert_from_registers(resp.registers, data_type, word_order=word_order.value), False def write(self,value: Union[int, float, bool, str, list[bool], list[int], list[float]], data_type: Optional[DataType ]= None, word_order: WorderOrder = WorderOrder.LITTLE, slave = 1) -> bool: @@ -132,7 +259,7 @@ class HoldRegister(Base): return self._client.write_register(self.address, value, slave= slave).isError() else: # noinspection PyTypeChecker - encoder_resp = self._client.convert_to_registers(value, data_type=data_type, word_order=word_order.value) + encoder_resp = _convert_to_registers(value, data_type=data_type, word_order=word_order.value) return self._client.write_registers(self.address, encoder_resp, slave=slave).isError() @@ -153,8 +280,19 @@ class InputRegister(Base): address = self.address, count = value, slave = slave) + + # 检查是否读取出错 + if resp.isError(): + # 根据数据类型返回默认值 + if data_type in [DataType.FLOAT32, DataType.FLOAT64]: + return 0.0, True + elif data_type == DataType.STRING: + return "", True + else: + return 0, True + # noinspection PyTypeChecker - return self._client.convert_from_registers(resp.registers, data_type, word_order=word_order.value), resp.isError() + return _convert_from_registers(resp.registers, data_type, word_order=word_order.value), False def write(self,value: Union[int, float, bool, str, list[bool], list[int], list[float]], data_type: Optional[DataType ]= None, word_order: WorderOrder = WorderOrder.LITTLE, slave = 1) -> bool: raise ValueError('input register only support read') diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025092701.xlsx b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025092701.xlsx deleted file mode 100644 index 2a45f93..0000000 Binary files a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025092701.xlsx and /dev/null differ diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025122301.xlsx b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025122301.xlsx new file mode 100644 index 0000000..2c82bef Binary files /dev/null and b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025122301.xlsx differ diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025122302.xlsx b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025122302.xlsx new file mode 100644 index 0000000..3357fd7 Binary files /dev/null and b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025122302.xlsx differ diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/20251224.xlsx b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/20251224.xlsx new file mode 100644 index 0000000..311afa0 Binary files /dev/null and b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/20251224.xlsx differ diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/bioyond_cell_workstation-2.py b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/bioyond_cell_workstation-2.py new file mode 100644 index 0000000..6ba85a6 --- /dev/null +++ b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/bioyond_cell_workstation-2.py @@ -0,0 +1,1234 @@ +# -*- coding: utf-8 -*- +from cgi import print_arguments +from doctest import debug +from typing import Dict, Any, List, Optional +import requests +from pylabrobot.resources.resource import Resource as ResourcePLR +from pathlib import Path +import pandas as pd +import time +from datetime import datetime, timedelta +import re +import threading +import json +from copy import deepcopy +from urllib3 import response +from unilabos.devices.workstation.bioyond_studio.station import BioyondWorkstation, BioyondResourceSynchronizer +from unilabos.devices.workstation.bioyond_studio.config import ( + API_CONFIG, MATERIAL_TYPE_MAPPINGS, WAREHOUSE_MAPPING, SOLID_LIQUID_MAPPINGS +) +from unilabos.devices.workstation.workstation_http_service import WorkstationHTTPService +from unilabos.resources.bioyond.decks import BIOYOND_YB_Deck +from unilabos.utils.log import logger +from unilabos.registry.registry import lab_registry + +def _iso_local_now_ms() -> str: + # 文档要求:到毫秒 + Z,例如 2025-08-15T05:43:22.814Z + dt = datetime.now() + # print(dt) + return dt.strftime("%Y-%m-%dT%H:%M:%S.") + f"{int(dt.microsecond/1000):03d}Z" + + +class BioyondCellWorkstation(BioyondWorkstation): + """ + 集成 Bioyond LIMS 的工作站示例, + 覆盖:入库(2.17/2.18) → 新建实验(2.14) → 启动调度(2.7) → + 运行中推送:物料变更(2.24)、步骤完成(2.21)、订单完成(2.23) → + 查询实验(2.5/2.6) → 3-2-1 转运(2.32) → 样品/废料取出(2.28) + """ + + def __init__(self, config: dict = None, deck=None, protocol_type=None, **kwargs): + + # 使用统一配置,支持自定义覆盖, 从 config.py 加载完整配置 + self.bioyond_config ={ + **API_CONFIG, + "material_type_mappings": MATERIAL_TYPE_MAPPINGS, + "warehouse_mapping": WAREHOUSE_MAPPING, + "debug_mode": False + } + + # "material_type_mappings": MATERIAL_TYPE_MAPPINGS + # "warehouse_mapping": WAREHOUSE_MAPPING + if deck is None and config: + deck = config.get('deck') + # print(self.bioyond_config) + self.debug_mode = self.bioyond_config["debug_mode"] + self.http_service_started = self.debug_mode + self._device_id = "bioyond_cell_workstation" # 默认值,后续会从_ros_node获取 + super().__init__(bioyond_config=config, deck=deck) + self.update_push_ip() #直接修改奔耀端的报送ip地址 + logger.info("已更新奔耀端推送 IP 地址") + + # 启动 HTTP 服务线程 + t = threading.Thread(target=self._start_http_service, daemon=True, name="unilab_http") + t.start() + logger.info("HTTP 服务线程已启动") + # 等到任务报送成功 + self.order_finish_event = threading.Event() + self.last_order_status = None + self.last_order_code = None + logger.info(f"Bioyond工作站初始化完成 (debug_mode={self.debug_mode})") + + @property + def device_id(self): + """获取设备ID,优先从_ros_node获取,否则返回默认值""" + if hasattr(self, '_ros_node') and self._ros_node is not None: + return getattr(self._ros_node, 'device_id', self._device_id) + return self._device_id + + def _start_http_service(self): + """启动 HTTP 服务""" + host = self.bioyond_config.get("HTTP_host", "") + port = self.bioyond_config.get("HTTP_port", None) + try: + self.service = WorkstationHTTPService(self, host=host, port=port) + self.service.start() + self.http_service_started = True + logger.info(f"WorkstationHTTPService 成功启动: {host}:{port}") + while True: + time.sleep(1) #一直挂着,直到进程退出 + except Exception as e: + self.http_service_started = False + logger.error(f"启动 WorkstationHTTPService 失败: {e}", exc_info=True) + + + # http报送服务,返回数据部分 + def process_step_finish_report(self, report_request): + stepId = report_request.data.get("stepId") + logger.info(f"步骤完成: stepId: {stepId}, stepName:{report_request.data.get('stepName')}") + return report_request.data.get('executionStatus') + + def process_sample_finish_report(self, report_request): + logger.info(f"通量完成: {report_request.data.get('sampleId')}") + return {"status": "received"} + + def process_order_finish_report(self, report_request, used_materials=None): + order_code = report_request.data.get("orderCode") + status = report_request.data.get("status") + logger.info(f"report_request: {report_request}") + logger.info(f"任务完成: {order_code}, status={status}") + + # 保存完整报文 + self.last_order_report = report_request.data + # 如果是当前等待的订单,触发事件 + if self.last_order_code == order_code: + self.order_finish_event.set() + + return {"status": "received"} + + def wait_for_order_finish(self, order_code: str, timeout: int = 36000) -> Dict[str, Any]: + """ + 等待指定 orderCode 的 /report/order_finish 报送。 + Args: + order_code: 任务编号 + timeout: 超时时间(秒) + Returns: + 完整的报送数据 + 状态判断结果 + """ + if not order_code: + logger.error("wait_for_order_finish() 被调用,但 order_code 为空!") + return {"status": "error", "message": "empty order_code"} + + self.last_order_code = order_code + self.last_order_report = None + self.order_finish_event.clear() + + logger.info(f"等待任务完成报送: orderCode={order_code} (timeout={timeout}s)") + + if not self.order_finish_event.wait(timeout=timeout): + logger.error(f"等待任务超时: orderCode={order_code}") + return {"status": "timeout", "orderCode": order_code} + + # 报送数据匹配验证 + report = self.last_order_report or {} + report_code = report.get("orderCode") + status = str(report.get("status", "")) + + if report_code != order_code: + logger.warning(f"收到的报送 orderCode 不匹配: {report_code} ≠ {order_code}") + return {"status": "mismatch", "report": report} + + if status == "30": + logger.info(f"任务成功完成 (orderCode={order_code})") + return {"status": "success", "report": report} + elif status == "-11": + logger.error(f"任务异常停止 (orderCode={order_code})") + return {"status": "abnormal_stop", "report": report} + elif status == "-12": + logger.warning(f"任务人工停止 (orderCode={order_code})") + return {"status": "manual_stop", "report": report} + else: + logger.warning(f"任务未知状态 ({status}) (orderCode={order_code})") + return {"status": f"unknown_{status}", "report": report} + + + # -------------------- 基础HTTP封装 -------------------- + def _url(self, path: str) -> str: + return f"{self.bioyond_config['api_host'].rstrip('/')}/{path.lstrip('/')}" + + def _post_lims(self, path: str, data: Optional[Any] = None) -> Dict[str, Any]: + """LIMS API:大多数接口用 {apiKey/requestTime,data} 包装""" + payload = { + "apiKey": self.bioyond_config["api_key"], + "requestTime": _iso_local_now_ms() + } + if data is not None: + payload["data"] = data + + if self.debug_mode: + # 模拟返回,不发真实请求 + logger.info(f"[DEBUG] POST {path} with payload={payload}") + + return {"debug": True, "url": self._url(path), "payload": payload, "status": "ok"} + + try: + logger.info(json.dumps(payload, ensure_ascii=False)) + response = requests.post( + self._url(path), + json=payload, + timeout=self.bioyond_config.get("timeout", 30), + headers={"Content-Type": "application/json"} + ) # 拼接网址+post bioyond接口 + response.raise_for_status() + return response.json() + except Exception as e: + logger.info(f"{self.bioyond_config['api_host'].rstrip('/')}/{path.lstrip('/')}") + logger.error(f"POST {path} 失败: {e}") + return {"error": str(e)} + + def _put_lims(self, path: str, data: Optional[Any] = None) -> Dict[str, Any]: + """LIMS API:PUT {apiKey/requestTime,data} 包装""" + payload = { + "apiKey": self.bioyond_config["api_key"], + "requestTime": _iso_local_now_ms() + } + if data is not None: + payload["data"] = data + + if self.debug_mode: + logger.info(f"[DEBUG] PUT {path} with payload={payload}") + return {"debug_mode": True, "url": self._url(path), "payload": payload, "status": "ok"} + + try: + response = requests.put( + self._url(path), + json=payload, + timeout=self.bioyond_config.get("timeout", 30), + headers={"Content-Type": "application/json"} + ) + response.raise_for_status() + return response.json() + except Exception as e: + logger.info(f"{self.bioyond_config['api_host'].rstrip('/')}/{path.lstrip('/')}") + logger.error(f"PUT {path} 失败: {e}") + return {"error": str(e)} + + # -------------------- 3.36 更新推送 IP 地址 -------------------- + def update_push_ip(self, ip: Optional[str] = None, port: Optional[int] = None) -> Dict[str, Any]: + """ + 3.36 更新推送 IP 地址接口(PUT) + URL: /api/lims/order/ip-config + 请求体:{ apiKey, requestTime, data: { ip, port } } + """ + target_ip = ip or self.bioyond_config.get("HTTP_host", "") + target_port = int(port or self.bioyond_config.get("HTTP_port", 0)) + data = {"ip": target_ip, "port": target_port} + + # 固定接口路径,不做其他路径兼容 + path = "/api/lims/order/ip-config" + return self._put_lims(path, data) + + # -------------------- 单点接口封装 -------------------- + # 2.17 入库物料(单个) + def storage_inbound(self, material_id: str, location_id: str) -> Dict[str, Any]: + return self._post_lims("/api/lims/storage/inbound", { + "materialId": material_id, + "locationId": location_id + }) + + # 2.18 批量入库(多个) + def storage_batch_inbound(self, items: List[Dict[str, str]]) -> Dict[str, Any]: + """ + items = [{"materialId": "...", "locationId": "..."}, ...] + """ + return self._post_lims("/api/lims/storage/batch-inbound", items) + + + def auto_feeding4to3( + self, + # ★ 修改点:默认模板路径 + xlsx_path: Optional[str] = "/Users/sml/work/Unilab/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx", + # ---------------- WH4 - 加样头面 (Z=1, 12个点位) ---------------- + WH4_x1_y1_z1_1_materialName: str = "", WH4_x1_y1_z1_1_quantity: float = 0.0, + WH4_x2_y1_z1_2_materialName: str = "", WH4_x2_y1_z1_2_quantity: float = 0.0, + WH4_x3_y1_z1_3_materialName: str = "", WH4_x3_y1_z1_3_quantity: float = 0.0, + WH4_x4_y1_z1_4_materialName: str = "", WH4_x4_y1_z1_4_quantity: float = 0.0, + WH4_x5_y1_z1_5_materialName: str = "", WH4_x5_y1_z1_5_quantity: float = 0.0, + WH4_x1_y2_z1_6_materialName: str = "", WH4_x1_y2_z1_6_quantity: float = 0.0, + WH4_x2_y2_z1_7_materialName: str = "", WH4_x2_y2_z1_7_quantity: float = 0.0, + WH4_x3_y2_z1_8_materialName: str = "", WH4_x3_y2_z1_8_quantity: float = 0.0, + WH4_x4_y2_z1_9_materialName: str = "", WH4_x4_y2_z1_9_quantity: float = 0.0, + WH4_x5_y2_z1_10_materialName: str = "", WH4_x5_y2_z1_10_quantity: float = 0.0, + WH4_x1_y3_z1_11_materialName: str = "", WH4_x1_y3_z1_11_quantity: float = 0.0, + WH4_x2_y3_z1_12_materialName: str = "", WH4_x2_y3_z1_12_quantity: float = 0.0, + + # ---------------- WH4 - 原液瓶面 (Z=2, 9个点位) ---------------- + WH4_x1_y1_z2_1_materialName: str = "", WH4_x1_y1_z2_1_quantity: float = 0.0, WH4_x1_y1_z2_1_materialType: str = "", WH4_x1_y1_z2_1_targetWH: str = "", + WH4_x2_y1_z2_2_materialName: str = "", WH4_x2_y1_z2_2_quantity: float = 0.0, WH4_x2_y1_z2_2_materialType: str = "", WH4_x2_y1_z2_2_targetWH: str = "", + WH4_x3_y1_z2_3_materialName: str = "", WH4_x3_y1_z2_3_quantity: float = 0.0, WH4_x3_y1_z2_3_materialType: str = "", WH4_x3_y1_z2_3_targetWH: str = "", + WH4_x1_y2_z2_4_materialName: str = "", WH4_x1_y2_z2_4_quantity: float = 0.0, WH4_x1_y2_z2_4_materialType: str = "", WH4_x1_y2_z2_4_targetWH: str = "", + WH4_x2_y2_z2_5_materialName: str = "", WH4_x2_y2_z2_5_quantity: float = 0.0, WH4_x2_y2_z2_5_materialType: str = "", WH4_x2_y2_z2_5_targetWH: str = "", + WH4_x3_y2_z2_6_materialName: str = "", WH4_x3_y2_z2_6_quantity: float = 0.0, WH4_x3_y2_z2_6_materialType: str = "", WH4_x3_y2_z2_6_targetWH: str = "", + WH4_x1_y3_z2_7_materialName: str = "", WH4_x1_y3_z2_7_quantity: float = 0.0, WH4_x1_y3_z2_7_materialType: str = "", WH4_x1_y3_z2_7_targetWH: str = "", + WH4_x2_y3_z2_8_materialName: str = "", WH4_x2_y3_z2_8_quantity: float = 0.0, WH4_x2_y3_z2_8_materialType: str = "", WH4_x2_y3_z2_8_targetWH: str = "", + WH4_x3_y3_z2_9_materialName: str = "", WH4_x3_y3_z2_9_quantity: float = 0.0, WH4_x3_y3_z2_9_materialType: str = "", WH4_x3_y3_z2_9_targetWH: str = "", + + # ---------------- WH3 - 人工堆栈 (Z=3, 15个点位) ---------------- + WH3_x1_y1_z3_1_materialType: str = "", WH3_x1_y1_z3_1_materialId: str = "", WH3_x1_y1_z3_1_quantity: float = 0, + WH3_x2_y1_z3_2_materialType: str = "", WH3_x2_y1_z3_2_materialId: str = "", WH3_x2_y1_z3_2_quantity: float = 0, + WH3_x3_y1_z3_3_materialType: str = "", WH3_x3_y1_z3_3_materialId: str = "", WH3_x3_y1_z3_3_quantity: float = 0, + WH3_x1_y2_z3_4_materialType: str = "", WH3_x1_y2_z3_4_materialId: str = "", WH3_x1_y2_z3_4_quantity: float = 0, + WH3_x2_y2_z3_5_materialType: str = "", WH3_x2_y2_z3_5_materialId: str = "", WH3_x2_y2_z3_5_quantity: float = 0, + WH3_x3_y2_z3_6_materialType: str = "", WH3_x3_y2_z3_6_materialId: str = "", WH3_x3_y2_z3_6_quantity: float = 0, + WH3_x1_y3_z3_7_materialType: str = "", WH3_x1_y3_z3_7_materialId: str = "", WH3_x1_y3_z3_7_quantity: float = 0, + WH3_x2_y3_z3_8_materialType: str = "", WH3_x2_y3_z3_8_materialId: str = "", WH3_x2_y3_z3_8_quantity: float = 0, + WH3_x3_y3_z3_9_materialType: str = "", WH3_x3_y3_z3_9_materialId: str = "", WH3_x3_y3_z3_9_quantity: float = 0, + WH3_x1_y4_z3_10_materialType: str = "", WH3_x1_y4_z3_10_materialId: str = "", WH3_x1_y4_z3_10_quantity: float = 0, + WH3_x2_y4_z3_11_materialType: str = "", WH3_x2_y4_z3_11_materialId: str = "", WH3_x2_y4_z3_11_quantity: float = 0, + WH3_x3_y4_z3_12_materialType: str = "", WH3_x3_y4_z3_12_materialId: str = "", WH3_x3_y4_z3_12_quantity: float = 0, + WH3_x1_y5_z3_13_materialType: str = "", WH3_x1_y5_z3_13_materialId: str = "", WH3_x1_y5_z3_13_quantity: float = 0, + WH3_x2_y5_z3_14_materialType: str = "", WH3_x2_y5_z3_14_materialId: str = "", WH3_x2_y5_z3_14_quantity: float = 0, + WH3_x3_y5_z3_15_materialType: str = "", WH3_x3_y5_z3_15_materialId: str = "", WH3_x3_y5_z3_15_quantity: float = 0, + ): + """ + 自动化上料(支持两种模式) + - Excel 路径存在 → 从 Excel 模板解析 + - Excel 路径不存在 → 使用手动参数 + """ + items: List[Dict[str, Any]] = [] + + # ---------- 模式 1: Excel 导入 ---------- + if xlsx_path: + path = Path(__file__).parent / Path(xlsx_path) + if path.exists(): # ★ 修改点:路径存在才加载 + try: + df = pd.read_excel(path, sheet_name=0, header=None, engine="openpyxl") + except Exception as e: + raise RuntimeError(f"读取 Excel 失败:{e}") + + # 四号手套箱加样头面 + for _, row in df.iloc[1:13, 2:7].iterrows(): + if pd.notna(row[5]): + items.append({ + "sourceWHName": "四号手套箱堆栈", + "posX": int(row[2]), "posY": int(row[3]), "posZ": int(row[4]), + "materialName": str(row[5]).strip(), + "quantity": float(row[6]) if pd.notna(row[6]) else 0.0, + }) + # 四号手套箱原液瓶面 + for _, row in df.iloc[14:23, 2:9].iterrows(): + if pd.notna(row[5]): + items.append({ + "sourceWHName": "四号手套箱堆栈", + "posX": int(row[2]), "posY": int(row[3]), "posZ": int(row[4]), + "materialName": str(row[5]).strip(), + "quantity": float(row[6]) if pd.notna(row[6]) else 0.0, + "materialType": str(row[7]).strip() if pd.notna(row[7]) else "", + "targetWH": str(row[8]).strip() if pd.notna(row[8]) else "", + }) + # 三号手套箱人工堆栈 + for _, row in df.iloc[25:40, 2:7].iterrows(): + if pd.notna(row[5]) or pd.notna(row[6]): + items.append({ + "sourceWHName": "三号手套箱人工堆栈", + "posX": int(row[2]), "posY": int(row[3]), "posZ": int(row[4]), + "materialType": str(row[5]).strip() if pd.notna(row[5]) else "", + "materialId": str(row[6]).strip() if pd.notna(row[6]) else "", + "quantity": 1 + }) + else: + logger.warning(f"未找到 Excel 文件 {xlsx_path},自动切换到手动参数模式。") + + # ---------- 模式 2: 手动填写 ---------- + if not items: + params = locals() + for name, value in params.items(): + if name.startswith("四号手套箱堆栈") and "materialName" in name and value: + idx = name.split("_") + items.append({ + "sourceWHName": "四号手套箱堆栈", + "posX": int(idx[1][1:]), "posY": int(idx[2][1:]), "posZ": int(idx[3][1:]), + "materialName": value, + "quantity": float(params.get(name.replace("materialName", "quantity"), 0.0)) + }) + elif name.startswith("四号手套箱堆栈") and "materialType" in name and (value or params.get(name.replace("materialType", "materialName"), "")): + idx = name.split("_") + items.append({ + "sourceWHName": "四号手套箱堆栈", + "posX": int(idx[1][1:]), "posY": int(idx[2][1:]), "posZ": int(idx[3][1:]), + "materialName": params.get(name.replace("materialType", "materialName"), ""), + "quantity": float(params.get(name.replace("materialType", "quantity"), 0.0)), + "materialType": value, + "targetWH": params.get(name.replace("materialType", "targetWH"), ""), + }) + elif name.startswith("三号手套箱人工堆栈") and "materialType" in name and (value or params.get(name.replace("materialType", "materialId"), "")): + idx = name.split("_") + items.append({ + "sourceWHName": "三号手套箱人工堆栈", + "posX": int(idx[1][1:]), "posY": int(idx[2][1:]), "posZ": int(idx[3][1:]), + "materialType": value, + "materialId": params.get(name.replace("materialType", "materialId"), ""), + "quantity": int(params.get(name.replace("materialType", "quantity"), 1)), + }) + + if not items: + logger.warning("没有有效的上料条目,已跳过提交。") + return {"code": 0, "message": "no valid items", "data": []} + logger.info(items) + response = self._post_lims("/api/lims/order/auto-feeding4to3", items) + + # 等待任务报送成功 + order_code = response.get("data", {}).get("orderCode") + if not order_code: + logger.error("上料任务未返回有效 orderCode!") + return response + # 等待完成报送 + result = self.wait_for_order_finish(order_code) + print("\n" + "="*60) + print("实验记录本结果auto_feeding4to3") + print("="*60) + print(json.dumps(result, indent=2, ensure_ascii=False)) + print("="*60 + "\n") + return result + + def auto_batch_outbound_from_xlsx(self, xlsx_path: str) -> Dict[str, Any]: + """ + 3.31 自动化下料(Excel -> JSON -> POST /api/lims/storage/auto-batch-out-bound) + """ + path = Path(xlsx_path) + if not path.exists(): + raise FileNotFoundError(f"未找到 Excel 文件:{path}") + + try: + df = pd.read_excel(path, sheet_name=0, engine="openpyxl") + except Exception as e: + raise RuntimeError(f"读取 Excel 失败:{e}") + + def pick(names: List[str]) -> Optional[str]: + for n in names: + if n in df.columns: + return n + return None + + c_loc = pick(["locationId", "库位ID", "库位Id", "库位id"]) + c_wh = pick(["warehouseId", "仓库ID", "仓库Id", "仓库id"]) + c_qty = pick(["数量", "quantity"]) + c_x = pick(["x", "X", "posX", "坐标X"]) + c_y = pick(["y", "Y", "posY", "坐标Y"]) + c_z = pick(["z", "Z", "posZ", "坐标Z"]) + + required = [c_loc, c_wh, c_qty, c_x, c_y, c_z] + if any(c is None for c in required): + raise KeyError("Excel 缺少必要列:locationId/warehouseId/数量/x/y/z(支持多别名,至少要能匹配到)。") + + def as_int(v, d=0): + try: + if pd.isna(v): return d + return int(v) + except Exception: + try: + return int(float(v)) + except Exception: + return d + + def as_float(v, d=0.0): + try: + if pd.isna(v): return d + return float(v) + except Exception: + return d + + def as_str(v, d=""): + if v is None or (isinstance(v, float) and pd.isna(v)): return d + s = str(v).strip() + return s if s else d + + items: List[Dict[str, Any]] = [] + for _, row in df.iterrows(): + items.append({ + "locationId": as_str(row[c_loc]), + "warehouseId": as_str(row[c_wh]), + "quantity": as_float(row[c_qty]), + "x": as_int(row[c_x]), + "y": as_int(row[c_y]), + "z": as_int(row[c_z]), + }) + + response = self._post_lims("/api/lims/storage/auto-batch-out-bound", items) + self.wait_for_response_orders(response, "auto_batch_outbound_from_xlsx") + return response + + # 2.14 新建实验 + def create_orders(self, xlsx_path: str) -> Dict[str, Any]: + """ + 从 Excel 解析并创建实验(2.14) + 约定: + - batchId = Excel 文件名(不含扩展名) + - 物料列:所有以 "(g)" 结尾(不再读取“总质量(g)”列) + - totalMass 自动计算为所有物料质量之和 + - createTime 缺失或为空时自动填充为当前日期(YYYY/M/D) + """ + default_path = Path("/Users/sml/work/Unilab/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025092701.xlsx") + path = Path(xlsx_path) if xlsx_path else default_path + print(f"[create_orders] 使用 Excel 路径: {path}") + if path != default_path: + print("[create_orders] 来源: 调用方传入自定义路径") + else: + print("[create_orders] 来源: 使用默认模板路径") + + if not path.exists(): + print(f"[create_orders] ⚠️ Excel 文件不存在: {path}") + raise FileNotFoundError(f"未找到 Excel 文件:{path}") + + try: + df = pd.read_excel(path, sheet_name=0, engine="openpyxl") + except Exception as e: + raise RuntimeError(f"读取 Excel 失败:{e}") + print(f"[create_orders] Excel 读取成功,行数: {len(df)}, 列: {list(df.columns)}") + + # 列名容错:返回可选列名,找不到则返回 None + def _pick(col_names: List[str]) -> Optional[str]: + for c in col_names: + if c in df.columns: + return c + return None + + col_order_name = _pick(["配方ID", "orderName", "订单编号"]) + col_create_time = _pick(["创建日期", "createTime"]) + col_bottle_type = _pick(["配液瓶类型", "bottleType"]) + col_mix_time = _pick(["混匀时间(s)", "mixTime"]) + col_load = _pick(["扣电组装分液体积", "loadSheddingInfo"]) + col_pouch = _pick(["软包组装分液体积", "pouchCellInfo"]) + col_cond = _pick(["电导测试分液体积", "conductivityInfo"]) + col_cond_cnt = _pick(["电导测试分液瓶数", "conductivityBottleCount"]) + print("[create_orders] 列匹配结果:", { + "order_name": col_order_name, + "create_time": col_create_time, + "bottle_type": col_bottle_type, + "mix_time": col_mix_time, + "load": col_load, + "pouch": col_pouch, + "conductivity": col_cond, + "conductivity_bottle_count": col_cond_cnt, + }) + + # 物料列:所有以 (g) 结尾 + material_cols = [c for c in df.columns if isinstance(c, str) and c.endswith("(g)")] + print(f"[create_orders] 识别到的物料列: {material_cols}") + if not material_cols: + raise KeyError("未发现任何以“(g)”结尾的物料列,请检查表头。") + + batch_id = path.stem + + def _to_ymd_slash(v) -> str: + # 统一为 "YYYY/M/D";为空或解析失败则用当前日期 + if v is None or (isinstance(v, float) and pd.isna(v)) or str(v).strip() == "": + ts = datetime.now() + else: + try: + ts = pd.to_datetime(v) + except Exception: + ts = datetime.now() + return f"{ts.year}/{ts.month}/{ts.day}" + + def _as_int(val, default=0) -> int: + try: + if pd.isna(val): + return default + return int(val) + except Exception: + return default + + def _as_float(val, default=0.0) -> float: + try: + if pd.isna(val): + return default + return float(val) + except Exception: + return default + + def _as_str(val, default="") -> str: + if val is None or (isinstance(val, float) and pd.isna(val)): + return default + s = str(val).strip() + return s if s else default + + orders: List[Dict[str, Any]] = [] + + for idx, row in df.iterrows(): + mats: List[Dict[str, Any]] = [] + total_mass = 0.0 + + for mcol in material_cols: + val = row.get(mcol, None) + if val is None or (isinstance(val, float) and pd.isna(val)): + continue + try: + mass = float(val) + except Exception: + continue + if mass > 0: + mats.append({"name": mcol.replace("(g)", ""), "mass": mass}) + total_mass += mass + else: + if mass < 0: + print(f"[create_orders] 第 {idx+1} 行物料 {mcol} 数值为负数: {mass}") + + order_data = { + "batchId": batch_id, + "orderName": _as_str(row[col_order_name], default=f"{batch_id}_order_{idx+1}") if col_order_name else f"{batch_id}_order_{idx+1}", + "createTime": _to_ymd_slash(row[col_create_time]) if col_create_time else _to_ymd_slash(None), + "bottleType": _as_str(row[col_bottle_type], default="配液小瓶") if col_bottle_type else "配液小瓶", + "mixTime": _as_int(row[col_mix_time]) if col_mix_time else 0, + "loadSheddingInfo": _as_float(row[col_load]) if col_load else 0.0, + "pouchCellInfo": _as_float(row[col_pouch]) if col_pouch else 0, + "conductivityInfo": _as_float(row[col_cond]) if col_cond else 0, + "conductivityBottleCount": _as_int(row[col_cond_cnt]) if col_cond_cnt else 0, + "materialInfos": mats, + "totalMass": round(total_mass, 4) # 自动汇总 + } + print(f"[create_orders] 第 {idx+1} 行解析结果: orderName={order_data['orderName']}, " + f"loadShedding={order_data['loadSheddingInfo']}, pouchCell={order_data['pouchCellInfo']}, " + f"conductivity={order_data['conductivityInfo']}, totalMass={order_data['totalMass']}, " + f"material_count={len(mats)}") + + if order_data["totalMass"] <= 0: + print(f"[create_orders] ⚠️ 第 {idx+1} 行总质量 <= 0,可能导致 LIMS 校验失败") + if not mats: + print(f"[create_orders] ⚠️ 第 {idx+1} 行未找到有效物料") + + orders.append(order_data) + print("================================================") + print("orders:", orders) + + print(f"[create_orders] 即将提交订单数量: {len(orders)}") + response = self._post_lims("/api/lims/order/orders", orders) + print(f"[create_orders] 接口返回: {response}") + # 等待任务报送成功 + data_list = response.get("data", []) + if data_list: + order_code = data_list[0].get("orderCode") + else: + order_code = None + + if not order_code: + logger.error("上料任务未返回有效 orderCode!") + return response + # 等待完成报送 + result = self.wait_for_order_finish(order_code) + print("实验记录本========================create_orders========================") + print(result) + print("========================") + return result + + # 2.7 启动调度 + def scheduler_start(self) -> Dict[str, Any]: + return self._post_lims("/api/lims/scheduler/start") + # 3.10 停止调度 + def scheduler_stop(self) -> Dict[str, Any]: + + """ + 停止调度 (3.10) + 请求体只包含 apiKey 和 requestTime + """ + return self._post_lims("/api/lims/scheduler/stop") + # 2.9 继续调度 + # 2.9 继续调度 + def scheduler_continue(self) -> Dict[str, Any]: + """ + 继续调度 (2.9) + 请求体只包含 apiKey 和 requestTime + """ + return self._post_lims("/api/lims/scheduler/continue") + def scheduler_reset(self) -> Dict[str, Any]: + """ + 复位调度 (2.11) + 请求体只包含 apiKey 和 requestTime + """ + return self._post_lims("/api/lims/scheduler/reset") + + + # 2.24 物料变更推送 + def report_material_change(self, material_obj: Dict[str, Any]) -> Dict[str, Any]: + """ + material_obj 按 2.24 的裸对象格式(包含 id/typeName/locations/detail 等) + """ + return self._post_report_raw("/report/material_change", material_obj) + + # 2.32 3-2-1 物料转运 + def transfer_3_to_2_to_1(self, + # source_wh_id: Optional[str] = None, + source_wh_id: Optional[str] = '3a19debc-84b4-0359-e2d4-b3beea49348b', + source_x: int = 1, source_y: int = 1, source_z: int = 1) -> Dict[str, Any]: + payload: Dict[str, Any] = { + "sourcePosX": source_x, "sourcePosY": source_y, "sourcePosZ": source_z + } + if source_wh_id: + payload["sourceWHID"] = source_wh_id + + response = self._post_lims("/api/lims/order/transfer-task3To2To1", payload) + # 等待任务报送成功 + order_code = response.get("data", {}).get("orderCode") + if not order_code: + logger.error("上料任务未返回有效 orderCode!") + return response + # 等待完成报送 + result = self.wait_for_order_finish(order_code) + return result + + # 3.35 1→2 物料转运 + def transfer_1_to_2(self) -> Dict[str, Any]: + """ + 1→2 物料转运 + URL: /api/lims/order/transfer-task1To2 + 只需要 apiKey 和 requestTime + """ + response = self._post_lims("/api/lims/order/transfer-task1To2") + # 等待任务报送成功 + order_code = response.get("data", {}).get("orderCode") + if not order_code: + logger.error("上料任务未返回有效 orderCode!") + return response + # 等待完成报送 + result = self.wait_for_order_finish(order_code) + return result + + # 2.5 批量查询实验报告(post过滤关键字查询) + def order_list_v2(self, + timeType: str = "", + beginTime: str = "", + endTime: str = "", + status: str = "", # 60表示正在运行,80表示完成,90表示失败 + filter: str = "", + skipCount: int = 0, + pageCount: int = 1, # 显示多少页数据 + sorting: str = "") -> Dict[str, Any]: + """ + 批量查询实验报告的详细信息 (2.5) + URL: /api/lims/order/order-list + 参数默认值和接口文档保持一致 + """ + data: Dict[str, Any] = { + "timeType": timeType, + "beginTime": beginTime, + "endTime": endTime, + "status": status, + "filter": filter, + "skipCount": skipCount, + "pageCount": pageCount, + "sorting": sorting + } + return self._post_lims("/api/lims/order/order-list", data) + + # 一直post执行bioyond接口查询任务状态 + def wait_for_transfer_task(self, timeout: int = 3000, interval: int = 5, filter_text: Optional[str] = None) -> bool: + """ + 轮询查询物料转移任务是否成功完成 (status=80) + - timeout: 最大等待秒数 (默认600秒) + - interval: 轮询间隔秒数 (默认3秒) + 返回 True 表示找到并成功完成,False 表示超时未找到 + """ + now = datetime.now() + beginTime = now.strftime("%Y-%m-%dT%H:%M:%SZ") + endTime = (now + timedelta(minutes=5)).strftime("%Y-%m-%dT%H:%M:%SZ") + print(beginTime, endTime) + + deadline = time.time() + timeout + + while time.time() < deadline: + result = self.order_list_v2( + timeType="", + beginTime=beginTime, + endTime=endTime, + status="", + filter=filter_text, + skipCount=0, + pageCount=1, + sorting="" + ) + print(result) + + items = result.get("data", {}).get("items", []) + for item in items: + name = item.get("name", "") + status = item.get("status") + # 改成用 filter_text 判断 + if (not filter_text or filter_text in name) and status == 80: + logger.info(f"硬件转移动作完成: {name}, status={status}") + return True + + logger.info(f"等待中: {name}, status={status}") + time.sleep(interval) + + logger.warning("超时未找到成功的物料转移任务") + return False + + def create_materials(self, mappings: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]: + """ + 将 SOLID_LIQUID_MAPPINGS 中的所有物料逐个 POST 到 /api/lims/storage/material + """ + results = [] + + for name, data in mappings.items(): + data = { + "typeId": data["typeId"], + "code": data.get("code", ""), + "barCode": data.get("barCode", ""), + "name": data["name"], + "unit": data.get("unit", "g"), + "parameters": data.get("parameters", ""), + "quantity": data.get("quantity", ""), + "warningQuantity": data.get("warningQuantity", ""), + "details": data.get("details", []) + } + + logger.info(f"正在创建第 {i}/{total} 个固体物料: {name}") + result = self._post_lims("/api/lims/storage/material", material_data) + + if result and result.get("code") == 1: + # data 字段可能是字符串(物料ID)或字典(包含id字段) + data = result.get("data") + if isinstance(data, str): + # data 直接是物料ID字符串 + material_id = data + elif isinstance(data, dict): + # data 是字典,包含id字段 + material_id = data.get("id") + else: + material_id = None + + if material_id: + created_materials.append({ + "name": name, + "materialId": material_id, + "typeId": type_id + }) + logger.info(f"✓ 成功创建物料: {name}, ID: {material_id}") + else: + logger.error(f"✗ 创建物料失败: {name}, 未返回ID") + logger.error(f" 响应数据: {result}") + else: + error_msg = result.get("error") or result.get("message", "未知错误") + logger.error(f"✗ 创建物料失败: {name}") + logger.error(f" 错误信息: {error_msg}") + logger.error(f" 完整响应: {result}") + + # 避免请求过快 + time.sleep(0.3) + + logger.info(f"物料创建完成,成功创建 {len(created_materials)}/{total} 个固体物料") + return created_materials + + def _sync_materials_safe(self) -> bool: + """仅使用 BioyondResourceSynchronizer 执行同步(与 station.py 保持一致)。""" + if hasattr(self, 'resource_synchronizer') and self.resource_synchronizer: + try: + return bool(self.resource_synchronizer.sync_from_external()) + except Exception as e: + logger.error(f"同步失败: {e}") + return False + logger.warning("资源同步器未初始化") + return False + + def _load_warehouse_locations(self, warehouse_name: str) -> tuple[List[str], List[str]]: + """从配置加载仓库位置信息 + + Args: + warehouse_name: 仓库名称 + + Returns: + (location_ids, position_names) 元组 + """ + warehouse_mapping = self.bioyond_config.get("warehouse_mapping", WAREHOUSE_MAPPING) + + if warehouse_name not in warehouse_mapping: + raise ValueError(f"配置中未找到仓库: {warehouse_name}。可用: {list(warehouse_mapping.keys())}") + + site_uuids = warehouse_mapping[warehouse_name].get("site_uuids", {}) + if not site_uuids: + raise ValueError(f"仓库 {warehouse_name} 没有配置位置") + + # 按顺序获取位置ID和名称 + location_ids = [] + position_names = [] + for key in sorted(site_uuids.keys()): + location_ids.append(site_uuids[key]) + position_names.append(key) + + return location_ids, position_names + + + def create_and_inbound_materials( + self, + material_names: Optional[List[str]] = None, + type_id: str = "3a190ca0-b2f6-9aeb-8067-547e72c11469", + warehouse_name: str = "粉末加样头堆栈" + ) -> Dict[str, Any]: + """ + 传参与默认列表方式创建物料并入库(不使用CSV)。 + + Args: + material_names: 物料名称列表;默认使用 [LiPF6, LiDFOB, DTD, LiFSI, LiPO2F2] + type_id: 物料类型ID + warehouse_name: 目标仓库名(用于取位置信息) + + Returns: + 执行结果字典 + """ + logger.info("=" * 60) + logger.info(f"开始执行:从参数创建物料并批量入库到 {warehouse_name}") + logger.info("=" * 60) + + try: + # 1) 准备物料名称(默认值) + default_materials = ["LiPF6", "LiDFOB", "DTD", "LiFSI", "LiPO2F2"] + mat_names = [m.strip() for m in (material_names or default_materials) if str(m).strip()] + if not mat_names: + return {"success": False, "error": "物料名称列表为空"} + + # 2) 加载仓库位置信息 + all_location_ids, position_names = self._load_warehouse_locations(warehouse_name) + logger.info(f"✓ 加载 {len(all_location_ids)} 个位置 ({position_names[0]} ~ {position_names[-1]})") + + # 限制数量不超过可用位置 + if len(mat_names) > len(all_location_ids): + logger.warning(f"物料数量超出位置数量,仅处理前 {len(all_location_ids)} 个") + mat_names = mat_names[:len(all_location_ids)] + + # 3) 创建物料 + logger.info(f"\n【步骤1/3】创建 {len(mat_names)} 个固体物料...") + created_materials = self.create_solid_materials(mat_names, type_id) + if not created_materials: + return {"success": False, "error": "没有成功创建任何物料"} + + # 4) 批量入库 + logger.info(f"\n【步骤2/3】批量入库物料...") + location_ids = all_location_ids[:len(created_materials)] + selected_positions = position_names[:len(created_materials)] + + inbound_items = [ + {"materialId": mat["materialId"], "locationId": loc_id} + for mat, loc_id in zip(created_materials, location_ids) + ] + + for material, position in zip(created_materials, selected_positions): + logger.info(f" - {material['name']} → {position}") + + result = self.storage_batch_inbound(inbound_items) + if result.get("code") != 1: + logger.error(f"✗ 批量入库失败: {result}") + return {"success": False, "error": "批量入库失败", "created_materials": created_materials, "inbound_result": result} + + logger.info("✓ 批量入库成功") + + # 5) 同步 + logger.info(f"\n【步骤3/3】同步物料数据...") + if self._sync_materials_safe(): + logger.info("✓ 物料数据同步完成") + else: + logger.warning("⚠ 物料数据同步未完成(可忽略,不影响已创建与入库的数据)") + + logger.info("\n" + "=" * 60) + logger.info("流程完成") + logger.info("=" * 60 + "\n") + + return { + "success": True, + "created_materials": created_materials, + "inbound_result": result, + "total_created": len(created_materials), + "total_inbound": len(inbound_items), + "warehouse": warehouse_name, + "positions": selected_positions + } + + except Exception as e: + logger.error(f"✗ 执行失败: {e}") + return {"success": False, "error": str(e)} + + def create_material( + self, + material_name: str, + type_id: str, + warehouse_name: str, + location_name_or_id: Optional[str] = None + ) -> Dict[str, Any]: + """创建单个物料并可选入库。 + Args: + material_name: 物料名称(会优先匹配配置模板)。 + type_id: 物料类型 ID(若为空则尝试从配置推断)。 + warehouse_name: 需要入库的仓库名称;若为空则仅创建不入库。 + location_name_or_id: 具体库位名称(如 A01)或库位 UUID,由用户指定。 + Returns: + 包含创建结果、物料ID以及入库结果的字典。 + """ + material_name = (material_name or "").strip() + + resolved_type_id = (type_id or "").strip() + # 优先从 SOLID_LIQUID_MAPPINGS 中获取模板数据 + template = SOLID_LIQUID_MAPPINGS.get(material_name) + if not template: + raise ValueError(f"在配置中未找到物料 {material_name} 的模板,请检查 SOLID_LIQUID_MAPPINGS。") + material_data: Dict[str, Any] + material_data = deepcopy(template) + # 最终确保 typeId 为调用方传入的值 + if resolved_type_id: + material_data["typeId"] = resolved_type_id + material_data["name"] = material_name + # 生成唯一编码 + def _generate_code(prefix: str) -> str: + normalized = re.sub(r"\W+", "_", prefix) + normalized = normalized.strip("_") or "material" + return f"{normalized}_{datetime.now().strftime('%Y%m%d%H%M%S')}" + if not material_data.get("code"): + material_data["code"] = _generate_code(material_name) + if not material_data.get("barCode"): + material_data["barCode"] = "" + # 处理数量字段类型 + def _to_number(value: Any, default: float = 0.0) -> float: + try: + if value is None: + return default + if isinstance(value, (int, float)): + return float(value) + if isinstance(value, str) and value.strip() == "": + return default + return float(value) + except (TypeError, ValueError): + return default + material_data["quantity"] = _to_number(material_data.get("quantity"), 1.0) + material_data["warningQuantity"] = _to_number(material_data.get("warningQuantity"), 0.0) + unit = material_data.get("unit") or "个" + material_data["unit"] = unit + if not material_data.get("parameters"): + material_data["parameters"] = json.dumps({"unit": unit}, ensure_ascii=False) + # 补充子物料信息 + details = material_data.get("details") or [] + if not isinstance(details, list): + logger.warning("details 字段不是列表,已忽略。") + details = [] + else: + for idx, detail in enumerate(details, start=1): + if not isinstance(detail, dict): + continue + if not detail.get("code"): + detail["code"] = f"{material_data['code']}_{idx:02d}" + if not detail.get("name"): + detail["name"] = f"{material_name}_detail_{idx:02d}" + if not detail.get("unit"): + detail["unit"] = unit + if not detail.get("parameters"): + detail["parameters"] = json.dumps({"unit": detail.get("unit", unit)}, ensure_ascii=False) + if "quantity" in detail: + detail["quantity"] = _to_number(detail.get("quantity"), 1.0) + material_data["details"] = details + create_result = self._post_lims("/api/lims/storage/material", material_data) + # 解析创建结果中的物料 ID + material_id: Optional[str] = None + if isinstance(create_result, dict): + data_field = create_result.get("data") + if isinstance(data_field, str): + material_id = data_field + elif isinstance(data_field, dict): + material_id = data_field.get("id") or data_field.get("materialId") + inbound_result: Optional[Dict[str, Any]] = None + location_id: Optional[str] = None + # 按用户指定位置入库 + if warehouse_name and material_id and location_name_or_id: + try: + location_ids, position_names = self._load_warehouse_locations(warehouse_name) + position_to_id = {name: loc_id for name, loc_id in zip(position_names, location_ids)} + target_location_id = position_to_id.get(location_name_or_id, location_name_or_id) + if target_location_id: + location_id = target_location_id + inbound_result = self.storage_inbound(material_id, target_location_id) + else: + inbound_result = {"error": f"未找到匹配的库位: {location_name_or_id}"} + except Exception as exc: + logger.error(f"获取仓库 {warehouse_name} 位置失败: {exc}") + inbound_result = {"error": str(exc)} + return { + "success": bool(isinstance(create_result, dict) and create_result.get("code") == 1 and material_id), + "material_name": material_name, + "material_id": material_id, + "warehouse": warehouse_name, + "location_id": location_id, + "location_name_or_id": location_name_or_id, + "create_result": create_result, + "inbound_result": inbound_result, + } + def resource_tree_transfer(self, old_parent: ResourcePLR, plr_resource: ResourcePLR, parent_resource: ResourcePLR): + # ROS2DeviceNode.run_async_func(self._ros_node.resource_tree_transfer, True, **{ + # "old_parent": old_parent, + # "plr_resource": plr_resource, + # "parent_resource": parent_resource, + # }) + print("resource_tree_transfer", plr_resource, parent_resource) + if hasattr(plr_resource, "unilabos_extra") and plr_resource.unilabos_extra: + if "update_resource_site" in plr_resource.unilabos_extra: + site = plr_resource.unilabos_extra["update_resource_site"] + plr_model = plr_resource.model + board_type = None + for key, (moudle_name,moudle_uuid) in MATERIAL_TYPE_MAPPINGS.items(): + if plr_model == moudle_name: + board_type = key + break + if board_type is None: + pass + bottle1 = plr_resource.children[0] + + bottle_moudle = bottle1.model + bottle_type = None + for key, (moudle_name, moudle_uuid) in MATERIAL_TYPE_MAPPINGS.items(): + if bottle_moudle == moudle_name: + bottle_type = key + break + + # 从 parent_resource 获取仓库名称 + warehouse_name = parent_resource.name if parent_resource else "手动堆栈" + logger.info(f"拖拽上料: {plr_resource.name} -> {warehouse_name} / {site}") + + self.create_sample(plr_resource.name, board_type, bottle_type, site, warehouse_name) + return + self.lab_logger().warning(f"无库位的上料,不处理,{plr_resource} 挂载到 {parent_resource}") + + def create_sample( + self, + name: str, + board_type: str, + bottle_type: str, + location_code: str, + warehouse_name: str = "手动堆栈" + ) -> Dict[str, Any]: + """创建配液板物料并自动入库。 + Args: + name: 物料名称 + board_type: 板类型,如 "5ml分液瓶板"、"配液瓶(小)板" + bottle_type: 瓶类型,如 "5ml分液瓶"、"配液瓶(小)" + location_code: 库位编号,例如 "A01" + warehouse_name: 仓库名称,默认为 "手动堆栈",支持 "自动堆栈-左"、"自动堆栈-右" 等 + """ + carrier_type_id = MATERIAL_TYPE_MAPPINGS[board_type][1] + bottle_type_id = MATERIAL_TYPE_MAPPINGS[bottle_type][1] + + # 从指定仓库获取库位UUID + if warehouse_name not in WAREHOUSE_MAPPING: + logger.error(f"未找到仓库: {warehouse_name},回退到手动堆栈") + warehouse_name = "手动堆栈" + + if location_code not in WAREHOUSE_MAPPING[warehouse_name]["site_uuids"]: + logger.error(f"仓库 {warehouse_name} 中未找到库位 {location_code}") + raise ValueError(f"库位 {location_code} 在仓库 {warehouse_name} 中不存在") + + location_id = WAREHOUSE_MAPPING[warehouse_name]["site_uuids"][location_code] + logger.info(f"创建样品入库: {name} -> {warehouse_name}/{location_code} (UUID: {location_id})") + + # 新建小瓶 + details = [] + for y in range(1, 5): + for x in range(1, 3): + details.append({ + "typeId": bottle_type_id, + "code": "", + "name": str(bottle_type) + str(x) + str(y), + "quantity": "1", + "x": x, + "y": y, + "z": 1, + "unit": "个", + "parameters": json.dumps({"unit": "个"}, ensure_ascii=False), + }) + + data = { + "typeId": carrier_type_id, + "code": "", + "barCode": "", + "name": name, + "unit": "块", + "parameters": json.dumps({"unit": "块"}, ensure_ascii=False), + "quantity": "1", + "details": details, + } + # print("xxx:",data) + create_result = self._post_lims("/api/lims/storage/material", data) + sample_uuid = create_result.get("data") + + final_result = self._post_lims("/api/lims/storage/inbound", { + "materialId": sample_uuid, + "locationId": location_id, + }) + return final_result + + + + +if __name__ == "__main__": + lab_registry.setup() + deck = BIOYOND_YB_Deck(setup=True) + ws = BioyondCellWorkstation(deck=deck) + # ws.create_sample(name="test", board_type="配液瓶(小)板", bottle_type="配液瓶(小)", location_code="B01") + # logger.info(ws.scheduler_stop()) + # logger.info(ws.scheduler_start()) + + # 继续后续流程 + logger.info(ws.auto_feeding4to3()) #搬运物料到3号箱 + # # # 使用正斜杠或 Path 对象来指定文件路径 + # excel_path = Path("unilabos\\devices\\workstation\\bioyond_studio\\bioyond_cell\\2025092701.xlsx") + # logger.info(ws.create_orders(excel_path)) + # logger.info(ws.transfer_3_to_2_to_1()) + + # logger.info(ws.transfer_1_to_2()) + # logger.info(ws.scheduler_start()) + + + while True: + time.sleep(1) + # re=ws.scheduler_stop() + # re = ws.transfer_3_to_2_to_1() + + # print(re) + # logger.info("调度启动完成") + + # ws.scheduler_continue() + # 3.30 上料:读取模板 Excel 自动解析并 POST + # r1 = ws.auto_feeding4to3_from_xlsx(r"C:\ML\GitHub\Uni-Lab-OS\unilabos\devices\workstation\bioyond_cell\样品导入模板.xlsx") + # ws.wait_for_transfer_task(filter_text="物料转移任务") + # logger.info("4号箱向3号箱转运物料转移任务已完成") + + # ws.scheduler_start() + # print(r1["payload"]["data"]) # 调试模式下可直接看到要发的 JSON items + + # # 新建实验 + # response = ws.create_orders("C:/ML/GitHub/Uni-Lab-OS/unilabos/devices/workstation/bioyond_cell/2025092701.xlsx") + # logger.info(response) + # data_list = response.get("data", []) + # order_name = data_list[0].get("orderName", "") + + # ws.wait_for_transfer_task(filter_text=order_name) + # ws.wait_for_transfer_task(filter_text='DP20250927001') + # logger.info("3号站内实验完成") + # # ws.scheduler_start() + # # print(res) + # ws.transfer_3_to_2_to_1() + # ws.wait_for_transfer_task(filter_text="物料转移任务") + # logger.info("3号站向2号站向1号站转移任务完成") + # r321 = self.wait_for_transfer_task() + #1号站启动 + # ws.transfer_1_to_2() + # ws.wait_for_transfer_task(filter_text="物料转移任务") + # logger.info("1号站向2号站转移任务完成") + # logger.info("全流程结束") + + # 3.31 下料:同理 + # r2 = ws.auto_batch_outbound_from_xlsx(r"C:/path/样品导入模板 (8).xlsx") + # print(r2["payload"]["data"]) diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/bioyond_cell_workstation.py b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/bioyond_cell_workstation.py index 3e3bff6..5d10f40 100644 --- a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/bioyond_cell_workstation.py +++ b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/bioyond_cell_workstation.py @@ -257,7 +257,7 @@ class BioyondCellWorkstation(BioyondWorkstation): def auto_feeding4to3( self, # ★ 修改点:默认模板路径 - xlsx_path: Optional[str] = "/Users/sml/work/Unilab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx", + xlsx_path: Optional[str] = "D:\\UniLab\\Uni-Lab-OS\\unilabos\\devices\\workstation\\bioyond_studio\\bioyond_cell\\material_template.xlsx", # ---------------- WH4 - 加样头面 (Z=1, 12个点位) ---------------- WH4_x1_y1_z1_1_materialName: str = "", WH4_x1_y1_z1_1_quantity: float = 0.0, WH4_x2_y1_z1_2_materialName: str = "", WH4_x2_y1_z1_2_quantity: float = 0.0, @@ -394,9 +394,13 @@ class BioyondCellWorkstation(BioyondWorkstation): return response # 等待完成报送 result = self.wait_for_order_finish(order_code) + print("\n" + "="*60) + print("实验记录本结果auto_feeding4to3") + print("="*60) + print(json.dumps(result, indent=2, ensure_ascii=False)) + print("="*60 + "\n") return result - def auto_batch_outbound_from_xlsx(self, xlsx_path: str) -> Dict[str, Any]: """ 3.31 自动化下料(Excel -> JSON -> POST /api/lims/storage/auto-batch-out-bound) @@ -474,7 +478,7 @@ class BioyondCellWorkstation(BioyondWorkstation): - totalMass 自动计算为所有物料质量之和 - createTime 缺失或为空时自动填充为当前日期(YYYY/M/D) """ - default_path = Path("/Users/sml/work/Unilab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025092701.xlsx") + default_path = Path("D:\\UniLab\\Uni-Lab-OS\\unilabos\\devices\\workstation\\bioyond_studio\\bioyond_cell\\2025122301.xlsx") path = Path(xlsx_path) if xlsx_path else default_path print(f"[create_orders] 使用 Excel 路径: {path}") if path != default_path: @@ -610,19 +614,63 @@ class BioyondCellWorkstation(BioyondWorkstation): print(f"[create_orders] 即将提交订单数量: {len(orders)}") response = self._post_lims("/api/lims/order/orders", orders) print(f"[create_orders] 接口返回: {response}") - # 等待任务报送成功 + + # 提取所有返回的 orderCode data_list = response.get("data", []) - if data_list: - order_code = data_list[0].get("orderCode") - else: - order_code = None - - if not order_code: - logger.error("上料任务未返回有效 orderCode!") + if not data_list: + logger.error("创建订单未返回有效数据!") return response - # 等待完成报送 - result = self.wait_for_order_finish(order_code) - return result + + # 收集所有 orderCode + order_codes = [] + for order_item in data_list: + code = order_item.get("orderCode") + if code: + order_codes.append(code) + + if not order_codes: + logger.error("未找到任何有效的 orderCode!") + return response + + print(f"[create_orders] 等待 {len(order_codes)} 个订单完成: {order_codes}") + + # 等待所有订单完成并收集报文 + all_reports = [] + for idx, order_code in enumerate(order_codes, 1): + print(f"[create_orders] 正在等待第 {idx}/{len(order_codes)} 个订单: {order_code}") + result = self.wait_for_order_finish(order_code) + + # 提取报文数据 + if result.get("status") == "success": + report = result.get("report", {}) + all_reports.append(report) + print(f"[create_orders] ✓ 订单 {order_code} 完成") + else: + logger.warning(f"订单 {order_code} 状态异常: {result.get('status')}") + # 即使订单失败,也记录下这个结果 + all_reports.append({ + "orderCode": order_code, + "status": result.get("status"), + "error": result.get("message", "未知错误") + }) + + print(f"[create_orders] 所有订单已完成,共收集 {len(all_reports)} 个报文") + print("实验记录本========================create_orders========================") + + # 返回所有订单的完成报文 + final_result = { + "status": "all_completed", + "total_orders": len(order_codes), + "reports": all_reports, + "original_response": response + } + + print(f"返回报文数量: {len(all_reports)}") + for i, report in enumerate(all_reports, 1): + print(f"报文 {i}: orderCode={report.get('orderCode', 'N/A')}, status={report.get('status', 'N/A')}") + print("========================") + + return final_result # 2.7 启动调度 def scheduler_start(self) -> Dict[str, Any]: @@ -650,6 +698,146 @@ class BioyondCellWorkstation(BioyondWorkstation): """ return self._post_lims("/api/lims/scheduler/reset") + def scheduler_start_and_auto_feeding( + self, + # ★ Excel路径参数 + xlsx_path: Optional[str] = "D:\\UniLab\\Uni-Lab-OS\\unilabos\\devices\\workstation\\bioyond_studio\\bioyond_cell\\material_template.xlsx", + # ---------------- WH4 - 加样头面 (Z=1, 12个点位) ---------------- + WH4_x1_y1_z1_1_materialName: str = "", WH4_x1_y1_z1_1_quantity: float = 0.0, + WH4_x2_y1_z1_2_materialName: str = "", WH4_x2_y1_z1_2_quantity: float = 0.0, + WH4_x3_y1_z1_3_materialName: str = "", WH4_x3_y1_z1_3_quantity: float = 0.0, + WH4_x4_y1_z1_4_materialName: str = "", WH4_x4_y1_z1_4_quantity: float = 0.0, + WH4_x5_y1_z1_5_materialName: str = "", WH4_x5_y1_z1_5_quantity: float = 0.0, + WH4_x1_y2_z1_6_materialName: str = "", WH4_x1_y2_z1_6_quantity: float = 0.0, + WH4_x2_y2_z1_7_materialName: str = "", WH4_x2_y2_z1_7_quantity: float = 0.0, + WH4_x3_y2_z1_8_materialName: str = "", WH4_x3_y2_z1_8_quantity: float = 0.0, + WH4_x4_y2_z1_9_materialName: str = "", WH4_x4_y2_z1_9_quantity: float = 0.0, + WH4_x5_y2_z1_10_materialName: str = "", WH4_x5_y2_z1_10_quantity: float = 0.0, + WH4_x1_y3_z1_11_materialName: str = "", WH4_x1_y3_z1_11_quantity: float = 0.0, + WH4_x2_y3_z1_12_materialName: str = "", WH4_x2_y3_z1_12_quantity: float = 0.0, + + # ---------------- WH4 - 原液瓶面 (Z=2, 9个点位) ---------------- + WH4_x1_y1_z2_1_materialName: str = "", WH4_x1_y1_z2_1_quantity: float = 0.0, WH4_x1_y1_z2_1_materialType: str = "", WH4_x1_y1_z2_1_targetWH: str = "", + WH4_x2_y1_z2_2_materialName: str = "", WH4_x2_y1_z2_2_quantity: float = 0.0, WH4_x2_y1_z2_2_materialType: str = "", WH4_x2_y1_z2_2_targetWH: str = "", + WH4_x3_y1_z2_3_materialName: str = "", WH4_x3_y1_z2_3_quantity: float = 0.0, WH4_x3_y1_z2_3_materialType: str = "", WH4_x3_y1_z2_3_targetWH: str = "", + WH4_x1_y2_z2_4_materialName: str = "", WH4_x1_y2_z2_4_quantity: float = 0.0, WH4_x1_y2_z2_4_materialType: str = "", WH4_x1_y2_z2_4_targetWH: str = "", + WH4_x2_y2_z2_5_materialName: str = "", WH4_x2_y2_z2_5_quantity: float = 0.0, WH4_x2_y2_z2_5_materialType: str = "", WH4_x2_y2_z2_5_targetWH: str = "", + WH4_x3_y2_z2_6_materialName: str = "", WH4_x3_y2_z2_6_quantity: float = 0.0, WH4_x3_y2_z2_6_materialType: str = "", WH4_x3_y2_z2_6_targetWH: str = "", + WH4_x1_y3_z2_7_materialName: str = "", WH4_x1_y3_z2_7_quantity: float = 0.0, WH4_x1_y3_z2_7_materialType: str = "", WH4_x1_y3_z2_7_targetWH: str = "", + WH4_x2_y3_z2_8_materialName: str = "", WH4_x2_y3_z2_8_quantity: float = 0.0, WH4_x2_y3_z2_8_materialType: str = "", WH4_x2_y3_z2_8_targetWH: str = "", + WH4_x3_y3_z2_9_materialName: str = "", WH4_x3_y3_z2_9_quantity: float = 0.0, WH4_x3_y3_z2_9_materialType: str = "", WH4_x3_y3_z2_9_targetWH: str = "", + + # ---------------- WH3 - 人工堆栈 (Z=3, 15个点位) ---------------- + WH3_x1_y1_z3_1_materialType: str = "", WH3_x1_y1_z3_1_materialId: str = "", WH3_x1_y1_z3_1_quantity: float = 0, + WH3_x2_y1_z3_2_materialType: str = "", WH3_x2_y1_z3_2_materialId: str = "", WH3_x2_y1_z3_2_quantity: float = 0, + WH3_x3_y1_z3_3_materialType: str = "", WH3_x3_y1_z3_3_materialId: str = "", WH3_x3_y1_z3_3_quantity: float = 0, + WH3_x1_y2_z3_4_materialType: str = "", WH3_x1_y2_z3_4_materialId: str = "", WH3_x1_y2_z3_4_quantity: float = 0, + WH3_x2_y2_z3_5_materialType: str = "", WH3_x2_y2_z3_5_materialId: str = "", WH3_x2_y2_z3_5_quantity: float = 0, + WH3_x3_y2_z3_6_materialType: str = "", WH3_x3_y2_z3_6_materialId: str = "", WH3_x3_y2_z3_6_quantity: float = 0, + WH3_x1_y3_z3_7_materialType: str = "", WH3_x1_y3_z3_7_materialId: str = "", WH3_x1_y3_z3_7_quantity: float = 0, + WH3_x2_y3_z3_8_materialType: str = "", WH3_x2_y3_z3_8_materialId: str = "", WH3_x2_y3_z3_8_quantity: float = 0, + WH3_x3_y3_z3_9_materialType: str = "", WH3_x3_y3_z3_9_materialId: str = "", WH3_x3_y3_z3_9_quantity: float = 0, + WH3_x1_y4_z3_10_materialType: str = "", WH3_x1_y4_z3_10_materialId: str = "", WH3_x1_y4_z3_10_quantity: float = 0, + WH3_x2_y4_z3_11_materialType: str = "", WH3_x2_y4_z3_11_materialId: str = "", WH3_x2_y4_z3_11_quantity: float = 0, + WH3_x3_y4_z3_12_materialType: str = "", WH3_x3_y4_z3_12_materialId: str = "", WH3_x3_y4_z3_12_quantity: float = 0, + WH3_x1_y5_z3_13_materialType: str = "", WH3_x1_y5_z3_13_materialId: str = "", WH3_x1_y5_z3_13_quantity: float = 0, + WH3_x2_y5_z3_14_materialType: str = "", WH3_x2_y5_z3_14_materialId: str = "", WH3_x2_y5_z3_14_quantity: float = 0, + WH3_x3_y5_z3_15_materialType: str = "", WH3_x3_y5_z3_15_materialId: str = "", WH3_x3_y5_z3_15_quantity: float = 0, + ) -> Dict[str, Any]: + """ + 组合函数:先启动调度,然后执行自动化上料 + + 此函数简化了工作流操作,将两个有顺序依赖的操作组合在一起: + 1. 启动调度(scheduler_start) + 2. 自动化上料(auto_feeding4to3) + + 参数与 auto_feeding4to3 完全相同,支持 Excel 和手动参数两种模式 + + Returns: + 包含调度启动结果和上料结果的字典 + """ + logger.info("=" * 60) + logger.info("开始执行组合操作:启动调度 + 自动化上料") + logger.info("=" * 60) + + # 步骤1: 启动调度 + logger.info("【步骤 1/2】启动调度...") + scheduler_result = self.scheduler_start() + logger.info(f"调度启动结果: {scheduler_result}") + + # 检查调度是否启动成功 + if scheduler_result.get("code") != 1: + logger.error(f"调度启动失败: {scheduler_result}") + return { + "success": False, + "step": "scheduler_start", + "scheduler_result": scheduler_result, + "error": "调度启动失败" + } + + logger.info("✓ 调度启动成功") + + # 步骤2: 执行自动化上料 + logger.info("【步骤 2/2】执行自动化上料...") + feeding_result = self.auto_feeding4to3( + xlsx_path=xlsx_path, + WH4_x1_y1_z1_1_materialName=WH4_x1_y1_z1_1_materialName, WH4_x1_y1_z1_1_quantity=WH4_x1_y1_z1_1_quantity, + WH4_x2_y1_z1_2_materialName=WH4_x2_y1_z1_2_materialName, WH4_x2_y1_z1_2_quantity=WH4_x2_y1_z1_2_quantity, + WH4_x3_y1_z1_3_materialName=WH4_x3_y1_z1_3_materialName, WH4_x3_y1_z1_3_quantity=WH4_x3_y1_z1_3_quantity, + WH4_x4_y1_z1_4_materialName=WH4_x4_y1_z1_4_materialName, WH4_x4_y1_z1_4_quantity=WH4_x4_y1_z1_4_quantity, + WH4_x5_y1_z1_5_materialName=WH4_x5_y1_z1_5_materialName, WH4_x5_y1_z1_5_quantity=WH4_x5_y1_z1_5_quantity, + WH4_x1_y2_z1_6_materialName=WH4_x1_y2_z1_6_materialName, WH4_x1_y2_z1_6_quantity=WH4_x1_y2_z1_6_quantity, + WH4_x2_y2_z1_7_materialName=WH4_x2_y2_z1_7_materialName, WH4_x2_y2_z1_7_quantity=WH4_x2_y2_z1_7_quantity, + WH4_x3_y2_z1_8_materialName=WH4_x3_y2_z1_8_materialName, WH4_x3_y2_z1_8_quantity=WH4_x3_y2_z1_8_quantity, + WH4_x4_y2_z1_9_materialName=WH4_x4_y2_z1_9_materialName, WH4_x4_y2_z1_9_quantity=WH4_x4_y2_z1_9_quantity, + WH4_x5_y2_z1_10_materialName=WH4_x5_y2_z1_10_materialName, WH4_x5_y2_z1_10_quantity=WH4_x5_y2_z1_10_quantity, + WH4_x1_y3_z1_11_materialName=WH4_x1_y3_z1_11_materialName, WH4_x1_y3_z1_11_quantity=WH4_x1_y3_z1_11_quantity, + WH4_x2_y3_z1_12_materialName=WH4_x2_y3_z1_12_materialName, WH4_x2_y3_z1_12_quantity=WH4_x2_y3_z1_12_quantity, + WH4_x1_y1_z2_1_materialName=WH4_x1_y1_z2_1_materialName, WH4_x1_y1_z2_1_quantity=WH4_x1_y1_z2_1_quantity, + WH4_x1_y1_z2_1_materialType=WH4_x1_y1_z2_1_materialType, WH4_x1_y1_z2_1_targetWH=WH4_x1_y1_z2_1_targetWH, + WH4_x2_y1_z2_2_materialName=WH4_x2_y1_z2_2_materialName, WH4_x2_y1_z2_2_quantity=WH4_x2_y1_z2_2_quantity, + WH4_x2_y1_z2_2_materialType=WH4_x2_y1_z2_2_materialType, WH4_x2_y1_z2_2_targetWH=WH4_x2_y1_z2_2_targetWH, + WH4_x3_y1_z2_3_materialName=WH4_x3_y1_z2_3_materialName, WH4_x3_y1_z2_3_quantity=WH4_x3_y1_z2_3_quantity, + WH4_x3_y1_z2_3_materialType=WH4_x3_y1_z2_3_materialType, WH4_x3_y1_z2_3_targetWH=WH4_x3_y1_z2_3_targetWH, + WH4_x1_y2_z2_4_materialName=WH4_x1_y2_z2_4_materialName, WH4_x1_y2_z2_4_quantity=WH4_x1_y2_z2_4_quantity, + WH4_x1_y2_z2_4_materialType=WH4_x1_y2_z2_4_materialType, WH4_x1_y2_z2_4_targetWH=WH4_x1_y2_z2_4_targetWH, + WH4_x2_y2_z2_5_materialName=WH4_x2_y2_z2_5_materialName, WH4_x2_y2_z2_5_quantity=WH4_x2_y2_z2_5_quantity, + WH4_x2_y2_z2_5_materialType=WH4_x2_y2_z2_5_materialType, WH4_x2_y2_z2_5_targetWH=WH4_x2_y2_z2_5_targetWH, + WH4_x3_y2_z2_6_materialName=WH4_x3_y2_z2_6_materialName, WH4_x3_y2_z2_6_quantity=WH4_x3_y2_z2_6_quantity, + WH4_x3_y2_z2_6_materialType=WH4_x3_y2_z2_6_materialType, WH4_x3_y2_z2_6_targetWH=WH4_x3_y2_z2_6_targetWH, + WH4_x1_y3_z2_7_materialName=WH4_x1_y3_z2_7_materialName, WH4_x1_y3_z2_7_quantity=WH4_x1_y3_z2_7_quantity, + WH4_x1_y3_z2_7_materialType=WH4_x1_y3_z2_7_materialType, WH4_x1_y3_z2_7_targetWH=WH4_x1_y3_z2_7_targetWH, + WH4_x2_y3_z2_8_materialName=WH4_x2_y3_z2_8_materialName, WH4_x2_y3_z2_8_quantity=WH4_x2_y3_z2_8_quantity, + WH4_x2_y3_z2_8_materialType=WH4_x2_y3_z2_8_materialType, WH4_x2_y3_z2_8_targetWH=WH4_x2_y3_z2_8_targetWH, + WH4_x3_y3_z2_9_materialName=WH4_x3_y3_z2_9_materialName, WH4_x3_y3_z2_9_quantity=WH4_x3_y3_z2_9_quantity, + WH4_x3_y3_z2_9_materialType=WH4_x3_y3_z2_9_materialType, WH4_x3_y3_z2_9_targetWH=WH4_x3_y3_z2_9_targetWH, + WH3_x1_y1_z3_1_materialType=WH3_x1_y1_z3_1_materialType, WH3_x1_y1_z3_1_materialId=WH3_x1_y1_z3_1_materialId, WH3_x1_y1_z3_1_quantity=WH3_x1_y1_z3_1_quantity, + WH3_x2_y1_z3_2_materialType=WH3_x2_y1_z3_2_materialType, WH3_x2_y1_z3_2_materialId=WH3_x2_y1_z3_2_materialId, WH3_x2_y1_z3_2_quantity=WH3_x2_y1_z3_2_quantity, + WH3_x3_y1_z3_3_materialType=WH3_x3_y1_z3_3_materialType, WH3_x3_y1_z3_3_materialId=WH3_x3_y1_z3_3_materialId, WH3_x3_y1_z3_3_quantity=WH3_x3_y1_z3_3_quantity, + WH3_x1_y2_z3_4_materialType=WH3_x1_y2_z3_4_materialType, WH3_x1_y2_z3_4_materialId=WH3_x1_y2_z3_4_materialId, WH3_x1_y2_z3_4_quantity=WH3_x1_y2_z3_4_quantity, + WH3_x2_y2_z3_5_materialType=WH3_x2_y2_z3_5_materialType, WH3_x2_y2_z3_5_materialId=WH3_x2_y2_z3_5_materialId, WH3_x2_y2_z3_5_quantity=WH3_x2_y2_z3_5_quantity, + WH3_x3_y2_z3_6_materialType=WH3_x3_y2_z3_6_materialType, WH3_x3_y2_z3_6_materialId=WH3_x3_y2_z3_6_materialId, WH3_x3_y2_z3_6_quantity=WH3_x3_y2_z3_6_quantity, + WH3_x1_y3_z3_7_materialType=WH3_x1_y3_z3_7_materialType, WH3_x1_y3_z3_7_materialId=WH3_x1_y3_z3_7_materialId, WH3_x1_y3_z3_7_quantity=WH3_x1_y3_z3_7_quantity, + WH3_x2_y3_z3_8_materialType=WH3_x2_y3_z3_8_materialType, WH3_x2_y3_z3_8_materialId=WH3_x2_y3_z3_8_materialId, WH3_x2_y3_z3_8_quantity=WH3_x2_y3_z3_8_quantity, + WH3_x3_y3_z3_9_materialType=WH3_x3_y3_z3_9_materialType, WH3_x3_y3_z3_9_materialId=WH3_x3_y3_z3_9_materialId, WH3_x3_y3_z3_9_quantity=WH3_x3_y3_z3_9_quantity, + WH3_x1_y4_z3_10_materialType=WH3_x1_y4_z3_10_materialType, WH3_x1_y4_z3_10_materialId=WH3_x1_y4_z3_10_materialId, WH3_x1_y4_z3_10_quantity=WH3_x1_y4_z3_10_quantity, + WH3_x2_y4_z3_11_materialType=WH3_x2_y4_z3_11_materialType, WH3_x2_y4_z3_11_materialId=WH3_x2_y4_z3_11_materialId, WH3_x2_y4_z3_11_quantity=WH3_x2_y4_z3_11_quantity, + WH3_x3_y4_z3_12_materialType=WH3_x3_y4_z3_12_materialType, WH3_x3_y4_z3_12_materialId=WH3_x3_y4_z3_12_materialId, WH3_x3_y4_z3_12_quantity=WH3_x3_y4_z3_12_quantity, + WH3_x1_y5_z3_13_materialType=WH3_x1_y5_z3_13_materialType, WH3_x1_y5_z3_13_materialId=WH3_x1_y5_z3_13_materialId, WH3_x1_y5_z3_13_quantity=WH3_x1_y5_z3_13_quantity, + WH3_x2_y5_z3_14_materialType=WH3_x2_y5_z3_14_materialType, WH3_x2_y5_z3_14_materialId=WH3_x2_y5_z3_14_materialId, WH3_x2_y5_z3_14_quantity=WH3_x2_y5_z3_14_quantity, + WH3_x3_y5_z3_15_materialType=WH3_x3_y5_z3_15_materialType, WH3_x3_y5_z3_15_materialId=WH3_x3_y5_z3_15_materialId, WH3_x3_y5_z3_15_quantity=WH3_x3_y5_z3_15_quantity, + ) + + logger.info("=" * 60) + logger.info("组合操作完成") + logger.info("=" * 60) + + return { + "success": True, + "scheduler_result": scheduler_result, + "feeding_result": feeding_result + } + # 2.24 物料变更推送 def report_material_change(self, material_obj: Dict[str, Any]) -> Dict[str, Any]: diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/bioyond_yihua_YB.json b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/bioyond_yihua_YB.json deleted file mode 100644 index 3119d0b..0000000 --- a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/bioyond_yihua_YB.json +++ /dev/null @@ -1,14487 +0,0 @@ -{ - "nodes": [ - { - "id": "bioyond_cell_workstation", - "name": "配液分液工站", - "children": [ - ], - "parent": null, - "type": "device", - "class": "bioyond_cell", - "config": { - "protocol_type": [], - "station_resource": {} - - }, - "data": {} - }, - { - "id": "BatteryStation", - "name": "扣电组装工作站", - "children": [ - "coin_cell_deck" - ], - "parent": null, - "type": "device", - "class": "bettery_station_registry", - "position": { - "x": 600, - "y": 400, - "z": 0 - }, - "config": { - "debug_mode": false, - "_comment": "protocol_type接外部工站固定写法字段,一般为空,deck写法也固定", - "protocol_type": [], - "deck": { - "data": { - "_resource_child_name": "coin_cell_deck", - "_resource_type": "unilabos.devices.workstation.coin_cell_assembly.button_battery_station:CoincellDeck" - } - }, - - "address": "192.168.1.20", - "port": 502 - }, - "data": {} - }, - { - "id": "coin_cell_deck", - "name": "coin_cell_deck", - "sample_id": null, - "children": [ - "zi_dan_jia", - "zi_dan_jia2", - "zi_dan_jia3", - "zi_dan_jia4", - "zi_dan_jia5", - "zi_dan_jia6", - "zi_dan_jia7", - "zi_dan_jia8", - "liaopan1", - "liaopan2", - "liaopan3", - "liaopan4", - "liaopan5", - "liaopan6", - "bottle_rack_3x4", - "bottle_rack_6x2", - "bottle_rack_6x2_2", - "tip_box_64", - "waste_tip_box" - ], - "parent": null, - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "CoincellDeck", - "size_x": 1620.0, - "size_y": 1270.0, - "size_z": 500.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "coin_cell_deck", - "barcode": null - }, - "data": {} - }, - { - "id": "zi_dan_jia", - "name": "zi_dan_jia", - "sample_id": null, - "children": [ - "zi_dan_jia_clipmagazinehole_0_0", - "zi_dan_jia_clipmagazinehole_0_1", - "zi_dan_jia_clipmagazinehole_1_0", - "zi_dan_jia_clipmagazinehole_1_1" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1400, - "y": 50, - "z": 0 - }, - "config": { - "type": "MagazineHolder_4", - "size_x": 80, - "size_y": 80, - "size_z": 10, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_four", - "model": null, - "barcode": null, - "ordering": { - "A1": "zi_dan_jia_clipmagazinehole_0_0", - "B1": "zi_dan_jia_clipmagazinehole_0_1", - "A2": "zi_dan_jia_clipmagazinehole_1_0", - "B2": "zi_dan_jia_clipmagazinehole_1_1" - }, - "hole_diameter": 14.0, - "hole_depth": 10.0, - "max_sheets_per_hole": 100 - }, - "data": {} - }, - { - "id": "zi_dan_jia_clipmagazinehole_0_0", - "name": "zi_dan_jia_clipmagazinehole_0_0", - "sample_id": null, - "children": [ - "zi_dan_jia2_jipian_0" - ], - "parent": "zi_dan_jia", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia2_jipian_0", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia_clipmagazinehole_0_0" - } - ] - } - }, - { - "id": "zi_dan_jia2_jipian_0", - "name": "zi_dan_jia2_jipian_0", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia_clipmagazinehole_0_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia_clipmagazinehole_0_1", - "name": "zi_dan_jia_clipmagazinehole_0_1", - "sample_id": null, - "children": [ - "zi_dan_jia2_jipian_1" - ], - "parent": "zi_dan_jia", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia2_jipian_1", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia_clipmagazinehole_0_1" - } - ] - } - }, - { - "id": "zi_dan_jia2_jipian_1", - "name": "zi_dan_jia2_jipian_1", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia_clipmagazinehole_0_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia_clipmagazinehole_1_0", - "name": "zi_dan_jia_clipmagazinehole_1_0", - "sample_id": null, - "children": [ - "zi_dan_jia2_jipian_2" - ], - "parent": "zi_dan_jia", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia2_jipian_2", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia_clipmagazinehole_1_0" - } - ] - } - }, - { - "id": "zi_dan_jia2_jipian_2", - "name": "zi_dan_jia2_jipian_2", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia_clipmagazinehole_1_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia_clipmagazinehole_1_1", - "name": "zi_dan_jia_clipmagazinehole_1_1", - "sample_id": null, - "children": [ - "zi_dan_jia2_jipian_3" - ], - "parent": "zi_dan_jia", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia2_jipian_3", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia_clipmagazinehole_1_1" - } - ] - } - }, - { - "id": "zi_dan_jia2_jipian_3", - "name": "zi_dan_jia2_jipian_3", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia_clipmagazinehole_1_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia2", - "name": "zi_dan_jia2", - "sample_id": null, - "children": [ - "zi_dan_jia2_clipmagazinehole_0_0", - "zi_dan_jia2_clipmagazinehole_0_1", - "zi_dan_jia2_clipmagazinehole_1_0", - "zi_dan_jia2_clipmagazinehole_1_1" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1600, - "y": 200, - "z": 0 - }, - "config": { - "type": "MagazineHolder_4", - "size_x": 80, - "size_y": 80, - "size_z": 10, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_four", - "model": null, - "barcode": null, - "ordering": { - "A1": "zi_dan_jia2_clipmagazinehole_0_0", - "B1": "zi_dan_jia2_clipmagazinehole_0_1", - "A2": "zi_dan_jia2_clipmagazinehole_1_0", - "B2": "zi_dan_jia2_clipmagazinehole_1_1" - }, - "hole_diameter": 14.0, - "hole_depth": 10.0, - "max_sheets_per_hole": 100 - }, - "data": {} - }, - { - "id": "zi_dan_jia2_clipmagazinehole_0_0", - "name": "zi_dan_jia2_clipmagazinehole_0_0", - "sample_id": null, - "children": [ - "zi_dan_jia_jipian_0" - ], - "parent": "zi_dan_jia2", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia_jipian_0", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia2_clipmagazinehole_0_0" - } - ] - } - }, - { - "id": "zi_dan_jia_jipian_0", - "name": "zi_dan_jia_jipian_0", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia2_clipmagazinehole_0_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia2_clipmagazinehole_0_1", - "name": "zi_dan_jia2_clipmagazinehole_0_1", - "sample_id": null, - "children": [ - "zi_dan_jia_jipian_1" - ], - "parent": "zi_dan_jia2", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia_jipian_1", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia2_clipmagazinehole_0_1" - } - ] - } - }, - { - "id": "zi_dan_jia_jipian_1", - "name": "zi_dan_jia_jipian_1", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia2_clipmagazinehole_0_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia2_clipmagazinehole_1_0", - "name": "zi_dan_jia2_clipmagazinehole_1_0", - "sample_id": null, - "children": [ - "zi_dan_jia_jipian_2" - ], - "parent": "zi_dan_jia2", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia_jipian_2", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia2_clipmagazinehole_1_0" - } - ] - } - }, - { - "id": "zi_dan_jia_jipian_2", - "name": "zi_dan_jia_jipian_2", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia2_clipmagazinehole_1_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia2_clipmagazinehole_1_1", - "name": "zi_dan_jia2_clipmagazinehole_1_1", - "sample_id": null, - "children": [ - "zi_dan_jia_jipian_3" - ], - "parent": "zi_dan_jia2", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia_jipian_3", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia2_clipmagazinehole_1_1" - } - ] - } - }, - { - "id": "zi_dan_jia_jipian_3", - "name": "zi_dan_jia_jipian_3", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia2_clipmagazinehole_1_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia3", - "name": "zi_dan_jia3", - "sample_id": null, - "children": [ - "zi_dan_jia3_clipmagazinehole_0_0", - "zi_dan_jia3_clipmagazinehole_0_1", - "zi_dan_jia3_clipmagazinehole_1_0", - "zi_dan_jia3_clipmagazinehole_1_1", - "zi_dan_jia3_clipmagazinehole_2_0", - "zi_dan_jia3_clipmagazinehole_2_1" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1500, - "y": 200, - "z": 0 - }, - "config": { - "type": "MagazineHolder_6", - "size_x": 80, - "size_y": 80, - "size_z": 10, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine", - "model": null, - "barcode": null, - "ordering": { - "A1": "zi_dan_jia3_clipmagazinehole_0_0", - "B1": "zi_dan_jia3_clipmagazinehole_0_1", - "A2": "zi_dan_jia3_clipmagazinehole_1_0", - "B2": "zi_dan_jia3_clipmagazinehole_1_1", - "A3": "zi_dan_jia3_clipmagazinehole_2_0", - "B3": "zi_dan_jia3_clipmagazinehole_2_1" - }, - "hole_diameter": 14.0, - "hole_depth": 10.0, - "max_sheets_per_hole": 100 - }, - "data": {} - }, - { - "id": "zi_dan_jia3_clipmagazinehole_0_0", - "name": "zi_dan_jia3_clipmagazinehole_0_0", - "sample_id": null, - "children": [ - "zi_dan_jia3_jipian_0" - ], - "parent": "zi_dan_jia3", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia3_jipian_0", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia3_clipmagazinehole_0_0" - } - ] - } - }, - { - "id": "zi_dan_jia3_jipian_0", - "name": "zi_dan_jia3_jipian_0", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia3_clipmagazinehole_0_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia3_clipmagazinehole_0_1", - "name": "zi_dan_jia3_clipmagazinehole_0_1", - "sample_id": null, - "children": [ - "zi_dan_jia3_jipian_1" - ], - "parent": "zi_dan_jia3", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia3_jipian_1", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia3_clipmagazinehole_0_1" - } - ] - } - }, - { - "id": "zi_dan_jia3_jipian_1", - "name": "zi_dan_jia3_jipian_1", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia3_clipmagazinehole_0_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia3_clipmagazinehole_1_0", - "name": "zi_dan_jia3_clipmagazinehole_1_0", - "sample_id": null, - "children": [ - "zi_dan_jia3_jipian_2" - ], - "parent": "zi_dan_jia3", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia3_jipian_2", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia3_clipmagazinehole_1_0" - } - ] - } - }, - { - "id": "zi_dan_jia3_jipian_2", - "name": "zi_dan_jia3_jipian_2", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia3_clipmagazinehole_1_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia3_clipmagazinehole_1_1", - "name": "zi_dan_jia3_clipmagazinehole_1_1", - "sample_id": null, - "children": [ - "zi_dan_jia3_jipian_3" - ], - "parent": "zi_dan_jia3", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia3_jipian_3", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia3_clipmagazinehole_1_1" - } - ] - } - }, - { - "id": "zi_dan_jia3_jipian_3", - "name": "zi_dan_jia3_jipian_3", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia3_clipmagazinehole_1_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia3_clipmagazinehole_2_0", - "name": "zi_dan_jia3_clipmagazinehole_2_0", - "sample_id": null, - "children": [ - "zi_dan_jia3_jipian_4" - ], - "parent": "zi_dan_jia3", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia3_jipian_4", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia3_clipmagazinehole_2_0" - } - ] - } - }, - { - "id": "zi_dan_jia3_jipian_4", - "name": "zi_dan_jia3_jipian_4", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia3_clipmagazinehole_2_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia3_clipmagazinehole_2_1", - "name": "zi_dan_jia3_clipmagazinehole_2_1", - "sample_id": null, - "children": [ - "zi_dan_jia3_jipian_5" - ], - "parent": "zi_dan_jia3", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia3_jipian_5", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia3_clipmagazinehole_2_1" - } - ] - } - }, - { - "id": "zi_dan_jia3_jipian_5", - "name": "zi_dan_jia3_jipian_5", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia3_clipmagazinehole_2_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia4", - "name": "zi_dan_jia4", - "sample_id": null, - "children": [ - "zi_dan_jia4_clipmagazinehole_0_0", - "zi_dan_jia4_clipmagazinehole_0_1", - "zi_dan_jia4_clipmagazinehole_1_0", - "zi_dan_jia4_clipmagazinehole_1_1", - "zi_dan_jia4_clipmagazinehole_2_0", - "zi_dan_jia4_clipmagazinehole_2_1" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1500, - "y": 300, - "z": 0 - }, - "config": { - "type": "MagazineHolder_6", - "size_x": 80, - "size_y": 80, - "size_z": 10, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine", - "model": null, - "barcode": null, - "ordering": { - "A1": "zi_dan_jia4_clipmagazinehole_0_0", - "B1": "zi_dan_jia4_clipmagazinehole_0_1", - "A2": "zi_dan_jia4_clipmagazinehole_1_0", - "B2": "zi_dan_jia4_clipmagazinehole_1_1", - "A3": "zi_dan_jia4_clipmagazinehole_2_0", - "B3": "zi_dan_jia4_clipmagazinehole_2_1" - }, - "hole_diameter": 14.0, - "hole_depth": 10.0, - "max_sheets_per_hole": 100 - }, - "data": {} - }, - { - "id": "zi_dan_jia4_clipmagazinehole_0_0", - "name": "zi_dan_jia4_clipmagazinehole_0_0", - "sample_id": null, - "children": [ - "zi_dan_jia4_jipian_0" - ], - "parent": "zi_dan_jia4", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia4_jipian_0", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia4_clipmagazinehole_0_0" - } - ] - } - }, - { - "id": "zi_dan_jia4_jipian_0", - "name": "zi_dan_jia4_jipian_0", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia4_clipmagazinehole_0_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia4_clipmagazinehole_0_1", - "name": "zi_dan_jia4_clipmagazinehole_0_1", - "sample_id": null, - "children": [ - "zi_dan_jia4_jipian_1" - ], - "parent": "zi_dan_jia4", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia4_jipian_1", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia4_clipmagazinehole_0_1" - } - ] - } - }, - { - "id": "zi_dan_jia4_jipian_1", - "name": "zi_dan_jia4_jipian_1", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia4_clipmagazinehole_0_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia4_clipmagazinehole_1_0", - "name": "zi_dan_jia4_clipmagazinehole_1_0", - "sample_id": null, - "children": [ - "zi_dan_jia4_jipian_2" - ], - "parent": "zi_dan_jia4", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia4_jipian_2", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia4_clipmagazinehole_1_0" - } - ] - } - }, - { - "id": "zi_dan_jia4_jipian_2", - "name": "zi_dan_jia4_jipian_2", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia4_clipmagazinehole_1_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia4_clipmagazinehole_1_1", - "name": "zi_dan_jia4_clipmagazinehole_1_1", - "sample_id": null, - "children": [ - "zi_dan_jia4_jipian_3" - ], - "parent": "zi_dan_jia4", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia4_jipian_3", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia4_clipmagazinehole_1_1" - } - ] - } - }, - { - "id": "zi_dan_jia4_jipian_3", - "name": "zi_dan_jia4_jipian_3", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia4_clipmagazinehole_1_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia4_clipmagazinehole_2_0", - "name": "zi_dan_jia4_clipmagazinehole_2_0", - "sample_id": null, - "children": [ - "zi_dan_jia4_jipian_4" - ], - "parent": "zi_dan_jia4", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia4_jipian_4", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia4_clipmagazinehole_2_0" - } - ] - } - }, - { - "id": "zi_dan_jia4_jipian_4", - "name": "zi_dan_jia4_jipian_4", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia4_clipmagazinehole_2_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia4_clipmagazinehole_2_1", - "name": "zi_dan_jia4_clipmagazinehole_2_1", - "sample_id": null, - "children": [ - "zi_dan_jia4_jipian_5" - ], - "parent": "zi_dan_jia4", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia4_jipian_5", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia4_clipmagazinehole_2_1" - } - ] - } - }, - { - "id": "zi_dan_jia4_jipian_5", - "name": "zi_dan_jia4_jipian_5", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia4_clipmagazinehole_2_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia5", - "name": "zi_dan_jia5", - "sample_id": null, - "children": [ - "zi_dan_jia5_clipmagazinehole_0_0", - "zi_dan_jia5_clipmagazinehole_0_1", - "zi_dan_jia5_clipmagazinehole_1_0", - "zi_dan_jia5_clipmagazinehole_1_1", - "zi_dan_jia5_clipmagazinehole_2_0", - "zi_dan_jia5_clipmagazinehole_2_1" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1600, - "y": 300, - "z": 0 - }, - "config": { - "type": "MagazineHolder_6", - "size_x": 80, - "size_y": 80, - "size_z": 10, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine", - "model": null, - "barcode": null, - "ordering": { - "A1": "zi_dan_jia5_clipmagazinehole_0_0", - "B1": "zi_dan_jia5_clipmagazinehole_0_1", - "A2": "zi_dan_jia5_clipmagazinehole_1_0", - "B2": "zi_dan_jia5_clipmagazinehole_1_1", - "A3": "zi_dan_jia5_clipmagazinehole_2_0", - "B3": "zi_dan_jia5_clipmagazinehole_2_1" - }, - "hole_diameter": 14.0, - "hole_depth": 10.0, - "max_sheets_per_hole": 100 - }, - "data": {} - }, - { - "id": "zi_dan_jia5_clipmagazinehole_0_0", - "name": "zi_dan_jia5_clipmagazinehole_0_0", - "sample_id": null, - "children": [ - "zi_dan_jia5_jipian_0" - ], - "parent": "zi_dan_jia5", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia5_jipian_0", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia5_clipmagazinehole_0_0" - } - ] - } - }, - { - "id": "zi_dan_jia5_jipian_0", - "name": "zi_dan_jia5_jipian_0", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia5_clipmagazinehole_0_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia5_clipmagazinehole_0_1", - "name": "zi_dan_jia5_clipmagazinehole_0_1", - "sample_id": null, - "children": [ - "zi_dan_jia5_jipian_1" - ], - "parent": "zi_dan_jia5", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia5_jipian_1", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia5_clipmagazinehole_0_1" - } - ] - } - }, - { - "id": "zi_dan_jia5_jipian_1", - "name": "zi_dan_jia5_jipian_1", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia5_clipmagazinehole_0_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia5_clipmagazinehole_1_0", - "name": "zi_dan_jia5_clipmagazinehole_1_0", - "sample_id": null, - "children": [ - "zi_dan_jia5_jipian_2" - ], - "parent": "zi_dan_jia5", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia5_jipian_2", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia5_clipmagazinehole_1_0" - } - ] - } - }, - { - "id": "zi_dan_jia5_jipian_2", - "name": "zi_dan_jia5_jipian_2", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia5_clipmagazinehole_1_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia5_clipmagazinehole_1_1", - "name": "zi_dan_jia5_clipmagazinehole_1_1", - "sample_id": null, - "children": [ - "zi_dan_jia5_jipian_3" - ], - "parent": "zi_dan_jia5", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia5_jipian_3", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia5_clipmagazinehole_1_1" - } - ] - } - }, - { - "id": "zi_dan_jia5_jipian_3", - "name": "zi_dan_jia5_jipian_3", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia5_clipmagazinehole_1_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia5_clipmagazinehole_2_0", - "name": "zi_dan_jia5_clipmagazinehole_2_0", - "sample_id": null, - "children": [ - "zi_dan_jia5_jipian_4" - ], - "parent": "zi_dan_jia5", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia5_jipian_4", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia5_clipmagazinehole_2_0" - } - ] - } - }, - { - "id": "zi_dan_jia5_jipian_4", - "name": "zi_dan_jia5_jipian_4", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia5_clipmagazinehole_2_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia5_clipmagazinehole_2_1", - "name": "zi_dan_jia5_clipmagazinehole_2_1", - "sample_id": null, - "children": [ - "zi_dan_jia5_jipian_5" - ], - "parent": "zi_dan_jia5", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia5_jipian_5", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia5_clipmagazinehole_2_1" - } - ] - } - }, - { - "id": "zi_dan_jia5_jipian_5", - "name": "zi_dan_jia5_jipian_5", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia5_clipmagazinehole_2_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia6", - "name": "zi_dan_jia6", - "sample_id": null, - "children": [ - "zi_dan_jia6_clipmagazinehole_0_0", - "zi_dan_jia6_clipmagazinehole_0_1", - "zi_dan_jia6_clipmagazinehole_1_0", - "zi_dan_jia6_clipmagazinehole_1_1", - "zi_dan_jia6_clipmagazinehole_2_0", - "zi_dan_jia6_clipmagazinehole_2_1" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1530, - "y": 500, - "z": 0 - }, - "config": { - "type": "MagazineHolder_6", - "size_x": 80, - "size_y": 80, - "size_z": 10, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine", - "model": null, - "barcode": null, - "ordering": { - "A1": "zi_dan_jia6_clipmagazinehole_0_0", - "B1": "zi_dan_jia6_clipmagazinehole_0_1", - "A2": "zi_dan_jia6_clipmagazinehole_1_0", - "B2": "zi_dan_jia6_clipmagazinehole_1_1", - "A3": "zi_dan_jia6_clipmagazinehole_2_0", - "B3": "zi_dan_jia6_clipmagazinehole_2_1" - }, - "hole_diameter": 14.0, - "hole_depth": 10.0, - "max_sheets_per_hole": 100 - }, - "data": {} - }, - { - "id": "zi_dan_jia6_clipmagazinehole_0_0", - "name": "zi_dan_jia6_clipmagazinehole_0_0", - "sample_id": null, - "children": [ - "zi_dan_jia6_jipian_0" - ], - "parent": "zi_dan_jia6", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia6_jipian_0", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia6_clipmagazinehole_0_0" - } - ] - } - }, - { - "id": "zi_dan_jia6_jipian_0", - "name": "zi_dan_jia6_jipian_0", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia6_clipmagazinehole_0_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia6_clipmagazinehole_0_1", - "name": "zi_dan_jia6_clipmagazinehole_0_1", - "sample_id": null, - "children": [ - "zi_dan_jia6_jipian_1" - ], - "parent": "zi_dan_jia6", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia6_jipian_1", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia6_clipmagazinehole_0_1" - } - ] - } - }, - { - "id": "zi_dan_jia6_jipian_1", - "name": "zi_dan_jia6_jipian_1", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia6_clipmagazinehole_0_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia6_clipmagazinehole_1_0", - "name": "zi_dan_jia6_clipmagazinehole_1_0", - "sample_id": null, - "children": [ - "zi_dan_jia6_jipian_2" - ], - "parent": "zi_dan_jia6", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia6_jipian_2", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia6_clipmagazinehole_1_0" - } - ] - } - }, - { - "id": "zi_dan_jia6_jipian_2", - "name": "zi_dan_jia6_jipian_2", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia6_clipmagazinehole_1_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia6_clipmagazinehole_1_1", - "name": "zi_dan_jia6_clipmagazinehole_1_1", - "sample_id": null, - "children": [ - "zi_dan_jia6_jipian_3" - ], - "parent": "zi_dan_jia6", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia6_jipian_3", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia6_clipmagazinehole_1_1" - } - ] - } - }, - { - "id": "zi_dan_jia6_jipian_3", - "name": "zi_dan_jia6_jipian_3", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia6_clipmagazinehole_1_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia6_clipmagazinehole_2_0", - "name": "zi_dan_jia6_clipmagazinehole_2_0", - "sample_id": null, - "children": [ - "zi_dan_jia6_jipian_4" - ], - "parent": "zi_dan_jia6", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia6_jipian_4", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia6_clipmagazinehole_2_0" - } - ] - } - }, - { - "id": "zi_dan_jia6_jipian_4", - "name": "zi_dan_jia6_jipian_4", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia6_clipmagazinehole_2_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia6_clipmagazinehole_2_1", - "name": "zi_dan_jia6_clipmagazinehole_2_1", - "sample_id": null, - "children": [ - "zi_dan_jia6_jipian_5" - ], - "parent": "zi_dan_jia6", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia6_jipian_5", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia6_clipmagazinehole_2_1" - } - ] - } - }, - { - "id": "zi_dan_jia6_jipian_5", - "name": "zi_dan_jia6_jipian_5", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia6_clipmagazinehole_2_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia7", - "name": "zi_dan_jia7", - "sample_id": null, - "children": [ - "zi_dan_jia7_clipmagazinehole_0_0", - "zi_dan_jia7_clipmagazinehole_0_1", - "zi_dan_jia7_clipmagazinehole_1_0", - "zi_dan_jia7_clipmagazinehole_1_1", - "zi_dan_jia7_clipmagazinehole_2_0", - "zi_dan_jia7_clipmagazinehole_2_1" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1180, - "y": 400, - "z": 0 - }, - "config": { - "type": "MagazineHolder_6", - "size_x": 80, - "size_y": 80, - "size_z": 10, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine", - "model": null, - "barcode": null, - "ordering": { - "A1": "zi_dan_jia7_clipmagazinehole_0_0", - "B1": "zi_dan_jia7_clipmagazinehole_0_1", - "A2": "zi_dan_jia7_clipmagazinehole_1_0", - "B2": "zi_dan_jia7_clipmagazinehole_1_1", - "A3": "zi_dan_jia7_clipmagazinehole_2_0", - "B3": "zi_dan_jia7_clipmagazinehole_2_1" - }, - "hole_diameter": 14.0, - "hole_depth": 10.0, - "max_sheets_per_hole": 100 - }, - "data": {} - }, - { - "id": "zi_dan_jia7_clipmagazinehole_0_0", - "name": "zi_dan_jia7_clipmagazinehole_0_0", - "sample_id": null, - "children": [ - "zi_dan_jia7_jipian_0" - ], - "parent": "zi_dan_jia7", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia7_jipian_0", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia7_clipmagazinehole_0_0" - } - ] - } - }, - { - "id": "zi_dan_jia7_jipian_0", - "name": "zi_dan_jia7_jipian_0", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia7_clipmagazinehole_0_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia7_clipmagazinehole_0_1", - "name": "zi_dan_jia7_clipmagazinehole_0_1", - "sample_id": null, - "children": [ - "zi_dan_jia7_jipian_1" - ], - "parent": "zi_dan_jia7", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia7_jipian_1", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia7_clipmagazinehole_0_1" - } - ] - } - }, - { - "id": "zi_dan_jia7_jipian_1", - "name": "zi_dan_jia7_jipian_1", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia7_clipmagazinehole_0_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia7_clipmagazinehole_1_0", - "name": "zi_dan_jia7_clipmagazinehole_1_0", - "sample_id": null, - "children": [ - "zi_dan_jia7_jipian_2" - ], - "parent": "zi_dan_jia7", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia7_jipian_2", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia7_clipmagazinehole_1_0" - } - ] - } - }, - { - "id": "zi_dan_jia7_jipian_2", - "name": "zi_dan_jia7_jipian_2", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia7_clipmagazinehole_1_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia7_clipmagazinehole_1_1", - "name": "zi_dan_jia7_clipmagazinehole_1_1", - "sample_id": null, - "children": [ - "zi_dan_jia7_jipian_3" - ], - "parent": "zi_dan_jia7", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia7_jipian_3", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia7_clipmagazinehole_1_1" - } - ] - } - }, - { - "id": "zi_dan_jia7_jipian_3", - "name": "zi_dan_jia7_jipian_3", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia7_clipmagazinehole_1_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia7_clipmagazinehole_2_0", - "name": "zi_dan_jia7_clipmagazinehole_2_0", - "sample_id": null, - "children": [ - "zi_dan_jia7_jipian_4" - ], - "parent": "zi_dan_jia7", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia7_jipian_4", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia7_clipmagazinehole_2_0" - } - ] - } - }, - { - "id": "zi_dan_jia7_jipian_4", - "name": "zi_dan_jia7_jipian_4", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia7_clipmagazinehole_2_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia7_clipmagazinehole_2_1", - "name": "zi_dan_jia7_clipmagazinehole_2_1", - "sample_id": null, - "children": [ - "zi_dan_jia7_jipian_5" - ], - "parent": "zi_dan_jia7", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia7_jipian_5", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia7_clipmagazinehole_2_1" - } - ] - } - }, - { - "id": "zi_dan_jia7_jipian_5", - "name": "zi_dan_jia7_jipian_5", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia7_clipmagazinehole_2_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia8", - "name": "zi_dan_jia8", - "sample_id": null, - "children": [ - "zi_dan_jia8_clipmagazinehole_0_0", - "zi_dan_jia8_clipmagazinehole_0_1", - "zi_dan_jia8_clipmagazinehole_1_0", - "zi_dan_jia8_clipmagazinehole_1_1", - "zi_dan_jia8_clipmagazinehole_2_0", - "zi_dan_jia8_clipmagazinehole_2_1" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1280, - "y": 400, - "z": 0 - }, - "config": { - "type": "MagazineHolder_6", - "size_x": 80, - "size_y": 80, - "size_z": 10, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine", - "model": null, - "barcode": null, - "ordering": { - "A1": "zi_dan_jia8_clipmagazinehole_0_0", - "B1": "zi_dan_jia8_clipmagazinehole_0_1", - "A2": "zi_dan_jia8_clipmagazinehole_1_0", - "B2": "zi_dan_jia8_clipmagazinehole_1_1", - "A3": "zi_dan_jia8_clipmagazinehole_2_0", - "B3": "zi_dan_jia8_clipmagazinehole_2_1" - }, - "hole_diameter": 14.0, - "hole_depth": 10.0, - "max_sheets_per_hole": 100 - }, - "data": {} - }, - { - "id": "zi_dan_jia8_clipmagazinehole_0_0", - "name": "zi_dan_jia8_clipmagazinehole_0_0", - "sample_id": null, - "children": [ - "zi_dan_jia8_jipian_0" - ], - "parent": "zi_dan_jia8", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia8_jipian_0", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia8_clipmagazinehole_0_0" - } - ] - } - }, - { - "id": "zi_dan_jia8_jipian_0", - "name": "zi_dan_jia8_jipian_0", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia8_clipmagazinehole_0_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia8_clipmagazinehole_0_1", - "name": "zi_dan_jia8_clipmagazinehole_0_1", - "sample_id": null, - "children": [ - "zi_dan_jia8_jipian_1" - ], - "parent": "zi_dan_jia8", - "type": "container", - "class": "", - "position": { - "x": 15.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia8_jipian_1", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia8_clipmagazinehole_0_1" - } - ] - } - }, - { - "id": "zi_dan_jia8_jipian_1", - "name": "zi_dan_jia8_jipian_1", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia8_clipmagazinehole_0_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia8_clipmagazinehole_1_0", - "name": "zi_dan_jia8_clipmagazinehole_1_0", - "sample_id": null, - "children": [ - "zi_dan_jia8_jipian_2" - ], - "parent": "zi_dan_jia8", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia8_jipian_2", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia8_clipmagazinehole_1_0" - } - ] - } - }, - { - "id": "zi_dan_jia8_jipian_2", - "name": "zi_dan_jia8_jipian_2", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia8_clipmagazinehole_1_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia8_clipmagazinehole_1_1", - "name": "zi_dan_jia8_clipmagazinehole_1_1", - "sample_id": null, - "children": [ - "zi_dan_jia8_jipian_3" - ], - "parent": "zi_dan_jia8", - "type": "container", - "class": "", - "position": { - "x": 40.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia8_jipian_3", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia8_clipmagazinehole_1_1" - } - ] - } - }, - { - "id": "zi_dan_jia8_jipian_3", - "name": "zi_dan_jia8_jipian_3", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia8_clipmagazinehole_1_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia8_clipmagazinehole_2_0", - "name": "zi_dan_jia8_clipmagazinehole_2_0", - "sample_id": null, - "children": [ - "zi_dan_jia8_jipian_4" - ], - "parent": "zi_dan_jia8", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 52.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia8_jipian_4", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia8_clipmagazinehole_2_0" - } - ] - } - }, - { - "id": "zi_dan_jia8_jipian_4", - "name": "zi_dan_jia8_jipian_4", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia8_clipmagazinehole_2_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "zi_dan_jia8_clipmagazinehole_2_1", - "name": "zi_dan_jia8_clipmagazinehole_2_1", - "sample_id": null, - "children": [ - "zi_dan_jia8_jipian_5" - ], - "parent": "zi_dan_jia8", - "type": "container", - "class": "", - "position": { - "x": 65.0, - "y": 27.5, - "z": 10 - }, - "config": { - "type": "Magazine", - "size_x": 14.0, - "size_y": 14.0, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "clip_magazine_hole", - "model": null, - "barcode": null, - "max_volume": 1960.0, - "material_z_thickness": null, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "sheet_count": 1, - "sheets": [ - { - "name": "zi_dan_jia8_jipian_5", - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "location": null, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null, - "children": [], - "parent_name": "zi_dan_jia8_clipmagazinehole_2_1" - } - ] - } - }, - { - "id": "zi_dan_jia8_jipian_5", - "name": "zi_dan_jia8_jipian_5", - "sample_id": null, - "children": [], - "parent": "zi_dan_jia8_clipmagazinehole_2_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1", - "name": "liaopan1", - "sample_id": null, - "children": [ - "liaopan1_materialhole_0_0", - "liaopan1_materialhole_0_1", - "liaopan1_materialhole_0_2", - "liaopan1_materialhole_0_3", - "liaopan1_materialhole_1_0", - "liaopan1_materialhole_1_1", - "liaopan1_materialhole_1_2", - "liaopan1_materialhole_1_3", - "liaopan1_materialhole_2_0", - "liaopan1_materialhole_2_1", - "liaopan1_materialhole_2_2", - "liaopan1_materialhole_2_3", - "liaopan1_materialhole_3_0", - "liaopan1_materialhole_3_1", - "liaopan1_materialhole_3_2", - "liaopan1_materialhole_3_3" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1010, - "y": 50, - "z": 0 - }, - "config": { - "type": "MaterialPlate", - "size_x": 120, - "size_y": 100, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_plate", - "model": null, - "barcode": null, - "ordering": { - "A1": "liaopan1_materialhole_0_0", - "B1": "liaopan1_materialhole_0_1", - "C1": "liaopan1_materialhole_0_2", - "D1": "liaopan1_materialhole_0_3", - "A2": "liaopan1_materialhole_1_0", - "B2": "liaopan1_materialhole_1_1", - "C2": "liaopan1_materialhole_1_2", - "D2": "liaopan1_materialhole_1_3", - "A3": "liaopan1_materialhole_2_0", - "B3": "liaopan1_materialhole_2_1", - "C3": "liaopan1_materialhole_2_2", - "D3": "liaopan1_materialhole_2_3", - "A4": "liaopan1_materialhole_3_0", - "B4": "liaopan1_materialhole_3_1", - "C4": "liaopan1_materialhole_3_2", - "D4": "liaopan1_materialhole_3_3" - } - }, - "data": {} - }, - { - "id": "liaopan1_materialhole_0_0", - "name": "liaopan1_materialhole_0_0", - "sample_id": null, - "children": [ - "liaopan1_jipian_0" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_0", - "name": "liaopan1_jipian_0", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_0_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_0_1", - "name": "liaopan1_materialhole_0_1", - "sample_id": null, - "children": [ - "liaopan1_jipian_1" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_1", - "name": "liaopan1_jipian_1", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_0_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_0_2", - "name": "liaopan1_materialhole_0_2", - "sample_id": null, - "children": [ - "liaopan1_jipian_2" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_2", - "name": "liaopan1_jipian_2", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_0_2", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_0_3", - "name": "liaopan1_materialhole_0_3", - "sample_id": null, - "children": [ - "liaopan1_jipian_3" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_3", - "name": "liaopan1_jipian_3", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_0_3", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_1_0", - "name": "liaopan1_materialhole_1_0", - "sample_id": null, - "children": [ - "liaopan1_jipian_4" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_4", - "name": "liaopan1_jipian_4", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_1_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_1_1", - "name": "liaopan1_materialhole_1_1", - "sample_id": null, - "children": [ - "liaopan1_jipian_5" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_5", - "name": "liaopan1_jipian_5", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_1_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_1_2", - "name": "liaopan1_materialhole_1_2", - "sample_id": null, - "children": [ - "liaopan1_jipian_6" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_6", - "name": "liaopan1_jipian_6", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_1_2", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_1_3", - "name": "liaopan1_materialhole_1_3", - "sample_id": null, - "children": [ - "liaopan1_jipian_7" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_7", - "name": "liaopan1_jipian_7", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_1_3", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_2_0", - "name": "liaopan1_materialhole_2_0", - "sample_id": null, - "children": [ - "liaopan1_jipian_8" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_8", - "name": "liaopan1_jipian_8", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_2_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_2_1", - "name": "liaopan1_materialhole_2_1", - "sample_id": null, - "children": [ - "liaopan1_jipian_9" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_9", - "name": "liaopan1_jipian_9", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_2_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_2_2", - "name": "liaopan1_materialhole_2_2", - "sample_id": null, - "children": [ - "liaopan1_jipian_10" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_10", - "name": "liaopan1_jipian_10", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_2_2", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_2_3", - "name": "liaopan1_materialhole_2_3", - "sample_id": null, - "children": [ - "liaopan1_jipian_11" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_11", - "name": "liaopan1_jipian_11", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_2_3", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_3_0", - "name": "liaopan1_materialhole_3_0", - "sample_id": null, - "children": [ - "liaopan1_jipian_12" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_12", - "name": "liaopan1_jipian_12", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_3_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_3_1", - "name": "liaopan1_materialhole_3_1", - "sample_id": null, - "children": [ - "liaopan1_jipian_13" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_13", - "name": "liaopan1_jipian_13", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_3_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_3_2", - "name": "liaopan1_materialhole_3_2", - "sample_id": null, - "children": [ - "liaopan1_jipian_14" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_14", - "name": "liaopan1_jipian_14", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_3_2", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan1_materialhole_3_3", - "name": "liaopan1_materialhole_3_3", - "sample_id": null, - "children": [ - "liaopan1_jipian_15" - ], - "parent": "liaopan1", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan1_jipian_15", - "name": "liaopan1_jipian_15", - "sample_id": null, - "children": [], - "parent": "liaopan1_materialhole_3_3", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan2", - "name": "liaopan2", - "sample_id": null, - "children": [ - "liaopan2_materialhole_0_0", - "liaopan2_materialhole_0_1", - "liaopan2_materialhole_0_2", - "liaopan2_materialhole_0_3", - "liaopan2_materialhole_1_0", - "liaopan2_materialhole_1_1", - "liaopan2_materialhole_1_2", - "liaopan2_materialhole_1_3", - "liaopan2_materialhole_2_0", - "liaopan2_materialhole_2_1", - "liaopan2_materialhole_2_2", - "liaopan2_materialhole_2_3", - "liaopan2_materialhole_3_0", - "liaopan2_materialhole_3_1", - "liaopan2_materialhole_3_2", - "liaopan2_materialhole_3_3" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1130, - "y": 50, - "z": 0 - }, - "config": { - "type": "MaterialPlate", - "size_x": 120, - "size_y": 100, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_plate", - "model": null, - "barcode": null, - "ordering": { - "A1": "liaopan2_materialhole_0_0", - "B1": "liaopan2_materialhole_0_1", - "C1": "liaopan2_materialhole_0_2", - "D1": "liaopan2_materialhole_0_3", - "A2": "liaopan2_materialhole_1_0", - "B2": "liaopan2_materialhole_1_1", - "C2": "liaopan2_materialhole_1_2", - "D2": "liaopan2_materialhole_1_3", - "A3": "liaopan2_materialhole_2_0", - "B3": "liaopan2_materialhole_2_1", - "C3": "liaopan2_materialhole_2_2", - "D3": "liaopan2_materialhole_2_3", - "A4": "liaopan2_materialhole_3_0", - "B4": "liaopan2_materialhole_3_1", - "C4": "liaopan2_materialhole_3_2", - "D4": "liaopan2_materialhole_3_3" - } - }, - "data": {} - }, - { - "id": "liaopan2_materialhole_0_0", - "name": "liaopan2_materialhole_0_0", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_0_1", - "name": "liaopan2_materialhole_0_1", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_0_2", - "name": "liaopan2_materialhole_0_2", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_0_3", - "name": "liaopan2_materialhole_0_3", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_1_0", - "name": "liaopan2_materialhole_1_0", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_1_1", - "name": "liaopan2_materialhole_1_1", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_1_2", - "name": "liaopan2_materialhole_1_2", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_1_3", - "name": "liaopan2_materialhole_1_3", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_2_0", - "name": "liaopan2_materialhole_2_0", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_2_1", - "name": "liaopan2_materialhole_2_1", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_2_2", - "name": "liaopan2_materialhole_2_2", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_2_3", - "name": "liaopan2_materialhole_2_3", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_3_0", - "name": "liaopan2_materialhole_3_0", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_3_1", - "name": "liaopan2_materialhole_3_1", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_3_2", - "name": "liaopan2_materialhole_3_2", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan2_materialhole_3_3", - "name": "liaopan2_materialhole_3_3", - "sample_id": null, - "children": [], - "parent": "liaopan2", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3", - "name": "liaopan3", - "sample_id": null, - "children": [ - "liaopan3_materialhole_0_0", - "liaopan3_materialhole_0_1", - "liaopan3_materialhole_0_2", - "liaopan3_materialhole_0_3", - "liaopan3_materialhole_1_0", - "liaopan3_materialhole_1_1", - "liaopan3_materialhole_1_2", - "liaopan3_materialhole_1_3", - "liaopan3_materialhole_2_0", - "liaopan3_materialhole_2_1", - "liaopan3_materialhole_2_2", - "liaopan3_materialhole_2_3", - "liaopan3_materialhole_3_0", - "liaopan3_materialhole_3_1", - "liaopan3_materialhole_3_2", - "liaopan3_materialhole_3_3" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1250, - "y": 50, - "z": 0 - }, - "config": { - "type": "MaterialPlate", - "size_x": 120, - "size_y": 100, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_plate", - "model": null, - "barcode": null, - "ordering": { - "A1": "liaopan3_materialhole_0_0", - "B1": "liaopan3_materialhole_0_1", - "C1": "liaopan3_materialhole_0_2", - "D1": "liaopan3_materialhole_0_3", - "A2": "liaopan3_materialhole_1_0", - "B2": "liaopan3_materialhole_1_1", - "C2": "liaopan3_materialhole_1_2", - "D2": "liaopan3_materialhole_1_3", - "A3": "liaopan3_materialhole_2_0", - "B3": "liaopan3_materialhole_2_1", - "C3": "liaopan3_materialhole_2_2", - "D3": "liaopan3_materialhole_2_3", - "A4": "liaopan3_materialhole_3_0", - "B4": "liaopan3_materialhole_3_1", - "C4": "liaopan3_materialhole_3_2", - "D4": "liaopan3_materialhole_3_3" - } - }, - "data": {} - }, - { - "id": "liaopan3_materialhole_0_0", - "name": "liaopan3_materialhole_0_0", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_0_1", - "name": "liaopan3_materialhole_0_1", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_0_2", - "name": "liaopan3_materialhole_0_2", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_0_3", - "name": "liaopan3_materialhole_0_3", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_1_0", - "name": "liaopan3_materialhole_1_0", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_1_1", - "name": "liaopan3_materialhole_1_1", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_1_2", - "name": "liaopan3_materialhole_1_2", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_1_3", - "name": "liaopan3_materialhole_1_3", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_2_0", - "name": "liaopan3_materialhole_2_0", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_2_1", - "name": "liaopan3_materialhole_2_1", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_2_2", - "name": "liaopan3_materialhole_2_2", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_2_3", - "name": "liaopan3_materialhole_2_3", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_3_0", - "name": "liaopan3_materialhole_3_0", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_3_1", - "name": "liaopan3_materialhole_3_1", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_3_2", - "name": "liaopan3_materialhole_3_2", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan3_materialhole_3_3", - "name": "liaopan3_materialhole_3_3", - "sample_id": null, - "children": [], - "parent": "liaopan3", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4", - "name": "liaopan4", - "sample_id": null, - "children": [ - "liaopan4_materialhole_0_0", - "liaopan4_materialhole_0_1", - "liaopan4_materialhole_0_2", - "liaopan4_materialhole_0_3", - "liaopan4_materialhole_1_0", - "liaopan4_materialhole_1_1", - "liaopan4_materialhole_1_2", - "liaopan4_materialhole_1_3", - "liaopan4_materialhole_2_0", - "liaopan4_materialhole_2_1", - "liaopan4_materialhole_2_2", - "liaopan4_materialhole_2_3", - "liaopan4_materialhole_3_0", - "liaopan4_materialhole_3_1", - "liaopan4_materialhole_3_2", - "liaopan4_materialhole_3_3" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1010, - "y": 150, - "z": 0 - }, - "config": { - "type": "MaterialPlate", - "size_x": 120, - "size_y": 100, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_plate", - "model": null, - "barcode": null, - "ordering": { - "A1": "liaopan4_materialhole_0_0", - "B1": "liaopan4_materialhole_0_1", - "C1": "liaopan4_materialhole_0_2", - "D1": "liaopan4_materialhole_0_3", - "A2": "liaopan4_materialhole_1_0", - "B2": "liaopan4_materialhole_1_1", - "C2": "liaopan4_materialhole_1_2", - "D2": "liaopan4_materialhole_1_3", - "A3": "liaopan4_materialhole_2_0", - "B3": "liaopan4_materialhole_2_1", - "C3": "liaopan4_materialhole_2_2", - "D3": "liaopan4_materialhole_2_3", - "A4": "liaopan4_materialhole_3_0", - "B4": "liaopan4_materialhole_3_1", - "C4": "liaopan4_materialhole_3_2", - "D4": "liaopan4_materialhole_3_3" - } - }, - "data": {} - }, - { - "id": "liaopan4_materialhole_0_0", - "name": "liaopan4_materialhole_0_0", - "sample_id": null, - "children": [ - "liaopan4_jipian_0" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_0", - "name": "liaopan4_jipian_0", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_0_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_0_1", - "name": "liaopan4_materialhole_0_1", - "sample_id": null, - "children": [ - "liaopan4_jipian_1" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_1", - "name": "liaopan4_jipian_1", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_0_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_0_2", - "name": "liaopan4_materialhole_0_2", - "sample_id": null, - "children": [ - "liaopan4_jipian_2" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_2", - "name": "liaopan4_jipian_2", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_0_2", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_0_3", - "name": "liaopan4_materialhole_0_3", - "sample_id": null, - "children": [ - "liaopan4_jipian_3" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_3", - "name": "liaopan4_jipian_3", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_0_3", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_1_0", - "name": "liaopan4_materialhole_1_0", - "sample_id": null, - "children": [ - "liaopan4_jipian_4" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_4", - "name": "liaopan4_jipian_4", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_1_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_1_1", - "name": "liaopan4_materialhole_1_1", - "sample_id": null, - "children": [ - "liaopan4_jipian_5" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_5", - "name": "liaopan4_jipian_5", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_1_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_1_2", - "name": "liaopan4_materialhole_1_2", - "sample_id": null, - "children": [ - "liaopan4_jipian_6" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_6", - "name": "liaopan4_jipian_6", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_1_2", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_1_3", - "name": "liaopan4_materialhole_1_3", - "sample_id": null, - "children": [ - "liaopan4_jipian_7" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_7", - "name": "liaopan4_jipian_7", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_1_3", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_2_0", - "name": "liaopan4_materialhole_2_0", - "sample_id": null, - "children": [ - "liaopan4_jipian_8" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_8", - "name": "liaopan4_jipian_8", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_2_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_2_1", - "name": "liaopan4_materialhole_2_1", - "sample_id": null, - "children": [ - "liaopan4_jipian_9" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_9", - "name": "liaopan4_jipian_9", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_2_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_2_2", - "name": "liaopan4_materialhole_2_2", - "sample_id": null, - "children": [ - "liaopan4_jipian_10" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_10", - "name": "liaopan4_jipian_10", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_2_2", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_2_3", - "name": "liaopan4_materialhole_2_3", - "sample_id": null, - "children": [ - "liaopan4_jipian_11" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_11", - "name": "liaopan4_jipian_11", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_2_3", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_3_0", - "name": "liaopan4_materialhole_3_0", - "sample_id": null, - "children": [ - "liaopan4_jipian_12" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_12", - "name": "liaopan4_jipian_12", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_3_0", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_3_1", - "name": "liaopan4_materialhole_3_1", - "sample_id": null, - "children": [ - "liaopan4_jipian_13" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_13", - "name": "liaopan4_jipian_13", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_3_1", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_3_2", - "name": "liaopan4_materialhole_3_2", - "sample_id": null, - "children": [ - "liaopan4_jipian_14" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_14", - "name": "liaopan4_jipian_14", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_3_2", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan4_materialhole_3_3", - "name": "liaopan4_materialhole_3_3", - "sample_id": null, - "children": [ - "liaopan4_jipian_15" - ], - "parent": "liaopan4", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan4_jipian_15", - "name": "liaopan4_jipian_15", - "sample_id": null, - "children": [], - "parent": "liaopan4_materialhole_3_3", - "type": "container", - "class": "", - "position": { - "x": 0, - "y": 0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "liaopan5", - "name": "liaopan5", - "sample_id": null, - "children": [ - "liaopan5_materialhole_0_0", - "liaopan5_materialhole_0_1", - "liaopan5_materialhole_0_2", - "liaopan5_materialhole_0_3", - "liaopan5_materialhole_1_0", - "liaopan5_materialhole_1_1", - "liaopan5_materialhole_1_2", - "liaopan5_materialhole_1_3", - "liaopan5_materialhole_2_0", - "liaopan5_materialhole_2_1", - "liaopan5_materialhole_2_2", - "liaopan5_materialhole_2_3", - "liaopan5_materialhole_3_0", - "liaopan5_materialhole_3_1", - "liaopan5_materialhole_3_2", - "liaopan5_materialhole_3_3" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1130, - "y": 150, - "z": 0 - }, - "config": { - "type": "MaterialPlate", - "size_x": 120, - "size_y": 100, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_plate", - "model": null, - "barcode": null, - "ordering": { - "A1": "liaopan5_materialhole_0_0", - "B1": "liaopan5_materialhole_0_1", - "C1": "liaopan5_materialhole_0_2", - "D1": "liaopan5_materialhole_0_3", - "A2": "liaopan5_materialhole_1_0", - "B2": "liaopan5_materialhole_1_1", - "C2": "liaopan5_materialhole_1_2", - "D2": "liaopan5_materialhole_1_3", - "A3": "liaopan5_materialhole_2_0", - "B3": "liaopan5_materialhole_2_1", - "C3": "liaopan5_materialhole_2_2", - "D3": "liaopan5_materialhole_2_3", - "A4": "liaopan5_materialhole_3_0", - "B4": "liaopan5_materialhole_3_1", - "C4": "liaopan5_materialhole_3_2", - "D4": "liaopan5_materialhole_3_3" - } - }, - "data": {} - }, - { - "id": "liaopan5_materialhole_0_0", - "name": "liaopan5_materialhole_0_0", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_0_1", - "name": "liaopan5_materialhole_0_1", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_0_2", - "name": "liaopan5_materialhole_0_2", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_0_3", - "name": "liaopan5_materialhole_0_3", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_1_0", - "name": "liaopan5_materialhole_1_0", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_1_1", - "name": "liaopan5_materialhole_1_1", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_1_2", - "name": "liaopan5_materialhole_1_2", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_1_3", - "name": "liaopan5_materialhole_1_3", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_2_0", - "name": "liaopan5_materialhole_2_0", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_2_1", - "name": "liaopan5_materialhole_2_1", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_2_2", - "name": "liaopan5_materialhole_2_2", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_2_3", - "name": "liaopan5_materialhole_2_3", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_3_0", - "name": "liaopan5_materialhole_3_0", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_3_1", - "name": "liaopan5_materialhole_3_1", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_3_2", - "name": "liaopan5_materialhole_3_2", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan5_materialhole_3_3", - "name": "liaopan5_materialhole_3_3", - "sample_id": null, - "children": [], - "parent": "liaopan5", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6", - "name": "liaopan6", - "sample_id": null, - "children": [ - "liaopan6_materialhole_0_0", - "liaopan6_materialhole_0_1", - "liaopan6_materialhole_0_2", - "liaopan6_materialhole_0_3", - "liaopan6_materialhole_1_0", - "liaopan6_materialhole_1_1", - "liaopan6_materialhole_1_2", - "liaopan6_materialhole_1_3", - "liaopan6_materialhole_2_0", - "liaopan6_materialhole_2_1", - "liaopan6_materialhole_2_2", - "liaopan6_materialhole_2_3", - "liaopan6_materialhole_3_0", - "liaopan6_materialhole_3_1", - "liaopan6_materialhole_3_2", - "liaopan6_materialhole_3_3" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 1250, - "y": 150, - "z": 0 - }, - "config": { - "type": "MaterialPlate", - "size_x": 120, - "size_y": 100, - "size_z": 10.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_plate", - "model": null, - "barcode": null, - "ordering": { - "A1": "liaopan6_materialhole_0_0", - "B1": "liaopan6_materialhole_0_1", - "C1": "liaopan6_materialhole_0_2", - "D1": "liaopan6_materialhole_0_3", - "A2": "liaopan6_materialhole_1_0", - "B2": "liaopan6_materialhole_1_1", - "C2": "liaopan6_materialhole_1_2", - "D2": "liaopan6_materialhole_1_3", - "A3": "liaopan6_materialhole_2_0", - "B3": "liaopan6_materialhole_2_1", - "C3": "liaopan6_materialhole_2_2", - "D3": "liaopan6_materialhole_2_3", - "A4": "liaopan6_materialhole_3_0", - "B4": "liaopan6_materialhole_3_1", - "C4": "liaopan6_materialhole_3_2", - "D4": "liaopan6_materialhole_3_3" - } - }, - "data": {} - }, - { - "id": "liaopan6_materialhole_0_0", - "name": "liaopan6_materialhole_0_0", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_0_1", - "name": "liaopan6_materialhole_0_1", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_0_2", - "name": "liaopan6_materialhole_0_2", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_0_3", - "name": "liaopan6_materialhole_0_3", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 12.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_1_0", - "name": "liaopan6_materialhole_1_0", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_1_1", - "name": "liaopan6_materialhole_1_1", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_1_2", - "name": "liaopan6_materialhole_1_2", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_1_3", - "name": "liaopan6_materialhole_1_3", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 36.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_2_0", - "name": "liaopan6_materialhole_2_0", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_2_1", - "name": "liaopan6_materialhole_2_1", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_2_2", - "name": "liaopan6_materialhole_2_2", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_2_3", - "name": "liaopan6_materialhole_2_3", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 60.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_3_0", - "name": "liaopan6_materialhole_3_0", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 74.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_3_1", - "name": "liaopan6_materialhole_3_1", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 50.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_3_2", - "name": "liaopan6_materialhole_3_2", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 26.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "liaopan6_materialhole_3_3", - "name": "liaopan6_materialhole_3_3", - "sample_id": null, - "children": [], - "parent": "liaopan6", - "type": "container", - "class": "", - "position": { - "x": 84.0, - "y": 2.0, - "z": 10.0 - }, - "config": { - "type": "MaterialHole", - "size_x": 16, - "size_y": 16, - "size_z": 16, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "material_hole", - "model": null, - "barcode": null - }, - "data": { - "diameter": 20, - "depth": 10, - "max_sheets": 1, - "info": null - } - }, - { - "id": "bottle_rack_3x4", - "name": "bottle_rack_3x4", - "sample_id": null, - "children": [ - "sheet_3x4_0", - "sheet_3x4_1", - "sheet_3x4_2", - "sheet_3x4_3", - "sheet_3x4_4", - "sheet_3x4_5", - "sheet_3x4_6", - "sheet_3x4_7", - "sheet_3x4_8", - "sheet_3x4_9", - "sheet_3x4_10", - "sheet_3x4_11" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 100, - "y": 200, - "z": 0 - }, - "config": { - "type": "BottleRack", - "size_x": 210.0, - "size_y": 140.0, - "size_z": 100.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "bottle_rack", - "model": null, - "barcode": null, - "num_items_x": 3, - "num_items_y": 4, - "position_spacing": 35.0, - "orientation": "vertical", - "padding_x": 20.0, - "padding_y": 20.0 - }, - "data": { - "bottle_diameter": 30.0, - "bottle_height": 100.0, - "position_spacing": 35.0, - "name_to_index": {} - } - }, - { - "id": "sheet_3x4_0", - "name": "sheet_3x4_0", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 20.0, - "y": 20.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_1", - "name": "sheet_3x4_1", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 20.0, - "y": 55.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_2", - "name": "sheet_3x4_2", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 20.0, - "y": 90.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_3", - "name": "sheet_3x4_3", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 55.0, - "y": 20.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_4", - "name": "sheet_3x4_4", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 55.0, - "y": 55.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_5", - "name": "sheet_3x4_5", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 55.0, - "y": 90.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_6", - "name": "sheet_3x4_6", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 90.0, - "y": 20.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_7", - "name": "sheet_3x4_7", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 90.0, - "y": 55.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_8", - "name": "sheet_3x4_8", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 90.0, - "y": 90.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_9", - "name": "sheet_3x4_9", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 125.0, - "y": 20.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_10", - "name": "sheet_3x4_10", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 125.0, - "y": 55.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_3x4_11", - "name": "sheet_3x4_11", - "sample_id": null, - "children": [], - "parent": "bottle_rack_3x4", - "type": "container", - "class": "", - "position": { - "x": 125.0, - "y": 90.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "bottle_rack_6x2", - "name": "bottle_rack_6x2", - "sample_id": null, - "children": [ - "sheet_6x2_0", - "sheet_6x2_1", - "sheet_6x2_2", - "sheet_6x2_3", - "sheet_6x2_4", - "sheet_6x2_5", - "sheet_6x2_6", - "sheet_6x2_7", - "sheet_6x2_8", - "sheet_6x2_9", - "sheet_6x2_10", - "sheet_6x2_11" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 300, - "y": 300, - "z": 0 - }, - "config": { - "type": "BottleRack", - "size_x": 120.0, - "size_y": 250.0, - "size_z": 100.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "bottle_rack", - "model": null, - "barcode": null, - "num_items_x": 6, - "num_items_y": 2, - "position_spacing": 35.0, - "orientation": "vertical", - "padding_x": 20.0, - "padding_y": 20.0 - }, - "data": { - "bottle_diameter": 30.0, - "bottle_height": 100.0, - "position_spacing": 35.0, - "name_to_index": {} - } - }, - { - "id": "sheet_6x2_0", - "name": "sheet_6x2_0", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 20.0, - "y": 20.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_1", - "name": "sheet_6x2_1", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 20.0, - "y": 55.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_2", - "name": "sheet_6x2_2", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 20.0, - "y": 90.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_3", - "name": "sheet_6x2_3", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 20.0, - "y": 125.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_4", - "name": "sheet_6x2_4", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 20.0, - "y": 160.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_5", - "name": "sheet_6x2_5", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 20.0, - "y": 195.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_6", - "name": "sheet_6x2_6", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 55.0, - "y": 20.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_7", - "name": "sheet_6x2_7", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 55.0, - "y": 55.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_8", - "name": "sheet_6x2_8", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 55.0, - "y": 90.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_9", - "name": "sheet_6x2_9", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 55.0, - "y": 125.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_10", - "name": "sheet_6x2_10", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 55.0, - "y": 160.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "sheet_6x2_11", - "name": "sheet_6x2_11", - "sample_id": null, - "children": [], - "parent": "bottle_rack_6x2", - "type": "container", - "class": "", - "position": { - "x": 55.0, - "y": 195.0, - "z": 0 - }, - "config": { - "type": "ElectrodeSheet", - "size_x": 12, - "size_y": 12, - "size_z": 0.1, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "electrode_sheet", - "model": null, - "barcode": null - }, - "data": { - "diameter": 14, - "thickness": 0.1, - "mass": 0.5, - "material_type": "copper", - "info": null - } - }, - { - "id": "bottle_rack_6x2_2", - "name": "bottle_rack_6x2_2", - "sample_id": null, - "children": [], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 430, - "y": 300, - "z": 0 - }, - "config": { - "type": "BottleRack", - "size_x": 120.0, - "size_y": 250.0, - "size_z": 100.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "bottle_rack", - "model": null, - "barcode": null, - "num_items_x": 6, - "num_items_y": 2, - "position_spacing": 35.0, - "orientation": "vertical", - "padding_x": 20.0, - "padding_y": 20.0 - }, - "data": { - "bottle_diameter": 30.0, - "bottle_height": 100.0, - "position_spacing": 35.0, - "name_to_index": {} - } - }, - { - "id": "tip_box_64", - "name": "tip_box_64", - "sample_id": null, - "children": [ - "tip_box_64_tipspot_0_0", - "tip_box_64_tipspot_0_1", - "tip_box_64_tipspot_0_2", - "tip_box_64_tipspot_0_3", - "tip_box_64_tipspot_0_4", - "tip_box_64_tipspot_0_5", - "tip_box_64_tipspot_0_6", - "tip_box_64_tipspot_0_7", - "tip_box_64_tipspot_1_0", - "tip_box_64_tipspot_1_1", - "tip_box_64_tipspot_1_2", - "tip_box_64_tipspot_1_3", - "tip_box_64_tipspot_1_4", - "tip_box_64_tipspot_1_5", - "tip_box_64_tipspot_1_6", - "tip_box_64_tipspot_1_7", - "tip_box_64_tipspot_2_0", - "tip_box_64_tipspot_2_1", - "tip_box_64_tipspot_2_2", - "tip_box_64_tipspot_2_3", - "tip_box_64_tipspot_2_4", - "tip_box_64_tipspot_2_5", - "tip_box_64_tipspot_2_6", - "tip_box_64_tipspot_2_7", - "tip_box_64_tipspot_3_0", - "tip_box_64_tipspot_3_1", - "tip_box_64_tipspot_3_2", - "tip_box_64_tipspot_3_3", - "tip_box_64_tipspot_3_4", - "tip_box_64_tipspot_3_5", - "tip_box_64_tipspot_3_6", - "tip_box_64_tipspot_3_7", - "tip_box_64_tipspot_4_0", - "tip_box_64_tipspot_4_1", - "tip_box_64_tipspot_4_2", - "tip_box_64_tipspot_4_3", - "tip_box_64_tipspot_4_4", - "tip_box_64_tipspot_4_5", - "tip_box_64_tipspot_4_6", - "tip_box_64_tipspot_4_7", - "tip_box_64_tipspot_5_0", - "tip_box_64_tipspot_5_1", - "tip_box_64_tipspot_5_2", - "tip_box_64_tipspot_5_3", - "tip_box_64_tipspot_5_4", - "tip_box_64_tipspot_5_5", - "tip_box_64_tipspot_5_6", - "tip_box_64_tipspot_5_7", - "tip_box_64_tipspot_6_0", - "tip_box_64_tipspot_6_1", - "tip_box_64_tipspot_6_2", - "tip_box_64_tipspot_6_3", - "tip_box_64_tipspot_6_4", - "tip_box_64_tipspot_6_5", - "tip_box_64_tipspot_6_6", - "tip_box_64_tipspot_6_7", - "tip_box_64_tipspot_7_0", - "tip_box_64_tipspot_7_1", - "tip_box_64_tipspot_7_2", - "tip_box_64_tipspot_7_3", - "tip_box_64_tipspot_7_4", - "tip_box_64_tipspot_7_5", - "tip_box_64_tipspot_7_6", - "tip_box_64_tipspot_7_7" - ], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 300, - "y": 100, - "z": 0 - }, - "config": { - "type": "TipBox64", - "size_x": 127.8, - "size_y": 85.5, - "size_z": 60.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_box_64", - "model": null, - "barcode": null, - "ordering": { - "A1": "tip_box_64_tipspot_0_0", - "B1": "tip_box_64_tipspot_0_1", - "C1": "tip_box_64_tipspot_0_2", - "D1": "tip_box_64_tipspot_0_3", - "E1": "tip_box_64_tipspot_0_4", - "F1": "tip_box_64_tipspot_0_5", - "G1": "tip_box_64_tipspot_0_6", - "H1": "tip_box_64_tipspot_0_7", - "A2": "tip_box_64_tipspot_1_0", - "B2": "tip_box_64_tipspot_1_1", - "C2": "tip_box_64_tipspot_1_2", - "D2": "tip_box_64_tipspot_1_3", - "E2": "tip_box_64_tipspot_1_4", - "F2": "tip_box_64_tipspot_1_5", - "G2": "tip_box_64_tipspot_1_6", - "H2": "tip_box_64_tipspot_1_7", - "A3": "tip_box_64_tipspot_2_0", - "B3": "tip_box_64_tipspot_2_1", - "C3": "tip_box_64_tipspot_2_2", - "D3": "tip_box_64_tipspot_2_3", - "E3": "tip_box_64_tipspot_2_4", - "F3": "tip_box_64_tipspot_2_5", - "G3": "tip_box_64_tipspot_2_6", - "H3": "tip_box_64_tipspot_2_7", - "A4": "tip_box_64_tipspot_3_0", - "B4": "tip_box_64_tipspot_3_1", - "C4": "tip_box_64_tipspot_3_2", - "D4": "tip_box_64_tipspot_3_3", - "E4": "tip_box_64_tipspot_3_4", - "F4": "tip_box_64_tipspot_3_5", - "G4": "tip_box_64_tipspot_3_6", - "H4": "tip_box_64_tipspot_3_7", - "A5": "tip_box_64_tipspot_4_0", - "B5": "tip_box_64_tipspot_4_1", - "C5": "tip_box_64_tipspot_4_2", - "D5": "tip_box_64_tipspot_4_3", - "E5": "tip_box_64_tipspot_4_4", - "F5": "tip_box_64_tipspot_4_5", - "G5": "tip_box_64_tipspot_4_6", - "H5": "tip_box_64_tipspot_4_7", - "A6": "tip_box_64_tipspot_5_0", - "B6": "tip_box_64_tipspot_5_1", - "C6": "tip_box_64_tipspot_5_2", - "D6": "tip_box_64_tipspot_5_3", - "E6": "tip_box_64_tipspot_5_4", - "F6": "tip_box_64_tipspot_5_5", - "G6": "tip_box_64_tipspot_5_6", - "H6": "tip_box_64_tipspot_5_7", - "A7": "tip_box_64_tipspot_6_0", - "B7": "tip_box_64_tipspot_6_1", - "C7": "tip_box_64_tipspot_6_2", - "D7": "tip_box_64_tipspot_6_3", - "E7": "tip_box_64_tipspot_6_4", - "F7": "tip_box_64_tipspot_6_5", - "G7": "tip_box_64_tipspot_6_6", - "H7": "tip_box_64_tipspot_6_7", - "A8": "tip_box_64_tipspot_7_0", - "B8": "tip_box_64_tipspot_7_1", - "C8": "tip_box_64_tipspot_7_2", - "D8": "tip_box_64_tipspot_7_3", - "E8": "tip_box_64_tipspot_7_4", - "F8": "tip_box_64_tipspot_7_5", - "G8": "tip_box_64_tipspot_7_6", - "H8": "tip_box_64_tipspot_7_7" - }, - "num_items_x": 8, - "num_items_y": 8, - "dx": 8.0, - "dy": 8.0, - "item_dx": 9.0, - "item_dy": 9.0 - }, - "data": {} - }, - { - "id": "tip_box_64_tipspot_0_0", - "name": "tip_box_64_tipspot_0_0", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 8.0, - "y": 71.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_0_1", - "name": "tip_box_64_tipspot_0_1", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 8.0, - "y": 62.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_0_2", - "name": "tip_box_64_tipspot_0_2", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 8.0, - "y": 53.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_0_3", - "name": "tip_box_64_tipspot_0_3", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 8.0, - "y": 44.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_0_4", - "name": "tip_box_64_tipspot_0_4", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 8.0, - "y": 35.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_0_5", - "name": "tip_box_64_tipspot_0_5", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 8.0, - "y": 26.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_0_6", - "name": "tip_box_64_tipspot_0_6", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 8.0, - "y": 17.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_0_7", - "name": "tip_box_64_tipspot_0_7", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 8.0, - "y": 8.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_1_0", - "name": "tip_box_64_tipspot_1_0", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 17.0, - "y": 71.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_1_1", - "name": "tip_box_64_tipspot_1_1", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 17.0, - "y": 62.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_1_2", - "name": "tip_box_64_tipspot_1_2", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 17.0, - "y": 53.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_1_3", - "name": "tip_box_64_tipspot_1_3", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 17.0, - "y": 44.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_1_4", - "name": "tip_box_64_tipspot_1_4", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 17.0, - "y": 35.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_1_5", - "name": "tip_box_64_tipspot_1_5", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 17.0, - "y": 26.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_1_6", - "name": "tip_box_64_tipspot_1_6", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 17.0, - "y": 17.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_1_7", - "name": "tip_box_64_tipspot_1_7", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 17.0, - "y": 8.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_2_0", - "name": "tip_box_64_tipspot_2_0", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 26.0, - "y": 71.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_2_1", - "name": "tip_box_64_tipspot_2_1", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 26.0, - "y": 62.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_2_2", - "name": "tip_box_64_tipspot_2_2", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 26.0, - "y": 53.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_2_3", - "name": "tip_box_64_tipspot_2_3", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 26.0, - "y": 44.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_2_4", - "name": "tip_box_64_tipspot_2_4", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 26.0, - "y": 35.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_2_5", - "name": "tip_box_64_tipspot_2_5", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 26.0, - "y": 26.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_2_6", - "name": "tip_box_64_tipspot_2_6", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 26.0, - "y": 17.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_2_7", - "name": "tip_box_64_tipspot_2_7", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 26.0, - "y": 8.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_3_0", - "name": "tip_box_64_tipspot_3_0", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 35.0, - "y": 71.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_3_1", - "name": "tip_box_64_tipspot_3_1", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 35.0, - "y": 62.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_3_2", - "name": "tip_box_64_tipspot_3_2", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 35.0, - "y": 53.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_3_3", - "name": "tip_box_64_tipspot_3_3", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 35.0, - "y": 44.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_3_4", - "name": "tip_box_64_tipspot_3_4", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 35.0, - "y": 35.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_3_5", - "name": "tip_box_64_tipspot_3_5", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 35.0, - "y": 26.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_3_6", - "name": "tip_box_64_tipspot_3_6", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 35.0, - "y": 17.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_3_7", - "name": "tip_box_64_tipspot_3_7", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 35.0, - "y": 8.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_4_0", - "name": "tip_box_64_tipspot_4_0", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 44.0, - "y": 71.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_4_1", - "name": "tip_box_64_tipspot_4_1", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 44.0, - "y": 62.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_4_2", - "name": "tip_box_64_tipspot_4_2", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 44.0, - "y": 53.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_4_3", - "name": "tip_box_64_tipspot_4_3", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 44.0, - "y": 44.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_4_4", - "name": "tip_box_64_tipspot_4_4", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 44.0, - "y": 35.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_4_5", - "name": "tip_box_64_tipspot_4_5", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 44.0, - "y": 26.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_4_6", - "name": "tip_box_64_tipspot_4_6", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 44.0, - "y": 17.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_4_7", - "name": "tip_box_64_tipspot_4_7", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 44.0, - "y": 8.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_5_0", - "name": "tip_box_64_tipspot_5_0", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 53.0, - "y": 71.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_5_1", - "name": "tip_box_64_tipspot_5_1", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 53.0, - "y": 62.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_5_2", - "name": "tip_box_64_tipspot_5_2", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 53.0, - "y": 53.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_5_3", - "name": "tip_box_64_tipspot_5_3", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 53.0, - "y": 44.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_5_4", - "name": "tip_box_64_tipspot_5_4", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 53.0, - "y": 35.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_5_5", - "name": "tip_box_64_tipspot_5_5", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 53.0, - "y": 26.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_5_6", - "name": "tip_box_64_tipspot_5_6", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 53.0, - "y": 17.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_5_7", - "name": "tip_box_64_tipspot_5_7", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 53.0, - "y": 8.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_6_0", - "name": "tip_box_64_tipspot_6_0", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 62.0, - "y": 71.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_6_1", - "name": "tip_box_64_tipspot_6_1", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 62.0, - "y": 62.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_6_2", - "name": "tip_box_64_tipspot_6_2", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 62.0, - "y": 53.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_6_3", - "name": "tip_box_64_tipspot_6_3", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 62.0, - "y": 44.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_6_4", - "name": "tip_box_64_tipspot_6_4", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 62.0, - "y": 35.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_6_5", - "name": "tip_box_64_tipspot_6_5", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 62.0, - "y": 26.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_6_6", - "name": "tip_box_64_tipspot_6_6", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 62.0, - "y": 17.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_6_7", - "name": "tip_box_64_tipspot_6_7", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 62.0, - "y": 8.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_7_0", - "name": "tip_box_64_tipspot_7_0", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 71.0, - "y": 71.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_7_1", - "name": "tip_box_64_tipspot_7_1", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 71.0, - "y": 62.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_7_2", - "name": "tip_box_64_tipspot_7_2", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 71.0, - "y": 53.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_7_3", - "name": "tip_box_64_tipspot_7_3", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 71.0, - "y": 44.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_7_4", - "name": "tip_box_64_tipspot_7_4", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 71.0, - "y": 35.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_7_5", - "name": "tip_box_64_tipspot_7_5", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 71.0, - "y": 26.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_7_6", - "name": "tip_box_64_tipspot_7_6", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 71.0, - "y": 17.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "tip_box_64_tipspot_7_7", - "name": "tip_box_64_tipspot_7_7", - "sample_id": null, - "children": [], - "parent": "tip_box_64", - "type": "container", - "class": "", - "position": { - "x": 71.0, - "y": 8.0, - "z": 0.0 - }, - "config": { - "type": "TipSpot", - "size_x": 10, - "size_y": 10, - "size_z": 0.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "tip_spot", - "model": null, - "barcode": null, - "prototype_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - }, - "data": { - "tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - }, - "tip_state": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - }, - "pending_tip": { - "type": "Tip", - "total_tip_length": 20.0, - "has_filter": false, - "maximal_volume": 1000, - "fitting_depth": 8.0 - } - } - }, - { - "id": "waste_tip_box", - "name": "waste_tip_box", - "sample_id": null, - "children": [], - "parent": "coin_cell_deck", - "type": "container", - "class": "", - "position": { - "x": 300, - "y": 200, - "z": 0 - }, - "config": { - "type": "WasteTipBox", - "size_x": 127.8, - "size_y": 85.5, - "size_z": 60.0, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "waste_tip_box", - "model": null, - "barcode": null, - "max_volume": "Infinity", - "material_z_thickness": 0, - "compute_volume_from_height": null, - "compute_height_from_volume": null - }, - "data": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - } - } - ], - "links": [] -} \ No newline at end of file diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_id_CAS.xlsx b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_id_CAS.xlsx new file mode 100644 index 0000000..1fefc1b Binary files /dev/null and b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_id_CAS.xlsx differ diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx index 698bf96..1b0eb9b 100644 Binary files a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx and b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx differ diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/output_example.json b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/output_example.json new file mode 100644 index 0000000..ae404c4 --- /dev/null +++ b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/output_example.json @@ -0,0 +1,197 @@ +{ + "token": "", + "request_time": "2025-12-24T15:32:09.2148671+08:00", + "data": { + "orderId": "3a1e614d-a082-c44a-60be-68647a35e6f1", + "orderCode": "BSO2025122400024", + "orderName": "DP20251224001", + "startTime": "2025-12-24T14:51:50.549848", + "endTime": "2025-12-24T15:32:09.000765", + "status": "30", + "workflowStatus": "completed", + "completionTime": "2025-12-24T15:32:09.000765", + "usedMaterials": [ + { + "materialId": "3a1e614b-53a6-0ec4-10bd-956b240c0f04", + "locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff", + "typemode": "1", + "usedQuantity": 2, + "realQuantity": 2 + }, + { + "materialId": "3a1e614b-4da7-cf62-3a40-7e5879255c0c", + "locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb", + "typemode": "1", + "usedQuantity": 1, + "realQuantity": 1 + }, + { + "materialId": "3a1e614b-53a7-2850-42c8-a7a2de8ff4bf", + "locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff", + "typemode": "1", + "usedQuantity": 1, + "realQuantity": 1 + }, + { + "materialId": "3a1e614b-4da6-ac9d-02be-4b0716796bd2", + "locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb", + "typemode": "1", + "usedQuantity": 2, + "realQuantity": 2 + }, + { + "materialId": "3a1e614d-9c9a-fafa-4757-c7411b03bd9f", + "locationId": "3a1abd46-18fe-1f56-6ced-a1f7fe08e36c", + "typemode": "0", + "usedQuantity": 1, + "realQuantity": 1 + }, + { + "materialId": "3a1e614b-6917-b8f9-7987-7a33a3792829", + "locationId": "3a19da43-57b5-294f-d663-154a1cc32270", + "typemode": "2", + "usedQuantity": 3.51, + "realQuantity": 3.5155000000000000000000000000 + }, + { + "materialId": "3a1e614b-6914-d92b-e348-f52e13817a5d", + "locationId": "3a19da56-1379-ff7c-1745-07e200b44ce2", + "typemode": "2", + "usedQuantity": 0.33, + "realQuantity": 0.3336000000000000000000000000 + } + ] + } +} + +{ + "token": "", + "request_time": "2025-12-24T15:32:09.9999039+08:00", + "data": { + "orderId": "3a1e614d-a0a2-f7a9-9360-610021c9479d", + "orderCode": "BSO2025122400025", + "orderName": "DP20251224002", + "startTime": "2025-12-24T14:53:03.44259", + "endTime": "2025-12-24T15:32:09.828261", + "status": "30", + "workflowStatus": "completed", + "completionTime": "2025-12-24T15:32:09.828261", + "usedMaterials": [ + { + "materialId": "3a1e614b-4da7-6527-9f1c-b39e3de8ff2b", + "locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb", + "typemode": "1", + "usedQuantity": 1, + "realQuantity": 1 + }, + { + "materialId": "3a1e614b-53a6-0ec4-10bd-956b240c0f04", + "locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff", + "typemode": "1", + "usedQuantity": 2, + "realQuantity": 2 + }, + { + "materialId": "3a1e614b-4da6-ac9d-02be-4b0716796bd2", + "locationId": "3a1a224d-ed49-710c-a9c3-3fc61d479cbb", + "typemode": "1", + "usedQuantity": 2, + "realQuantity": 2 + }, + { + "materialId": "3a1e614b-53a8-8474-cac8-0fd7d349e4b2", + "locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff", + "typemode": "1", + "usedQuantity": 1, + "realQuantity": 1 + }, + { + "materialId": "3a1e614d-9c9a-fafa-4757-c7411b03bd9f", + "locationId": null, + "typemode": "0", + "usedQuantity": 1, + "realQuantity": 1 + }, + { + "materialId": "3a1e614b-6917-b8f9-7987-7a33a3792829", + "locationId": "3a19da43-57b5-294f-d663-154a1cc32270", + "typemode": "2", + "usedQuantity": 0.7, + "realQuantity": 0 + }, + { + "materialId": "3a1e614b-6914-d92b-e348-f52e13817a5d", + "locationId": "3a19da56-1379-ff7c-1745-07e200b44ce2", + "typemode": "2", + "usedQuantity": 1.15, + "realQuantity": 1.1627000000000000000000000000 + } + ] + } +} + +{ + "token": "", + "request_time": "2025-12-24T15:34:00.4139986+08:00", + "data": { + "orderId": "3a1e614d-a0cd-81ca-9f7f-2f4e93af01cd", + "orderCode": "BSO2025122400026", + "orderName": "DP20251224003", + "startTime": "2025-12-24T14:54:24.443344", + "endTime": "2025-12-24T15:34:00.26321", + "status": "30", + "workflowStatus": "completed", + "completionTime": "2025-12-24T15:34:00.26321", + "usedMaterials": [ + { + "materialId": "3a1e614b-4da6-ac9d-02be-4b0716796bd2", + "locationId": "3a19deae-2c7a-b9eb-f4e3-e308e0cf839a", + "typemode": "1", + "usedQuantity": 2, + "realQuantity": 2 + }, + { + "materialId": "3a1e614b-4da8-b678-f204-207076f09c83", + "locationId": "3a19deae-2c7a-b9eb-f4e3-e308e0cf839a", + "typemode": "1", + "usedQuantity": 1, + "realQuantity": 1 + }, + { + "materialId": "3a1e614b-53a6-0ec4-10bd-956b240c0f04", + "locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff", + "typemode": "1", + "usedQuantity": 2, + "realQuantity": 2 + }, + { + "materialId": "3a1e614b-53a8-e3f2-dee0-fa97b600b652", + "locationId": "3a19debc-84b5-4c1c-d3a1-26830cf273ff", + "typemode": "1", + "usedQuantity": 1, + "realQuantity": 1 + }, + { + "materialId": "3a1e614d-9c9a-fafa-4757-c7411b03bd9f", + "locationId": null, + "typemode": "0", + "usedQuantity": 1, + "realQuantity": 1 + }, + { + "materialId": "3a1e614b-6917-b8f9-7987-7a33a3792829", + "locationId": "3a19da43-57b5-294f-d663-154a1cc32270", + "typemode": "2", + "usedQuantity": 2.0, + "realQuantity": 2.0075000000000000000000000000 + }, + { + "materialId": "3a1e614b-6914-d92b-e348-f52e13817a5d", + "locationId": "3a19da56-1379-ff7c-1745-07e200b44ce2", + "typemode": "2", + "usedQuantity": 1.2, + "realQuantity": 1.2126000000000000000000000000 + } + ] + } +} \ No newline at end of file diff --git a/unilabos/devices/workstation/bioyond_studio/bioyond_cell/多订单返回说明.md b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/多订单返回说明.md new file mode 100644 index 0000000..baecac9 --- /dev/null +++ b/unilabos/devices/workstation/bioyond_studio/bioyond_cell/多订单返回说明.md @@ -0,0 +1,113 @@ +# Bioyond Cell 工作站 - 多订单返回示例 + +本文档说明了 `create_orders` 函数如何收集并返回所有订单的完成报文。 + +## 问题描述 + +之前的实现只会等待并返回第一个订单的完成报文,如果有多个订单(例如从 Excel 解析出 3 个订单),只能得到第一个订单的推送信息。 + +## 解决方案 + +修改后的 `create_orders` 函数现在会: + +1. **提取所有 orderCode**:从 LIMS 接口返回的 `data` 列表中提取所有订单编号 +2. **逐个等待完成**:遍历所有 orderCode,调用 `wait_for_order_finish` 等待每个订单完成 +3. **收集所有报文**:将每个订单的完成报文存入 `all_reports` 列表 +4. **统一返回**:返回包含所有订单报文的 JSON 格式数据 + +## 返回格式 + +```json +{ + "status": "all_completed", + "total_orders": 3, + "reports": [ + { + "token": "", + "request_time": "2025-12-24T15:32:09.2148671+08:00", + "data": { + "orderId": "3a1e614d-a082-c44a-60be-68647a35e6f1", + "orderCode": "BSO2025122400024", + "orderName": "DP20251224001", + "status": "30", + "workflowStatus": "completed", + "usedMaterials": [...] + } + }, + { + "token": "", + "request_time": "2025-12-24T15:32:09.9999039+08:00", + "data": { + "orderId": "3a1e614d-a0a2-f7a9-9360-610021c9479d", + "orderCode": "BSO2025122400025", + "orderName": "DP20251224002", + "status": "30", + "workflowStatus": "completed", + "usedMaterials": [...] + } + }, + { + "token": "", + "request_time": "2025-12-24T15:34:00.4139986+08:00", + "data": { + "orderId": "3a1e614d-a0cd-81ca-9f7f-2f4e93af01cd", + "orderCode": "BSO2025122400026", + "orderName": "DP20251224003", + "status": "30", + "workflowStatus": "completed", + "usedMaterials": [...] + } + } + ], + "original_response": {...} +} +``` + +## 使用示例 + +```python +# 调用 create_orders +result = workstation.create_orders("20251224.xlsx") + +# 访问返回数据 +print(f"总订单数: {result['total_orders']}") +print(f"状态: {result['status']}") + +# 遍历所有订单的报文 +for i, report in enumerate(result['reports'], 1): + order_data = report.get('data', {}) + print(f"\n订单 {i}:") + print(f" orderCode: {order_data.get('orderCode')}") + print(f" orderName: {order_data.get('orderName')}") + print(f" status: {order_data.get('status')}") + print(f" 使用物料数: {len(order_data.get('usedMaterials', []))}") +``` + +## 控制台输出示例 + +``` +[create_orders] 即将提交订单数量: 3 +[create_orders] 接口返回: {...} +[create_orders] 等待 3 个订单完成: ['BSO2025122400024', 'BSO2025122400025', 'BSO2025122400026'] +[create_orders] 正在等待第 1/3 个订单: BSO2025122400024 +[create_orders] ✓ 订单 BSO2025122400024 完成 +[create_orders] 正在等待第 2/3 个订单: BSO2025122400025 +[create_orders] ✓ 订单 BSO2025122400025 完成 +[create_orders] 正在等待第 3/3 个订单: BSO2025122400026 +[create_orders] ✓ 订单 BSO2025122400026 完成 +[create_orders] 所有订单已完成,共收集 3 个报文 +实验记录本========================create_orders======================== +返回报文数量: 3 +报文 1: orderCode=BSO2025122400024, status=30 +报文 2: orderCode=BSO2025122400025, status=30 +报文 3: orderCode=BSO2025122400026, status=30 +======================== +``` + +## 关键改进 + +1. ✅ **等待所有订单**:不再只等待第一个订单,而是遍历所有 orderCode +2. ✅ **收集完整报文**:每个订单的完整推送报文都被保存在 `reports` 数组中 +3. ✅ **详细日志**:清晰显示正在等待哪个订单,以及完成情况 +4. ✅ **错误处理**:即使某个订单失败,也会记录其状态信息 +5. ✅ **统一格式**:返回的 JSON 格式便于后续处理和分析 diff --git a/unilabos/devices/workstation/bioyond_studio/config.py b/unilabos/devices/workstation/bioyond_studio/config.py index 736ca66..9a70d5c 100644 --- a/unilabos/devices/workstation/bioyond_studio/config.py +++ b/unilabos/devices/workstation/bioyond_studio/config.py @@ -8,8 +8,10 @@ import os # BioyondCellWorkstation 默认配置(包含所有必需参数) API_CONFIG = { # API 连接配置 - # "api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.1.143:44389"),#实机 - "api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.11.219:44388"),# 仿真机 + # 实机 + #"api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.11.118:44389"), + # 仿真机 + "api_host": os.getenv("BIOYOND_API_HOST", "http://172.16.11.219:44388"), "api_key": os.getenv("BIOYOND_API_KEY", "8A819E5C"), "timeout": int(os.getenv("BIOYOND_TIMEOUT", "30")), @@ -17,7 +19,7 @@ API_CONFIG = { "report_token": os.getenv("BIOYOND_REPORT_TOKEN", "CHANGE_ME_TOKEN"), # HTTP 服务配置 - "HTTP_host": os.getenv("BIOYOND_HTTP_HOST", "172.16.11.2"), # HTTP服务监听地址,监听计算机飞连ip地址 + "HTTP_host": os.getenv("BIOYOND_HTTP_HOST", "172.16.11.206"), # HTTP服务监听地址,监听计算机飞连ip地址 "HTTP_port": int(os.getenv("BIOYOND_HTTP_PORT", "8080")), "debug_mode": False,# 调试模式 } diff --git a/unilabos/devices/workstation/coin_cell_assembly/Modbus_CSV_Mapping_Guide.md b/unilabos/devices/workstation/coin_cell_assembly/Modbus_CSV_Mapping_Guide.md new file mode 100644 index 0000000..8af63e7 --- /dev/null +++ b/unilabos/devices/workstation/coin_cell_assembly/Modbus_CSV_Mapping_Guide.md @@ -0,0 +1,84 @@ +# Modbus CSV 地址映射说明 + +本文档说明 `coin_cell_assembly_a.csv` 文件如何将命名节点映射到实际的 Modbus 地址,以及如何在代码中使用它们。 + +## 1. CSV 文件结构 + +地址表文件位于同级目录下:`coin_cell_assembly_a.csv` + +每一行定义了一个 Modbus 节点,包含以下关键列: + +| 列名 | 说明 | 示例 | +|------|------|------| +| **Name** | **节点名称** (代码中引用的 Key) | `COIL_ALUMINUM_FOIL` | +| **DataType** | 数据类型 (BOOL, INT16, FLOAT32, STRING) | `BOOL` | +| **Comment** | 注释说明 | `使用铝箔垫` | +| **Attribute** | 属性 (通常留空或用于额外标记) | | +| **DeviceType** | Modbus 寄存器类型 (`coil`, `hold_register`) | `coil` | +| **Address** | **Modbus 地址** (十进制) | `8340` | + +### 示例行 (铝箔垫片) + +```csv +COIL_ALUMINUM_FOIL,BOOL,,使用铝箔垫,,coil,8340, +``` + +- **名称**: `COIL_ALUMINUM_FOIL` +- **类型**: `coil` (线圈,读写单个位) +- **地址**: `8340` + +--- + +## 2. 加载与注册流程 + +在 `coin_cell_assembly.py` 的初始化代码中: + +1. **加载 CSV**: `BaseClient.load_csv()` 读取 CSV 并解析每行定义。 +2. **注册节点**: `modbus_client.register_node_list()` 将解析后的节点注册到 Modbus 客户端实例中。 + +```python +# 代码位置: coin_cell_assembly.py (L174-175) +self.nodes = BaseClient.load_csv(os.path.join(os.path.dirname(__file__), 'coin_cell_assembly_a.csv')) +self.client = modbus_client.register_node_list(self.nodes) +``` + +--- + +## 3. 代码中的使用方式 + +注册后,通过 `self.client.use_node('节点名称')` 即可获取该节点对象并进行读写操作,无需关心具体地址。 + +### 控制铝箔垫片 (COIL_ALUMINUM_FOIL) + +```python +# 代码位置: qiming_coin_cell_code 函数 (L1048) +self.client.use_node('COIL_ALUMINUM_FOIL').write(not lvbodian) +``` + +- **写入 True**: 对应 Modbus 功能码 05 (Write Single Coil),向地址 `8340` 写入 `1` (ON)。 +- **写入 False**: 向地址 `8340` 写入 `0` (OFF)。 + +> **注意**: 代码中使用了 `not lvbodian`,这意味着逻辑是反转的。如果 `lvbodian` 参数为 `True` (默认),写入的是 `False` (不使用铝箔垫)。 + +--- + +## 4. 地址转换注意事项 (Modbus vs PLC) + +CSV 中的 `Address` 列(如 `8340`)是 **Modbus 协议地址**。 + +如果使用 InoProShop (汇川 PLC 编程软件),看到的可能是 **PLC 内部地址** (如 `%QX...` 或 `%MW...`)。这两者之间通常需要转换。 + +### 常见的转换规则 (示例) + +- **Coil (线圈) %QX**: + - `Modbus地址 = 字节地址 * 8 + 位偏移` + - *例子*: `%QX834.0` -> `834 * 8 + 0` = `6672` + - *注意*: 如果 CSV 中配置的是 `8340`,这可能是一个自定义映射,或者是基于不同规则(如直接对应 Word 地址的某种映射,或者可能就是地址写错了/使用了非标准映射)。 + +- **Register (寄存器) %MW**: + - 通常直接对应,或者有偏移量 (如 Modbus 40001 = PLC MW0)。 + +### 验证方法 +由于 `test_unilab_interact.py` 中发现 `8450` (CSV风格) 不工作,而 `6760` (%QX845.0 计算值) 工作正常,**建议对 CSV 中的其他地址也进行核实**,特别是像 `8340` 这样以 0 结尾看起来像是 "字节地址+0" 的数值,可能实际上应该是 `%QX834.0` 对应的 `6672`。 + +如果发现设备控制无反应,请尝试按照标准的 Modbus 计算方式转换 PLC 地址。 diff --git a/unilabos/devices/workstation/coin_cell_assembly/YB_YH_materials.py b/unilabos/devices/workstation/coin_cell_assembly/YB_YH_materials.py index bc8dc4f..c9187e6 100644 --- a/unilabos/devices/workstation/coin_cell_assembly/YB_YH_materials.py +++ b/unilabos/devices/workstation/coin_cell_assembly/YB_YH_materials.py @@ -634,6 +634,12 @@ class CoincellDeck(Deck): self.assign_child_resource(waste_tip_box, Coordinate(x=778.0, y=622.0, z=0)) +def YH_Deck(name=""): + cd = CoincellDeck(name=name) + cd.setup() + return cd + + if __name__ == "__main__": deck = create_coin_cell_deck() print(deck) \ No newline at end of file diff --git a/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly.py b/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly.py index ef942e2..f47f560 100644 --- a/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly.py +++ b/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly.py @@ -1,4 +1,3 @@ - import csv import inspect import json @@ -21,6 +20,39 @@ from unilabos.ros.nodes.presets.workstation import ROS2WorkstationNode from unilabos.devices.workstation.coin_cell_assembly.YB_YH_materials import CoincellDeck from unilabos.resources.graphio import convert_resources_to_type from unilabos.utils.log import logger +from pymodbus.payload import BinaryPayloadDecoder +from pymodbus.constants import Endian + + +def _decode_float32_correct(registers): + """ + 正确解码FLOAT32类型的Modbus寄存器 + + Args: + registers: 从Modbus读取的原始寄存器值列表 + + Returns: + 正确解码的浮点数值 + + Note: + 根据test_glove_box_pressure.py验证的配置: + - Byte Order: Big (Modbus标准) + - Word Order: Little (PLC配置) + """ + if not registers or len(registers) < 2: + return 0.0 + + try: + # 使用正确的字节序配置 + decoder = BinaryPayloadDecoder.fromRegisters( + registers, + byteorder=Endian.Big, # 字节序始终为Big + wordorder=Endian.Little # 字序为Little (根据PLC配置) + ) + return decoder.decode_32bit_float() + except Exception as e: + logger.error(f"解码FLOAT32失败: {e}, registers: {registers}") + return 0.0 def _ensure_modbus_slave_kw_alias(modbus_client): @@ -139,7 +171,7 @@ class CoinCellAssemblyWorkstation(WorkstationBase): time.sleep(2) if not modbus_client.client.is_socket_open(): raise ValueError('modbus tcp connection failed') - self.nodes = BaseClient.load_csv(os.path.join(os.path.dirname(__file__), 'coin_cell_assembly_1105.csv')) + self.nodes = BaseClient.load_csv(os.path.join(os.path.dirname(__file__), 'coin_cell_assembly_b.csv')) self.client = modbus_client.register_node_list(self.nodes) else: print("测试模式,跳过连接") @@ -502,48 +534,72 @@ class CoinCellAssemblyWorkstation(WorkstationBase): """单颗电池组装时间 (秒, REAL/FLOAT32)""" if self.debug_mode: return 0 - time, read_err = self.client.use_node('REG_DATA_ASSEMBLY_PER_TIME').read(2, word_order=WorderOrder.LITTLE) - return time + # 读取原始寄存器并正确解码FLOAT32 + result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_ASSEMBLY_PER_TIME').address, count=2) + if result.isError(): + logger.error(f"读取组装时间失败") + return 0.0 + return _decode_float32_correct(result.registers) @property def data_open_circuit_voltage(self) -> float: """开路电压值 (FLOAT32)""" if self.debug_mode: return 0 - vol, read_err = self.client.use_node('REG_DATA_OPEN_CIRCUIT_VOLTAGE').read(2, word_order=WorderOrder.LITTLE) - return vol + # 读取原始寄存器并正确解码FLOAT32 + result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_OPEN_CIRCUIT_VOLTAGE').address, count=2) + if result.isError(): + logger.error(f"读取开路电压失败") + return 0.0 + return _decode_float32_correct(result.registers) @property def data_axis_x_pos(self) -> float: """分液X轴当前位置 (FLOAT32)""" if self.debug_mode: return 0 - pos, read_err = self.client.use_node('REG_DATA_AXIS_X_POS').read(2, word_order=WorderOrder.LITTLE) - return pos + # 读取原始寄存器并正确解码FLOAT32 + result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_AXIS_X_POS').address, count=2) + if result.isError(): + logger.error(f"读取X轴位置失败") + return 0.0 + return _decode_float32_correct(result.registers) @property def data_axis_y_pos(self) -> float: """分液Y轴当前位置 (FLOAT32)""" if self.debug_mode: return 0 - pos, read_err = self.client.use_node('REG_DATA_AXIS_Y_POS').read(2, word_order=WorderOrder.LITTLE) - return pos + # 读取原始寄存器并正确解码FLOAT32 + result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_AXIS_Y_POS').address, count=2) + if result.isError(): + logger.error(f"读变Y轴位置失败") + return 0.0 + return _decode_float32_correct(result.registers) @property def data_axis_z_pos(self) -> float: """分液Z轴当前位置 (FLOAT32)""" if self.debug_mode: return 0 - pos, read_err = self.client.use_node('REG_DATA_AXIS_Z_POS').read(2, word_order=WorderOrder.LITTLE) - return pos + # 读取原始寄存器并正确解码FLOAT32 + result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_AXIS_Z_POS').address, count=2) + if result.isError(): + logger.error(f"读取Z轴位置失败") + return 0.0 + return _decode_float32_correct(result.registers) @property def data_pole_weight(self) -> float: """当前电池正极片称重数据 (FLOAT32)""" if self.debug_mode: return 0 - weight, read_err = self.client.use_node('REG_DATA_POLE_WEIGHT').read(2, word_order=WorderOrder.LITTLE) - return weight + # 读取原始寄存器并正确解码FLOAT32 + result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_POLE_WEIGHT').address, count=2) + if result.isError(): + logger.error(f"读取极片质量失败") + return 0.0 + return _decode_float32_correct(result.registers) @property def data_assembly_pressure(self) -> int: @@ -573,11 +629,28 @@ class CoinCellAssemblyWorkstation(WorkstationBase): def data_coin_cell_code(self) -> str: """电池二维码序列号 (STRING)""" try: - # 尝试不同的字节序读取 + # 读取 STRING 类型数据 code_little, read_err = self.client.use_node('REG_DATA_COIN_CELL_CODE').read(10, word_order=WorderOrder.LITTLE) - # logger.debug(f"读取电池二维码原始数据: {code_little}") - clean_code = code_little[-8:][::-1] - return clean_code + + # 处理 bytes 或 string 类型 + if isinstance(code_little, bytes): + code_str = code_little.decode('utf-8', errors='ignore') + elif isinstance(code_little, str): + code_str = code_little + else: + logger.warning(f"电池二维码返回的类型不支持: {type(code_little)}") + return "N/A" + + # 取前8个字符 + raw_code = code_str[:8] + + # LITTLE字节序需要每2个字符交换位置 + clean_code = ''.join([raw_code[i+1] + raw_code[i] for i in range(0, len(raw_code), 2)]) + + # 去除空字符和空格 + decoded = clean_code.replace('\x00', '').replace('\r', '').replace('\n', '').strip() + + return decoded if decoded else "N/A" except Exception as e: logger.error(f"读取电池二维码失败: {e}") return "N/A" @@ -585,12 +658,30 @@ class CoinCellAssemblyWorkstation(WorkstationBase): @property def data_electrolyte_code(self) -> str: + """电解液二维码序列号 (STRING)""" try: - # 尝试不同的字节序读取 + # 读取 STRING 类型数据 code_little, read_err = self.client.use_node('REG_DATA_ELECTROLYTE_CODE').read(10, word_order=WorderOrder.LITTLE) - # logger.debug(f"读取电解液二维码原始数据: {code_little}") - clean_code = code_little[-8:][::-1] - return clean_code + + # 处理 bytes 或 string 类型 + if isinstance(code_little, bytes): + code_str = code_little.decode('utf-8', errors='ignore') + elif isinstance(code_little, str): + code_str = code_little + else: + logger.warning(f"电解液二维码返回的类型不支持: {type(code_little)}") + return "N/A" + + # 取前8个字符 + raw_code = code_str[:8] + + # LITTLE字节序需要每2个字符交换位置 + clean_code = ''.join([raw_code[i+1] + raw_code[i] for i in range(0, len(raw_code), 2)]) + + # 去除空字符和空格 + decoded = clean_code.replace('\x00', '').replace('\r', '').replace('\n', '').strip() + + return decoded if decoded else "N/A" except Exception as e: logger.error(f"读取电解液二维码失败: {e}") return "N/A" @@ -598,27 +689,39 @@ class CoinCellAssemblyWorkstation(WorkstationBase): # ===================== 环境监控区 ====================== @property def data_glove_box_pressure(self) -> float: - """手套箱压力 (bar, FLOAT32)""" + """手套箱压力 (mbar, FLOAT32)""" if self.debug_mode: return 0 - status, read_err = self.client.use_node('REG_DATA_GLOVE_BOX_PRESSURE').read(2, word_order=WorderOrder.LITTLE) - return status + # 读取原始寄存器并正确解码FLOAT32 + result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_GLOVE_BOX_PRESSURE').address, count=2) + if result.isError(): + logger.error(f"读取手套箱压力失败") + return 0.0 + return _decode_float32_correct(result.registers) @property def data_glove_box_o2_content(self) -> float: """手套箱氧含量 (ppm, FLOAT32)""" if self.debug_mode: return 0 - value, read_err = self.client.use_node('REG_DATA_GLOVE_BOX_O2_CONTENT').read(2, word_order=WorderOrder.LITTLE) - return value + # 读取原始寄存器并正确解码FLOAT32 + result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_GLOVE_BOX_O2_CONTENT').address, count=2) + if result.isError(): + logger.error(f"读取手套箱氧含量失败") + return 0.0 + return _decode_float32_correct(result.registers) @property def data_glove_box_water_content(self) -> float: """手套箱水含量 (ppm, FLOAT32)""" if self.debug_mode: return 0 - value, read_err = self.client.use_node('REG_DATA_GLOVE_BOX_WATER_CONTENT').read(2, word_order=WorderOrder.LITTLE) - return value + # 读取原始寄存器并正确解码FLOAT32 + result = self.client.client.read_holding_registers(address=self.client.use_node('REG_DATA_GLOVE_BOX_WATER_CONTENT').address, count=2) + if result.isError(): + logger.error(f"读取手套箱水含量失败") + return 0.0 + return _decode_float32_correct(result.registers) # @property # def data_stack_vision_code(self) -> int: @@ -690,6 +793,130 @@ class CoinCellAssemblyWorkstation(WorkstationBase): print("waiting for start_cmd") time.sleep(1) + def func_pack_device_init_auto_start_combined(self) -> bool: + """ + 组合函数:设备初始化 + 切换自动模式 + 启动 + + 整合了原有的三个独立函数: + 1. func_pack_device_init() - 设备初始化 + 2. func_pack_device_auto() - 切换自动模式 + 3. func_pack_device_start() - 启动设备 + + Returns: + bool: 操作成功返回 True,失败返回 False + """ + logger.info("=" * 60) + logger.info("开始组合操作:设备初始化 → 自动模式 → 启动") + logger.info("=" * 60) + + # 步骤0: 前置条件检查 + logger.info("\n【步骤 0/3】前置条件检查...") + try: + # 检查 REG_UNILAB_INTERACT (应该为False,表示使用Unilab交互) + unilab_interact_node = self.client.use_node('REG_UNILAB_INTERACT') + unilab_interact_value, read_err = unilab_interact_node.read(1) + + if read_err: + error_msg = "❌ 无法读取 REG_UNILAB_INTERACT 状态!请检查设备连接。" + logger.error(error_msg) + raise RuntimeError(error_msg) + + # 提取实际值(处理可能的列表或单值) + if isinstance(unilab_interact_value, (list, tuple)): + unilab_interact_actual = unilab_interact_value[0] if len(unilab_interact_value) > 0 else None + else: + unilab_interact_actual = unilab_interact_value + + logger.info(f" REG_UNILAB_INTERACT 当前值: {unilab_interact_actual}") + + if unilab_interact_actual != False: + error_msg = ( + "❌ 前置条件检查失败!\n" + f" REG_UNILAB_INTERACT = {unilab_interact_actual} (期望值: False)\n" + " 说明: 当前设备设置为'忽略Unilab交互'模式\n" + " 操作: 请在HMI上确认并切换为'使用Unilab交互'模式\n" + " 提示: REG_UNILAB_INTERACT应该为False才能继续" + ) + logger.error(error_msg) + raise RuntimeError(error_msg) + + logger.info(" ✓ REG_UNILAB_INTERACT 检查通过 (值为False,使用Unilab交互)") + + # 检查 COIL_GB_L_IGNORE_CMD (应该为False,表示使用左手套箱) + gb_l_ignore_node = self.client.use_node('COIL_GB_L_IGNORE_CMD') + gb_l_ignore_value, read_err = gb_l_ignore_node.read(1) + + if read_err: + error_msg = "❌ 无法读取 COIL_GB_L_IGNORE_CMD 状态!请检查设备连接。" + logger.error(error_msg) + raise RuntimeError(error_msg) + + # 提取实际值 + if isinstance(gb_l_ignore_value, (list, tuple)): + gb_l_ignore_actual = gb_l_ignore_value[0] if len(gb_l_ignore_value) > 0 else None + else: + gb_l_ignore_actual = gb_l_ignore_value + + logger.info(f" COIL_GB_L_IGNORE_CMD 当前值: {gb_l_ignore_actual}") + + if gb_l_ignore_actual != False: + error_msg = ( + "❌ 前置条件检查失败!\n" + f" COIL_GB_L_IGNORE_CMD = {gb_l_ignore_actual} (期望值: False)\n" + " 说明: 当前设备设置为'忽略左手套箱'模式\n" + " 操作: 请在HMI上确认并切换为'使用左手套箱'模式\n" + " 提示: COIL_GB_L_IGNORE_CMD应该为False才能继续" + ) + logger.error(error_msg) + raise RuntimeError(error_msg) + + logger.info(" ✓ COIL_GB_L_IGNORE_CMD 检查通过 (值为False,使用左手套箱)") + logger.info("✓ 所有前置条件检查通过!") + + except ValueError as e: + # 节点未找到 + error_msg = f"❌ 配置错误:{str(e)}\n请检查CSV配置文件是否包含必要的节点。" + logger.error(error_msg) + raise RuntimeError(error_msg) + except Exception as e: + # 其他异常 + error_msg = f"❌ 前置条件检查异常:{str(e)}" + logger.error(error_msg) + raise + + # 步骤1: 设备初始化 + logger.info("\n【步骤 1/3】设备初始化...") + try: + self.func_pack_device_init() + logger.info("✓ 设备初始化完成") + except Exception as e: + logger.error(f"❌ 设备初始化失败: {e}") + return False + + # 步骤2: 切换自动模式 + logger.info("\n【步骤 2/3】切换自动模式...") + try: + self.func_pack_device_auto() + logger.info("✓ 切换自动模式完成") + except Exception as e: + logger.error(f"❌ 切换自动模式失败: {e}") + return False + + # 步骤3: 启动设备 + logger.info("\n【步骤 3/3】启动设备...") + try: + self.func_pack_device_start() + logger.info("✓ 启动设备完成") + except Exception as e: + logger.error(f"❌ 启动设备失败: {e}") + return False + + logger.info("\n" + "=" * 60) + logger.info("组合操作完成:设备已成功初始化、切换自动模式并启动") + logger.info("=" * 60) + + return True + def func_pack_send_bottle_num(self, bottle_num): bottle_num = int(bottle_num) #发送电解液平台数 @@ -774,14 +1001,59 @@ class CoinCellAssemblyWorkstation(WorkstationBase): while self.request_send_msg_status == False: print("waiting for send_read_msg_status to True") time.sleep(1) - data_open_circuit_voltage = self.data_open_circuit_voltage - data_pole_weight = self.data_pole_weight + + # 处理开路电压 - 确保是数值类型 + try: + data_open_circuit_voltage = self.data_open_circuit_voltage + if isinstance(data_open_circuit_voltage, (list, tuple)) and len(data_open_circuit_voltage) > 0: + data_open_circuit_voltage = float(data_open_circuit_voltage[0]) + else: + data_open_circuit_voltage = float(data_open_circuit_voltage) + except Exception as e: + print(f"读取开路电压失败: {e}") + logger.error(f"读取开路电压失败: {e}") + data_open_circuit_voltage = 0.0 + + # 处理极片质量 - 确保是数值类型 + try: + data_pole_weight = self.data_pole_weight + if isinstance(data_pole_weight, (list, tuple)) and len(data_pole_weight) > 0: + data_pole_weight = float(data_pole_weight[0]) + else: + data_pole_weight = float(data_pole_weight) + except Exception as e: + print(f"读取正极片重量失败: {e}") + logger.error(f"读取正极片重量失败: {e}") + data_pole_weight = 0.0 + data_assembly_time = self.data_assembly_time data_assembly_pressure = self.data_assembly_pressure data_electrolyte_volume = self.data_electrolyte_volume data_coin_num = self.data_coin_num - data_electrolyte_code = self.data_electrolyte_code - data_coin_cell_code = self.data_coin_cell_code + + # 处理电解液二维码 - 确保是字符串类型 + try: + data_electrolyte_code = self.data_electrolyte_code + if isinstance(data_electrolyte_code, str): + data_electrolyte_code = data_electrolyte_code.strip() + else: + data_electrolyte_code = str(data_electrolyte_code) + except Exception as e: + print(f"读取电解液二维码失败: {e}") + logger.error(f"读取电解液二维码失败: {e}") + data_electrolyte_code = "N/A" + + # 处理电池二维码 - 确保是字符串类型 + try: + data_coin_cell_code = self.data_coin_cell_code + if isinstance(data_coin_cell_code, str): + data_coin_cell_code = data_coin_cell_code.strip() + else: + data_coin_cell_code = str(data_coin_cell_code) + except Exception as e: + print(f"读取电池二维码失败: {e}") + logger.error(f"读取电池二维码失败: {e}") + data_coin_cell_code = "N/A" logger.debug(f"data_open_circuit_voltage: {data_open_circuit_voltage}") logger.debug(f"data_pole_weight: {data_pole_weight}") logger.debug(f"data_assembly_time: {data_assembly_time}") @@ -792,8 +1064,25 @@ class CoinCellAssemblyWorkstation(WorkstationBase): logger.debug(f"data_coin_cell_code: {data_coin_cell_code}") #接收完信息后,读取完毕标志位置True liaopan3 = self.deck.get_resource("成品弹夹") - #把物料解绑后放到另一盘上 - battery = ElectrodeSheet(name=f"battery_{self.coin_num_N}", size_x=14, size_y=14, size_z=2) + + # 生成唯一的电池名称(使用时间戳确保唯一性) + timestamp_suffix = datetime.now().strftime("%Y%m%d_%H%M%S_%f") + battery_name = f"battery_{self.coin_num_N}_{timestamp_suffix}" + + # 检查目标位置是否已有资源,如果有则先卸载 + target_slot = liaopan3.children[self.coin_num_N] + if target_slot.children: + logger.warning(f"位置 {self.coin_num_N} 已有资源,将先卸载旧资源") + try: + # 卸载所有现有子资源 + for child in list(target_slot.children): + target_slot.unassign_child_resource(child) + logger.info(f"已卸载旧资源: {child.name}") + except Exception as e: + logger.error(f"卸载旧资源时出错: {e}") + + # 创建新的电池资源 + battery = ElectrodeSheet(name=battery_name, size_x=14, size_y=14, size_z=2) battery._unilabos_state = { "electrolyte_name": data_coin_cell_code, "data_electrolyte_code": data_electrolyte_code, @@ -801,7 +1090,16 @@ class CoinCellAssemblyWorkstation(WorkstationBase): "assembly_pressure": data_assembly_pressure, "electrolyte_volume": data_electrolyte_volume } - liaopan3.children[self.coin_num_N].assign_child_resource(battery, location=None) + + # 分配新资源到目标位置 + try: + target_slot.assign_child_resource(battery, location=None) + logger.info(f"成功分配电池 {battery_name} 到位置 {self.coin_num_N}") + except Exception as e: + logger.error(f"分配电池资源失败: {e}") + # 如果分配失败,尝试使用更简单的方法 + raise + #print(jipian2.parent) ROS2DeviceNode.run_async_func(self._ros_node.update_resource, True, **{ "resources": [self.deck] @@ -879,11 +1177,14 @@ class CoinCellAssemblyWorkstation(WorkstationBase): return self.success - def func_allpack_cmd(self, elec_num, elec_use_num, elec_vol:int=50, assembly_type:int=7, assembly_pressure:int=4200, file_path: str="/Users/sml/work") -> bool: + def func_allpack_cmd(self, elec_num, elec_use_num, elec_vol:int=50, assembly_type:int=7, assembly_pressure:int=4200, file_path: str="/Users/sml/work") -> Dict[str, Any]: elec_num, elec_use_num, elec_vol, assembly_type, assembly_pressure = int(elec_num), int(elec_use_num), int(elec_vol), int(assembly_type), int(assembly_pressure) summary_csv_file = os.path.join(file_path, "duandian.csv") - # 如果断点文件存在,先读取之前的进度 + # 用于收集所有电池的数据 + battery_data_list = [] + + # 如果断点文件存在,先读取之前的进度 if os.path.exists(summary_csv_file): read_status_flag = True with open(summary_csv_file, 'r', newline='', encoding='utf-8') as csvfile: @@ -900,7 +1201,12 @@ class CoinCellAssemblyWorkstation(WorkstationBase): print("断点文件与当前任务匹配,继续") else: print("断点文件中elec_num、elec_use_num与当前任务不匹配,请检查任务下发参数或修改断点文件") - return False + return { + "success": False, + "error": "断点文件参数不匹配", + "total_batteries": 0, + "batteries": [] + } print(f"从断点文件读取进度: elec_num_N={elec_num_N}, elec_use_num_N={elec_use_num_N}, coin_num_N={coin_num_N}") else: @@ -935,13 +1241,63 @@ class CoinCellAssemblyWorkstation(WorkstationBase): for j in range(j_start, elec_use_num): print(f"开始第{last_i+i+1}瓶电解液的第{j+j_start+1}个电池组装") + #读取电池组装数据并存入csv self.func_pack_get_msg_cmd(file_path) + + # 收集当前电池的数据 + # 处理电池二维码 + try: + battery_qr_code = self.data_coin_cell_code + except Exception as e: + print(f"读取电池二维码失败: {e}") + battery_qr_code = "N/A" + + # 处理电解液二维码 + try: + electrolyte_qr_code = self.data_electrolyte_code + except Exception as e: + print(f"读取电解液二维码失败: {e}") + electrolyte_qr_code = "N/A" + + # 处理开路电压 - 确保是数值类型 + try: + open_circuit_voltage = self.data_open_circuit_voltage + if isinstance(open_circuit_voltage, (list, tuple)) and len(open_circuit_voltage) > 0: + open_circuit_voltage = float(open_circuit_voltage[0]) + else: + open_circuit_voltage = float(open_circuit_voltage) + except Exception as e: + print(f"读取开路电压失败: {e}") + open_circuit_voltage = 0.0 + + # 处理极片质量 - 确保是数值类型 + try: + pole_weight = self.data_pole_weight + if isinstance(pole_weight, (list, tuple)) and len(pole_weight) > 0: + pole_weight = float(pole_weight[0]) + else: + pole_weight = float(pole_weight) + except Exception as e: + print(f"读取正极片重量失败: {e}") + pole_weight = 0.0 + + battery_info = { + "battery_index": coin_num_N + 1, + "battery_barcode": battery_qr_code, + "electrolyte_barcode": electrolyte_qr_code, + "open_circuit_voltage": open_circuit_voltage, + "pole_weight": pole_weight, + "assembly_time": self.data_assembly_time, + "assembly_pressure": self.data_assembly_pressure, + "electrolyte_volume": self.data_electrolyte_volume + } + battery_data_list.append(battery_info) + print(f"已收集第 {coin_num_N + 1} 个电池数据: 电池码={battery_info['battery_barcode']}, 电解液码={battery_info['electrolyte_barcode']}") + time.sleep(1) # TODO:读完再将电池数加一还是进入循环就将电池数加一需要考虑 - - # 生成断点文件 # 生成包含elec_num_N、coin_num_N、timestamp的CSV文件 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") @@ -960,8 +1316,284 @@ class CoinCellAssemblyWorkstation(WorkstationBase): os.remove(summary_csv_file) #全部完成后等待依华发送完成信号 self.func_pack_send_finished_cmd() + + # 返回JSON格式数据 + result = { + "success": True, + "total_batteries": len(battery_data_list), + "batteries": battery_data_list, + "summary": { + "electrolyte_bottles_used": elec_num, + "batteries_per_bottle": elec_use_num, + "electrolyte_volume": elec_vol, + "assembly_type": assembly_type, + "assembly_pressure": assembly_pressure + } + } + + print(f"\n{'='*60}") + print(f"组装完成统计:") + print(f" 总组装电池数: {result['total_batteries']}") + print(f" 使用电解液瓶数: {elec_num}") + print(f" 每瓶电池数: {elec_use_num}") + print(f"{'='*60}\n") + + return result + def func_allpack_cmd_simp( + self, + elec_num, + elec_use_num, + elec_vol: int = 50, + # 电解液双滴模式参数 + dual_drop_mode: bool = False, + dual_drop_first_volume: int = 25, + dual_drop_suction_timing: bool = False, + dual_drop_start_timing: bool = False, + assembly_type: int = 7, + assembly_pressure: int = 4200, + # 来自原 qiming_coin_cell_code 的参数 + fujipian_panshu: int = 0, + fujipian_juzhendianwei: int = 0, + gemopanshu: int = 0, + gemo_juzhendianwei: int = 0, + qiangtou_juzhendianwei: int = 0, + lvbodian: bool = True, + battery_pressure_mode: bool = True, + battery_clean_ignore: bool = False, + file_path: str = "/Users/sml/work" + ) -> Dict[str, Any]: + """ + 简化版电池组装函数,整合了原 qiming_coin_cell_code 的参数设置和双滴模式 + + 此函数是 func_allpack_cmd 的增强版本,自动处理以下配置: + - 负极片和隔膜的盘数及矩阵点位 + - 枪头盒矩阵点位 + - 铝箔垫片使用设置 + - 压力模式和清洁忽略选项 + - 电解液双滴模式(分两次滴液) + + Args: + elec_num: 电解液瓶数 + elec_use_num: 每瓶电解液组装的电池数 + elec_vol: 电解液吸液量 (μL) + dual_drop_mode: 电解液添加模式 (False=单次滴液, True=二次滴液) + dual_drop_first_volume: 二次滴液第一次排液体积 (μL) + dual_drop_suction_timing: 二次滴液吸液时机 (False=正常吸液, True=先吸液) + dual_drop_start_timing: 二次滴液开始滴液时机 (False=正极片前, True=正极片后) + assembly_type: 组装类型 (7=不用铝箔垫, 8=使用铝箔垫) + assembly_pressure: 电池压制力 (N) + fujipian_panshu: 负极片盘数 + fujipian_juzhendianwei: 负极片矩阵点位 + gemopanshu: 隔膜盘数 + gemo_juzhendianwei: 隔膜矩阵点位 + qiangtou_juzhendianwei: 枪头盒矩阵点位 + lvbodian: 是否使用铝箔垫片 + battery_pressure_mode: 是否启用压力模式 + battery_clean_ignore: 是否忽略电池清洁 + file_path: 实验记录保存路径 + + Returns: + dict: 包含组装结果的字典 + """ + # 参数类型转换 + elec_num = int(elec_num) + elec_use_num = int(elec_use_num) + elec_vol = int(elec_vol) + dual_drop_first_volume = int(dual_drop_first_volume) + assembly_type = int(assembly_type) + assembly_pressure = int(assembly_pressure) + fujipian_panshu = int(fujipian_panshu) + fujipian_juzhendianwei = int(fujipian_juzhendianwei) + gemopanshu = int(gemopanshu) + gemo_juzhendianwei = int(gemo_juzhendianwei) + qiangtou_juzhendianwei = int(qiangtou_juzhendianwei) + + # 步骤1: 设置设备参数(原 qiming_coin_cell_code 的功能) + logger.info("=" * 60) + logger.info("设置设备参数...") + logger.info(f" 负极片盘数: {fujipian_panshu}, 矩阵点位: {fujipian_juzhendianwei}") + logger.info(f" 隔膜盘数: {gemopanshu}, 矩阵点位: {gemo_juzhendianwei}") + logger.info(f" 枪头盒矩阵点位: {qiangtou_juzhendianwei}") + logger.info(f" 铝箔垫片: {lvbodian}, 压力模式: {battery_pressure_mode}") + logger.info(f" 压制力: {assembly_pressure}") + logger.info(f" 忽略电池清洁: {battery_clean_ignore}") + logger.info("=" * 60) + + # 写入基础参数到PLC + self.client.use_node('REG_MSG_NE_PLATE_NUM').write(fujipian_panshu) + self.client.use_node('REG_MSG_NE_PLATE_MATRIX').write(fujipian_juzhendianwei) + self.client.use_node('REG_MSG_SEPARATOR_PLATE_NUM').write(gemopanshu) + self.client.use_node('REG_MSG_SEPARATOR_PLATE_MATRIX').write(gemo_juzhendianwei) + self.client.use_node('REG_MSG_TIP_BOX_MATRIX').write(qiangtou_juzhendianwei) + self.client.use_node('COIL_ALUMINUM_FOIL').write(not lvbodian) + self.client.use_node('REG_MSG_PRESS_MODE').write(not battery_pressure_mode) + self.client.use_node('REG_MSG_BATTERY_CLEAN_IGNORE').write(battery_clean_ignore) + + # 设置电解液双滴模式参数 + self.client.use_node('COIL_ELECTROLYTE_DUAL_DROP_MODE').write(dual_drop_mode) + self.client.use_node('REG_MSG_DUAL_DROP_FIRST_VOLUME').write(dual_drop_first_volume) + self.client.use_node('COIL_DUAL_DROP_SUCTION_TIMING').write(dual_drop_suction_timing) + self.client.use_node('COIL_DUAL_DROP_START_TIMING').write(dual_drop_start_timing) + + if dual_drop_mode: + logger.info(f"✓ 双滴模式已启用: 第一次排液={dual_drop_first_volume}μL, " + f"吸液时机={'先吸液' if dual_drop_suction_timing else '正常吸液'}, " + f"滴液时机={'正极片后' if dual_drop_start_timing else '正极片前'}") + else: + logger.info("✓ 单次滴液模式") + + logger.info("✓ 设备参数设置完成") + + # 步骤2: 执行组装流程(复用 func_allpack_cmd 的主体逻辑) + summary_csv_file = os.path.join(file_path, "duandian.csv") + + # 用于收集所有电池的数据 + battery_data_list = [] + + # 如果断点文件存在,先读取之前的进度 + if os.path.exists(summary_csv_file): + read_status_flag = True + with open(summary_csv_file, 'r', newline='', encoding='utf-8') as csvfile: + reader = csv.reader(csvfile) + header = next(reader) # 跳过标题行 + data_row = next(reader) # 读取数据行 + if len(data_row) >= 2: + elec_num_r = int(data_row[0]) + elec_use_num_r = int(data_row[1]) + elec_num_N = int(data_row[2]) + elec_use_num_N = int(data_row[3]) + coin_num_N = int(data_row[4]) + if elec_num_r == elec_num and elec_use_num_r == elec_use_num: + print("断点文件与当前任务匹配,继续") + else: + print("断点文件中elec_num、elec_use_num与当前任务不匹配,请检查任务下发参数或修改断点文件") + return { + "success": False, + "error": "断点文件参数不匹配", + "total_batteries": 0, + "batteries": [] + } + print(f"从断点文件读取进度: elec_num_N={elec_num_N}, elec_use_num_N={elec_use_num_N}, coin_num_N={coin_num_N}") + + else: + read_status_flag = False + print("未找到断点文件,从头开始") + elec_num_N = 0 + elec_use_num_N = 0 + coin_num_N = 0 + + for i in range(20): + print(f"剩余电解液瓶数: {elec_num}, 已组装电池数: {elec_use_num}") + print(f"剩余电解液瓶数: {type(elec_num)}, 已组装电池数: {type(elec_use_num)}") + print(f"剩余电解液瓶数: {type(int(elec_num))}, 已组装电池数: {type(int(elec_use_num))}") + + last_i = elec_num_N + last_j = elec_use_num_N + for i in range(last_i, elec_num): + print(f"开始第{last_i+i+1}瓶电解液的组装") + # 第一个循环从上次断点继续,后续循环从0开始 + j_start = last_j if i == last_i else 0 + self.func_pack_send_msg_cmd(elec_use_num-j_start, elec_vol, assembly_type, assembly_pressure) + + for j in range(j_start, elec_use_num): + print(f"开始第{last_i+i+1}瓶电解液的第{j+j_start+1}个电池组装") + + # 读取电池组装数据并存入csv + self.func_pack_get_msg_cmd(file_path) + + # 收集当前电池的数据 + try: + battery_qr_code = self.data_coin_cell_code + except Exception as e: + print(f"读取电池二维码失败: {e}") + battery_qr_code = "N/A" + + try: + electrolyte_qr_code = self.data_electrolyte_code + except Exception as e: + print(f"读取电解液二维码失败: {e}") + electrolyte_qr_code = "N/A" + + try: + open_circuit_voltage = self.data_open_circuit_voltage + if isinstance(open_circuit_voltage, (list, tuple)) and len(open_circuit_voltage) > 0: + open_circuit_voltage = float(open_circuit_voltage[0]) + else: + open_circuit_voltage = float(open_circuit_voltage) + except Exception as e: + print(f"读取开路电压失败: {e}") + open_circuit_voltage = 0.0 + + try: + pole_weight = self.data_pole_weight + if isinstance(pole_weight, (list, tuple)) and len(pole_weight) > 0: + pole_weight = float(pole_weight[0]) + else: + pole_weight = float(pole_weight) + except Exception as e: + print(f"读取正极片重量失败: {e}") + pole_weight = 0.0 + + battery_info = { + "battery_index": coin_num_N + 1, + "battery_barcode": battery_qr_code, + "electrolyte_barcode": electrolyte_qr_code, + "open_circuit_voltage": open_circuit_voltage, + "pole_weight": pole_weight, + "assembly_time": self.data_assembly_time, + "assembly_pressure": self.data_assembly_pressure, + "electrolyte_volume": self.data_electrolyte_volume + } + battery_data_list.append(battery_info) + print(f"已收集第 {coin_num_N + 1} 个电池数据: 电池码={battery_info['battery_barcode']}, 电解液码={battery_info['electrolyte_barcode']}") + + time.sleep(1) + + # 生成断点文件 + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + with open(summary_csv_file, 'w', newline='', encoding='utf-8') as csvfile: + writer = csv.writer(csvfile) + writer.writerow(['elec_num','elec_use_num', 'elec_num_N', 'elec_use_num_N', 'coin_num_N', 'timestamp']) + writer.writerow([elec_num, elec_use_num, elec_num_N, elec_use_num_N, coin_num_N, timestamp]) + csvfile.flush() + coin_num_N += 1 + self.coin_num_N = coin_num_N + elec_use_num_N += 1 + elec_num_N += 1 + elec_use_num_N = 0 + + # 循环正常结束,则删除断点文件 + os.remove(summary_csv_file) + # 全部完成后等待依华发送完成信号 + self.func_pack_send_finished_cmd() + + # 返回JSON格式数据 + result = { + "success": True, + "total_batteries": len(battery_data_list), + "batteries": battery_data_list, + "summary": { + "electrolyte_bottles_used": elec_num, + "batteries_per_bottle": elec_use_num, + "electrolyte_volume": elec_vol, + "assembly_type": assembly_type, + "assembly_pressure": assembly_pressure, + "dual_drop_mode": dual_drop_mode + } + } + + print(f"\n{'='*60}") + print(f"组装完成统计:") + print(f" 总组装电池数: {result['total_batteries']}") + print(f" 使用电解液瓶数: {elec_num}") + print(f" 每瓶电池数: {elec_use_num}") + print(f" 双滴模式: {'启用' if dual_drop_mode else '禁用'}") + print(f"{'='*60}\n") + + return result + def func_pack_device_stop(self) -> bool: """打包指令:设备停止""" for i in range(3): diff --git a/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_1223.csv b/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_1223.csv new file mode 100644 index 0000000..9212f9b --- /dev/null +++ b/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_1223.csv @@ -0,0 +1,159 @@ +Name,DataType,Comment,DeviceType,Address,, +COIL_SYS_START_CMD,BOOL,豸,coil,8010,, +COIL_SYS_STOP_CMD,BOOL,豸ֹͣ,coil,8020,, +COIL_SYS_RESET_CMD,BOOL,豸λ,coil,8030,, +COIL_SYS_HAND_CMD,BOOL,豸ֶģʽ,coil,8040,, +COIL_SYS_AUTO_CMD,BOOL,豸Զģʽ,coil,8050,, +COIL_SYS_INIT_CMD,BOOL,豸ʼģʽ,coil,8060,, +COIL_SYS_STOP_STATUS,BOOL,豸ͣ,coil,8220,, +,,,,,, +,BOOL,UNILAB͵Һƿ,coil,8720,, +,BOOL,豸ܵҺƿ,coil,8520,, +REG_MSG_ELECTROLYTE_NUM,WORD,Һʹƿ,hold_register,496,, +,WORD,Ƭ̾λʼλ0,hold_register,440,, +,WORD,Ĥ̾λʼλ0,hold_register,450,, +,WORD,Һƿ_Ͼλʼλ0,hold_register,460,, +,WORD,Һƿ_վλʼλ0,hold_register,430,, +,WORD,g_Һƿ_޸˸׾λʼλ0,hold_register,470,, +,WORD,Һǹͷλʼλ0,hold_register,480,, +,WORD,øƬ,hold_register,443,, +,WORD,øĤ,hold_register,453,, +,,,,,, +COIL_UNILAB_SEND_MSG_SUCC_CMD,BOOL,UNILAB䷽,coil,8700,, +COIL_REQUEST_REC_MSG_STATUS,BOOL,豸䷽,coil,8500,, +REG_MSG_ELECTROLYTE_USE_NUM,INT16,ƿҺʹô,hold_register,11000,, +REG_MSG_ELECTROLYTE_VOLUME,INT16,Һȡ,hold_register,11004,, +REG_MSG_ASSEMBLY_PRESSURE,INT16,װѹ,hold_register,11008,, +REG_DATA_ELECTROLYTE_CODE,STRING,Һάк,hold_register,10020,, +,BOOL,Ӿλfalse:ʹãtrue:ԣ,coil,8300,, +,BOOL,죨false:ʹãtrue:ԣ,coil,8310,, +,BOOL,_֣false:ʹãtrue:ԣ,coil,8320,, +,BOOL,_Ҳ֣false:ʹãtrue:ԣ,coil,8420,, +,BOOL,еְ̣false:ʹãtrue:ԣ,coil,8330,, +,BOOL,ϣfalse:ʹãtrue:ԣ,coil,8340,, +,BOOL,ռ֪false:ʹãtrue:ԣ,coil,8350,, +,BOOL,ѹģʽfalse:ѹģʽTrue:ģʽ,coil,8360,, +,BOOL,Һģʽfalse:εҺtrue:εҺ,coil,8370,, +,BOOL,Ƭأfalse:ʹãtrue:ԣ,coil,8380,, +,BOOL,Ƭװʽfalse:װtrue:װ,coil,8390,, +,BOOL,ѹࣨfalse:ʹãtrue:ԣ,coil,8400,, +,BOOL,̷̰ʽfalse:ˮƽ̣true:ѵ̣,coil,8410,, +COIL_SYS_UNILAB_INTERACT ,BOOL,Unilabfalse:ʹãtrue:ԣ,coil,8450,, +,BOOL,Եࣨfalse:ʹãtrue:ԣ,colil,8460,, +,,,,,, +COIL_UNILAB_SEND_MSG_SUCC_CMD,BOOL,UNILAB䷽,coil,8510,, +COIL_UNILAB_REC_MSG_SUCC_CMD,BOOL,UNILABܲ,coil,8710,, +REG_DATA_POLE_WEIGHT,FLOAT32,ǰƬ,hold_register,10010,, +REG_DATA_ASSEMBLY_PER_TIME,FLOAT32,ǰŵװʱ,hold_register,10012,, +REG_DATA_ASSEMBLY_PRESSURE,INT16,ǰװѹ,hold_register,10014,, +REG_DATA_ELECTROLYTE_VOLUME,INT16,ǰҺע,hold_register,10016,, +REG_DATA_ASSEMBLY_TYPE,INT16,װƬѵʽ(7/8),hold_register,10018,, +REG_DATA_ELECTROLYTE_CODE,STRING,Һάк,hold_register,10020,, +REG_DATA_COIN_CELL_CODE,STRING,ضάк,hold_register,10030,, +REG_DATA_STACK_VISON_CODE,STRING,϶ѵͼƬ,hold_register,10040,, +REG_DATA_ELECTROLYTE_USE_NUM,INT16,ǰ缫ҺװR,hold_register,10000,, +REG_DATA_OPEN_CIRCUIT_VOLTAGE,FLOAT32,ǰصѹ,hold_register,10002,, +,INT,еȡϼĴ1-ǡ2-桢3-Ƭ4-Ĥ5-Ƭ6-ƽ桢7-桢8-ǣ,hold_register,10060,, +,,,,,, +,INT,ǰƬʣR,hold_register,10062,PLCַ,1223- +,INT,ǰĤR,hold_register,10064,, +,INT,Һ״̬루R,hold_register,10066,, +,REAL,·ѹOKֵR,hold_register,10068,, +,REAL,·ѹOKֵR,hold_register,10070,, +,INT,ǰװR,hold_register,10072,, +,INT,ǰװR,hold_register,10074,, +,REAL,10mmƬʣR,hold_register,520,HMIַ, +,REAL,12mmƬʣR,hold_register,522,, +,REAL,16mmƬʣR,hold_register,524,, +,REAL,ʣR,hold_register,526,, +,REAL,ʣR,hold_register,528,, +,REAL,ƽʣR,hold_register,530,, +,REAL,ʣR,hold_register,532,, +,REAL,ʣR,hold_register,534,, +,REAL,ƷʣR,hold_register,536,, +,REAL,ƷNGʣR,hold_register,538,, +,,,,,, +,REAL,10mmƬȣW,hold_register,540,, +,REAL,12mmƬȣW,hold_register,542,, +,REAL,16mmƬȣW,hold_register,544,, +,REAL,ȣW,hold_register,546,, +,REAL,ǺȣW,hold_register,548,, +,REAL,ƽȣW,hold_register,550,, +,REAL,øǺȣW,hold_register,552,, +,REAL,õȣW,hold_register,554,, +,REAL,óƷغȣW,hold_register,556,, +,,,,,, +,,,,,, +REG_DATA_GLOVE_BOX_PRESSURE,FLOAT32,ѹ,hold_register,10050,, +REG_DATA_GLOVE_BOX_WATER_CONTENT,FLOAT32,ˮ,hold_register,10052,, +REG_DATA_GLOVE_BOX_O2_CONTENT,FLOAT32,,hold_register,10054,, +,,,,,, +,BOOL,쳣100-ϵͳ쳣,coil,1000,, +,BOOL,쳣101-ͣ,coil,1010,, +,BOOL,쳣111-伱ͣ,coil,1110,, +,BOOL,쳣112-ڹդڵ,coil,1120,, +,BOOL,쳣160-Һǹͷȱ,coil,1600,, +,BOOL,쳣161-ȱ,coil,1610,, +,BOOL,쳣162-ȱ,coil,1620,, +,BOOL,쳣163-Ƭȱ,coil,1630,, +,BOOL,쳣164-Ĥȱ,coil,1640,, +,BOOL,쳣165-Ƭȱ,coil,1650,, +,BOOL,쳣166-ƽȱ,coil,1660,, +,BOOL,쳣167-ȱ,coil,1670,, +,BOOL,쳣168-ȱ,coil,1680,, +,BOOL,쳣169-Ʒ,coil,1690,, +,BOOL,쳣201-ŷ01쳣,coil,2010,, +,BOOL,쳣202-ŷ02쳣,coil,2020,, +,BOOL,쳣203-ŷ03쳣,coil,2030,, +,BOOL,쳣204-ŷ04쳣,coil,2040,, +,BOOL,쳣205-ŷ05쳣,coil,2050,, +,BOOL,쳣206-ŷ06쳣,coil,2060,, +,BOOL,쳣207-ŷ07쳣,coil,2070,, +,BOOL,쳣208-ŷ08쳣,coil,2080,, +,BOOL,쳣209-ŷ09쳣,coil,2090,, +,BOOL,쳣210-ŷ10쳣,coil,2100,, +,BOOL,쳣211-ŷ11쳣,coil,2110,, +,BOOL,쳣212-ŷ12쳣,coil,2120,, +,BOOL,쳣213-ŷ13쳣,coil,2130,, +,BOOL,쳣214-ŷ14쳣,coil,2140,, +,BOOL,쳣250-Ԫ쳣,coil,2500,, +,BOOL,쳣251-ҺǹͨѶ쳣,coil,2510,, +,BOOL,쳣252-Һǹ,coil,2520,, +,BOOL,쳣256-צ쳣,coil,2560,, +,BOOL,쳣262-RBδ֪λ,coil,2620,, +,BOOL,쳣263-RBXYZ,coil,2630,, +,BOOL,쳣264-RBӾ,coil,2640,, +,BOOL,쳣265-RB1#ȡʧ,coil,2650,, +,BOOL,쳣266-RB2#ȡʧ,coil,2660,, +,BOOL,쳣267-RB3#ȡʧ,coil,2670,, +,BOOL,쳣268-RB4#ȡʧ,coil,2680,, +,BOOL,쳣269-RBȡʧ,coil,2690,, +,BOOL,쳣280-RBײ쳣,coil,2800,, +,BOOL,쳣290-ӾϵͳͨѶ쳣,coil,2900,, +,BOOL,쳣291-ӾλNG쳣,coil,2910,, +,BOOL,쳣292-ɨǹͨѶ쳣,coil,2920,, +,BOOL,쳣310-쳣,coil,3100,, +,BOOL,쳣311-쳣,coil,3110,, +,BOOL,쳣312-쳣,coil,3120,, +,BOOL,쳣313-쳣,coil,3130,, +,BOOL,쳣340-·ѹ쳣,coil,3400,, +,BOOL,쳣342-·ѹ쳣,coil,3420,, +,BOOL,쳣344-·ѹѹ쳣,coil,3440,, +,BOOL,쳣350-쳣,coil,3500,, +,BOOL,쳣352-쳣,coil,3520,, +,BOOL,쳣354-ϴ޳쳣,coil,3540,, +,BOOL,쳣356-ϴ޳ѹ쳣,coil,3560,, +,BOOL,쳣360-Һƿλ쳣,coil,3600,, +,BOOL,쳣362-Һǹͷжλ쳣,coil,3620,, +COIL ALARM_364_SERVO_DRIVE_ERROR,BOOL,쳣364-Լƿצ쳣,coil,3640,, +COIL ALARM_367_SERVO_DRIVER_ERROR,BOOL,쳣366-Լƿצ쳣,coil,3660,, +COIL ALARM_370_SERVO_MODULE_ERROR,BOOL,쳣370-ѹģ鴵쳣,coil,3700,, +,,,,,, +,,,,,, +,,,,,, +,,,,,, +,,,,,, +,,,,,, +,,,,,, +COIL + ģ/ + д+»߷ָ--boolֵ,,,,,, +REG + ģ/ + д+»߷ָ--ԼĴ,,,,,, diff --git a/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_20260106.xlsx b/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_20260106.xlsx new file mode 100644 index 0000000..1add6c1 Binary files /dev/null and b/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_20260106.xlsx differ diff --git a/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_a.csv b/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_a.csv deleted file mode 100644 index 98f9038..0000000 --- a/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_a.csv +++ /dev/null @@ -1,64 +0,0 @@ -Name,DataType,InitValue,Comment,Attribute,DeviceType,Address, -COIL_SYS_START_CMD,BOOL,,,,coil,8010, -COIL_SYS_STOP_CMD,BOOL,,,,coil,8020, -COIL_SYS_RESET_CMD,BOOL,,,,coil,8030, -COIL_SYS_HAND_CMD,BOOL,,,,coil,8040, -COIL_SYS_AUTO_CMD,BOOL,,,,coil,8050, -COIL_SYS_INIT_CMD,BOOL,,,,coil,8060, -COIL_UNILAB_SEND_MSG_SUCC_CMD,BOOL,,,,coil,8700, -COIL_UNILAB_REC_MSG_SUCC_CMD,BOOL,,,,coil,8710,unilab_rec_msg_succ_cmd -COIL_SYS_START_STATUS,BOOL,,,,coil,8210, -COIL_SYS_STOP_STATUS,BOOL,,,,coil,8220, -COIL_SYS_RESET_STATUS,BOOL,,,,coil,8230, -COIL_SYS_HAND_STATUS,BOOL,,,,coil,8240, -COIL_SYS_AUTO_STATUS,BOOL,,,,coil,8250, -COIL_SYS_INIT_STATUS,BOOL,,,,coil,8260, -COIL_REQUEST_REC_MSG_STATUS,BOOL,,,,coil,8500, -COIL_REQUEST_SEND_MSG_STATUS,BOOL,,,,coil,8510,request_send_msg_status -REG_MSG_ELECTROLYTE_USE_NUM,INT16,,,,hold_register,11000, -REG_MSG_ELECTROLYTE_NUM,INT16,,,,hold_register,11002,unilab_send_msg_electrolyte_num -REG_MSG_ELECTROLYTE_VOLUME,INT16,,,,hold_register,11004,unilab_send_msg_electrolyte_vol -REG_MSG_ASSEMBLY_TYPE,INT16,,,,hold_register,11006,unilab_send_msg_assembly_type -REG_MSG_ASSEMBLY_PRESSURE,INT16,,,,hold_register,11008,unilab_send_msg_assembly_pressure -REG_DATA_ASSEMBLY_COIN_CELL_NUM,INT16,,,,hold_register,10000,data_assembly_coin_cell_num -REG_DATA_OPEN_CIRCUIT_VOLTAGE,FLOAT32,,,,hold_register,10002,data_open_circuit_voltage -REG_DATA_AXIS_X_POS,FLOAT32,,,,hold_register,10004, -REG_DATA_AXIS_Y_POS,FLOAT32,,,,hold_register,10006, -REG_DATA_AXIS_Z_POS,FLOAT32,,,,hold_register,10008, -REG_DATA_POLE_WEIGHT,FLOAT32,,,,hold_register,10010,data_pole_weight -REG_DATA_ASSEMBLY_PER_TIME,FLOAT32,,,,hold_register,10012,data_assembly_time -REG_DATA_ASSEMBLY_PRESSURE,INT16,,,,hold_register,10014,data_assembly_pressure -REG_DATA_ELECTROLYTE_VOLUME,INT16,,,,hold_register,10016,data_electrolyte_volume -REG_DATA_COIN_NUM,INT16,,,,hold_register,10018,data_coin_num -REG_DATA_ELECTROLYTE_CODE,STRING,,,,hold_register,10020,data_electrolyte_code() -REG_DATA_COIN_CELL_CODE,STRING,,,,hold_register,10030,data_coin_cell_code() -REG_DATA_STACK_VISON_CODE,STRING,,,,hold_register,12004,data_stack_vision_code() -REG_DATA_GLOVE_BOX_PRESSURE,FLOAT32,,,,hold_register,10050,data_glove_box_pressure -REG_DATA_GLOVE_BOX_WATER_CONTENT,FLOAT32,,,,hold_register,10052,data_glove_box_water_content -REG_DATA_GLOVE_BOX_O2_CONTENT,FLOAT32,,,,hold_register,10054,data_glove_box_o2_content -UNILAB_SEND_ELECTROLYTE_BOTTLE_NUM,BOOL,,,,coil,8720, -UNILAB_RECE_ELECTROLYTE_BOTTLE_NUM,BOOL,,,,coil,8520, -REG_MSG_ELECTROLYTE_NUM_USED,INT16,,,,hold_register,496, -REG_DATA_ELECTROLYTE_USE_NUM,INT16,,,,hold_register,10000, -UNILAB_SEND_FINISHED_CMD,BOOL,,,,coil,8730, -UNILAB_RECE_FINISHED_CMD,BOOL,,,,coil,8530, -REG_DATA_ASSEMBLY_TYPE,INT16,,,,hold_register,10018,ASSEMBLY_TYPE7or8 -COIL_ALUMINUM_FOIL,BOOL,,使用铝箔垫,,coil,8340, -REG_MSG_NE_PLATE_MATRIX,INT16,,负极片矩阵点位,,hold_register,440, -REG_MSG_SEPARATOR_PLATE_MATRIX,INT16,,隔膜矩阵点位,,hold_register,450, -REG_MSG_TIP_BOX_MATRIX,INT16,,移液枪头矩阵点位,,hold_register,480, -REG_MSG_NE_PLATE_NUM,INT16,,负极片盘数,,hold_register,443, -REG_MSG_SEPARATOR_PLATE_NUM,INT16,,隔膜盘数,,hold_register,453, -REG_MSG_PRESS_MODE,BOOL,,压制模式(false:压力检测模式,True:距离模式),,coil,8360,电池压制模式 -,,,,,,, -,BOOL,,视觉对位(false:使用,true:忽略),,coil,8300,视觉对位 -,BOOL,,复检(false:使用,true:忽略),,coil,8310,视觉复检 -,BOOL,,手套箱_左仓(false:使用,true:忽略),,coil,8320,手套箱左仓 -,BOOL,,手套箱_右仓(false:使用,true:忽略),,coil,8420,手套箱右仓 -,BOOL,,真空检知(false:使用,true:忽略),,coil,8350,真空检知 -,BOOL,,电解液添加模式(false:单次滴液,true:二次滴液),,coil,8370,滴液模式 -,BOOL,,正极片称重(false:使用,true:忽略),,coil,8380,正极片称重 -,BOOL,,正负极片组装方式(false:正装,true:倒装),,coil,8390,正负极反装 -,BOOL,,压制清洁(false:使用,true:忽略),,coil,8400,压制清洁 -,BOOL,,物料盘摆盘方式(false:水平摆盘,true:堆叠摆盘),,coil,8410,负极片摆盘方式 -REG_MSG_BATTERY_CLEAN_IGNORE,BOOL,,忽略电池清洁(false:使用,true:忽略),,coil,8460, \ No newline at end of file diff --git a/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_b.csv b/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_b.csv new file mode 100644 index 0000000..fc10967 --- /dev/null +++ b/unilabos/devices/workstation/coin_cell_assembly/coin_cell_assembly_b.csv @@ -0,0 +1,130 @@ +Name,DataType,InitValue,Comment,Attribute,DeviceType,Address, +COIL_SYS_START_CMD,BOOL,,,,coil,8010, +COIL_SYS_STOP_CMD,BOOL,,,,coil,8020, +COIL_SYS_RESET_CMD,BOOL,,,,coil,8030, +COIL_SYS_HAND_CMD,BOOL,,,,coil,8040, +COIL_SYS_AUTO_CMD,BOOL,,,,coil,8050, +COIL_SYS_INIT_CMD,BOOL,,,,coil,8060, +COIL_UNILAB_SEND_MSG_SUCC_CMD,BOOL,,,,coil,8700, +COIL_UNILAB_REC_MSG_SUCC_CMD,BOOL,,,,coil,8710,unilab_rec_msg_succ_cmd +COIL_SYS_START_STATUS,BOOL,,,,coil,8210, +COIL_SYS_STOP_STATUS,BOOL,,,,coil,8220, +COIL_SYS_RESET_STATUS,BOOL,,,,coil,8230, +COIL_SYS_HAND_STATUS,BOOL,,,,coil,8240, +COIL_SYS_AUTO_STATUS,BOOL,,,,coil,8250, +COIL_SYS_INIT_STATUS,BOOL,,,,coil,8260, +COIL_REQUEST_REC_MSG_STATUS,BOOL,,,,coil,8500, +COIL_REQUEST_SEND_MSG_STATUS,BOOL,,,,coil,8510,request_send_msg_status +REG_MSG_ELECTROLYTE_USE_NUM,INT16,,,,hold_register,11000, +REG_MSG_ELECTROLYTE_NUM,INT16,,,,hold_register,11002,unilab_send_msg_electrolyte_num +REG_MSG_ELECTROLYTE_VOLUME,INT16,,,,hold_register,11004,unilab_send_msg_electrolyte_vol +REG_MSG_ASSEMBLY_TYPE,INT16,,,,hold_register,11006,unilab_send_msg_assembly_type +REG_MSG_ASSEMBLY_PRESSURE,INT16,,,,hold_register,11008,unilab_send_msg_assembly_pressure +REG_DATA_ASSEMBLY_COIN_CELL_NUM,INT16,,,,hold_register,10000,data_assembly_coin_cell_num +REG_DATA_OPEN_CIRCUIT_VOLTAGE,FLOAT32,,,,hold_register,10002,data_open_circuit_voltage +REG_DATA_AXIS_X_POS,FLOAT32,,,,hold_register,10004, +REG_DATA_AXIS_Y_POS,FLOAT32,,,,hold_register,10006, +REG_DATA_AXIS_Z_POS,FLOAT32,,,,hold_register,10008, +REG_DATA_POLE_WEIGHT,FLOAT32,,,,hold_register,10010,data_pole_weight +REG_DATA_ASSEMBLY_PER_TIME,FLOAT32,,,,hold_register,10012,data_assembly_time +REG_DATA_ASSEMBLY_PRESSURE,INT16,,,,hold_register,10014,data_assembly_pressure +REG_DATA_ELECTROLYTE_VOLUME,INT16,,,,hold_register,10016,data_electrolyte_volume +REG_DATA_COIN_NUM,INT16,,,,hold_register,10018,data_coin_num +REG_DATA_ELECTROLYTE_CODE,STRING,,,,hold_register,10020,data_electrolyte_code() +REG_DATA_COIN_CELL_CODE,STRING,,,,hold_register,10030,data_coin_cell_code() +REG_DATA_STACK_VISON_CODE,STRING,,,,hold_register,12004,data_stack_vision_code() +REG_DATA_GLOVE_BOX_PRESSURE,FLOAT32,,,,hold_register,10050,data_glove_box_pressure +REG_DATA_GLOVE_BOX_WATER_CONTENT,FLOAT32,,,,hold_register,10052,data_glove_box_water_content +REG_DATA_GLOVE_BOX_O2_CONTENT,FLOAT32,,,,hold_register,10054,data_glove_box_o2_content +UNILAB_SEND_ELECTROLYTE_BOTTLE_NUM,BOOL,,,,coil,8720, +UNILAB_RECE_ELECTROLYTE_BOTTLE_NUM,BOOL,,,,coil,8520, +REG_MSG_ELECTROLYTE_NUM_USED,INT16,,,,hold_register,496, +REG_DATA_ELECTROLYTE_USE_NUM,INT16,,,,hold_register,10000, +UNILAB_SEND_FINISHED_CMD,BOOL,,,,coil,8730, +UNILAB_RECE_FINISHED_CMD,BOOL,,,,coil,8530, +REG_DATA_ASSEMBLY_TYPE,INT16,,,,hold_register,10018,ASSEMBLY_TYPE7or8 +REG_UNILAB_INTERACT,BOOL,,,,coil,8450, +,,,,,coil,8320, +COIL_ALUMINUM_FOIL,BOOL,,,,coil,8340, +REG_MSG_NE_PLATE_MATRIX,INT16,,,,hold_register,440, +REG_MSG_SEPARATOR_PLATE_MATRIX,INT16,,,,hold_register,450, +REG_MSG_TIP_BOX_MATRIX,INT16,,,,hold_register,480, +REG_MSG_NE_PLATE_NUM,INT16,,,,hold_register,443, +REG_MSG_SEPARATOR_PLATE_NUM,INT16,,,,hold_register,453, +REG_MSG_PRESS_MODE,BOOL,,,,coil,8360, +,BOOL,,,,coil,8300, +,BOOL,,,,coil,8310, +COIL_GB_L_IGNORE_CMD,BOOL,,,,coil,8320, +COIL_GB_R_IGNORE_CMD,BOOL,,,,coil,8420, +,BOOL,,,,coil,8350, +COIL_ELECTROLYTE_DUAL_DROP_MODE,BOOL,,,,coil,8370, +,BOOL,,,,coil,8380, +,BOOL,,,,coil,8390, +,BOOL,,,,coil,8400, +,BOOL,,,,coil,8410, +REG_MSG_DUAL_DROP_FIRST_VOLUME,INT16,,,,hold_register,4001, +COIL_DUAL_DROP_SUCTION_TIMING,BOOL,,,,coil,8430, +COIL_DUAL_DROP_START_TIMING,BOOL,,,,coil,8470, +REG_MSG_BATTERY_CLEAN_IGNORE,BOOL,,,,coil,8460, +COIL_ALARM_100_SYSTEM_ERROR,BOOL,,,,coil,1000,异常100-系统异常 +COIL_ALARM_101_EMERGENCY_STOP,BOOL,,,,coil,1010,异常101-急停 +COIL_ALARM_111_GLOVEBOX_EMERGENCY_STOP,BOOL,,,,coil,1110,异常111-手套箱急停 +COIL_ALARM_112_GLOVEBOX_GRATING_BLOCKED,BOOL,,,,coil,1120,异常112-手套箱内光栅遮挡 +COIL_ALARM_160_PIPETTE_TIP_SHORTAGE,BOOL,,,,coil,1600,异常160-移液枪头缺料 +COIL_ALARM_161_POSITIVE_SHELL_SHORTAGE,BOOL,,,,coil,1610,异常161-正极壳缺料 +COIL_ALARM_162_ALUMINUM_FOIL_SHORTAGE,BOOL,,,,coil,1620,异常162-铝箔垫缺料 +COIL_ALARM_163_POSITIVE_PLATE_SHORTAGE,BOOL,,,,coil,1630,异常163-正极片缺料 +COIL_ALARM_164_SEPARATOR_SHORTAGE,BOOL,,,,coil,1640,异常164-隔膜缺料 +COIL_ALARM_165_NEGATIVE_PLATE_SHORTAGE,BOOL,,,,coil,1650,异常165-负极片缺料 +COIL_ALARM_166_FLAT_WASHER_SHORTAGE,BOOL,,,,coil,1660,异常166-平垫缺料 +COIL_ALARM_167_SPRING_WASHER_SHORTAGE,BOOL,,,,coil,1670,异常167-弹垫缺料 +COIL_ALARM_168_NEGATIVE_SHELL_SHORTAGE,BOOL,,,,coil,1680,异常168-负极壳缺料 +COIL_ALARM_169_FINISHED_BATTERY_FULL,BOOL,,,,coil,1690,异常169-成品电池满料 +COIL_ALARM_201_SERVO_AXIS_01_ERROR,BOOL,,,,coil,2010,异常201-伺服轴01异常 +COIL_ALARM_202_SERVO_AXIS_02_ERROR,BOOL,,,,coil,2020,异常202-伺服轴02异常 +COIL_ALARM_203_SERVO_AXIS_03_ERROR,BOOL,,,,coil,2030,异常203-伺服轴03异常 +COIL_ALARM_204_SERVO_AXIS_04_ERROR,BOOL,,,,coil,2040,异常204-伺服轴04异常 +COIL_ALARM_205_SERVO_AXIS_05_ERROR,BOOL,,,,coil,2050,异常205-伺服轴05异常 +COIL_ALARM_206_SERVO_AXIS_06_ERROR,BOOL,,,,coil,2060,异常206-伺服轴06异常 +COIL_ALARM_207_SERVO_AXIS_07_ERROR,BOOL,,,,coil,2070,异常207-伺服轴07异常 +COIL_ALARM_208_SERVO_AXIS_08_ERROR,BOOL,,,,coil,2080,异常208-伺服轴08异常 +COIL_ALARM_209_SERVO_AXIS_09_ERROR,BOOL,,,,coil,2090,异常209-伺服轴09异常 +COIL_ALARM_210_SERVO_AXIS_10_ERROR,BOOL,,,,coil,2100,异常210-伺服轴10异常 +COIL_ALARM_211_SERVO_AXIS_11_ERROR,BOOL,,,,coil,2110,异常211-伺服轴11异常 +COIL_ALARM_212_SERVO_AXIS_12_ERROR,BOOL,,,,coil,2120,异常212-伺服轴12异常 +COIL_ALARM_213_SERVO_AXIS_13_ERROR,BOOL,,,,coil,2130,异常213-伺服轴13异常 +COIL_ALARM_214_SERVO_AXIS_14_ERROR,BOOL,,,,coil,2140,异常214-伺服轴14异常 +COIL_ALARM_250_OTHER_COMPONENT_ERROR,BOOL,,,,coil,2500,异常250-其他元件异常 +COIL_ALARM_251_PIPETTE_COMM_ERROR,BOOL,,,,coil,2510,异常251-移液枪通讯异常 +COIL_ALARM_252_PIPETTE_ALARM,BOOL,,,,coil,2520,异常252-移液枪报警 +COIL_ALARM_256_ELECTRIC_GRIPPER_ERROR,BOOL,,,,coil,2560,异常256-电爪异常 +COIL_ALARM_262_RB_UNKNOWN_POSITION_ERROR,BOOL,,,,coil,2620,异常262-RB报警:未知点位错误 +COIL_ALARM_263_RB_XYZ_PARAM_LIMIT_ERROR,BOOL,,,,coil,2630,异常263-RB报警:X、Y、Z参数超限制 +COIL_ALARM_264_RB_VISION_PARAM_ERROR,BOOL,,,,coil,2640,异常264-RB报警:视觉参数误差过大 +COIL_ALARM_265_RB_NOZZLE_1_PICK_FAIL,BOOL,,,,coil,2650,异常265-RB报警:1#吸嘴取料失败 +COIL_ALARM_266_RB_NOZZLE_2_PICK_FAIL,BOOL,,,,coil,2660,异常266-RB报警:2#吸嘴取料失败 +COIL_ALARM_267_RB_NOZZLE_3_PICK_FAIL,BOOL,,,,coil,2670,异常267-RB报警:3#吸嘴取料失败 +COIL_ALARM_268_RB_NOZZLE_4_PICK_FAIL,BOOL,,,,coil,2680,异常268-RB报警:4#吸嘴取料失败 +COIL_ALARM_269_RB_TRAY_PICK_FAIL,BOOL,,,,coil,2690,异常269-RB报警:取物料盘失败 +COIL_ALARM_280_RB_COLLISION_ERROR,BOOL,,,,coil,2800,异常280-RB碰撞异常 +COIL_ALARM_290_VISION_SYSTEM_COMM_ERROR,BOOL,,,,coil,2900,异常290-视觉系统通讯异常 +COIL_ALARM_291_VISION_ALIGNMENT_NG,BOOL,,,,coil,2910,异常291-视觉对位NG异常 +COIL_ALARM_292_BARCODE_SCANNER_COMM_ERROR,BOOL,,,,coil,2920,异常292-扫码枪通讯异常 +COIL_ALARM_310_OCV_TRANSFER_NOZZLE_SUCTION_ERROR,BOOL,,,,coil,3100,异常310-开电移载吸嘴吸真空异常 +COIL_ALARM_311_OCV_TRANSFER_NOZZLE_BREAK_ERROR,BOOL,,,,coil,3110,异常311-开电移载吸嘴破真空异常 +COIL_ALARM_312_WEIGHT_TRANSFER_NOZZLE_SUCTION_ERROR,BOOL,,,,coil,3120,异常312-称重移载吸嘴吸真空异常 +COIL_ALARM_313_WEIGHT_TRANSFER_NOZZLE_BREAK_ERROR,BOOL,,,,coil,3130,异常313-称重移载吸嘴破真空异常 +COIL_ALARM_340_OCV_NOZZLE_TRANSFER_CYLINDER_ERROR,BOOL,,,,coil,3400,异常340-开路电压吸嘴移载气缸异常 +COIL_ALARM_342_OCV_NOZZLE_LIFT_CYLINDER_ERROR,BOOL,,,,coil,3420,异常342-开路电压吸嘴升降气缸异常 +COIL_ALARM_344_OCV_CRIMPING_CYLINDER_ERROR,BOOL,,,,coil,3440,异常344-开路电压旋压气缸异常 +COIL_ALARM_350_WEIGHT_NOZZLE_TRANSFER_CYLINDER_ERROR,BOOL,,,,coil,3500,异常350-称重吸嘴移载气缸异常 +COIL_ALARM_352_WEIGHT_NOZZLE_LIFT_CYLINDER_ERROR,BOOL,,,,coil,3520,异常352-称重吸嘴升降气缸异常 +COIL_ALARM_354_CLEANING_CLOTH_TRANSFER_CYLINDER_ERROR,BOOL,,,,coil,3540,异常354-清洗无尘布移载气缸异常 +COIL_ALARM_356_CLEANING_CLOTH_PRESS_CYLINDER_ERROR,BOOL,,,,coil,3560,异常356-清洗无尘布压紧气缸异常 +COIL_ALARM_360_ELECTROLYTE_BOTTLE_POSITION_CYLINDER_ERROR,BOOL,,,,coil,3600,异常360-电解液瓶定位气缸异常 +COIL_ALARM_362_PIPETTE_TIP_BOX_POSITION_CYLINDER_ERROR,BOOL,,,,coil,3620,异常362-移液枪头盒定位气缸异常 +COIL_ALARM_364_REAGENT_BOTTLE_GRIPPER_LIFT_CYLINDER_ERROR,BOOL,,,,coil,3640,异常364-试剂瓶夹爪升降气缸异常 +COIL_ALARM_366_REAGENT_BOTTLE_GRIPPER_CYLINDER_ERROR,BOOL,,,,coil,3660,异常366-试剂瓶夹爪气缸异常 +COIL_ALARM_370_PRESS_MODULE_BLOW_CYLINDER_ERROR,BOOL,,,,coil,3700,异常370-压制模块吹气气缸异常 +COIL_ALARM_151_ELECTROLYTE_BOTTLE_POSITION_ERROR,BOOL,,,,coil,1510,异常151-电解液瓶定位在籍异常 +COIL_ALARM_152_ELECTROLYTE_BOTTLE_CAP_ERROR,BOOL,,,,coil,1520,异常152-电解液瓶盖在籍异常 diff --git a/unilabos/devices/workstation/coin_cell_assembly/date_20251224.csv b/unilabos/devices/workstation/coin_cell_assembly/date_20251224.csv new file mode 100644 index 0000000..8a8c176 --- /dev/null +++ b/unilabos/devices/workstation/coin_cell_assembly/date_20251224.csv @@ -0,0 +1,2 @@ +Time,open_circuit_voltage,pole_weight,assembly_time,assembly_pressure,electrolyte_volume,coin_num,electrolyte_code,coin_cell_code +20251224_172304,-5.537573695435827e-37,-48.45097351074219,1.372190511464448e+16,3820,30,7,b'\x00\x00d\x00eaoR',b'\x00\x00\x01\x00\x00\x00\r\n' diff --git a/unilabos/devices/workstation/coin_cell_assembly/date_20251225.csv b/unilabos/devices/workstation/coin_cell_assembly/date_20251225.csv new file mode 100644 index 0000000..d51070e --- /dev/null +++ b/unilabos/devices/workstation/coin_cell_assembly/date_20251225.csv @@ -0,0 +1,2 @@ +Time,open_circuit_voltage,pole_weight,assembly_time,assembly_pressure,electrolyte_volume,coin_num,electrolyte_code,coin_cell_code +20251225_105600,5.566961054206384e-37,-53149746331648.0,3271557120.0,3658,10,7,b'\x00\x00d\x00eaoR',b'\x00\x00\x01\x00\x00\x00\r\n' diff --git a/unilabos/devices/workstation/coin_cell_assembly/date_20251229.csv b/unilabos/devices/workstation/coin_cell_assembly/date_20251229.csv new file mode 100644 index 0000000..124bff1 --- /dev/null +++ b/unilabos/devices/workstation/coin_cell_assembly/date_20251229.csv @@ -0,0 +1,2 @@ +Time,open_circuit_voltage,pole_weight,assembly_time,assembly_pressure,electrolyte_volume,coin_num,electrolyte_code,coin_cell_code +20251229_161836,-5.537573695435827e-37,8.919000478163591e+20,-3.806253867691382e-29,3544,20,7,b'\x00\x00d\x00eaoR',b'\x00\x00\x01\x00\x00\x00\r\n' diff --git a/unilabos/devices/workstation/coin_cell_assembly/date_20251230.csv b/unilabos/devices/workstation/coin_cell_assembly/date_20251230.csv new file mode 100644 index 0000000..7fefb59 --- /dev/null +++ b/unilabos/devices/workstation/coin_cell_assembly/date_20251230.csv @@ -0,0 +1,9 @@ +Time,open_circuit_voltage,pole_weight,assembly_time,assembly_pressure,electrolyte_volume,coin_num,electrolyte_code,coin_cell_code +20251230_182319,0.01600000075995922,13.899999618530273,175.0,3836,20,7,b'\x00\x00d\x00eaoR',b'\x00\x00\x01\x00\x00\x00\r\n' +20251230_185306,0.01600000075995922,13.639999389648438,625.0,3819,20,7,deaoR, +20251230_192124,0.0,8.949999809265137,414.0,3803,20,8,deaoR, +20251230_195621,3.8359999656677246,10.069999694824219,205.0,3350,20,8,LG600001,19311909 +20251230_200830,0.7929999828338623,9.34999942779541,18.0,3318,20,8,LG600001,19533419 +20251230_201123,0.0,9.169999122619629,17.0,3269,20,8,LG600001,20054389 +20251230_201410,0.0,9.569999694824219,18.0,3237,20,8,LG600001,YS102704 +20251230_201659,0.0,9.699999809265137,169.0,3318,20,8,LG600001,20112754 diff --git a/unilabos/devices/workstation/coin_cell_assembly/date_20260106.csv b/unilabos/devices/workstation/coin_cell_assembly/date_20260106.csv new file mode 100644 index 0000000..f9cde47 --- /dev/null +++ b/unilabos/devices/workstation/coin_cell_assembly/date_20260106.csv @@ -0,0 +1,3 @@ +Time,open_circuit_voltage,pole_weight,assembly_time,assembly_pressure,electrolyte_volume,coin_num,electrolyte_code,coin_cell_code +20260106_221708,0.03200000151991844,26.26999855041504,18.0,3803,30,7,NoRead88,22000063 +20260106_221957,0.11299999803304672,26.26999855041504,170.0,3787,30,7,LG600001,22124813 diff --git a/unilabos/devices/workstation/coin_cell_assembly/interactive_battery_export_demo.py b/unilabos/devices/workstation/coin_cell_assembly/interactive_battery_export_demo.py new file mode 100644 index 0000000..adf2082 --- /dev/null +++ b/unilabos/devices/workstation/coin_cell_assembly/interactive_battery_export_demo.py @@ -0,0 +1,536 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""扣式电池组装系统 - 交互式CSV导出演示脚本(增强版) + +此脚本专为交互式使用优化,提供清洁的命令行界面, +禁用了所有调试信息输出,确保用户可以顺畅地输入命令。 + +主要功能: +1. 手动导出设备数据到CSV文件(包含6个关键数据字段) +2. 查看CSV文件内容和导出状态 +3. 兼容原有的电池组装完成状态自动导出功能 +4. 实时查看设备数据和电池数量 + +数据字段: +- timestamp: 时间戳 +- assembly_time: 单颗电池组装时间(秒) +- open_circuit_voltage: 开路电压值(V) +- pole_weight: 正极片称重数据(g) +- battery_qr_code: 电池二维码序列号 +- electrolyte_qr_code: 电解液二维码序列号 + +使用方法: +1. 确保设备已连接并可正常通信 +2. 运行此脚本: python interactive_battery_export_demo.py +3. 使用交互式命令控制导出功能 +""" + +import time +import os +import sys +import logging +import csv +from datetime import datetime +from pathlib import Path + +# 完全禁用所有调试和信息级别的日志输出 +logging.getLogger().setLevel(logging.CRITICAL) +logging.getLogger('pymodbus').setLevel(logging.CRITICAL) +logging.getLogger('unilabos').setLevel(logging.CRITICAL) +logging.getLogger('pymodbus.logging').setLevel(logging.CRITICAL) +logging.getLogger('pymodbus.logging.tcp').setLevel(logging.CRITICAL) +logging.getLogger('pymodbus.logging.base').setLevel(logging.CRITICAL) +logging.getLogger('pymodbus.logging.decoders').setLevel(logging.CRITICAL) + +# 添加当前目录到Python路径,以便正确导入模块 +current_dir = Path(__file__).parent +sys.path.insert(0, str(current_dir.parent.parent.parent)) # 添加unilabos根目录 +sys.path.insert(0, str(current_dir)) # 添加当前目录 + +# 导入扣式电池组装系统 +try: + from unilabos.devices.coin_cell_assembly.coin_cell_assembly_system import Coin_Cell_Assembly +except ImportError: + # 如果上述导入失败,尝试直接导入 + try: + from coin_cell_assembly_system import Coin_Cell_Assembly + except ImportError as e: + print(f"导入错误: {e}") + print("请确保在正确的目录下运行此脚本,或者将unilabos添加到Python路径中") + sys.exit(1) + +def clear_screen(): + """清屏函数""" + os.system('cls' if os.name == 'nt' else 'clear') + +def print_header(): + """打印程序头部信息""" + print("="*60) + print(" 扣式电池组装系统 - 交互式CSV导出控制台") + print("="*60) + print() + +def print_commands(): + """打印可用命令""" + print("可用命令:") + print(" start - 启动电池组装完成状态导出") + print(" stop - 停止导出") + print(" status - 查看导出状态") + print(" data - 查看当前设备数据") + print(" count - 查看当前电池数量") + print(" export - 手动导出当前数据到CSV") + print(" setpath - 设置自定义CSV文件路径") + print(" view - 查看CSV文件内容") + print(" force - 强制继续CSV导出(即使设备停止)") + print(" detail - 显示详细设备状态") + print(" clear - 清屏") + print(" help - 显示帮助信息") + print(" quit - 退出程序") + print("-"*60) + +def print_status_info(device, csv_file_path): + """打印状态信息""" + try: + status = device.get_csv_export_status() + is_running = status.get('running', False) + export_file = status.get('file_path', None) + thread_alive = status.get('thread_alive', False) + device_status = status.get('device_status', 'N/A') + battery_count = status.get('battery_count', 'N/A') + + print(f"导出状态: {'运行中' if is_running else '已停止'}") + print(f"导出文件: {export_file if export_file else 'N/A'}") + print(f"线程状态: {'活跃' if thread_alive else '非活跃'}") + print(f"设备状态: {device_status}") + print(f"电池计数: {battery_count}") + + # 检查手动导出的CSV文件 + if os.path.exists(csv_file_path): + file_size = os.path.getsize(csv_file_path) + print(f"手动导出文件: {csv_file_path} ({file_size} 字节)") + else: + print(f"手动导出文件: {csv_file_path} (不存在)") + + # 显示设备运行状态 + try: + print("\n=== 设备运行状态 ===") + print(f"系统启动状态: {device.sys_start_status}") + print(f"系统停止状态: {device.sys_stop_status}") + print(f"自动模式状态: {device.sys_auto_status}") + print(f"手动模式状态: {device.sys_hand_status}") + except Exception as e: + print(f"获取设备运行状态失败: {e}") + + except Exception as e: + print(f"获取状态失败: {e}") + +def collect_device_data(device): + """收集设备的六个关键数据""" + try: + timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + # 读取各项数据,添加错误处理和重试机制 + try: + assembly_time = device.data_assembly_time # 单颗电池组装时间(秒) + # 确保返回的是数值类型 + if isinstance(assembly_time, (list, tuple)) and len(assembly_time) > 0: + assembly_time = float(assembly_time[0]) + else: + assembly_time = float(assembly_time) + except Exception as e: + print(f"读取组装时间失败: {e}") + assembly_time = 0.0 + + try: + open_circuit_voltage = device.data_open_circuit_voltage # 开路电压值(V) + # 确保返回的是数值类型 + if isinstance(open_circuit_voltage, (list, tuple)) and len(open_circuit_voltage) > 0: + open_circuit_voltage = float(open_circuit_voltage[0]) + else: + open_circuit_voltage = float(open_circuit_voltage) + except Exception as e: + print(f"读取开路电压失败: {e}") + open_circuit_voltage = 0.0 + + try: + pole_weight = device.data_pole_weight # 正极片称重数据(g) + # 确保返回的是数值类型 + if isinstance(pole_weight, (list, tuple)) and len(pole_weight) > 0: + pole_weight = float(pole_weight[0]) + else: + pole_weight = float(pole_weight) + except Exception as e: + print(f"读取正极片重量失败: {e}") + pole_weight = 0.0 + + try: + assembly_pressure = device.data_assembly_pressure # 电池压制力(N) + # 确保返回的是数值类型 + if isinstance(assembly_pressure, (list, tuple)) and len(assembly_pressure) > 0: + assembly_pressure = int(assembly_pressure[0]) + else: + assembly_pressure = int(assembly_pressure) + except Exception as e: + print(f"读取压制力失败: {e}") + assembly_pressure = 0 + + try: + battery_qr_code = device.data_coin_cell_code # 电池二维码序列号 + # 处理字符串类型数据 + if isinstance(battery_qr_code, str): + battery_qr_code = battery_qr_code.strip() + else: + battery_qr_code = str(battery_qr_code) + except Exception as e: + print(f"读取电池二维码失败: {e}") + battery_qr_code = "N/A" + + try: + electrolyte_qr_code = device.data_electrolyte_code # 电解液二维码序列号 + # 处理字符串类型数据 + if isinstance(electrolyte_qr_code, str): + electrolyte_qr_code = electrolyte_qr_code.strip() + else: + electrolyte_qr_code = str(electrolyte_qr_code) + except Exception as e: + print(f"读取电解液二维码失败: {e}") + electrolyte_qr_code = "N/A" + + # 获取电池数量 + try: + battery_count = device.data_assembly_coin_cell_num + # 确保返回的是数值类型 + if isinstance(battery_count, (list, tuple)) and len(battery_count) > 0: + battery_count = int(battery_count[0]) + else: + battery_count = int(battery_count) + except Exception as e: + print(f"读取电池数量失败: {e}") + battery_count = 0 + + return { + 'Timestamp': timestamp, + 'Battery_Count': battery_count, + 'Assembly_Time': assembly_time, + 'Open_Circuit_Voltage': open_circuit_voltage, + 'Pole_Weight': pole_weight, + 'Assembly_Pressure': assembly_pressure, + 'Battery_Code': battery_qr_code, + 'Electrolyte_Code': electrolyte_qr_code + } + except Exception as e: + print(f"收集数据时出错: {e}") + return None + +def export_to_csv(data, csv_file_path): + """将数据导出到CSV文件""" + try: + # 检查文件是否存在,如果不存在则创建并写入表头 + file_exists = os.path.exists(csv_file_path) + + # 确保目录存在 + csv_dir = os.path.dirname(csv_file_path) + if csv_dir: + os.makedirs(csv_dir, exist_ok=True) + + # 确保数值字段为正确的数值类型,避免前导单引号问题 + processed_data = data.copy() + + # 处理数值字段,确保它们是数值类型而不是字符串,增强错误处理 + numeric_fields = ['Battery_Count', 'Assembly_Time', 'Open_Circuit_Voltage', 'Pole_Weight', 'Assembly_Pressure'] + for field in numeric_fields: + if field in processed_data: + try: + value = processed_data[field] + # 处理可能的列表或元组类型 + if isinstance(value, (list, tuple)) and len(value) > 0: + value = value[0] + + if field == 'Battery_Count' or field == 'Assembly_Pressure': + processed_data[field] = int(float(value)) # 先转float再转int,处理字符串数字 + else: + processed_data[field] = float(value) + except (ValueError, TypeError, IndexError) as e: + print(f"字段 {field} 类型转换失败: {e}, 使用默认值") + processed_data[field] = 0 if field == 'Battery_Count' else 0.0 + + # 处理字符串字段 + for field in ['Battery_Code', 'Electrolyte_Code']: + if field in processed_data: + try: + value = processed_data[field] + if isinstance(value, (list, tuple)) and len(value) > 0: + value = value[0] + processed_data[field] = str(value).strip() + except Exception as e: + print(f"字段 {field} 处理失败: {e}, 使用默认值") + processed_data[field] = "N/A" + + with open(csv_file_path, 'a', newline='', encoding='utf-8') as csvfile: + fieldnames = ['Timestamp', 'Battery_Count', 'Assembly_Time', 'Open_Circuit_Voltage', + 'Pole_Weight', 'Assembly_Pressure', 'Battery_QR_Code', 'Electrolyte_QR_Code'] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames, quoting=csv.QUOTE_MINIMAL) + + # 如果文件不存在,写入表头 + if not file_exists: + writer.writeheader() + print(f"创建新的CSV文件: {csv_file_path}") + + # 写入数据 + writer.writerow(processed_data) + print(f"数据已导出到: {csv_file_path}") + + return True + except Exception as e: + print(f"导出CSV时出错: {e}") + return False + +def view_csv_content(csv_file_path, lines=10): + """查看CSV文件内容""" + try: + if not os.path.exists(csv_file_path): + print("CSV文件不存在") + return + + with open(csv_file_path, 'r', encoding='utf-8') as csvfile: + content = csvfile.readlines() + + if not content: + print("CSV文件为空") + return + + print(f"CSV文件内容 (显示最后{min(lines, len(content))}行):") + print("-" * 80) + + # 显示表头 + if len(content) > 0: + print(content[0].strip()) + print("-" * 80) + + # 显示最后几行数据 + start_line = max(1, len(content) - lines + 1) + for i in range(start_line, len(content)): + print(content[i].strip()) + + print("-" * 80) + print(f"总共 {len(content)-1} 条数据记录") + + except Exception as e: + print(f"读取CSV文件时出错: {e}") + +def interactive_demo(): + """ + 交互式演示模式(优化版) + """ + clear_screen() + print_header() + + print("正在初始化设备连接...") + print("设备地址: 192.168.1.20:502") + print("正在尝试连接...") + + try: + device = Coin_Cell_Assembly(address="192.168.1.20", port="502") + print("✓ 设备连接成功") + + # 测试设备数据读取 + print("正在测试设备数据读取...") + try: + test_count = device.data_assembly_coin_cell_num + print(f"✓ 当前电池数量: {test_count}") + except Exception as e: + print(f"⚠ 数据读取测试失败: {e}") + print("设备连接正常,但数据读取可能存在问题") + + except Exception as e: + print(f"✗ 设备连接失败: {e}") + print("请检查以下项目:") + print("1. 设备是否已开机并正常运行") + print("2. 网络连接是否正常") + print("3. 设备IP地址是否为192.168.1.20") + print("4. Modbus服务是否在端口502上运行") + input("按回车键退出...") + return + + csv_file_path = "battery_data_export.csv" + print(f"CSV文件路径: {os.path.abspath(csv_file_path)}") + print() + print("功能说明:") + print("- 支持手动导出当前设备数据到CSV文件") + print("- 包含六个关键数据: 组装时间、开路电压、正极片重量、电池码、电解液码") + print("- 电池码和电解液码可能显示为N/A(当二维码读取失败时)") + print("- 支持查看CSV文件内容和导出状态") + print("- 兼容原有的电池组装完成状态自动导出功能") + print() + + print_commands() + + while True: + try: + command = input("\n请输入命令 > ").strip().lower() + + if command == "start": + print("启动电池组装完成状态导出...") + try: + success, message = device.start_battery_completion_export(csv_file_path) + if success: + print(f"✓ {message}") + print("系统正在监控电池组装完成状态...") + else: + print(f"✗ {message}") + except Exception as e: + print(f"启动导出时出错: {e}") + + elif command == "stop": + print("停止导出...") + try: + success, message = device.stop_csv_export() + if success: + print(f"✓ {message}") + else: + print(f"✗ {message}") + except Exception as e: + print(f"停止导出时出错: {e}") + + elif command == "force": + print("强制继续CSV导出...") + try: + success, message = device.force_continue_csv_export() + if success: + print(f"✓ {message}") + print("注意: CSV导出将继续监控数据变化,即使设备处于停止状态") + else: + print(f"✗ {message}") + except AttributeError: + print("✗ 当前版本不支持强制继续功能") + except Exception as e: + print(f"✗ 强制继续失败: {e}") + + elif command == "detail": + print("=== 详细设备状态 ===") + print_status_info(device, csv_file_path) + + elif command == "status": + print_status_info(device, csv_file_path) + + elif command == "data": + print("读取当前设备数据...") + try: + data = collect_device_data(device) + if data: + print("\n=== 当前设备数据 ===") + print(f"时间戳: {data['Timestamp']}") + print(f"电池数量: {data['Battery_Count']}") + print(f"单颗电池组装时间: {data['Assembly_Time']:.2f} 秒") + print(f"开路电压值: {data['Open_Circuit_Voltage']:.4f} V") + print(f"正极片称重数据: {data['Pole_Weight']:.4f} g") + print(f"电池压制力: {data['Assembly_Pressure']} N") + print(f"电池二维码序列号: {data['Battery_Code']}") + print(f"电解液二维码序列号: {data['Electrolyte_Code']}") + print("===================") + else: + print("无法获取设备数据") + except Exception as e: + print(f"读取数据时出错: {e}") + + elif command == "count": + print("读取当前电池数量...") + try: + count = device.data_assembly_coin_cell_num + print(f"当前已完成电池数量: {count}") + except Exception as e: + print(f"读取电池数量时出错: {e}") + + elif command == "export": + print("正在收集设备数据并导出到CSV...") + data = collect_device_data(device) + if data: + print(f"收集到数据: 电池数量={data.get('Battery_Count', 'N/A')}, 组装时间={data.get('Assembly_Time', 'N/A')}s") + if export_to_csv(data, csv_file_path): + print("✓ 数据已成功导出到CSV文件") + print(f"导出数据: 时间={data['Timestamp']}, 电池数量={data['Battery_Count']}, 组装时间={data['Assembly_Time']}秒, " + f"电压={data['Open_Circuit_Voltage']}V, 重量={data['Pole_Weight']}g, 压制力={data['Assembly_Pressure']}N") + print(f"电池码={data['Battery_Code']}, 电解液码={data['Electrolyte_Code']}") + else: + print("✗ 导出失败") + else: + print("✗ 数据收集失败,无法导出!请检查设备连接状态。") + # 尝试重新连接设备 + try: + if hasattr(device, 'connect'): + device.connect() + print("尝试重新连接设备...") + except Exception as e: + print(f"重新连接失败: {e}") + + elif command == "setpath": + print("设置自定义CSV文件路径") + print(f"当前CSV文件路径: {csv_file_path}") + new_path = input("请输入新的CSV文件路径(包含文件名,如: D:/data/my_battery_data.csv): ").strip() + if new_path: + try: + # 确保目录存在 + new_dir = os.path.dirname(new_path) + if new_dir and not os.path.exists(new_dir): + os.makedirs(new_dir, exist_ok=True) + print(f"✓ 已创建目录: {new_dir}") + + csv_file_path = new_path + print(f"✓ CSV文件路径已更新为: {os.path.abspath(csv_file_path)}") + + # 检查文件是否存在 + if os.path.exists(csv_file_path): + file_size = os.path.getsize(csv_file_path) + print(f"文件已存在,大小: {file_size} 字节") + else: + print("文件不存在,将在首次导出时创建") + except Exception as e: + print(f"✗ 设置路径失败: {e}") + else: + print("路径不能为空") + + elif command == "view": + print("查看CSV文件内容...") + view_csv_content(csv_file_path) + + elif command == "clear": + clear_screen() + print_header() + print_commands() + + elif command == "help": + print_commands() + + elif command == "quit" or command == "exit": + print("正在退出...") + # 停止导出 + try: + device.stop_csv_export() + print("✓ 导出已停止") + except: + pass + print("程序已退出") + break + + elif command == "": + # 空命令,不做任何操作 + continue + + else: + print(f"未知命令: {command}") + print("输入 'help' 查看可用命令") + + except KeyboardInterrupt: + print("\n\n检测到 Ctrl+C,正在退出...") + try: + device.stop_csv_export() + print("✓ 导出已停止") + except: + pass + print("程序已退出") + break + except Exception as e: + print(f"执行命令时出错: {e}") + +if __name__ == '__main__': + interactive_demo() \ No newline at end of file diff --git a/unilabos/devices/workstation/coin_cell_assembly/电池资源冲突修复说明.md b/unilabos/devices/workstation/coin_cell_assembly/电池资源冲突修复说明.md new file mode 100644 index 0000000..685fc08 --- /dev/null +++ b/unilabos/devices/workstation/coin_cell_assembly/电池资源冲突修复说明.md @@ -0,0 +1,107 @@ +# 电池组装资源冲突问题修复说明 + +## 问题描述 + +在运行 `func_allpack_cmd` 函数时,遇到以下错误: + +``` +ValueError: Resource 'battery_0' already assigned to deck +``` + +**错误位置**:`coin_cell_assembly.py` 第 849 行 +```python +liaopan3.children[self.coin_num_N].assign_child_resource(battery, location=None) +``` + +## 原因分析 + +1. **资源名称冲突**: + - 每次创建电池资源使用固定格式 `battery_{coin_num_N}` + - 如果程序重启或断点恢复,`coin_num_N` 可能重置为 0 + - Deck 上可能已存在 `battery_0` 等同名资源 + +2. **缺少冲突处理**: + - 在分配资源前没有检查目标位置是否已有资源 + - 没有清理机制来移除旧资源 + +## 解决方案 + +### 1. 使用时间戳确保资源名称唯一 + +```python +# 之前 +battery = ElectrodeSheet(name=f"battery_{self.coin_num_N}", ...) + +# 修复后 +timestamp_suffix = datetime.now().strftime("%Y%m%d_%H%M%S_%f") +battery_name = f"battery_{self.coin_num_N}_{timestamp_suffix}" +battery = ElectrodeSheet(name=battery_name, ...) +``` + +### 2. 添加资源冲突检查和清理 + +```python +# 检查目标位置是否已有资源 +target_slot = liaopan3.children[self.coin_num_N] +if target_slot.children: + logger.warning(f"位置 {self.coin_num_N} 已有资源,将先卸载旧资源") + try: + # 卸载所有现有子资源 + for child in list(target_slot.children): + target_slot.unassign_child_resource(child) + logger.info(f"已卸载旧资源: {child.name}") + except Exception as e: + logger.error(f"卸载旧资源时出错: {e}") +``` + +### 3. 增强错误处理 + +```python +# 分配新资源到目标位置 +try: + target_slot.assign_child_resource(battery, location=None) + logger.info(f"成功分配电池 {battery_name} 到位置 {self.coin_num_N}") +except Exception as e: + logger.error(f"分配电池资源失败: {e}") + raise +``` + +## 修复效果 + +✅ **不再出现重复资源名称错误** +- 每个电池资源都有唯一的时间戳后缀 +- 即使 `coin_num_N` 相同,资源名称也不会冲突 + +✅ **自动清理旧资源** +- 在分配新资源前检查目标位置 +- 自动卸载已存在的旧资源 + +✅ **增强日志记录** +- 记录资源卸载操作 +- 记录资源分配成功/失败 +- 便于调试和问题追踪 + +## 测试建议 + +1. **正常运行测试**: + ```python + workstation.func_allpack_cmd( + elec_num=1, + elec_use_num=1, + elec_vol=20, + file_path="..." + ) + ``` + +2. **断点恢复测试**: + - 运行一次后中断 + - 再次运行相同参数 + - 验证不会出现资源冲突错误 + +3. **连续运行测试**: + - 连续多次运行 + - 验证每次都能正常分配资源 + +## 相关文件 + +- `coin_cell_assembly.py` - 第 838-875 行(`func_pack_get_msg_cmd` 函数) diff --git a/unilabos/registry/devices/bioyond_cell.yaml b/unilabos/registry/devices/bioyond_cell.yaml index c379e27..09690f1 100644 --- a/unilabos/registry/devices/bioyond_cell.yaml +++ b/unilabos/registry/devices/bioyond_cell.yaml @@ -32,7 +32,7 @@ bioyond_cell: feedback: {} goal: {} goal_default: - xlsx_path: /Users/sml/work/Unilab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx + xlsx_path: D:/UniLab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx handles: {} placeholder_keys: {} result: {} @@ -42,323 +42,8 @@ bioyond_cell: feedback: {} goal: properties: - WH3_x1_y1_z3_1_materialId: - default: '' - type: string - WH3_x1_y1_z3_1_materialType: - default: '' - type: string - WH3_x1_y1_z3_1_quantity: - default: 0 - type: number - WH3_x1_y2_z3_4_materialId: - default: '' - type: string - WH3_x1_y2_z3_4_materialType: - default: '' - type: string - WH3_x1_y2_z3_4_quantity: - default: 0 - type: number - WH3_x1_y3_z3_7_materialId: - default: '' - type: string - WH3_x1_y3_z3_7_materialType: - default: '' - type: string - WH3_x1_y3_z3_7_quantity: - default: 0 - type: number - WH3_x1_y4_z3_10_materialId: - default: '' - type: string - WH3_x1_y4_z3_10_materialType: - default: '' - type: string - WH3_x1_y4_z3_10_quantity: - default: 0 - type: number - WH3_x1_y5_z3_13_materialId: - default: '' - type: string - WH3_x1_y5_z3_13_materialType: - default: '' - type: string - WH3_x1_y5_z3_13_quantity: - default: 0 - type: number - WH3_x2_y1_z3_2_materialId: - default: '' - type: string - WH3_x2_y1_z3_2_materialType: - default: '' - type: string - WH3_x2_y1_z3_2_quantity: - default: 0 - type: number - WH3_x2_y2_z3_5_materialId: - default: '' - type: string - WH3_x2_y2_z3_5_materialType: - default: '' - type: string - WH3_x2_y2_z3_5_quantity: - default: 0 - type: number - WH3_x2_y3_z3_8_materialId: - default: '' - type: string - WH3_x2_y3_z3_8_materialType: - default: '' - type: string - WH3_x2_y3_z3_8_quantity: - default: 0 - type: number - WH3_x2_y4_z3_11_materialId: - default: '' - type: string - WH3_x2_y4_z3_11_materialType: - default: '' - type: string - WH3_x2_y4_z3_11_quantity: - default: 0 - type: number - WH3_x2_y5_z3_14_materialId: - default: '' - type: string - WH3_x2_y5_z3_14_materialType: - default: '' - type: string - WH3_x2_y5_z3_14_quantity: - default: 0 - type: number - WH3_x3_y1_z3_3_materialId: - default: '' - type: string - WH3_x3_y1_z3_3_materialType: - default: '' - type: string - WH3_x3_y1_z3_3_quantity: - default: 0 - type: number - WH3_x3_y2_z3_6_materialId: - default: '' - type: string - WH3_x3_y2_z3_6_materialType: - default: '' - type: string - WH3_x3_y2_z3_6_quantity: - default: 0 - type: number - WH3_x3_y3_z3_9_materialId: - default: '' - type: string - WH3_x3_y3_z3_9_materialType: - default: '' - type: string - WH3_x3_y3_z3_9_quantity: - default: 0 - type: number - WH3_x3_y4_z3_12_materialId: - default: '' - type: string - WH3_x3_y4_z3_12_materialType: - default: '' - type: string - WH3_x3_y4_z3_12_quantity: - default: 0 - type: number - WH3_x3_y5_z3_15_materialId: - default: '' - type: string - WH3_x3_y5_z3_15_materialType: - default: '' - type: string - WH3_x3_y5_z3_15_quantity: - default: 0 - type: number - WH4_x1_y1_z1_1_materialName: - default: '' - type: string - WH4_x1_y1_z1_1_quantity: - default: 0.0 - type: number - WH4_x1_y1_z2_1_materialName: - default: '' - type: string - WH4_x1_y1_z2_1_materialType: - default: '' - type: string - WH4_x1_y1_z2_1_quantity: - default: 0.0 - type: number - WH4_x1_y1_z2_1_targetWH: - default: '' - type: string - WH4_x1_y2_z1_6_materialName: - default: '' - type: string - WH4_x1_y2_z1_6_quantity: - default: 0.0 - type: number - WH4_x1_y2_z2_4_materialName: - default: '' - type: string - WH4_x1_y2_z2_4_materialType: - default: '' - type: string - WH4_x1_y2_z2_4_quantity: - default: 0.0 - type: number - WH4_x1_y2_z2_4_targetWH: - default: '' - type: string - WH4_x1_y3_z1_11_materialName: - default: '' - type: string - WH4_x1_y3_z1_11_quantity: - default: 0.0 - type: number - WH4_x1_y3_z2_7_materialName: - default: '' - type: string - WH4_x1_y3_z2_7_materialType: - default: '' - type: string - WH4_x1_y3_z2_7_quantity: - default: 0.0 - type: number - WH4_x1_y3_z2_7_targetWH: - default: '' - type: string - WH4_x2_y1_z1_2_materialName: - default: '' - type: string - WH4_x2_y1_z1_2_quantity: - default: 0.0 - type: number - WH4_x2_y1_z2_2_materialName: - default: '' - type: string - WH4_x2_y1_z2_2_materialType: - default: '' - type: string - WH4_x2_y1_z2_2_quantity: - default: 0.0 - type: number - WH4_x2_y1_z2_2_targetWH: - default: '' - type: string - WH4_x2_y2_z1_7_materialName: - default: '' - type: string - WH4_x2_y2_z1_7_quantity: - default: 0.0 - type: number - WH4_x2_y2_z2_5_materialName: - default: '' - type: string - WH4_x2_y2_z2_5_materialType: - default: '' - type: string - WH4_x2_y2_z2_5_quantity: - default: 0.0 - type: number - WH4_x2_y2_z2_5_targetWH: - default: '' - type: string - WH4_x2_y3_z1_12_materialName: - default: '' - type: string - WH4_x2_y3_z1_12_quantity: - default: 0.0 - type: number - WH4_x2_y3_z2_8_materialName: - default: '' - type: string - WH4_x2_y3_z2_8_materialType: - default: '' - type: string - WH4_x2_y3_z2_8_quantity: - default: 0.0 - type: number - WH4_x2_y3_z2_8_targetWH: - default: '' - type: string - WH4_x3_y1_z1_3_materialName: - default: '' - type: string - WH4_x3_y1_z1_3_quantity: - default: 0.0 - type: number - WH4_x3_y1_z2_3_materialName: - default: '' - type: string - WH4_x3_y1_z2_3_materialType: - default: '' - type: string - WH4_x3_y1_z2_3_quantity: - default: 0.0 - type: number - WH4_x3_y1_z2_3_targetWH: - default: '' - type: string - WH4_x3_y2_z1_8_materialName: - default: '' - type: string - WH4_x3_y2_z1_8_quantity: - default: 0.0 - type: number - WH4_x3_y2_z2_6_materialName: - default: '' - type: string - WH4_x3_y2_z2_6_materialType: - default: '' - type: string - WH4_x3_y2_z2_6_quantity: - default: 0.0 - type: number - WH4_x3_y2_z2_6_targetWH: - default: '' - type: string - WH4_x3_y3_z2_9_materialName: - default: '' - type: string - WH4_x3_y3_z2_9_materialType: - default: '' - type: string - WH4_x3_y3_z2_9_quantity: - default: 0.0 - type: number - WH4_x3_y3_z2_9_targetWH: - default: '' - type: string - WH4_x4_y1_z1_4_materialName: - default: '' - type: string - WH4_x4_y1_z1_4_quantity: - default: 0.0 - type: number - WH4_x4_y2_z1_9_materialName: - default: '' - type: string - WH4_x4_y2_z1_9_quantity: - default: 0.0 - type: number - WH4_x5_y1_z1_5_materialName: - default: '' - type: string - WH4_x5_y1_z1_5_quantity: - default: 0.0 - type: number - WH4_x5_y2_z1_10_materialName: - default: '' - type: string - WH4_x5_y2_z1_10_quantity: - default: 0.0 - type: number xlsx_path: - default: /Users/sml/work/Unilab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx + default: D:/UniLab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/2025122301.xlsx type: string required: [] type: object @@ -466,7 +151,14 @@ bioyond_cell: goal: {} goal_default: xlsx_path: null - handles: {} + handles: + output: + - data_key: total_orders + data_source: executor + data_type: integer + handler_key: bottle_count + io_type: sink + label: 配液瓶数 placeholder_keys: {} result: {} schema: @@ -779,6 +471,31 @@ bioyond_cell: title: scheduler_start参数 type: object type: UniLabJsonCommand + auto-scheduler_start_and_auto_feeding: + feedback: {} + goal: {} + goal_default: + xlsx_path: D:/UniLab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx + handles: {} + placeholder_keys: {} + result: {} + schema: + description: 组合函数:先启动调度,然后执行自动化上料 + properties: + feedback: {} + goal: + properties: + xlsx_path: + default: D:/UniLab/Uni-Lab-OS/unilabos/devices/workstation/bioyond_studio/bioyond_cell/material_template.xlsx + type: string + required: [] + type: object + result: {} + required: + - goal + title: scheduler_start_and_auto_feeding参数 + type: object + type: UniLabJsonCommand auto-scheduler_stop: feedback: {} goal: {} diff --git a/unilabos/registry/devices/coin_cell_workstation.yaml b/unilabos/registry/devices/coin_cell_workstation.yaml index b3eb7b4..e2cb91a 100644 --- a/unilabos/registry/devices/coin_cell_workstation.yaml +++ b/unilabos/registry/devices/coin_cell_workstation.yaml @@ -115,6 +115,117 @@ coincellassemblyworkstation_device: title: func_allpack_cmd参数 type: object type: UniLabJsonCommand + auto-func_allpack_cmd_simp: + feedback: {} + goal: {} + goal_default: + assembly_pressure: 4200 + assembly_type: 7 + battery_clean_ignore: false + battery_pressure_mode: true + dual_drop_first_volume: 25 + dual_drop_mode: false + dual_drop_start_timing: false + dual_drop_suction_timing: false + elec_num: null + elec_use_num: null + elec_vol: 50 + file_path: /Users/sml/work + fujipian_juzhendianwei: 0 + fujipian_panshu: 0 + gemo_juzhendianwei: 0 + gemopanshu: 0 + lvbodian: true + qiangtou_juzhendianwei: 0 + handles: {} + placeholder_keys: {} + result: {} + schema: + description: 简化版电池组装函数,整合了参数设置和双滴模式 + properties: + feedback: {} + goal: + properties: + assembly_pressure: + default: 4200 + description: 电池压制力(N) + type: integer + assembly_type: + default: 7 + description: 组装类型(7=不用铝箔垫, 8=使用铝箔垫) + type: integer + battery_clean_ignore: + default: false + description: 是否忽略电池清洁步骤 + type: boolean + battery_pressure_mode: + default: true + description: 是否启用压力模式 + type: boolean + dual_drop_first_volume: + default: 25 + description: 二次滴液第一次排液体积(μL) + type: integer + dual_drop_mode: + default: false + description: 电解液添加模式(false=单次滴液, true=二次滴液) + type: boolean + dual_drop_start_timing: + default: false + description: 二次滴液开始滴液时机(false=正极片前, true=正极片后) + type: boolean + dual_drop_suction_timing: + default: false + description: 二次滴液吸液时机(false=正常吸液, true=先吸液) + type: boolean + elec_num: + description: 电解液瓶数 + type: string + elec_use_num: + description: 每瓶电解液组装电池数 + type: string + elec_vol: + default: 50 + description: 电解液吸液量(μL) + type: integer + file_path: + default: /Users/sml/work + description: 实验记录保存路径 + type: string + fujipian_juzhendianwei: + default: 0 + description: 负极片矩阵点位 + type: integer + fujipian_panshu: + default: 0 + description: 负极片盘数 + type: integer + gemo_juzhendianwei: + default: 0 + description: 隔膜矩阵点位 + type: integer + gemopanshu: + default: 0 + description: 隔膜盘数 + type: integer + lvbodian: + default: true + description: 是否使用铝箔垫片 + type: boolean + qiangtou_juzhendianwei: + default: 0 + description: 枪头盒矩阵点位 + type: integer + required: + - elec_num + - elec_use_num + type: object + result: {} + required: + - goal + title: func_allpack_cmd_simp参数 + type: object + type: UniLabJsonCommand auto-func_get_csv_export_status: feedback: {} goal: {} @@ -178,6 +289,27 @@ coincellassemblyworkstation_device: title: func_pack_device_init参数 type: object type: UniLabJsonCommand + auto-func_pack_device_init_auto_start_combined: + feedback: {} + goal: {} + goal_default: {} + handles: {} + placeholder_keys: {} + result: {} + schema: + description: 组合函数:设备初始化 + 切换自动模式 + 启动 + properties: + feedback: {} + goal: + properties: {} + required: [] + type: object + result: {} + required: + - goal + title: func_pack_device_init_auto_start_combined参数 + type: object + type: UniLabJsonCommand auto-func_pack_device_start: feedback: {} goal: {} @@ -250,7 +382,15 @@ coincellassemblyworkstation_device: goal: {} goal_default: bottle_num: null - handles: {} + handles: + input: + - data_key: bottle_num + data_source: workflow + data_type: integer + handler_key: bottle_count + io_type: source + label: 配液瓶数 + required: true placeholder_keys: {} result: {} schema: @@ -260,7 +400,7 @@ coincellassemblyworkstation_device: goal: properties: bottle_num: - type: string + type: integer required: - bottle_num type: object diff --git a/unilabos/registry/devices/laiyu_liquid.yaml b/unilabos/registry/devices/laiyu_liquid.yaml deleted file mode 100644 index 64c0c18..0000000 --- a/unilabos/registry/devices/laiyu_liquid.yaml +++ /dev/null @@ -1,1919 +0,0 @@ -laiyu_liquid: - category: - - liquid_handler - - workstation - - laiyu_liquid - class: - action_value_mappings: - add_liquid: - feedback: {} - goal: - asp_vols: asp_vols - dis_vols: dis_vols - flow_rates: flow_rates - offsets: offsets - reagent_sources: reagent_sources - targets: targets - use_channels: use_channels - goal_default: - asp_vols: - - 0.0 - blow_out_air_volume: - - 0.0 - dis_vols: - - 0.0 - flow_rates: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - mix_liquid_height: 0.0 - mix_rate: 0 - mix_time: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - reagent_sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - placeholder_keys: - reagent_sources: unilabos_resources - targets: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerAdd_Feedback - type: object - goal: - properties: - asp_vols: - items: - type: number - type: array - blow_out_air_volume: - items: - type: number - type: array - dis_vols: - items: - type: number - type: array - flow_rates: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - mix_liquid_height: - type: number - mix_rate: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_time: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - reagent_sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: reagent_sources - type: object - type: array - spread: - type: string - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - asp_vols - - dis_vols - - reagent_sources - - targets - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - - is_96_well - - mix_time - - mix_vol - - mix_rate - - mix_liquid_height - - none_keys - title: LiquidHandlerAdd_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerAdd_Result - type: object - required: - - goal - title: LiquidHandlerAdd - type: object - type: LiquidHandlerAdd - aspirate: - feedback: {} - goal: - flow_rates: flow_rates - resources: resources - use_channels: use_channels - vols: vols - goal_default: - blow_out_air_volume: - - 0.0 - flow_rates: - - 0.0 - liquid_height: - - 0.0 - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - resources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - use_channels: - - 0 - vols: - - 0.0 - handles: {} - placeholder_keys: - resources: unilabos_resources - result: - success: success - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerAspirate_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - type: number - type: array - flow_rates: - items: - type: number - type: array - liquid_height: - items: - type: number - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - resources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: resources - type: object - type: array - spread: - type: string - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - required: - - resources - - vols - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - title: LiquidHandlerAspirate_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerAspirate_Result - type: object - required: - - goal - title: LiquidHandlerAspirate - type: object - type: LiquidHandlerAspirate - auto-add_resource: - feedback: {} - goal: {} - goal_default: - name: null - position: null - resource_type: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: '' - properties: - feedback: {} - goal: - properties: - name: - type: string - position: - items: - type: number - type: array - resource_type: - type: string - required: - - name - - resource_type - - position - type: object - result: {} - required: - - goal - title: add_resource参数 - type: object - type: UniLabJsonCommand - dispense: - feedback: {} - goal: - flow_rates: flow_rates - resources: resources - use_channels: use_channels - vols: vols - goal_default: - blow_out_air_volume: - - 0 - flow_rates: - - 0.0 - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - resources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - use_channels: - - 0 - vols: - - 0.0 - handles: {} - placeholder_keys: - resources: unilabos_resources - result: - success: success - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDispense_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - flow_rates: - items: - type: number - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - resources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: resources - type: object - type: array - spread: - type: string - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - required: - - resources - - vols - - use_channels - - flow_rates - - offsets - - blow_out_air_volume - - spread - title: LiquidHandlerDispense_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDispense_Result - type: object - required: - - goal - title: LiquidHandlerDispense - type: object - type: LiquidHandlerDispense - drop_tip: - feedback: {} - goal: - use_channels: use_channels - goal_default: - allow_nonzero_volume: false - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - tip_spots: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - result: - success: success - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDropTips_Feedback - type: object - goal: - properties: - allow_nonzero_volume: - type: boolean - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - tip_spots: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_spots - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - tip_spots - - use_channels - - offsets - - allow_nonzero_volume - title: LiquidHandlerDropTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDropTips_Result - type: object - required: - - goal - title: LiquidHandlerDropTips - type: object - type: LiquidHandlerDropTips - move_to: - feedback: {} - goal: - channel: channel - dis_to_top: dis_to_top - well: well - goal_default: - channel: 0 - dis_to_top: 0.0 - well: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - placeholder_keys: - well: unilabos_resources - result: - success: success - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerMoveTo_Feedback - type: object - goal: - properties: - channel: - maximum: 2147483647 - minimum: -2147483648 - type: integer - dis_to_top: - type: number - well: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: well - type: object - required: - - well - - dis_to_top - - channel - title: LiquidHandlerMoveTo_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerMoveTo_Result - type: object - required: - - goal - title: LiquidHandlerMoveTo - type: object - type: LiquidHandlerMoveTo - pick_up_tip: - feedback: {} - goal: - tip_rack: tip_rack - use_channels: use_channels - goal_default: - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - tip_spots: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - placeholder_keys: - tip_rack: unilabos_resources - result: - success: success - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerPickUpTips_Feedback - type: object - goal: - properties: - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - tip_spots: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_spots - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - tip_spots - - use_channels - - offsets - title: LiquidHandlerPickUpTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerPickUpTips_Result - type: object - required: - - goal - title: LiquidHandlerPickUpTips - type: object - type: LiquidHandlerPickUpTips - setup: - feedback: {} - goal: - string: string - goal_default: - string: '' - handles: {} - result: - success: success - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: StrSingleInput_Feedback - type: object - goal: - properties: - string: - type: string - required: - - string - title: StrSingleInput_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: StrSingleInput_Result - type: object - required: - - goal - title: StrSingleInput - type: object - type: StrSingleInput - stop: - feedback: {} - goal: - string: string - goal_default: - string: '' - handles: {} - result: - success: success - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: StrSingleInput_Feedback - type: object - goal: - properties: - string: - type: string - required: - - string - title: StrSingleInput_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: StrSingleInput_Result - type: object - required: - - goal - title: StrSingleInput - type: object - type: StrSingleInput - transfer: - feedback: {} - goal: - source: source - target: target - tip_position: tip_position - tip_rack: tip_rack - volume: volume - goal_default: - asp_flow_rates: - - 0.0 - asp_vols: - - 0.0 - blow_out_air_volume: - - 0.0 - delays: - - 0 - dis_flow_rates: - - 0.0 - dis_vols: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - mix_liquid_height: 0.0 - mix_rate: 0 - mix_stage: '' - mix_times: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - tip_racks: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - touch_tip: false - use_channels: - - 0 - handles: {} - placeholder_keys: - source: unilabos_resources - target: unilabos_resources - tip_rack: unilabos_resources - result: - success: success - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerTransfer_Feedback - type: object - goal: - properties: - asp_flow_rates: - items: - type: number - type: array - asp_vols: - items: - type: number - type: array - blow_out_air_volume: - items: - type: number - type: array - delays: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - dis_flow_rates: - items: - type: number - type: array - dis_vols: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - mix_liquid_height: - type: number - mix_rate: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_stage: - type: string - mix_times: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: sources - type: object - type: array - spread: - type: string - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - tip_racks: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_racks - type: object - type: array - touch_tip: - type: boolean - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - asp_vols - - dis_vols - - sources - - targets - - tip_racks - - use_channels - - asp_flow_rates - - dis_flow_rates - - offsets - - touch_tip - - liquid_height - - blow_out_air_volume - - spread - - is_96_well - - mix_stage - - mix_times - - mix_vol - - mix_rate - - mix_liquid_height - - delays - - none_keys - title: LiquidHandlerTransfer_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerTransfer_Result - type: object - required: - - goal - title: LiquidHandlerTransfer - type: object - type: LiquidHandlerTransfer - module: unilabos.devices.laiyu_liquid.core.laiyu_liquid_main:LaiYuLiquid - status_types: - current_position: String - current_volume: float - is_connected: bool - is_initialized: bool - status: dict - tip_attached: bool - type: python - config_info: - - default: /dev/cu.usbserial-3130 - description: RS485转USB端口 - name: port - type: string - - default: 1 - description: 设备地址 - name: address - type: integer - - default: 9600 - description: 波特率 - name: baudrate - type: integer - - default: 5.0 - description: 通信超时时间 (秒) - name: timeout - type: number - - default: 340.0 - description: 工作台宽度 (mm) - name: deck_width - type: number - - default: 250.0 - description: 工作台高度 (mm) - name: deck_height - type: number - - default: 160.0 - description: 工作台深度 (mm) - name: deck_depth - type: number - - default: 77000.0 - description: 最大体积 (μL) - name: max_volume - type: number - - default: 0.1 - description: 最小体积 (μL) - name: min_volume - type: number - - default: 100.0 - description: 最大速度 (mm/s) - name: max_speed - type: number - - default: 50.0 - description: 加速度 (mm/s²) - name: acceleration - type: number - - default: 50.0 - description: 安全高度 (mm) - name: safe_height - type: number - - default: 10.0 - description: 吸头拾取深度 (mm) - name: tip_pickup_depth - type: number - - default: true - description: 液面检测功能 - name: liquid_detection - type: boolean - - default: 10.0 - description: X轴最小安全边距 (mm) - name: safety_margin_x_min - type: number - - default: 10.0 - description: X轴最大安全边距 (mm) - name: safety_margin_x_max - type: number - - default: 10.0 - description: Y轴最小安全边距 (mm) - name: safety_margin_y_min - type: number - - default: 10.0 - description: Y轴最大安全边距 (mm) - name: safety_margin_y_max - type: number - - default: 20.0 - description: Z轴安全间隙 (mm) - name: safety_margin_z_clearance - type: number - description: LaiYu液体处理工作站,基于RS485通信协议的自动化液体处理设备。集成XYZ三轴运动平台和SOPA气动式移液器,支持精确的液体分配和转移操作。具备完整的硬件控制、资源管理和标准化接口,适用于实验室自动化液体处理、样品制备、试剂分配等应用场景。设备通过RS485总线控制步进电机和移液器,提供高精度的位置控制和液体处理能力。 - handles: [] - icon: '' - init_param_schema: - config: - properties: - config: - type: string - required: [] - type: object - data: - properties: - current_position: - items: - type: number - type: array - current_volume: - type: number - is_connected: - type: boolean - is_initialized: - type: boolean - status: - type: object - tip_attached: - type: boolean - required: - - current_position - - current_volume - - is_connected - - is_initialized - - tip_attached - - status - type: object - model: - mesh: laiyu_liquid_handler - type: device - version: 1.0.0 diff --git a/unilabos/registry/devices/liquid_handler.yaml b/unilabos/registry/devices/liquid_handler.yaml deleted file mode 100644 index fdfb6b5..0000000 --- a/unilabos/registry/devices/liquid_handler.yaml +++ /dev/null @@ -1,9956 +0,0 @@ -liquid_handler: - category: - - liquid_handler - class: - action_value_mappings: - add_liquid: - feedback: {} - goal: - asp_vols: asp_vols - blow_out_air_volume: blow_out_air_volume - dis_vols: dis_vols - flow_rates: flow_rates - is_96_well: is_96_well - liquid_height: liquid_height - mix_liquid_height: mix_liquid_height - mix_rate: mix_rate - mix_time: mix_time - mix_vol: mix_vol - none_keys: none_keys - offsets: offsets - reagent_sources: reagent_sources - spread: spread - targets: targets - use_channels: use_channels - goal_default: - asp_vols: - - 0.0 - blow_out_air_volume: - - 0.0 - dis_vols: - - 0.0 - flow_rates: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - mix_liquid_height: 0.0 - mix_rate: 0 - mix_time: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - reagent_sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - placeholder_keys: - reagent_sources: unilabos_resources - targets: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerAdd_Feedback - type: object - goal: - properties: - asp_vols: - items: - type: number - type: array - blow_out_air_volume: - items: - type: number - type: array - dis_vols: - items: - type: number - type: array - flow_rates: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - mix_liquid_height: - type: number - mix_rate: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_time: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - reagent_sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: reagent_sources - type: object - type: array - spread: - type: string - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - asp_vols - - dis_vols - - reagent_sources - - targets - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - - is_96_well - - mix_time - - mix_vol - - mix_rate - - mix_liquid_height - - none_keys - title: LiquidHandlerAdd_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerAdd_Result - type: object - required: - - goal - title: LiquidHandlerAdd - type: object - type: LiquidHandlerAdd - aspirate: - feedback: {} - goal: - blow_out_air_volume: blow_out_air_volume - flow_rates: flow_rates - liquid_height: liquid_height - offsets: offsets - resources: resources - use_channels: use_channels - vols: vols - goal_default: - blow_out_air_volume: - - 0.0 - flow_rates: - - 0.0 - liquid_height: - - 0.0 - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - resources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - use_channels: - - 0 - vols: - - 0.0 - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerAspirate_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - type: number - type: array - flow_rates: - items: - type: number - type: array - liquid_height: - items: - type: number - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - resources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: resources - type: object - type: array - spread: - type: string - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - required: - - resources - - vols - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - title: LiquidHandlerAspirate_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerAspirate_Result - type: object - required: - - goal - title: LiquidHandlerAspirate - type: object - type: LiquidHandlerAspirate - auto-create_protocol: - feedback: {} - goal: {} - goal_default: - none_keys: [] - protocol_author: null - protocol_date: null - protocol_description: null - protocol_name: null - protocol_type: null - protocol_version: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: 创建实验协议函数。用于建立新的液体处理实验协议,定义协议名称、描述、版本、作者、日期等基本信息。该函数支持协议模板化管理,便于实验流程的标准化和重复性。适用于实验设计、方法开发、标准操作程序建立等需要协议管理的应用场景。 - properties: - feedback: {} - goal: - properties: - none_keys: - default: [] - type: string - protocol_author: - type: string - protocol_date: - type: string - protocol_description: - type: string - protocol_name: - type: string - protocol_type: - type: string - protocol_version: - type: string - required: - - protocol_name - - protocol_description - - protocol_version - - protocol_author - - protocol_date - - protocol_type - type: object - result: {} - required: - - goal - title: create_protocol参数 - type: object - type: UniLabJsonCommandAsync - auto-custom_delay: - feedback: {} - goal: {} - goal_default: - msg: null - seconds: 0 - handles: {} - placeholder_keys: {} - result: {} - schema: - description: 自定义延时函数。在实验流程中插入可配置的等待时间,用于满足特定的反应时间、孵育时间或设备稳定时间要求。支持自定义延时消息和秒数设置,提供流程控制和时间管理功能。适用于酶反应等待、温度平衡、样品孵育等需要时间控制的实验步骤。 - properties: - feedback: {} - goal: - properties: - msg: - type: string - seconds: - default: 0 - type: string - required: [] - type: object - result: {} - required: - - goal - title: custom_delay参数 - type: object - type: UniLabJsonCommandAsync - auto-iter_tips: - feedback: {} - goal: {} - goal_default: - tip_racks: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: 吸头迭代函数。用于自动管理和切换吸头架中的吸头,实现批量实验中的吸头自动分配和追踪。该函数监控吸头使用状态,自动切换到下一个可用吸头位置,确保实验流程的连续性。适用于高通量实验、批量处理、自动化流水线等需要大量吸头管理的应用场景。 - properties: - feedback: {} - goal: - properties: - tip_racks: - type: string - required: - - tip_racks - type: object - result: {} - required: - - goal - title: iter_tips参数 - type: object - type: UniLabJsonCommand - auto-post_init: - feedback: {} - goal: {} - goal_default: - ros_node: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: '' - properties: - feedback: {} - goal: - properties: - ros_node: - type: string - required: - - ros_node - type: object - result: {} - required: - - goal - title: post_init参数 - type: object - type: UniLabJsonCommand - auto-set_group: - feedback: {} - goal: {} - goal_default: - group_name: null - volumes: null - wells: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: '' - properties: - feedback: {} - goal: - properties: - group_name: - type: string - volumes: - type: string - wells: - type: string - required: - - group_name - - wells - - volumes - type: object - result: {} - required: - - goal - title: set_group参数 - type: object - type: UniLabJsonCommand - auto-set_tiprack: - feedback: {} - goal: {} - goal_default: - tip_racks: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: 吸头架设置函数。用于配置和初始化液体处理系统的吸头架信息,包括吸头架位置、类型、容量等参数。该函数建立吸头资源管理系统,为后续的吸头选择和使用提供基础配置。适用于系统初始化、吸头架更换、实验配置等需要吸头资源管理的操作场景。 - properties: - feedback: {} - goal: - properties: - tip_racks: - type: string - required: - - tip_racks - type: object - result: {} - required: - - goal - title: set_tiprack参数 - type: object - type: UniLabJsonCommand - auto-touch_tip: - feedback: {} - goal: {} - goal_default: - targets: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: 吸头碰触函数。控制移液器吸头轻触容器边缘或底部,用于去除吸头外壁附着的液滴,提高移液精度和减少污染。该函数支持多目标位置操作,可配置碰触参数和位置偏移。适用于精密移液、减少液体残留、防止交叉污染等需要提高移液质量的实验操作。 - properties: - feedback: {} - goal: - properties: - targets: - type: string - required: - - targets - type: object - result: {} - required: - - goal - title: touch_tip参数 - type: object - type: UniLabJsonCommandAsync - auto-transfer_group: - feedback: {} - goal: {} - goal_default: - source_group_name: null - target_group_name: null - unit_volume: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: '' - properties: - feedback: {} - goal: - properties: - source_group_name: - type: string - target_group_name: - type: string - unit_volume: - type: number - required: - - source_group_name - - target_group_name - - unit_volume - type: object - result: {} - required: - - goal - title: transfer_group参数 - type: object - type: UniLabJsonCommandAsync - discard_tips: - feedback: {} - goal: - use_channels: use_channels - goal_default: - use_channels: - - 0 - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDiscardTips_Feedback - type: object - goal: - properties: - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - use_channels - title: LiquidHandlerDiscardTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDiscardTips_Result - type: object - required: - - goal - title: LiquidHandlerDiscardTips - type: object - type: LiquidHandlerDiscardTips - dispense: - feedback: {} - goal: - blow_out_air_volume: blow_out_air_volume - flow_rates: flow_rates - offsets: offsets - resources: resources - spread: spread - use_channels: use_channels - vols: vols - goal_default: - blow_out_air_volume: - - 0 - flow_rates: - - 0.0 - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - resources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - use_channels: - - 0 - vols: - - 0.0 - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDispense_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - flow_rates: - items: - type: number - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - resources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: resources - type: object - type: array - spread: - type: string - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - required: - - resources - - vols - - use_channels - - flow_rates - - offsets - - blow_out_air_volume - - spread - title: LiquidHandlerDispense_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDispense_Result - type: object - required: - - goal - title: LiquidHandlerDispense - type: object - type: LiquidHandlerDispense - drop_tips: - feedback: {} - goal: - allow_nonzero_volume: allow_nonzero_volume - offsets: offsets - tip_spots: tip_spots - use_channels: use_channels - goal_default: - allow_nonzero_volume: false - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - tip_spots: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - placeholder_keys: - tip_spots: unilabos_resources - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDropTips_Feedback - type: object - goal: - properties: - allow_nonzero_volume: - type: boolean - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - tip_spots: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_spots - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - tip_spots - - use_channels - - offsets - - allow_nonzero_volume - title: LiquidHandlerDropTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDropTips_Result - type: object - required: - - goal - title: LiquidHandlerDropTips - type: object - type: LiquidHandlerDropTips - drop_tips96: - feedback: {} - goal: - allow_nonzero_volume: allow_nonzero_volume - offset: offset - tip_rack: tip_rack - goal_default: - allow_nonzero_volume: false - offset: - x: 0.0 - y: 0.0 - z: 0.0 - tip_rack: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDropTips96_Feedback - type: object - goal: - properties: - allow_nonzero_volume: - type: boolean - offset: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offset - type: object - tip_rack: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_rack - type: object - required: - - tip_rack - - offset - - allow_nonzero_volume - title: LiquidHandlerDropTips96_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDropTips96_Result - type: object - required: - - goal - title: LiquidHandlerDropTips96 - type: object - type: LiquidHandlerDropTips96 - mix: - feedback: {} - goal: - height_to_bottom: height_to_bottom - mix_rate: mix_rate - mix_time: mix_time - mix_vol: mix_vol - none_keys: none_keys - offsets: offsets - targets: targets - goal_default: - height_to_bottom: 0.0 - mix_rate: 0.0 - mix_time: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerMix_Feedback - type: object - goal: - properties: - height_to_bottom: - type: number - mix_rate: - type: number - mix_time: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - required: - - targets - - mix_time - - mix_vol - - height_to_bottom - - offsets - - mix_rate - - none_keys - title: LiquidHandlerMix_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerMix_Result - type: object - required: - - goal - title: LiquidHandlerMix - type: object - type: LiquidHandlerMix - move_lid: - feedback: {} - goal: - destination_offset: destination_offset - drop_direction: drop_direction - get_direction: get_direction - intermediate_locations: intermediate_locations - lid: lid - pickup_direction: pickup_direction - pickup_distance_from_top: pickup_distance_from_top - put_direction: put_direction - resource_offset: resource_offset - to: to - goal_default: - destination_offset: - x: 0.0 - y: 0.0 - z: 0.0 - drop_direction: '' - get_direction: '' - intermediate_locations: - - x: 0.0 - y: 0.0 - z: 0.0 - lid: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - pickup_direction: '' - pickup_distance_from_top: 0.0 - put_direction: '' - resource_offset: - x: 0.0 - y: 0.0 - z: 0.0 - to: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerMoveLid_Feedback - type: object - goal: - properties: - destination_offset: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: destination_offset - type: object - drop_direction: - type: string - get_direction: - type: string - intermediate_locations: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: intermediate_locations - type: object - type: array - lid: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: lid - type: object - pickup_direction: - type: string - pickup_distance_from_top: - type: number - put_direction: - type: string - resource_offset: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: resource_offset - type: object - to: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: to - type: object - required: - - lid - - to - - intermediate_locations - - resource_offset - - destination_offset - - pickup_direction - - drop_direction - - get_direction - - put_direction - - pickup_distance_from_top - title: LiquidHandlerMoveLid_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerMoveLid_Result - type: object - required: - - goal - title: LiquidHandlerMoveLid - type: object - type: LiquidHandlerMoveLid - move_plate: - feedback: {} - goal: - destination_offset: destination_offset - drop_direction: drop_direction - get_direction: get_direction - intermediate_locations: intermediate_locations - pickup_direction: pickup_direction - pickup_offset: pickup_offset - plate: plate - put_direction: put_direction - resource_offset: resource_offset - to: to - goal_default: - destination_offset: - x: 0.0 - y: 0.0 - z: 0.0 - drop_direction: '' - get_direction: '' - intermediate_locations: - - x: 0.0 - y: 0.0 - z: 0.0 - pickup_direction: '' - pickup_distance_from_top: 0.0 - pickup_offset: - x: 0.0 - y: 0.0 - z: 0.0 - plate: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - put_direction: '' - resource_offset: - x: 0.0 - y: 0.0 - z: 0.0 - to: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerMovePlate_Feedback - type: object - goal: - properties: - destination_offset: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: destination_offset - type: object - drop_direction: - type: string - get_direction: - type: string - intermediate_locations: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: intermediate_locations - type: object - type: array - pickup_direction: - type: string - pickup_distance_from_top: - type: number - pickup_offset: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: pickup_offset - type: object - plate: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: plate - type: object - put_direction: - type: string - resource_offset: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: resource_offset - type: object - to: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: to - type: object - required: - - plate - - to - - intermediate_locations - - resource_offset - - pickup_offset - - destination_offset - - pickup_direction - - drop_direction - - get_direction - - put_direction - - pickup_distance_from_top - title: LiquidHandlerMovePlate_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerMovePlate_Result - type: object - required: - - goal - title: LiquidHandlerMovePlate - type: object - type: LiquidHandlerMovePlate - move_resource: - feedback: {} - goal: - destination_offset: destination_offset - drop_direction: drop_direction - get_direction: get_direction - intermediate_locations: intermediate_locations - pickup_direction: pickup_direction - pickup_distance_from_top: pickup_distance_from_top - put_direction: put_direction - resource: resource - resource_offset: resource_offset - to: to - goal_default: - destination_offset: - x: 0.0 - y: 0.0 - z: 0.0 - drop_direction: '' - get_direction: '' - intermediate_locations: - - x: 0.0 - y: 0.0 - z: 0.0 - pickup_direction: '' - pickup_distance_from_top: 0.0 - put_direction: '' - resource: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - resource_offset: - x: 0.0 - y: 0.0 - z: 0.0 - to: - x: 0.0 - y: 0.0 - z: 0.0 - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerMoveResource_Feedback - type: object - goal: - properties: - destination_offset: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: destination_offset - type: object - drop_direction: - type: string - get_direction: - type: string - intermediate_locations: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: intermediate_locations - type: object - type: array - pickup_direction: - type: string - pickup_distance_from_top: - type: number - put_direction: - type: string - resource: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: resource - type: object - resource_offset: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: resource_offset - type: object - to: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: to - type: object - required: - - resource - - to - - intermediate_locations - - resource_offset - - destination_offset - - pickup_distance_from_top - - pickup_direction - - drop_direction - - get_direction - - put_direction - title: LiquidHandlerMoveResource_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerMoveResource_Result - type: object - required: - - goal - title: LiquidHandlerMoveResource - type: object - type: LiquidHandlerMoveResource - move_to: - feedback: {} - goal: - channel: channel - dis_to_top: dis_to_top - well: well - goal_default: - channel: 0 - dis_to_top: 0.0 - well: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerMoveTo_Feedback - type: object - goal: - properties: - channel: - maximum: 2147483647 - minimum: -2147483648 - type: integer - dis_to_top: - type: number - well: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: well - type: object - required: - - well - - dis_to_top - - channel - title: LiquidHandlerMoveTo_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerMoveTo_Result - type: object - required: - - goal - title: LiquidHandlerMoveTo - type: object - type: LiquidHandlerMoveTo - pick_up_tips: - feedback: {} - goal: - offsets: offsets - tip_spots: tip_spots - use_channels: use_channels - goal_default: - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - tip_spots: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerPickUpTips_Feedback - type: object - goal: - properties: - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - tip_spots: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_spots - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - tip_spots - - use_channels - - offsets - title: LiquidHandlerPickUpTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerPickUpTips_Result - type: object - required: - - goal - title: LiquidHandlerPickUpTips - type: object - type: LiquidHandlerPickUpTips - pick_up_tips96: - feedback: {} - goal: - offset: offset - tip_rack: tip_rack - goal_default: - offset: - x: 0.0 - y: 0.0 - z: 0.0 - tip_rack: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerPickUpTips96_Feedback - type: object - goal: - properties: - offset: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offset - type: object - tip_rack: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_rack - type: object - required: - - tip_rack - - offset - title: LiquidHandlerPickUpTips96_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerPickUpTips96_Result - type: object - required: - - goal - title: LiquidHandlerPickUpTips96 - type: object - type: LiquidHandlerPickUpTips96 - remove: - feedback: {} - goal: - blow_out_air_volume: blow_out_air_volume - delays: delays - flow_rates: flow_rates - is_96_well: is_96_well - liquid_height: liquid_height - none_keys: none_keys - offsets: offsets - sources: sources - spread: spread - top: top - use_channels: use_channels - vols: vols - waste_liquid: waste_liquid - goal_default: - blow_out_air_volume: - - 0.0 - delays: - - 0 - flow_rates: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - top: - - 0.0 - use_channels: - - 0 - vols: - - 0.0 - waste_liquid: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerRemove_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - type: number - type: array - delays: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - flow_rates: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: sources - type: object - type: array - spread: - type: string - top: - items: - type: number - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - waste_liquid: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: waste_liquid - type: object - required: - - vols - - sources - - waste_liquid - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - - delays - - is_96_well - - top - - none_keys - title: LiquidHandlerRemove_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerRemove_Result - type: object - required: - - goal - title: LiquidHandlerRemove - type: object - type: LiquidHandlerRemove - remove_liquid: - feedback: {} - goal: - blow_out_air_volume: blow_out_air_volume - delays: delays - flow_rates: flow_rates - is_96_well: is_96_well - liquid_height: liquid_height - none_keys: none_keys - offsets: offsets - sources: sources - spread: spread - top: top - use_channels: use_channels - vols: vols - waste_liquid: waste_liquid - goal_default: - blow_out_air_volume: - - 0.0 - delays: - - 0 - flow_rates: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - top: - - 0.0 - use_channels: - - 0 - vols: - - 0.0 - waste_liquid: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - placeholder_keys: - sources: unilabos_resources - waste_liquid: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerRemove_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - type: number - type: array - delays: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - flow_rates: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: sources - type: object - type: array - spread: - type: string - top: - items: - type: number - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - waste_liquid: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: waste_liquid - type: object - required: - - vols - - sources - - waste_liquid - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - - delays - - is_96_well - - top - - none_keys - title: LiquidHandlerRemove_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerRemove_Result - type: object - required: - - goal - title: LiquidHandlerRemove - type: object - type: LiquidHandlerRemove - return_tips: - feedback: {} - goal: - allow_nonzero_volume: allow_nonzero_volume - use_channels: use_channels - goal_default: - allow_nonzero_volume: false - use_channels: - - 0 - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerReturnTips_Feedback - type: object - goal: - properties: - allow_nonzero_volume: - type: boolean - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - use_channels - - allow_nonzero_volume - title: LiquidHandlerReturnTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerReturnTips_Result - type: object - required: - - goal - title: LiquidHandlerReturnTips - type: object - type: LiquidHandlerReturnTips - return_tips96: - feedback: {} - goal: - allow_nonzero_volume: allow_nonzero_volume - goal_default: - allow_nonzero_volume: false - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerReturnTips96_Feedback - type: object - goal: - properties: - allow_nonzero_volume: - type: boolean - required: - - allow_nonzero_volume - title: LiquidHandlerReturnTips96_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerReturnTips96_Result - type: object - required: - - goal - title: LiquidHandlerReturnTips96 - type: object - type: LiquidHandlerReturnTips96 - stamp: - feedback: {} - goal: - aspiration_flow_rate: aspiration_flow_rate - dispense_flow_rate: dispense_flow_rate - source: source - target: target - volume: volume - goal_default: - aspiration_flow_rate: 0.0 - dispense_flow_rate: 0.0 - source: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - target: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - volume: 0.0 - handles: {} - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerStamp_Feedback - type: object - goal: - properties: - aspiration_flow_rate: - type: number - dispense_flow_rate: - type: number - source: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: source - type: object - target: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: target - type: object - volume: - type: number - required: - - source - - target - - volume - - aspiration_flow_rate - - dispense_flow_rate - title: LiquidHandlerStamp_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerStamp_Result - type: object - required: - - goal - title: LiquidHandlerStamp - type: object - type: LiquidHandlerStamp - transfer: - goal: - aspiration_flow_rate: aspiration_flow_rate - dispense_flow_rates: dispense_flow_rates - ratios: ratios - source: source - source_vol: source_vol - target_vols: target_vols - targets: targets - goal_default: - amount: '' - from_vessel: '' - rinsing_repeats: 0 - rinsing_solvent: '' - rinsing_volume: 0.0 - solid: false - time: 0.0 - to_vessel: '' - viscous: false - volume: 0.0 - handles: {} - schema: - description: '' - properties: - feedback: - properties: - current_status: - type: string - progress: - type: number - transferred_volume: - type: number - required: - - progress - - transferred_volume - - current_status - title: Transfer_Feedback - type: object - goal: - properties: - amount: - type: string - from_vessel: - type: string - rinsing_repeats: - maximum: 2147483647 - minimum: -2147483648 - type: integer - rinsing_solvent: - type: string - rinsing_volume: - type: number - solid: - type: boolean - time: - type: number - to_vessel: - type: string - viscous: - type: boolean - volume: - type: number - required: - - from_vessel - - to_vessel - - volume - - amount - - time - - viscous - - rinsing_solvent - - rinsing_volume - - rinsing_repeats - - solid - title: Transfer_Goal - type: object - result: - properties: - message: - type: string - return_info: - type: string - success: - type: boolean - required: - - success - - message - - return_info - title: Transfer_Result - type: object - required: - - goal - title: Transfer - type: object - type: Transfer - transfer_liquid: - feedback: {} - goal: - asp_flow_rates: asp_flow_rates - asp_vols: asp_vols - blow_out_air_volume: blow_out_air_volume - delays: delays - dis_flow_rates: dis_flow_rates - dis_vols: dis_vols - is_96_well: is_96_well - liquid_height: liquid_height - mix_liquid_height: mix_liquid_height - mix_rate: mix_rate - mix_stage: mix_stage - mix_times: mix_times - mix_vol: mix_vol - none_keys: none_keys - offsets: offsets - sources: sources - spread: spread - targets: targets - tip_racks: tip_racks - touch_tip: touch_tip - use_channels: use_channels - goal_default: - asp_flow_rates: - - 0.0 - asp_vols: - - 0.0 - blow_out_air_volume: - - 0.0 - delays: - - 0 - dis_flow_rates: - - 0.0 - dis_vols: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - mix_liquid_height: 0.0 - mix_rate: 0 - mix_stage: '' - mix_times: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - tip_racks: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - touch_tip: false - use_channels: - - 0 - handles: - input: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: sources - label: sources - - data_key: liquid - data_source: executor - data_type: resource - handler_key: targets - label: targets - - data_key: liquid - data_source: executor - data_type: resource - handler_key: tip_rack - label: tip_rack - output: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: sources_out - label: sources - - data_key: liquid - data_source: executor - data_type: resource - handler_key: targets_out - label: targets - placeholder_keys: - sources: unilabos_resources - targets: unilabos_resources - tip_racks: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerTransfer_Feedback - type: object - goal: - properties: - asp_flow_rates: - items: - type: number - type: array - asp_vols: - items: - type: number - type: array - blow_out_air_volume: - items: - type: number - type: array - delays: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - dis_flow_rates: - items: - type: number - type: array - dis_vols: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - mix_liquid_height: - type: number - mix_rate: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_stage: - type: string - mix_times: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: sources - type: object - type: array - spread: - type: string - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - tip_racks: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_racks - type: object - type: array - touch_tip: - type: boolean - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - asp_vols - - dis_vols - - sources - - targets - - tip_racks - - use_channels - - asp_flow_rates - - dis_flow_rates - - offsets - - touch_tip - - liquid_height - - blow_out_air_volume - - spread - - is_96_well - - mix_stage - - mix_times - - mix_vol - - mix_rate - - mix_liquid_height - - delays - - none_keys - title: LiquidHandlerTransfer_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerTransfer_Result - type: object - required: - - goal - title: LiquidHandlerTransfer - type: object - type: LiquidHandlerTransfer - module: unilabos.devices.liquid_handling.liquid_handler_abstract:LiquidHandlerAbstract - status_types: {} - type: python - config_info: [] - description: Liquid handler device controlled by pylabrobot - handles: [] - icon: icon_yiyezhan.webp - init_param_schema: - config: - properties: - backend: - type: string - channel_num: - default: 8 - type: integer - deck: - type: string - simulator: - default: false - type: boolean - required: - - backend - - deck - type: object - data: - properties: {} - required: [] - type: object - version: 1.0.0 -liquid_handler.biomek: - category: - - liquid_handler - class: - action_value_mappings: - auto-create_resource: - feedback: {} - goal: {} - goal_default: - bind_location: null - bind_parent_id: null - liquid_input_slot: null - liquid_type: null - liquid_volume: null - resource_tracker: null - resources: null - slot_on_deck: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: create_resource的参数schema - properties: - feedback: {} - goal: - properties: - bind_location: - type: object - bind_parent_id: - type: string - liquid_input_slot: - items: - type: integer - type: array - liquid_type: - items: - type: string - type: array - liquid_volume: - items: - type: integer - type: array - resource_tracker: - type: object - resources: - items: - type: object - type: array - slot_on_deck: - type: integer - required: - - resource_tracker - - resources - - bind_parent_id - - bind_location - - liquid_input_slot - - liquid_type - - liquid_volume - - slot_on_deck - type: object - result: {} - required: - - goal - title: create_resource参数 - type: object - type: UniLabJsonCommand - auto-instrument_setup_biomek: - feedback: {} - goal: {} - goal_default: - class_name: null - id: null - liquid_input_wells: null - liquid_type: null - liquid_volume: null - parent: null - slot_on_deck: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: instrument_setup_biomek的参数schema - properties: - feedback: {} - goal: - properties: - class_name: - type: string - id: - type: string - liquid_input_wells: - items: - type: string - type: array - liquid_type: - items: - type: string - type: array - liquid_volume: - items: - type: integer - type: array - parent: - type: string - slot_on_deck: - type: string - required: - - id - - parent - - slot_on_deck - - class_name - - liquid_type - - liquid_volume - - liquid_input_wells - type: object - result: {} - required: - - goal - title: instrument_setup_biomek参数 - type: object - type: UniLabJsonCommand - create_protocol: - feedback: {} - goal: - none_keys: none_keys - protocol_author: protocol_author - protocol_date: protocol_date - protocol_description: protocol_description - protocol_name: protocol_name - protocol_type: protocol_type - protocol_version: protocol_version - goal_default: - none_keys: - - '' - protocol_author: '' - protocol_date: '' - protocol_description: '' - protocol_name: '' - protocol_type: '' - protocol_version: '' - handles: {} - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerProtocolCreation_Feedback - type: object - goal: - properties: - none_keys: - items: - type: string - type: array - protocol_author: - type: string - protocol_date: - type: string - protocol_description: - type: string - protocol_name: - type: string - protocol_type: - type: string - protocol_version: - type: string - required: - - protocol_name - - protocol_description - - protocol_version - - protocol_author - - protocol_date - - protocol_type - - none_keys - title: LiquidHandlerProtocolCreation_Goal - type: object - result: - properties: - return_info: - type: string - required: - - return_info - title: LiquidHandlerProtocolCreation_Result - type: object - required: - - goal - title: LiquidHandlerProtocolCreation - type: object - type: LiquidHandlerProtocolCreation - incubation_biomek: - feedback: {} - goal: - time: time - goal_default: - time: 0 - handles: - input: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: plate - label: plate - output: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: plate_out - label: plate - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerIncubateBiomek_Feedback - type: object - goal: - properties: - time: - maximum: 2147483647 - minimum: -2147483648 - type: integer - required: - - time - title: LiquidHandlerIncubateBiomek_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerIncubateBiomek_Result - type: object - required: - - goal - title: LiquidHandlerIncubateBiomek - type: object - type: LiquidHandlerIncubateBiomek - move_biomek: - feedback: {} - goal: - source: sources - target: targets - goal_default: - sources: '' - targets: '' - handles: - input: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: sources - label: sources - output: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: targets - label: targets - result: - name: name - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerMoveBiomek_Feedback - type: object - goal: - properties: - sources: - type: string - targets: - type: string - required: - - sources - - targets - title: LiquidHandlerMoveBiomek_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerMoveBiomek_Result - type: object - required: - - goal - title: LiquidHandlerMoveBiomek - type: object - type: LiquidHandlerMoveBiomek - oscillation_biomek: - feedback: {} - goal: - rpm: rpm - time: time - goal_default: - rpm: 0 - time: 0 - handles: - input: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: plate - label: plate - output: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: plate_out - label: plate - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerOscillateBiomek_Feedback - type: object - goal: - properties: - rpm: - maximum: 2147483647 - minimum: -2147483648 - type: integer - time: - maximum: 2147483647 - minimum: -2147483648 - type: integer - required: - - rpm - - time - title: LiquidHandlerOscillateBiomek_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerOscillateBiomek_Result - type: object - required: - - goal - title: LiquidHandlerOscillateBiomek - type: object - type: LiquidHandlerOscillateBiomek - run_protocol: - feedback: {} - goal: {} - goal_default: {} - handles: {} - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: EmptyIn_Feedback - type: object - goal: - properties: {} - required: [] - title: EmptyIn_Goal - type: object - result: - properties: - return_info: - type: string - required: - - return_info - title: EmptyIn_Result - type: object - required: - - goal - title: EmptyIn - type: object - type: EmptyIn - transfer_biomek: - feedback: {} - goal: - aspirate_techniques: aspirate_techniques - dispense_techniques: dispense_techniques - sources: sources - targets: targets - tip_rack: tip_rack - volume: volume - goal_default: - aspirate_technique: '' - dispense_technique: '' - sources: '' - targets: '' - tip_rack: '' - volume: 0.0 - handles: - input: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: sources - label: sources - - data_key: liquid - data_source: executor - data_type: resource - handler_key: targets - label: targets - - data_key: liquid - data_source: executor - data_type: resource - handler_key: tip_rack - label: tip_rack - output: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: sources_out - label: sources - - data_key: liquid - data_source: executor - data_type: resource - handler_key: targets_out - label: targets - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerTransferBiomek_Feedback - type: object - goal: - properties: - aspirate_technique: - type: string - dispense_technique: - type: string - sources: - type: string - targets: - type: string - tip_rack: - type: string - volume: - type: number - required: - - sources - - targets - - tip_rack - - volume - - aspirate_technique - - dispense_technique - title: LiquidHandlerTransferBiomek_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerTransferBiomek_Result - type: object - required: - - goal - title: LiquidHandlerTransferBiomek - type: object - type: LiquidHandlerTransferBiomek - transfer_liquid: - feedback: {} - goal: - asp_flow_rates: asp_flow_rates - asp_vols: asp_vols - blow_out_air_volume: blow_out_air_volume - delays: delays - dis_flow_rates: dis_flow_rates - dis_vols: dis_vols - is_96_well: is_96_well - liquid_height: liquid_height - mix_liquid_height: mix_liquid_height - mix_rate: mix_rate - mix_stage: mix_stage - mix_times: mix_times - mix_vol: mix_vol - none_keys: none_keys - offsets: offsets - sources: sources - spread: spread - targets: targets - tip_racks: tip_racks - touch_tip: touch_tip - use_channels: use_channels - goal_default: - asp_flow_rates: - - 0.0 - asp_vols: - - 0.0 - blow_out_air_volume: - - 0.0 - delays: - - 0 - dis_flow_rates: - - 0.0 - dis_vols: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - mix_liquid_height: 0.0 - mix_rate: 0 - mix_stage: '' - mix_times: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - tip_racks: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - touch_tip: false - use_channels: - - 0 - handles: - input: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: liquid-input - io_type: target - label: Liquid Input - output: - - data_key: liquid - data_source: executor - data_type: resource - handler_key: liquid-output - io_type: source - label: Liquid Output - placeholder_keys: - sources: unilabos_resources - targets: unilabos_resources - tip_racks: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerTransfer_Feedback - type: object - goal: - properties: - asp_flow_rates: - items: - type: number - type: array - asp_vols: - items: - type: number - type: array - blow_out_air_volume: - items: - type: number - type: array - delays: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - dis_flow_rates: - items: - type: number - type: array - dis_vols: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - mix_liquid_height: - type: number - mix_rate: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_stage: - type: string - mix_times: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: sources - type: object - type: array - spread: - type: string - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - tip_racks: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_racks - type: object - type: array - touch_tip: - type: boolean - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - asp_vols - - dis_vols - - sources - - targets - - tip_racks - - use_channels - - asp_flow_rates - - dis_flow_rates - - offsets - - touch_tip - - liquid_height - - blow_out_air_volume - - spread - - is_96_well - - mix_stage - - mix_times - - mix_vol - - mix_rate - - mix_liquid_height - - delays - - none_keys - title: LiquidHandlerTransfer_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerTransfer_Result - type: object - required: - - goal - title: LiquidHandlerTransfer - type: object - type: LiquidHandlerTransfer - module: unilabos.devices.liquid_handling.biomek:LiquidHandlerBiomek - status_types: - success: String - type: python - config_info: [] - description: Biomek液体处理器设备,基于pylabrobot控制 - handles: [] - icon: icon_yiyezhan.webp - init_param_schema: - config: - properties: {} - required: [] - type: object - data: - properties: - success: - type: string - required: - - success - type: object - version: 1.0.0 -liquid_handler.laiyu: - category: - - liquid_handler - class: - action_value_mappings: - add_liquid: - feedback: {} - goal: - asp_vols: asp_vols - blow_out_air_volume: blow_out_air_volume - dis_vols: dis_vols - flow_rates: flow_rates - is_96_well: is_96_well - liquid_height: liquid_height - mix_liquid_height: mix_liquid_height - mix_rate: mix_rate - mix_time: mix_time - mix_vol: mix_vol - none_keys: none_keys - offsets: offsets - reagent_sources: reagent_sources - spread: spread - targets: targets - use_channels: use_channels - goal_default: - asp_vols: - - 0.0 - blow_out_air_volume: - - 0.0 - dis_vols: - - 0.0 - flow_rates: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - mix_liquid_height: 0.0 - mix_rate: 0 - mix_time: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - reagent_sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - placeholder_keys: - reagent_sources: unilabos_resources - targets: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerAdd_Feedback - type: object - goal: - properties: - asp_vols: - items: - type: number - type: array - blow_out_air_volume: - items: - type: number - type: array - dis_vols: - items: - type: number - type: array - flow_rates: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - mix_liquid_height: - type: number - mix_rate: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_time: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - reagent_sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: reagent_sources - type: object - type: array - spread: - type: string - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - asp_vols - - dis_vols - - reagent_sources - - targets - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - - is_96_well - - mix_time - - mix_vol - - mix_rate - - mix_liquid_height - - none_keys - title: LiquidHandlerAdd_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerAdd_Result - type: object - required: - - goal - title: LiquidHandlerAdd - type: object - type: LiquidHandlerAdd - aspirate: - feedback: {} - goal: - blow_out_air_volume: blow_out_air_volume - flow_rates: flow_rates - liquid_height: liquid_height - offsets: offsets - resources: resources - use_channels: use_channels - vols: vols - goal_default: - blow_out_air_volume: - - 0.0 - flow_rates: - - 0.0 - liquid_height: - - 0.0 - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - resources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - use_channels: - - 0 - vols: - - 0.0 - handles: {} - placeholder_keys: - resources: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerAspirate_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - type: number - type: array - flow_rates: - items: - type: number - type: array - liquid_height: - items: - type: number - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - resources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: resources - type: object - type: array - spread: - type: string - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - required: - - resources - - vols - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - title: LiquidHandlerAspirate_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerAspirate_Result - type: object - required: - - goal - title: LiquidHandlerAspirate - type: object - type: LiquidHandlerAspirate - auto-transfer_liquid: - feedback: {} - goal: {} - goal_default: - asp_flow_rates: null - asp_vols: null - blow_out_air_volume: null - delays: null - dis_flow_rates: null - dis_vols: null - is_96_well: false - liquid_height: null - mix_liquid_height: null - mix_rate: null - mix_stage: none - mix_times: null - mix_vol: null - none_keys: [] - offsets: null - sources: null - spread: wide - targets: null - tip_racks: null - touch_tip: false - use_channels: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: '' - properties: - feedback: {} - goal: - properties: - asp_flow_rates: - type: string - asp_vols: - type: string - blow_out_air_volume: - type: string - delays: - type: string - dis_flow_rates: - type: string - dis_vols: - type: string - is_96_well: - default: false - type: boolean - liquid_height: - type: string - mix_liquid_height: - type: string - mix_rate: - type: string - mix_stage: - default: none - type: string - mix_times: - type: string - mix_vol: - type: string - none_keys: - default: [] - items: - type: string - type: array - offsets: - type: string - sources: - type: string - spread: - default: wide - type: string - targets: - type: string - tip_racks: - type: string - touch_tip: - default: false - type: boolean - use_channels: - type: string - required: - - sources - - targets - - tip_racks - - asp_vols - - dis_vols - type: object - result: {} - required: - - goal - title: transfer_liquid参数 - type: object - type: UniLabJsonCommandAsync - dispense: - feedback: {} - goal: - blow_out_air_volume: blow_out_air_volume - flow_rates: flow_rates - liquid_height: liquid_height - offsets: offsets - resources: resources - use_channels: use_channels - vols: vols - goal_default: - blow_out_air_volume: - - 0 - flow_rates: - - 0.0 - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - resources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - use_channels: - - 0 - vols: - - 0.0 - handles: {} - placeholder_keys: - resources: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDispense_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - flow_rates: - items: - type: number - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - resources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: resources - type: object - type: array - spread: - type: string - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - required: - - resources - - vols - - use_channels - - flow_rates - - offsets - - blow_out_air_volume - - spread - title: LiquidHandlerDispense_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDispense_Result - type: object - required: - - goal - title: LiquidHandlerDispense - type: object - type: LiquidHandlerDispense - drop_tips: - feedback: {} - goal: - allow_nonzero_volume: allow_nonzero_volume - offsets: offsets - tip_spots: tip_spots - use_channels: use_channels - goal_default: - allow_nonzero_volume: false - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - tip_spots: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - placeholder_keys: - tip_spots: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDropTips_Feedback - type: object - goal: - properties: - allow_nonzero_volume: - type: boolean - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - tip_spots: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_spots - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - tip_spots - - use_channels - - offsets - - allow_nonzero_volume - title: LiquidHandlerDropTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDropTips_Result - type: object - required: - - goal - title: LiquidHandlerDropTips - type: object - type: LiquidHandlerDropTips - mix: - feedback: {} - goal: - height_to_bottom: height_to_bottom - mix_rate: mix_rate - mix_time: mix_time - mix_vol: mix_vol - none_keys: none_keys - offsets: offsets - targets: targets - goal_default: - height_to_bottom: 0.0 - mix_rate: 0.0 - mix_time: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - placeholder_keys: - targets: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerMix_Feedback - type: object - goal: - properties: - height_to_bottom: - type: number - mix_rate: - type: number - mix_time: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - required: - - targets - - mix_time - - mix_vol - - height_to_bottom - - offsets - - mix_rate - - none_keys - title: LiquidHandlerMix_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerMix_Result - type: object - required: - - goal - title: LiquidHandlerMix - type: object - type: LiquidHandlerMix - pick_up_tips: - feedback: {} - goal: - offsets: offsets - tip_spots: tip_spots - use_channels: use_channels - goal_default: - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - tip_spots: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - placeholder_keys: - tip_spots: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerPickUpTips_Feedback - type: object - goal: - properties: - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - tip_spots: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_spots - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - tip_spots - - use_channels - - offsets - title: LiquidHandlerPickUpTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerPickUpTips_Result - type: object - required: - - goal - title: LiquidHandlerPickUpTips - type: object - type: LiquidHandlerPickUpTips - module: unilabos.devices.liquid_handling.laiyu.laiyu:TransformXYZHandler - properties: - support_touch_tip: bool - status_types: {} - type: python - config_info: [] - description: Laiyu液体处理器设备,基于pylabrobot控制 - handles: [] - icon: icon_yiyezhan.webp - init_param_schema: - config: - properties: - channel_num: - default: 1 - type: string - deck: - type: object - host: - default: 127.0.0.1 - type: string - port: - default: 9999 - type: integer - simulator: - default: true - type: string - timeout: - default: 10.0 - type: number - required: - - deck - type: object - data: - properties: {} - required: [] - type: object - version: 1.0.0 -liquid_handler.prcxi: - category: - - liquid_handler - class: - action_value_mappings: - add_liquid: - feedback: {} - goal: - asp_vols: asp_vols - blow_out_air_volume: blow_out_air_volume - dis_vols: dis_vols - flow_rates: flow_rates - is_96_well: is_96_well - liquid_height: liquid_height - mix_liquid_height: mix_liquid_height - mix_rate: mix_rate - mix_time: mix_time - mix_vol: mix_vol - none_keys: none_keys - offsets: offsets - reagent_sources: reagent_sources - spread: spread - targets: targets - use_channels: use_channels - goal_default: - asp_vols: - - 0.0 - blow_out_air_volume: - - 0.0 - dis_vols: - - 0.0 - flow_rates: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - mix_liquid_height: 0.0 - mix_rate: 0 - mix_time: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - reagent_sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - placeholder_keys: - reagent_sources: unilabos_resources - targets: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerAdd_Feedback - type: object - goal: - properties: - asp_vols: - items: - type: number - type: array - blow_out_air_volume: - items: - type: number - type: array - dis_vols: - items: - type: number - type: array - flow_rates: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - mix_liquid_height: - type: number - mix_rate: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_time: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - reagent_sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: reagent_sources - type: object - type: array - spread: - type: string - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - asp_vols - - dis_vols - - reagent_sources - - targets - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - - is_96_well - - mix_time - - mix_vol - - mix_rate - - mix_liquid_height - - none_keys - title: LiquidHandlerAdd_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerAdd_Result - type: object - required: - - goal - title: LiquidHandlerAdd - type: object - type: LiquidHandlerAdd - aspirate: - feedback: {} - goal: - blow_out_air_volume: blow_out_air_volume - flow_rates: flow_rates - liquid_height: liquid_height - offsets: offsets - resources: resources - use_channels: use_channels - vols: vols - goal_default: - blow_out_air_volume: - - 0.0 - flow_rates: - - 0.0 - liquid_height: - - 0.0 - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - resources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - use_channels: - - 0 - vols: - - 0.0 - handles: {} - placeholder_keys: - resources: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerAspirate_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - type: number - type: array - flow_rates: - items: - type: number - type: array - liquid_height: - items: - type: number - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - resources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: resources - type: object - type: array - spread: - type: string - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - required: - - resources - - vols - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - title: LiquidHandlerAspirate_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerAspirate_Result - type: object - required: - - goal - title: LiquidHandlerAspirate - type: object - type: LiquidHandlerAspirate - auto-create_protocol: - feedback: {} - goal: {} - goal_default: - none_keys: [] - protocol_author: '' - protocol_date: '' - protocol_description: '' - protocol_name: '' - protocol_type: '' - protocol_version: '' - handles: {} - placeholder_keys: {} - result: {} - schema: - description: create_protocol的参数schema - properties: - feedback: {} - goal: - properties: - none_keys: - default: [] - items: - type: string - type: array - protocol_author: - default: '' - type: string - protocol_date: - default: '' - type: string - protocol_description: - default: '' - type: string - protocol_name: - default: '' - type: string - protocol_type: - default: '' - type: string - protocol_version: - default: '' - type: string - required: [] - type: object - result: {} - required: - - goal - title: create_protocol参数 - type: object - type: UniLabJsonCommandAsync - auto-custom_delay: - feedback: {} - goal: {} - goal_default: - msg: null - seconds: 0 - handles: {} - placeholder_keys: {} - result: {} - schema: - description: custom_delay的参数schema - properties: - feedback: {} - goal: - properties: - msg: - type: string - seconds: - default: 0 - type: string - required: [] - type: object - result: {} - required: - - goal - title: custom_delay参数 - type: object - type: UniLabJsonCommandAsync - auto-iter_tips: - feedback: {} - goal: {} - goal_default: - tip_racks: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: iter_tips的参数schema - properties: - feedback: {} - goal: - properties: - tip_racks: - type: string - required: - - tip_racks - type: object - result: {} - required: - - goal - title: iter_tips参数 - type: object - type: UniLabJsonCommand - auto-move_to: - feedback: {} - goal: {} - goal_default: - channel: 0 - dis_to_top: 0 - well: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: move_to的参数schema - properties: - feedback: {} - goal: - properties: - channel: - default: 0 - type: integer - dis_to_top: - default: 0 - type: number - well: - type: object - required: - - well - type: object - result: {} - required: - - goal - title: move_to参数 - type: object - type: UniLabJsonCommandAsync - auto-post_init: - feedback: {} - goal: {} - goal_default: - ros_node: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: '' - properties: - feedback: {} - goal: - properties: - ros_node: - type: object - required: - - ros_node - type: object - result: {} - required: - - goal - title: post_init参数 - type: object - type: UniLabJsonCommand - auto-run_protocol: - feedback: {} - goal: {} - goal_default: {} - handles: {} - placeholder_keys: {} - result: {} - schema: - description: run_protocol的参数schema - properties: - feedback: {} - goal: - properties: {} - required: [] - type: object - result: {} - required: - - goal - title: run_protocol参数 - type: object - type: UniLabJsonCommandAsync - auto-set_group: - feedback: {} - goal: {} - goal_default: - group_name: null - volumes: null - wells: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: '' - properties: - feedback: {} - goal: - properties: - group_name: - type: string - volumes: - items: - type: number - type: array - wells: - items: - type: object - type: array - required: - - group_name - - wells - - volumes - type: object - result: {} - required: - - goal - title: set_group参数 - type: object - type: UniLabJsonCommand - auto-touch_tip: - feedback: {} - goal: {} - goal_default: - targets: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: touch_tip的参数schema - properties: - feedback: {} - goal: - properties: - targets: - type: string - required: - - targets - type: object - result: {} - required: - - goal - title: touch_tip参数 - type: object - type: UniLabJsonCommandAsync - auto-transfer_group: - feedback: {} - goal: {} - goal_default: - source_group_name: null - target_group_name: null - unit_volume: null - handles: {} - placeholder_keys: {} - result: {} - schema: - description: '' - properties: - feedback: {} - goal: - properties: - source_group_name: - type: string - target_group_name: - type: string - unit_volume: - type: number - required: - - source_group_name - - target_group_name - - unit_volume - type: object - result: {} - required: - - goal - title: transfer_group参数 - type: object - type: UniLabJsonCommandAsync - discard_tips: - feedback: {} - goal: - use_channels: use_channels - goal_default: - use_channels: - - 0 - handles: {} - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDiscardTips_Feedback - type: object - goal: - properties: - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - use_channels - title: LiquidHandlerDiscardTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDiscardTips_Result - type: object - required: - - goal - title: LiquidHandlerDiscardTips - type: object - type: LiquidHandlerDiscardTips - dispense: - feedback: {} - goal: - blow_out_air_volume: blow_out_air_volume - flow_rates: flow_rates - offsets: offsets - resources: resources - spread: spread - use_channels: use_channels - vols: vols - goal_default: - blow_out_air_volume: - - 0 - flow_rates: - - 0.0 - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - resources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - use_channels: - - 0 - vols: - - 0.0 - handles: {} - placeholder_keys: - resources: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDispense_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - flow_rates: - items: - type: number - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - resources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: resources - type: object - type: array - spread: - type: string - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - required: - - resources - - vols - - use_channels - - flow_rates - - offsets - - blow_out_air_volume - - spread - title: LiquidHandlerDispense_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDispense_Result - type: object - required: - - goal - title: LiquidHandlerDispense - type: object - type: LiquidHandlerDispense - drop_tips: - feedback: {} - goal: - allow_nonzero_volume: allow_nonzero_volume - offsets: offsets - tip_spots: tip_spots - use_channels: use_channels - goal_default: - allow_nonzero_volume: false - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - tip_spots: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - placeholder_keys: - tip_spots: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerDropTips_Feedback - type: object - goal: - properties: - allow_nonzero_volume: - type: boolean - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - tip_spots: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_spots - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - tip_spots - - use_channels - - offsets - - allow_nonzero_volume - title: LiquidHandlerDropTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerDropTips_Result - type: object - required: - - goal - title: LiquidHandlerDropTips - type: object - type: LiquidHandlerDropTips - mix: - feedback: {} - goal: - height_to_bottom: height_to_bottom - mix_rate: mix_rate - mix_time: mix_time - mix_vol: mix_vol - none_keys: none_keys - offsets: offsets - targets: targets - goal_default: - height_to_bottom: 0.0 - mix_rate: 0.0 - mix_time: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - placeholder_keys: - targets: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerMix_Feedback - type: object - goal: - properties: - height_to_bottom: - type: number - mix_rate: - type: number - mix_time: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - required: - - targets - - mix_time - - mix_vol - - height_to_bottom - - offsets - - mix_rate - - none_keys - title: LiquidHandlerMix_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerMix_Result - type: object - required: - - goal - title: LiquidHandlerMix - type: object - type: LiquidHandlerMix - pick_up_tips: - feedback: {} - goal: - offsets: offsets - tip_spots: tip_spots - use_channels: use_channels - goal_default: - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - tip_spots: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - use_channels: - - 0 - handles: {} - placeholder_keys: - tip_spots: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerPickUpTips_Feedback - type: object - goal: - properties: - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - tip_spots: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_spots - type: object - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - tip_spots - - use_channels - - offsets - title: LiquidHandlerPickUpTips_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerPickUpTips_Result - type: object - required: - - goal - title: LiquidHandlerPickUpTips - type: object - type: LiquidHandlerPickUpTips - remove_liquid: - feedback: {} - goal: - blow_out_air_volume: blow_out_air_volume - delays: delays - flow_rates: flow_rates - is_96_well: is_96_well - liquid_height: liquid_height - none_keys: none_keys - offsets: offsets - sources: sources - spread: spread - top: top - use_channels: use_channels - vols: vols - waste_liquid: waste_liquid - goal_default: - blow_out_air_volume: - - 0.0 - delays: - - 0 - flow_rates: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - top: - - 0.0 - use_channels: - - 0 - vols: - - 0.0 - waste_liquid: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - placeholder_keys: - sources: unilabos_resources - waste_liquid: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerRemove_Feedback - type: object - goal: - properties: - blow_out_air_volume: - items: - type: number - type: array - delays: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - flow_rates: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: sources - type: object - type: array - spread: - type: string - top: - items: - type: number - type: array - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - vols: - items: - type: number - type: array - waste_liquid: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: waste_liquid - type: object - required: - - vols - - sources - - waste_liquid - - use_channels - - flow_rates - - offsets - - liquid_height - - blow_out_air_volume - - spread - - delays - - is_96_well - - top - - none_keys - title: LiquidHandlerRemove_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerRemove_Result - type: object - required: - - goal - title: LiquidHandlerRemove - type: object - type: LiquidHandlerRemove - set_liquid: - feedback: {} - goal: - liquid_names: liquid_names - volumes: volumes - wells: wells - goal_default: - liquid_names: - - '' - volumes: - - 0.0 - wells: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - placeholder_keys: - wells: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerSetLiquid_Feedback - type: object - goal: - properties: - liquid_names: - items: - type: string - type: array - volumes: - items: - type: number - type: array - wells: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: wells - type: object - type: array - required: - - wells - - liquid_names - - volumes - title: LiquidHandlerSetLiquid_Goal - type: object - result: - properties: - return_info: - type: string - required: - - return_info - title: LiquidHandlerSetLiquid_Result - type: object - required: - - goal - title: LiquidHandlerSetLiquid - type: object - type: LiquidHandlerSetLiquid - set_tiprack: - feedback: {} - goal: - tip_racks: tip_racks - goal_default: - tip_racks: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - handles: {} - placeholder_keys: - tip_racks: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerSetTipRack_Feedback - type: object - goal: - properties: - tip_racks: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_racks - type: object - type: array - required: - - tip_racks - title: LiquidHandlerSetTipRack_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerSetTipRack_Result - type: object - required: - - goal - title: LiquidHandlerSetTipRack - type: object - type: LiquidHandlerSetTipRack - transfer: - goal: - aspiration_flow_rate: aspiration_flow_rate - dispense_flow_rates: dispense_flow_rates - ratios: ratios - source: source - source_vol: source_vol - target_vols: target_vols - targets: targets - goal_default: - amount: '' - from_vessel: '' - rinsing_repeats: 0 - rinsing_solvent: '' - rinsing_volume: 0.0 - solid: false - time: 0.0 - to_vessel: '' - viscous: false - volume: 0.0 - handles: {} - schema: - description: '' - properties: - feedback: - properties: - current_status: - type: string - progress: - type: number - transferred_volume: - type: number - required: - - progress - - transferred_volume - - current_status - title: Transfer_Feedback - type: object - goal: - properties: - amount: - type: string - from_vessel: - type: string - rinsing_repeats: - maximum: 2147483647 - minimum: -2147483648 - type: integer - rinsing_solvent: - type: string - rinsing_volume: - type: number - solid: - type: boolean - time: - type: number - to_vessel: - type: string - viscous: - type: boolean - volume: - type: number - required: - - from_vessel - - to_vessel - - volume - - amount - - time - - viscous - - rinsing_solvent - - rinsing_volume - - rinsing_repeats - - solid - title: Transfer_Goal - type: object - result: - properties: - message: - type: string - return_info: - type: string - success: - type: boolean - required: - - success - - message - - return_info - title: Transfer_Result - type: object - required: - - goal - title: Transfer - type: object - type: Transfer - transfer_liquid: - feedback: {} - goal: - asp_flow_rates: asp_flow_rates - asp_vols: asp_vols - blow_out_air_volume: blow_out_air_volume - delays: delays - dis_flow_rates: dis_flow_rates - dis_vols: dis_vols - is_96_well: is_96_well - liquid_height: liquid_height - mix_liquid_height: mix_liquid_height - mix_rate: mix_rate - mix_stage: mix_stage - mix_times: mix_times - mix_vol: mix_vol - none_keys: none_keys - offsets: offsets - sources: sources - spread: spread - targets: targets - tip_racks: tip_racks - touch_tip: touch_tip - use_channels: use_channels - goal_default: - asp_flow_rates: - - 0.0 - asp_vols: - - 0.0 - blow_out_air_volume: - - 0.0 - delays: - - 0 - dis_flow_rates: - - 0.0 - dis_vols: - - 0.0 - is_96_well: false - liquid_height: - - 0.0 - mix_liquid_height: 0.0 - mix_rate: 0 - mix_stage: '' - mix_times: 0 - mix_vol: 0 - none_keys: - - '' - offsets: - - x: 0.0 - y: 0.0 - z: 0.0 - sources: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - spread: '' - targets: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - tip_racks: - - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - touch_tip: false - use_channels: - - 0 - handles: - input: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: sources - label: sources - - data_key: liquid - data_source: executor - data_type: resource - handler_key: targets - label: targets - - data_key: liquid - data_source: executor - data_type: resource - handler_key: tip_rack - label: tip_rack - output: - - data_key: liquid - data_source: handle - data_type: resource - handler_key: sources_out - label: sources - - data_key: liquid - data_source: executor - data_type: resource - handler_key: targets_out - label: targets - placeholder_keys: - sources: unilabos_resources - targets: unilabos_resources - tip_racks: unilabos_resources - result: {} - schema: - description: '' - properties: - feedback: - properties: {} - required: [] - title: LiquidHandlerTransfer_Feedback - type: object - goal: - properties: - asp_flow_rates: - items: - type: number - type: array - asp_vols: - items: - type: number - type: array - blow_out_air_volume: - items: - type: number - type: array - delays: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - dis_flow_rates: - items: - type: number - type: array - dis_vols: - items: - type: number - type: array - is_96_well: - type: boolean - liquid_height: - items: - type: number - type: array - mix_liquid_height: - type: number - mix_rate: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_stage: - type: string - mix_times: - maximum: 2147483647 - minimum: -2147483648 - type: integer - mix_vol: - maximum: 2147483647 - minimum: -2147483648 - type: integer - none_keys: - items: - type: string - type: array - offsets: - items: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: offsets - type: object - type: array - sources: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: sources - type: object - type: array - spread: - type: string - targets: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: targets - type: object - type: array - tip_racks: - items: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: tip_racks - type: object - type: array - touch_tip: - type: boolean - use_channels: - items: - maximum: 2147483647 - minimum: -2147483648 - type: integer - type: array - required: - - asp_vols - - dis_vols - - sources - - targets - - tip_racks - - use_channels - - asp_flow_rates - - dis_flow_rates - - offsets - - touch_tip - - liquid_height - - blow_out_air_volume - - spread - - is_96_well - - mix_stage - - mix_times - - mix_vol - - mix_rate - - mix_liquid_height - - delays - - none_keys - title: LiquidHandlerTransfer_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: LiquidHandlerTransfer_Result - type: object - required: - - goal - title: LiquidHandlerTransfer - type: object - type: LiquidHandlerTransfer - module: unilabos.devices.liquid_handling.prcxi.prcxi:PRCXI9300Handler - status_types: - reset_ok: bool - type: python - config_info: [] - description: prcxi液体处理器设备,基于pylabrobot控制 - handles: [] - icon: icon_yiyezhan.webp - init_param_schema: - config: - properties: - axis: - default: Left - type: string - channel_num: - default: 8 - type: string - debug: - default: false - type: string - deck: - type: object - host: - type: string - is_9320: - default: false - type: string - matrix_id: - default: '' - type: string - port: - type: integer - setup: - default: true - type: string - simulator: - default: false - type: string - step_mode: - default: false - type: string - timeout: - type: number - required: - - deck - - host - - port - - timeout - type: object - data: - properties: - reset_ok: - type: boolean - required: - - reset_ok - type: object - version: 1.0.0 -liquid_handler.revvity: - category: - - liquid_handler - class: - action_value_mappings: - run: - feedback: - status: status - goal: - params: params - resource: resource - wf_name: file_path - goal_default: - params: '' - resource: - category: '' - children: [] - config: '' - data: '' - id: '' - name: '' - parent: '' - pose: - orientation: - w: 1.0 - x: 0.0 - y: 0.0 - z: 0.0 - position: - x: 0.0 - y: 0.0 - z: 0.0 - sample_id: '' - type: '' - wf_name: '' - handles: {} - result: - success: success - schema: - description: '' - properties: - feedback: - properties: - gantt: - type: string - status: - type: string - required: - - status - - gantt - title: WorkStationRun_Feedback - type: object - goal: - properties: - params: - type: string - resource: - properties: - category: - type: string - children: - items: - type: string - type: array - config: - type: string - data: - type: string - id: - type: string - name: - type: string - parent: - type: string - pose: - properties: - orientation: - properties: - w: - type: number - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - - w - title: orientation - type: object - position: - properties: - x: - type: number - y: - type: number - z: - type: number - required: - - x - - y - - z - title: position - type: object - required: - - position - - orientation - title: pose - type: object - sample_id: - type: string - type: - type: string - required: - - id - - name - - sample_id - - children - - parent - - type - - category - - pose - - config - - data - title: resource - type: object - wf_name: - type: string - required: - - wf_name - - params - - resource - title: WorkStationRun_Goal - type: object - result: - properties: - return_info: - type: string - success: - type: boolean - required: - - return_info - - success - title: WorkStationRun_Result - type: object - required: - - goal - title: WorkStationRun - type: object - type: WorkStationRun - module: unilabos.devices.liquid_handling.revvity:Revvity - status_types: - status: str - success: bool - type: python - config_info: [] - description: '' - handles: [] - icon: '' - init_param_schema: - config: - properties: {} - required: [] - type: object - data: - properties: - status: - type: string - success: - type: boolean - required: - - success - - status - type: object - version: 1.0.0 diff --git a/unilabos/registry/resources/bioyond/deck.yaml b/unilabos/registry/resources/bioyond/deck.yaml index bc15850..9fc73f3 100644 --- a/unilabos/registry/resources/bioyond/deck.yaml +++ b/unilabos/registry/resources/bioyond/deck.yaml @@ -22,7 +22,7 @@ BIOYOND_PolymerReactionStation_Deck: init_param_schema: {} registry_type: resource version: 1.0.0 -YB_Deck11: +BIOYOND_YB_Deck: category: - deck class: @@ -34,3 +34,15 @@ YB_Deck11: init_param_schema: {} registry_type: resource version: 1.0.0 +CoincellDeck: + category: + - deck + class: + module: unilabos.devices.workstation.coin_cell_assembly.YB_YH_materials:YH_Deck + type: pylabrobot + description: BIOYOND PolymerReactionStation Deck + handles: [] + icon: koudian.webp + init_param_schema: {} + registry_type: resource + version: 1.0.0 diff --git a/unilabos/resources/battery/electrode_sheet.py b/unilabos/resources/battery/electrode_sheet.py index e86af24..22f98af 100644 --- a/unilabos/resources/battery/electrode_sheet.py +++ b/unilabos/resources/battery/electrode_sheet.py @@ -16,9 +16,12 @@ electrode_colors = { } class ElectrodeSheetState(TypedDict): + diameter: float # 直径 (mm) + thickness: float # 厚度 (mm) mass: float # 质量 (g) material_type: str # 材料类型(铜、铝、不锈钢、弹簧钢等) color: str # 材料类型对应的颜色 + info: Optional[str] # 附加信息 class ElectrodeSheet(ResourcePLR): @@ -27,18 +30,23 @@ class ElectrodeSheet(ResourcePLR): def __init__( self, name: str = "极片", - size_x=10, - size_y=10, - size_z=10, + size_x: float = 10, + size_y: float = 10, + size_z: float = 10, category: str = "electrode_sheet", model: Optional[str] = None, + **kwargs ): """初始化极片 Args: name: 极片名称 + size_x: 长度 (mm) + size_y: 宽度 (mm) + size_z: 高度 (mm) category: 类别 model: 型号 + **kwargs: 其他参数传递给父类 """ super().__init__( name=name, @@ -47,12 +55,14 @@ class ElectrodeSheet(ResourcePLR): size_z=size_z, category=category, model=model, + **kwargs ) self._unilabos_state: ElectrodeSheetState = ElectrodeSheetState( diameter=14, thickness=0.1, mass=0.5, material_type="copper", + color="#8b4513", info=None ) @@ -72,7 +82,7 @@ class ElectrodeSheet(ResourcePLR): def PositiveCan(name: str) -> ElectrodeSheet: """创建正极壳""" sheet = ElectrodeSheet(name=name, size_x=12, size_y=12, size_z=3.0, model="PositiveCan") - sheet.load_state({"material_type": "aluminum", "color": electrode_colors["PositiveCan"]}) + sheet.load_state({"diameter": 20.0, "thickness": 0.5, "mass": 0.5, "material_type": "aluminum", "color": electrode_colors["PositiveCan"], "info": None}) return sheet @@ -135,18 +145,23 @@ class Battery(Container): def __init__( self, name: str = "电池", - size_x=12, - size_y=12, - size_z=6, + size_x: float = 12, + size_y: float = 12, + size_z: float = 6, category: str = "battery", model: Optional[str] = None, + **kwargs ): """初始化电池 Args: name: 电池名称 + size_x: 长度 (mm) + size_y: 宽度 (mm) + size_z: 高度 (mm) category: 类别 model: 型号 + **kwargs: 其他参数传递给父类 """ super().__init__( name=name, @@ -155,6 +170,7 @@ class Battery(Container): size_z=size_z, category=category, model=model, + **kwargs ) self._unilabos_state: BatteryState = BatteryState( color=electrode_colors["Battery"], diff --git a/unilabos/resources/bioyond/decks.py b/unilabos/resources/bioyond/decks.py index 5572536..67e6d79 100644 --- a/unilabos/resources/bioyond/decks.py +++ b/unilabos/resources/bioyond/decks.py @@ -1,7 +1,7 @@ from os import name from pylabrobot.resources import Deck, Coordinate, Rotation -from unilabos.resources.bioyond.warehouses import ( +from unilabos.resources.bioyond.YB_warehouses import ( bioyond_warehouse_1x4x4, bioyond_warehouse_1x4x4_right, # 新增:右侧仓库 (A05~D08) bioyond_warehouse_1x4x2,