From 308a4d882e416e092471f6455a1151c3c45b6fed Mon Sep 17 00:00:00 2001
From: Luca Della Vedova <lucadv@intrinsic.ai>
Date: Thu, 21 Nov 2024 10:49:32 +0800
Subject: [PATCH 1/4] Migrate to ros2dds bridge

Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
---
 .../config/zenoh/nexus_network_config.yaml    | 60 ++++++++++++---
 .../launch/zenoh_bridge.launch.py             |  2 +-
 .../nexus_network_configuration.py            | 26 +++----
 .../schemas/nexus_network_schema.json         | 73 ++++++++++++++-----
 nexus_zenoh_bridge_dds_vendor/CMakeLists.txt  |  4 +-
 5 files changed, 114 insertions(+), 51 deletions(-)

diff --git a/nexus_integration_tests/config/zenoh/nexus_network_config.yaml b/nexus_integration_tests/config/zenoh/nexus_network_config.yaml
index d16ae54..2dc2d46 100644
--- a/nexus_integration_tests/config/zenoh/nexus_network_config.yaml
+++ b/nexus_integration_tests/config/zenoh/nexus_network_config.yaml
@@ -2,32 +2,68 @@
 # Use 'client' when there is an available Zenoh router, otherwise
 # use 'peer' for a distributed system.
 mode: peer
-# When true, discovery info is forwarded to the remote plugins/bridges
-forward_discovery: false
 # When true, activates a REST API used to administer Zenoh Bridge configurations
 enable_rest_api: true
-# Additional endpoints to allow, these could be endpoints not defined in REDF but are necessary for lifecycle transitions
-add_allowed_endpoints: ["/list_workcells", "/.*/workcell_state", "/.*/is_task_doable", "/.*/request", "/.*/queue_task", "/.*/remove_pending_task", "/register_workcell", "/register_transporter", ".*/available", ".*/transport", "/estop", "/.*/pause", "/.*/get_state", "/.*/change_state", "/.*/signal"]
 
 system_orchestrators:
-  - ros_namespace: system_orchestrator # ROS Namespace of the endpoints
+  - namespace: system_orchestrator # ROS Namespace of the endpoints
     # ROS Domain ID
-    domain_id: 14
+    domain_id: 0
     # Listening TCP Address of Zenoh bridge
     tcp_listen: ["0.0.0.0:7447"]
     # HTTP Port for the REST API
     rest_api_http_port: 8000
+    allow:
+      publishers: []
+      # TODO(luca) check if we need estop
+      subscribers: ["/estop", "/.*/workcell_state"]
+      service_servers: ["/list_workcells", "/register_workcell", "/register_transporter"]
+      # TODO(luca) check if transporter needs available endpoint
+      service_clients: ["/.*/queue_task", "/.*/remove_pending_task", "/.*/pause", "/.*/signal", "/.*/get_state", "/.*/change_state", "/.*/is_task_doable"]
+      action_servers: []
+      # TODO(luca) check if we really need transporter client
+      action_clients: ["/.*/request", "/.*/transport"]
+    queries_timeout:
+      default: 600.0
+
 
 workcell_orchestrators:
-  - ros_namespace: workcell_1
-    domain_id: 15
+  - namespace: workcell_1
+    domain_id: 1
     tcp_connect: ["0.0.0.0:7447"]
     rest_api_http_port: 8001
-  - ros_namespace: workcell_2
-    domain_id: 16
+    allow:
+      publishers: ["/workcell_1/workcell_state"]
+      subscribers: []
+      service_servers: ["/workcell_1/is_task_doable", "/workcell_1/queue_task", "/workcell_1/remove_pending_task", "/workcell_1/get_state", "/workcell_1/change_state", "/workcell_1/signal", "/workcell_1/pause"]
+      service_clients: ["/register_workcell"]
+      action_servers: ["/workcell_1/request"]
+      action_clients: []
+    queries_timeout:
+      default: 600.0
+  - namespace: workcell_2
+    domain_id: 2
     tcp_connect: ["0.0.0.0:7447"]
     rest_api_http_port: 8002
-  - ros_namespace: workcell_3
-    domain_id: 17
+    allow:
+      publishers: ["/workcell_2/workcell_state"]
+      subscribers: []
+      service_servers: ["/workcell_2/is_task_doable", "/workcell_2/queue_task", "/workcell_2/remove_pending_task", "/workcell_2/get_state", "/workcell_2/change_state", "/workcell_2/signal", "/workcell_2/pause"]
+      service_clients: ["/register_workcell"]
+      action_servers: ["/workcell_2/request"]
+      action_clients: []
+    queries_timeout:
+      default: 600.0
+  - namespace: workcell_3
+    domain_id: 3
     tcp_connect: ["0.0.0.0:7447"]
     rest_api_http_port: 8003
+    allow:
+      publishers: ["workcell_3/workcell_state"]
+      subscribers: []
+      service_servers: ["workcell_3/is_task_doable", "workcell_3/queue_task", "workcell_3/remove_pending_task", "workcell_3/get_state", "workcell_3/change_state"]
+      service_clients: ["/register_workcell"]
+      action_servers: ["workcell_3/request"]
+      action_clients: []
+    queries_timeout:
+      default: 600.0
diff --git a/nexus_integration_tests/launch/zenoh_bridge.launch.py b/nexus_integration_tests/launch/zenoh_bridge.launch.py
index b6adb2c..acd5009 100644
--- a/nexus_integration_tests/launch/zenoh_bridge.launch.py
+++ b/nexus_integration_tests/launch/zenoh_bridge.launch.py
@@ -40,7 +40,7 @@ def launch_setup(context, *args, **kwargs):
 
     cmd = [
         ExecutableInPackage(
-            executable="zenoh_bridge_dds",
+            executable="zenoh_bridge_ros2dds",
             package="nexus_zenoh_bridge_dds_vendor",
         ),
         "--config",
diff --git a/nexus_network_configuration/nexus_network_configuration/nexus_network_configuration.py b/nexus_network_configuration/nexus_network_configuration/nexus_network_configuration.py
index d97de9e..7eb1064 100644
--- a/nexus_network_configuration/nexus_network_configuration/nexus_network_configuration.py
+++ b/nexus_network_configuration/nexus_network_configuration/nexus_network_configuration.py
@@ -48,10 +48,7 @@ def __init__(
 
         # Set global variables
         self.enable_rest_api = self.nexus_net_cfg["enable_rest_api"]
-        self.add_allowed_endpoints = self.nexus_net_cfg[
-            "add_allowed_endpoints"]
         self.bridge_mode = self.nexus_net_cfg["mode"]
-        self.forward_discovery = self.nexus_net_cfg["forward_discovery"]
 
         self.zenoh_cfg_file_extension = "json5"
 
@@ -146,11 +143,11 @@ def zenoh_cfg(
 
         zenoh_dict = {
             "plugins": {
-                "dds": {
+                "ros2dds": {
                     "domain": orchestrator["domain_id"],
-                    "group_member_id": orchestrator["ros_namespace"],
-                    "forward_discovery": self.forward_discovery,
-                    "allow": allowed_endpoints,
+                    "namespace": orchestrator["namespace"],
+                    "allow": orchestrator["allow"],
+                    "queries_timeout": orchestrator["queries_timeout"],
                 },
             },
             "mode": self.bridge_mode,
@@ -180,7 +177,7 @@ def generate_zenoh_config(self, output_dir):
         orchestrators_zenoh_cfg = []
 
         allowed_endpoints = self.generate_allowed_endpoints(
-            self.redf_cfg, self.add_allowed_endpoints)
+            self.redf_cfg)
 
         # Generate system orchestrator zenoh dictionary
         for orchestrator in nexus_net_cfg["system_orchestrators"]:
@@ -212,18 +209,17 @@ def generate_zenoh_config(self, output_dir):
         for zenoh_cfg in orchestrators_zenoh_cfg:
             write_filepath = os.path.join(
                 output_dir,
-                zenoh_cfg["plugins"]["dds"]["group_member_id"]
+                zenoh_cfg["plugins"]["ros2dds"]["namespace"]
                 + "."
                 + self.zenoh_cfg_file_extension,
             )
-            # This has been removed in Zenoh 1.0.0
-            del zenoh_cfg["plugins"]["dds"]["group_member_id"]
+            del zenoh_cfg["plugins"]["ros2dds"]["namespace"]
             self.write_to_json(write_filepath, zenoh_cfg)
             print(f"Generated Zenoh configuration at {write_filepath}")
 
     def generate_allowed_endpoints(self,
-                                   redf_cfg,
-                                   add_allowed_endpoints):
+                                   redf_cfg
+                                   ):
         """
         Generate allowed endpoints string from REDF configuration.
 
@@ -234,8 +230,6 @@ def generate_allowed_endpoints(self,
         ----------
         redf_cfg : dict
             REDF Configuration dictionary
-        add_allowed_endpoints : array
-            Additional endpoints allowed
 
         Returns
         -------
@@ -253,8 +247,6 @@ def generate_allowed_endpoints(self,
             elif endpoint.get("service_name"):
                 allowed_endpoints.append(endpoint["service_name"])
 
-        allowed_endpoints.extend(add_allowed_endpoints)
-
         allowed_endpoints_str = ""
         for endpoint_str in allowed_endpoints:
             # Searches for namespace defined in curly braces in REDF endpoints.
diff --git a/nexus_network_configuration/schemas/nexus_network_schema.json b/nexus_network_configuration/schemas/nexus_network_schema.json
index 9e208b2..c6cfc8d 100644
--- a/nexus_network_configuration/schemas/nexus_network_schema.json
+++ b/nexus_network_configuration/schemas/nexus_network_schema.json
@@ -6,9 +6,7 @@
   "type": "object",
   "required": [
     "mode",
-    "forward_discovery",
     "enable_rest_api",
-    "add_allowed_endpoints",
     "system_orchestrators",
     "workcell_orchestrators"
   ],
@@ -18,18 +16,10 @@
       "type": "string",
       "enum": ["peer", "client"]
     },
-    "forward_discovery": {
-      "description": "When true, discovery info is forwarded to the remote plugins/bridges",
-      "type": "boolean"
-    },
     "enable_rest_api":{
       "description": "When true, activates a REST API used to administer Zenoh Bridge configurations",
       "type": "boolean"
     },
-    "add_allowed_endpoints":{
-      "description": "Additional endpoints to allow, these could be endpoints not defined in REDF but are necessary for lifecycle transitions",
-      "type": "array"
-    },
     "system_orchestrators": {
       "type": "array",
       "items": { "$ref": "#/$defs/system_orchestrator_unit"}
@@ -41,12 +31,45 @@
   },
 
   "$defs": {
+    "queries_timeout": {
+      "description": "Timeout parameters for Zenoh queries",
+      "type": "object",
+      "properties": {
+        "default": {
+          "type": "number"
+        }
+      }
+    },
+    "allow": {
+      "description": "Additional endpoints to allow, these could be endpoints not defined in REDF but are necessary for lifecycle transitions",
+      "type": "object",
+      "properties": {
+        "subscribers": {
+          "type": "array"
+        },
+        "publishers": {
+          "type": "array"
+        },
+        "service_servers": {
+          "type": "array"
+        },
+        "service_clients": {
+          "type": "array"
+        },
+        "action_servers": {
+          "type": "array"
+        },
+        "action_clients": {
+          "type": "array"
+        }
+      }
+    },
     "system_orchestrator_unit": {
       "type": "object",
-      "required": ["ros_namespace", "domain_id", "tcp_listen"],
+      "required": ["namespace", "domain_id", "tcp_listen"],
       "properties": {
-        "ros_namespace":{
-          "$ref": "#/$defs/ros_namespace"
+        "namespace":{
+          "$ref": "#/$defs/namespace"
         },
         "domain_id":{
           "$ref": "#/$defs/domain_id"
@@ -56,15 +79,21 @@
         },
         "rest_api_http_port":{
           "$ref": "#/$defs/rest_api_http_port"
+        },
+        "allow":{
+          "$ref": "#/$defs/allow"
+        },
+        "queries_timeout":{
+          "$ref": "#/$defs/queries_timeout"
         }
       }
     },
     "workcell_orchestrator_unit": {
       "type": "object",
-      "required": ["ros_namespace", "domain_id", "tcp_connect"],
+      "required": ["namespace", "domain_id", "tcp_connect"],
       "properties": {
-        "ros_namespace":{
-          "$ref": "#/$defs/ros_namespace"
+        "namespace":{
+          "$ref": "#/$defs/namespace"
         },
         "domain_id":{
           "$ref": "#/$defs/domain_id"
@@ -74,10 +103,16 @@
         },
         "rest_api_http_port":{
           "$ref": "#/$defs/rest_api_http_port"
+        },
+        "allow":{
+          "$ref": "#/$defs/allow"
+        },
+        "queries_timeout":{
+          "$ref": "#/$defs/queries_timeout"
         }
       }
     },
-    "ros_namespace":{
+    "namespace":{
       "description": "ROS Namespace of the endpoints",
       "type": "string"
     },
@@ -85,7 +120,7 @@
       "description": "ROS Domain ID",
       "type": "integer",
       "minimum": 0,
-      "maxmimum": 232
+      "maximum": 232
     },
     "tcp_connect":{
       "description": "TCP Address of system orchestrator Zenoh bridge",
@@ -99,7 +134,7 @@
       "description": "HTTP Port for the REST API",
       "type": "integer",
       "minimum": 0,
-      "maxmimum": 65535
+      "maximum": 65535
     }
   }
 }
diff --git a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
index ea92efd..163404f 100644
--- a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
+++ b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
@@ -11,14 +11,14 @@ find_package(ament_cmake REQUIRED)
 find_package(ament_cmake_vendor_package REQUIRED)
 
 ament_vendor(zeno_bridge_dds_vendor
-  VCS_URL https://github.com/eclipse-zenoh/zenoh-plugin-dds.git
+  VCS_URL https://github.com/eclipse-zenoh/zenoh-plugin-ros2dds.git
   VCS_VERSION 1.0.2
 )
 
 # TODO(sloretz) make a nice way to get this path from ament_vendor
 set(INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/zeno_bridge_dds_vendor-prefix/install")
 install(
-  DIRECTORY "${INSTALL_DIR}/lib/zenoh_bridge_dds/"
+  DIRECTORY "${INSTALL_DIR}/lib/zenoh_bridge_ros2dds/"
   DESTINATION "lib/${PROJECT_NAME}"
   USE_SOURCE_PERMISSIONS
 )

From 0cbb8ece2be8a21825e593163c4e26242a10156d Mon Sep 17 00:00:00 2001
From: Luca Della Vedova <lucadv@intrinsic.ai>
Date: Wed, 11 Dec 2024 16:08:49 +0800
Subject: [PATCH 2/4] Bump ros2dds bridge version to fix warning spam

Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
---
 nexus_zenoh_bridge_dds_vendor/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
index 163404f..eeba689 100644
--- a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
+++ b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
@@ -12,7 +12,7 @@ find_package(ament_cmake_vendor_package REQUIRED)
 
 ament_vendor(zeno_bridge_dds_vendor
   VCS_URL https://github.com/eclipse-zenoh/zenoh-plugin-ros2dds.git
-  VCS_VERSION 1.0.2
+  VCS_VERSION 1.0.4
 )
 
 # TODO(sloretz) make a nice way to get this path from ament_vendor

From d813ae98af56b35a7fa66ed544d546425a12945b Mon Sep 17 00:00:00 2001
From: Luca Della Vedova <lucadv@intrinsic.ai>
Date: Thu, 26 Dec 2024 15:48:04 +0800
Subject: [PATCH 3/4] Revert patch bump

Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
---
 nexus_zenoh_bridge_dds_vendor/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
index eeba689..163404f 100644
--- a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
+++ b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
@@ -12,7 +12,7 @@ find_package(ament_cmake_vendor_package REQUIRED)
 
 ament_vendor(zeno_bridge_dds_vendor
   VCS_URL https://github.com/eclipse-zenoh/zenoh-plugin-ros2dds.git
-  VCS_VERSION 1.0.4
+  VCS_VERSION 1.0.2
 )
 
 # TODO(sloretz) make a nice way to get this path from ament_vendor

From 9af090301487a0b78f7b22bb9e5a3d0b1d5bd9e0 Mon Sep 17 00:00:00 2001
From: Luca Della Vedova <lucadv@intrinsic.ai>
Date: Thu, 26 Dec 2024 15:55:53 +0800
Subject: [PATCH 4/4] Bump to last known good patch version

Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
---
 nexus_zenoh_bridge_dds_vendor/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
index 163404f..13e508c 100644
--- a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
+++ b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt
@@ -12,7 +12,7 @@ find_package(ament_cmake_vendor_package REQUIRED)
 
 ament_vendor(zeno_bridge_dds_vendor
   VCS_URL https://github.com/eclipse-zenoh/zenoh-plugin-ros2dds.git
-  VCS_VERSION 1.0.2
+  VCS_VERSION 1.0.3
 )
 
 # TODO(sloretz) make a nice way to get this path from ament_vendor