mirror of
https://github.com/deepmodeling/Uni-Lab-OS
synced 2026-03-27 08:13:11 +00:00
new registry sys
exp. support with add device
This commit is contained in:
@@ -76,7 +76,7 @@ def canonicalize_nodes_data(
|
||||
if sample_id:
|
||||
logger.error(f"{node}的sample_id参数已弃用,sample_id: {sample_id}")
|
||||
for k in list(node.keys()):
|
||||
if k not in ["id", "uuid", "name", "description", "schema", "model", "icon", "parent_uuid", "parent", "type", "class", "position", "config", "data", "children", "pose", "extra"]:
|
||||
if k not in ["id", "uuid", "name", "description", "schema", "model", "icon", "parent_uuid", "parent", "type", "class", "position", "config", "data", "children", "pose", "extra", "machine_name"]:
|
||||
v = node.pop(k)
|
||||
node["config"][k] = v
|
||||
if outer_host_node_id is not None:
|
||||
@@ -288,6 +288,15 @@ def read_node_link_json(
|
||||
physical_setup_graph = nx.node_link_graph(graph_data, edges="links", multigraph=False)
|
||||
handle_communications(physical_setup_graph)
|
||||
|
||||
# Stamp machine_name on device trees only (resources are cloud-managed)
|
||||
local_machine = BasicConfig.machine_name or "本地"
|
||||
for tree in resource_tree_set.trees:
|
||||
if tree.root_node.res_content.type != "device":
|
||||
continue
|
||||
for node in tree.get_all_nodes():
|
||||
if not node.res_content.machine_name:
|
||||
node.res_content.machine_name = local_machine
|
||||
|
||||
return physical_setup_graph, resource_tree_set, standardized_links
|
||||
|
||||
|
||||
@@ -372,6 +381,15 @@ def read_graphml(graphml_file: str) -> tuple[nx.Graph, ResourceTreeSet, List[Dic
|
||||
physical_setup_graph = nx.node_link_graph(graph_data, link="links", multigraph=False)
|
||||
handle_communications(physical_setup_graph)
|
||||
|
||||
# Stamp machine_name on device trees only (resources are cloud-managed)
|
||||
local_machine = BasicConfig.machine_name or "本地"
|
||||
for tree in resource_tree_set.trees:
|
||||
if tree.root_node.res_content.type != "device":
|
||||
continue
|
||||
for node in tree.get_all_nodes():
|
||||
if not node.res_content.machine_name:
|
||||
node.res_content.machine_name = local_machine
|
||||
|
||||
return physical_setup_graph, resource_tree_set, standardized_links
|
||||
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ class ResourceDictType(TypedDict):
|
||||
config: Dict[str, Any]
|
||||
data: Dict[str, Any]
|
||||
extra: Dict[str, Any]
|
||||
machine_name: str
|
||||
|
||||
|
||||
# 统一的资源字典模型,parent 自动序列化为 parent_uuid,children 不序列化
|
||||
@@ -141,6 +142,7 @@ class ResourceDict(BaseModel):
|
||||
config: Dict[str, Any] = Field(description="Resource configuration")
|
||||
data: Dict[str, Any] = Field(description="Resource data, eg: container liquid data")
|
||||
extra: Dict[str, Any] = Field(description="Extra data, eg: slot index")
|
||||
machine_name: str = Field(description="Machine this resource belongs to", default="")
|
||||
|
||||
@field_serializer("parent_uuid")
|
||||
def _serialize_parent(self, parent_uuid: Optional["ResourceDict"]):
|
||||
@@ -196,22 +198,30 @@ class ResourceDictInstance(object):
|
||||
self.typ = "dict"
|
||||
|
||||
@classmethod
|
||||
def get_resource_instance_from_dict(cls, content: Dict[str, Any]) -> "ResourceDictInstance":
|
||||
def get_resource_instance_from_dict(cls, content: ResourceDictType) -> "ResourceDictInstance":
|
||||
"""从字典创建资源实例"""
|
||||
if "id" not in content:
|
||||
content["id"] = content["name"]
|
||||
if "uuid" not in content:
|
||||
content["uuid"] = str(uuid.uuid4())
|
||||
if "description" in content and content["description"] is None:
|
||||
# noinspection PyTypedDict
|
||||
del content["description"]
|
||||
if "model" in content and content["model"] is None:
|
||||
# noinspection PyTypedDict
|
||||
del content["model"]
|
||||
# noinspection PyTypedDict
|
||||
if "schema" in content and content["schema"] is None:
|
||||
# noinspection PyTypedDict
|
||||
del content["schema"]
|
||||
# noinspection PyTypedDict
|
||||
if "x" in content.get("position", {}):
|
||||
# 说明是老版本的position格式,转换成新的
|
||||
# noinspection PyTypedDict
|
||||
content["position"] = {"position": content["position"]}
|
||||
# noinspection PyTypedDict
|
||||
if not content.get("class"):
|
||||
# noinspection PyTypedDict
|
||||
content["class"] = ""
|
||||
if not content.get("config"): # todo: 后续从后端保证字段非空
|
||||
content["config"] = {}
|
||||
@@ -222,16 +232,18 @@ class ResourceDictInstance(object):
|
||||
if "position" in content:
|
||||
pose = content.get("pose", {})
|
||||
if "position" not in pose:
|
||||
# noinspection PyTypedDict
|
||||
if "position" in content["position"]:
|
||||
# noinspection PyTypedDict
|
||||
pose["position"] = content["position"]["position"]
|
||||
else:
|
||||
pose["position"] = {"x": 0, "y": 0, "z": 0}
|
||||
pose["position"] = ResourceDictPositionObjectType(x=0, y=0, z=0)
|
||||
if "size" not in pose:
|
||||
pose["size"] = {
|
||||
"width": content["config"].get("size_x", 0),
|
||||
"height": content["config"].get("size_y", 0),
|
||||
"depth": content["config"].get("size_z", 0),
|
||||
}
|
||||
pose["size"] = ResourceDictPositionSizeType(
|
||||
width= content["config"].get("size_x", 0),
|
||||
height= content["config"].get("size_y", 0),
|
||||
depth= content["config"].get("size_z", 0),
|
||||
)
|
||||
content["pose"] = pose
|
||||
try:
|
||||
res_dict = ResourceDict.model_validate(content)
|
||||
@@ -399,7 +411,7 @@ class ResourceTreeSet(object):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_plr_resources(cls, resources: List["PLRResource"], known_newly_created=False) -> "ResourceTreeSet":
|
||||
def from_plr_resources(cls, resources: List["PLRResource"], known_newly_created=False, old_size=False) -> "ResourceTreeSet":
|
||||
"""
|
||||
从plr资源创建ResourceTreeSet
|
||||
"""
|
||||
@@ -422,13 +434,20 @@ class ResourceTreeSet(object):
|
||||
"resource_group": "resource_group",
|
||||
"trash": "trash",
|
||||
"plate_adapter": "plate_adapter",
|
||||
"consumable": "consumable",
|
||||
"tool": "tool",
|
||||
"condenser": "condenser",
|
||||
"crucible": "crucible",
|
||||
"reagent_bottle": "reagent_bottle",
|
||||
"flask": "flask",
|
||||
"beaker": "beaker",
|
||||
}
|
||||
if source in replace_info:
|
||||
return replace_info[source]
|
||||
elif source is None:
|
||||
return ""
|
||||
else:
|
||||
print("转换pylabrobot的时候,出现未知类型", source)
|
||||
logger.trace(f"转换pylabrobot的时候,出现未知类型 {source}")
|
||||
return source
|
||||
|
||||
def build_uuid_mapping(res: "PLRResource", uuid_list: list, parent_uuid: Optional[str] = None):
|
||||
@@ -483,7 +502,7 @@ class ResourceTreeSet(object):
|
||||
k: v
|
||||
for k, v in d.items()
|
||||
if k
|
||||
not in [
|
||||
not in ([
|
||||
"name",
|
||||
"children",
|
||||
"parent_name",
|
||||
@@ -494,7 +513,15 @@ class ResourceTreeSet(object):
|
||||
"size_z",
|
||||
"cross_section_type",
|
||||
"bottom_type",
|
||||
]
|
||||
] if not old_size else [
|
||||
"name",
|
||||
"children",
|
||||
"parent_name",
|
||||
"location",
|
||||
"rotation",
|
||||
"cross_section_type",
|
||||
"bottom_type",
|
||||
])
|
||||
},
|
||||
"data": states[d["name"]],
|
||||
"extra": extra,
|
||||
@@ -793,7 +820,8 @@ class ResourceTreeSet(object):
|
||||
if remote_root_type == "device":
|
||||
# 情况1: 一级是 device
|
||||
if remote_root_id not in local_device_map:
|
||||
logger.warning(f"Device '{remote_root_id}' 在本地不存在,跳过该 device 下的物料同步")
|
||||
if remote_root_id != "host_node":
|
||||
logger.warning(f"Device '{remote_root_id}' 在本地不存在,跳过该 device 下的物料同步")
|
||||
continue
|
||||
|
||||
local_device = local_device_map[remote_root_id]
|
||||
@@ -883,7 +911,7 @@ class ResourceTreeSet(object):
|
||||
|
||||
return self
|
||||
|
||||
def dump(self) -> List[List[Dict[str, Any]]]:
|
||||
def dump(self, old_position=False) -> List[List[Dict[str, Any]]]:
|
||||
"""
|
||||
将 ResourceTreeSet 序列化为嵌套列表格式
|
||||
|
||||
@@ -899,6 +927,10 @@ class ResourceTreeSet(object):
|
||||
# 获取树的所有节点并序列化
|
||||
tree_nodes = [node.res_content.model_dump(by_alias=True) for node in tree.get_all_nodes()]
|
||||
result.append(tree_nodes)
|
||||
if old_position:
|
||||
for r in result:
|
||||
for rr in r:
|
||||
rr["position"] = rr["pose"]["position"]
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
|
||||
Reference in New Issue
Block a user