add resource edge upload

This commit is contained in:
Xuwznln
2025-06-16 11:51:02 +08:00
parent a303bd7c5b
commit 57cb120c8c
7 changed files with 73 additions and 16 deletions

View File

@@ -8,6 +8,7 @@ def start_backend(
backend: str, backend: str,
devices_config: dict = {}, devices_config: dict = {},
resources_config: list = [], resources_config: list = [],
resources_edge_config: list = [],
graph=None, graph=None,
controllers_config: dict = {}, controllers_config: dict = {},
bridges=[], bridges=[],
@@ -31,7 +32,7 @@ def start_backend(
backend_thread = threading.Thread( backend_thread = threading.Thread(
target=main if not without_host else slave, target=main if not without_host else slave,
args=(devices_config, resources_config, graph, controllers_config, bridges, visual, resources_mesh_config), args=(devices_config, resources_config, resources_edge_config, graph, controllers_config, bridges, visual, resources_mesh_config),
name="backend_thread", name="backend_thread",
daemon=True, daemon=True,
) )

View File

@@ -10,7 +10,7 @@ from copy import deepcopy
import yaml import yaml
from unilabos.resources.graphio import tree_to_list from unilabos.resources.graphio import tree_to_list, modify_to_backend_format
# 首先添加项目根目录到路径 # 首先添加项目根目录到路径
current_dir = os.path.dirname(os.path.abspath(__file__)) current_dir = os.path.dirname(os.path.abspath(__file__))
@@ -136,15 +136,16 @@ def main():
# 注册表 # 注册表
build_registry(args_dict["registry_path"]) build_registry(args_dict["registry_path"])
resource_edge_info = []
devices_and_resources = None devices_and_resources = None
if args_dict["graph"] is not None: if args_dict["graph"] is not None:
import unilabos.resources.graphio as graph_res import unilabos.resources.graphio as graph_res
graph_res.physical_setup_graph = ( if args_dict["graph"].endswith(".json"):
read_node_link_json(args_dict["graph"]) graph, data = read_node_link_json(args_dict["graph"])
if args_dict["graph"].endswith(".json") else:
else read_graphml(args_dict["graph"]) graph, data = read_graphml(args_dict["graph"])
) graph_res.physical_setup_graph = graph
resource_edge_info = modify_to_backend_format(data["links"])
devices_and_resources = dict_from_graph(graph_res.physical_setup_graph) devices_and_resources = dict_from_graph(graph_res.physical_setup_graph)
# args_dict["resources_config"] = initialize_resources(list(deepcopy(devices_and_resources).values())) # args_dict["resources_config"] = initialize_resources(list(deepcopy(devices_and_resources).values()))
args_dict["resources_config"] = list(devices_and_resources.values()) args_dict["resources_config"] = list(devices_and_resources.values())
@@ -185,6 +186,7 @@ def main():
signal.signal(signal.SIGTERM, _exit) signal.signal(signal.SIGTERM, _exit)
mqtt_client.start() mqtt_client.start()
args_dict["resources_mesh_config"] = {} args_dict["resources_mesh_config"] = {}
args_dict["resources_edge_config"] = resource_edge_info
# web visiualize 2D # web visiualize 2D
if args_dict["visual"] != "disable": if args_dict["visual"] != "disable":
enable_rviz = args_dict["visual"] == "rviz" enable_rviz = args_dict["visual"] == "rviz"

View File

@@ -30,7 +30,25 @@ class HTTPClient:
self.auth = MQConfig.lab_id self.auth = MQConfig.lab_id
info(f"HTTPClient 初始化完成: remote_addr={self.remote_addr}") info(f"HTTPClient 初始化完成: remote_addr={self.remote_addr}")
def resource_add(self, resources: List[Dict[str, Any]], database_process_later:bool) -> requests.Response: def resource_edge_add(self, resources: List[Dict[str, Any]], database_process_later: bool) -> requests.Response:
"""
添加资源
Args:
resources: 要添加的资源列表
database_process_later: 后台处理资源
Returns:
Response: API响应对象
"""
response = requests.post(
f"{self.remote_addr}/lab/resource/edge/batch_create/?database_process_later={1 if database_process_later else 0}",
json=resources,
headers={"Authorization": f"lab {self.auth}"},
timeout=5,
)
return response
def resource_add(self, resources: List[Dict[str, Any]], database_process_later: bool) -> requests.Response:
""" """
添加资源 添加资源

View File

@@ -16,7 +16,6 @@ from jinja2 import Environment, FileSystemLoader
from unilabos.config.config import BasicConfig from unilabos.config.config import BasicConfig
from unilabos.registry.registry import lab_registry from unilabos.registry.registry import lab_registry
from unilabos.app.mq import mqtt_client
from unilabos.ros.msgs.message_converter import msg_converter_manager from unilabos.ros.msgs.message_converter import msg_converter_manager
from unilabos.utils.log import error from unilabos.utils.log import error
from unilabos.utils.type_check import TypeEncoder from unilabos.utils.type_check import TypeEncoder

View File

@@ -1,7 +1,7 @@
import importlib import importlib
import inspect import inspect
import json import json
from typing import Union from typing import Union, Any
import numpy as np import numpy as np
import networkx as nx import networkx as nx
from unilabos_msgs.msg import Resource from unilabos_msgs.msg import Resource
@@ -84,6 +84,8 @@ def canonicalize_links_ports(data: dict) -> dict:
# 第一遍处理将字符串类型的port转换为字典格式 # 第一遍处理将字符串类型的port转换为字典格式
for link in data.get("links", []): for link in data.get("links", []):
port = link.get("port") port = link.get("port")
if link["type"] == "physical":
link["type"] = "fluid"
if isinstance(port, int): if isinstance(port, int):
port = str(port) port = str(port)
if isinstance(port, str): if isinstance(port, str):
@@ -157,7 +159,28 @@ def read_node_link_json(json_file):
physical_setup_graph = nx.node_link_graph(data, multigraph=False) # edges="links" 3.6 warning physical_setup_graph = nx.node_link_graph(data, multigraph=False) # edges="links" 3.6 warning
handle_communications(physical_setup_graph) handle_communications(physical_setup_graph)
return physical_setup_graph return physical_setup_graph, data
def modify_to_backend_format(data: list[dict[str, Any]]) -> list[dict[str, Any]]:
for edge in data:
port = edge.pop("port", {})
source = edge["source"]
target = edge["target"]
if source in port:
edge["sourceHandle"] = port[source]
elif "source_port" in edge:
edge["sourceHandle"] = edge.pop("source_port")
if target in port:
edge["targetHandle"] = port[target]
elif "target_port" in edge:
edge["targetHandle"] = edge.pop("target_port")
if "id" not in edge:
edge["id"] = f"link_generated_{source}_{target}"
for key in ["source_port", "target_port"]:
if key in edge:
edge.pop(key)
return data
def read_graphml(graphml_file): def read_graphml(graphml_file):
@@ -182,7 +205,7 @@ def read_graphml(graphml_file):
physical_setup_graph = nx.node_link_graph(data, edges="links", multigraph=False) # edges="links" 3.6 warning physical_setup_graph = nx.node_link_graph(data, edges="links", multigraph=False) # edges="links" 3.6 warning
handle_communications(physical_setup_graph) handle_communications(physical_setup_graph)
return physical_setup_graph return physical_setup_graph, data
def dict_from_graph(graph: nx.Graph) -> dict: def dict_from_graph(graph: nx.Graph) -> dict:

View File

@@ -45,6 +45,7 @@ def exit() -> None:
def main( def main(
devices_config: Dict[str, Any] = {}, devices_config: Dict[str, Any] = {},
resources_config: list=[], resources_config: list=[],
resources_edge_config: list=[],
graph: Optional[Dict[str, Any]] = None, graph: Optional[Dict[str, Any]] = None,
controllers_config: Dict[str, Any] = {}, controllers_config: Dict[str, Any] = {},
bridges: List[Any] = [], bridges: List[Any] = [],
@@ -62,6 +63,7 @@ def main(
"host_node", "host_node",
devices_config, devices_config,
resources_config, resources_config,
resources_edge_config,
graph, graph,
controllers_config, controllers_config,
bridges, bridges,
@@ -97,6 +99,7 @@ def main(
def slave( def slave(
devices_config: Dict[str, Any] = {}, devices_config: Dict[str, Any] = {},
resources_config=[], resources_config=[],
resources_edge_config=[],
graph: Optional[Dict[str, Any]] = None, graph: Optional[Dict[str, Any]] = None,
controllers_config: Dict[str, Any] = {}, controllers_config: Dict[str, Any] = {},
bridges: List[Any] = [], bridges: List[Any] = [],

View File

@@ -58,6 +58,7 @@ class HostNode(BaseROS2DeviceNode):
device_id: str, device_id: str,
devices_config: Dict[str, Any], devices_config: Dict[str, Any],
resources_config: list, resources_config: list,
resources_edge_config: list[dict],
physical_setup_graph: Optional[Dict[str, Any]] = None, physical_setup_graph: Optional[Dict[str, Any]] = None,
controllers_config: Optional[Dict[str, Any]] = None, controllers_config: Optional[Dict[str, Any]] = None,
bridges: Optional[List[Any]] = None, bridges: Optional[List[Any]] = None,
@@ -96,6 +97,7 @@ class HostNode(BaseROS2DeviceNode):
self.server_latest_timestamp = 0.0 # self.server_latest_timestamp = 0.0 #
self.devices_config = devices_config self.devices_config = devices_config
self.resources_config = resources_config self.resources_config = resources_config
self.resources_edge_config = resources_edge_config
self.physical_setup_graph = physical_setup_graph self.physical_setup_graph = physical_setup_graph
if controllers_config is None: if controllers_config is None:
controllers_config = {} controllers_config = {}
@@ -203,12 +205,19 @@ class HostNode(BaseROS2DeviceNode):
try: try:
for bridge in self.bridges: for bridge in self.bridges:
if hasattr(bridge, "resource_add"): if hasattr(bridge, "resource_add"):
from unilabos.app.web.client import HTTPClient
client: HTTPClient = bridge
resource_start_time = time.time() resource_start_time = time.time()
resource_add_res = bridge.resource_add(add_schema(resource_with_parent_name), True) resource_add_res = client.resource_add(add_schema(resource_with_parent_name), True)
resource_end_time = time.time() resource_end_time = time.time()
self.lab_logger().info( self.lab_logger().info(
f"[Host Node-Resource] 物料上传 {round(resource_end_time - resource_start_time, 5) * 1000} ms" f"[Host Node-Resource] 物料上传 {round(resource_end_time - resource_start_time, 5) * 1000} ms"
) )
resource_add_res = client.resource_edge_add(self.resources_edge_config, True)
resource_edge_end_time = time.time()
self.lab_logger().info(
f"[Host Node-Resource] 物料关系上传 {round(resource_edge_end_time - resource_end_time, 5) * 1000} ms"
)
except Exception as ex: except Exception as ex:
self.lab_logger().error("[Host Node-Resource] 添加物料出错!") self.lab_logger().error("[Host Node-Resource] 添加物料出错!")
self.lab_logger().error(traceback.format_exc()) self.lab_logger().error(traceback.format_exc())
@@ -757,8 +766,10 @@ class HostNode(BaseROS2DeviceNode):
self.lab_logger().info(f"[Host Node-Resource] Add request received: {len(resources)} resources") self.lab_logger().info(f"[Host Node-Resource] Add request received: {len(resources)} resources")
success = False success = False
if len(self.bridges) > 0: if len(self.bridges) > 0: # 边的提交待定
r = self.bridges[-1].resource_add(add_schema(resources)) from unilabos.app.web.client import HTTPClient
client: HTTPClient = self.bridges[-1]
r = client.resource_add(add_schema(resources), False)
success = bool(r) success = bool(r)
response.success = success response.success = success