Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/ros2_medkit_cmake/cmake/ROS2MedkitTestDomain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
# non-overlapping domain ID ranges to prevent DDS cross-contamination.
#
# Allocated ranges:
# ros2_medkit_sovd_service_iface: 1 - 9 (9 slots)
# ros2_medkit_fault_manager: 10 - 29 (20 slots)
# ros2_medkit_gateway: 30 - 89 (60 slots)
# ros2_medkit_diagnostic_bridge: 90 - 99 (10 slots)
Expand All @@ -27,7 +28,7 @@
# ros2_medkit_graph_provider: 120 - 129 (10 slots)
# ros2_medkit_linux_introspection: 130 - 139 (10 slots)
# ros2_medkit_integration_tests: 140 - 229 (90 slots)
# multi-domain tests (secondary): 230 - 232 (3 slots, via get_test_domain_id)
# multi-domain tests (secondary): 230 - 232 (3 slots, reserved for peer_aggregation etc.)
#
# To add a new package: pick the next free range and update this comment.

Expand Down
4 changes: 4 additions & 0 deletions src/ros2_medkit_msgs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ rosidl_generate_interfaces(${PROJECT_NAME}
"msg/Snapshot.msg"
"msg/EnvironmentData.msg"
"msg/MedkitDiscoveryHint.msg"
"msg/EntityInfo.msg"
"srv/ReportFault.srv"
"srv/ListFaults.srv"
"srv/GetFault.srv"
Expand All @@ -41,6 +42,9 @@ rosidl_generate_interfaces(${PROJECT_NAME}
"srv/GetRosbag.srv"
"srv/ListRosbags.srv"
"srv/ListFaultsForEntity.srv"
"srv/ListEntities.srv"
"srv/GetEntityData.srv"
"srv/GetCapabilities.srv"
DEPENDENCIES builtin_interfaces diagnostic_msgs
)

Expand Down
37 changes: 37 additions & 0 deletions src/ros2_medkit_msgs/msg/EntityInfo.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2026 mfaferek93
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# EntityInfo.msg - SOVD entity descriptor for service interface responses.
#
# Provides basic metadata about a SOVD entity (app, component, area, function)
# for consumers that need entity tree information via ROS 2 services.

# Unique entity identifier (e.g., "temp_sensor", "powertrain")
string id

# Human-readable entity name
string name

# Entity type: "app", "component", "area", "function"
string entity_type

# Parent entity ID ("" for top-level entities)
string parent_id

# Fully-qualified ROS 2 name (e.g., "/powertrain/engine/temp_sensor")
string fqn

# SOVD capabilities available for this entity
# (e.g., ["data", "faults", "operations", "configurations"])
string[] capabilities
34 changes: 34 additions & 0 deletions src/ros2_medkit_msgs/srv/GetCapabilities.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2026 mfaferek93
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# GetCapabilities.srv - Query SOVD capabilities for an entity or server.
#
# Returns the list of SOVD resource types available for the specified entity.
# Used by VDA 5050 agent to build factsheet protocolFeatures.

# Request fields

# Entity ID, or "" for server-level capabilities
string entity_id
---
# Response fields

bool success
string error_message

# Available SOVD capabilities (e.g., "data", "faults", "operations", "configurations")
string[] capabilities

# Available resource types (e.g., "apps", "components", "areas", "functions")
string[] resource_types
34 changes: 34 additions & 0 deletions src/ros2_medkit_msgs/srv/GetEntityData.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2026 mfaferek93
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# GetEntityData.srv - Retrieve data values for a SOVD entity.
#
# Returns latest topic data for the specified entity as a JSON string.
# Used by VDA 5050 agent to populate AGV state with sensor data.

# Request fields

# Entity ID to query
string entity_id

# Specific data keys (topic names) to return, [] for all available
string[] data_keys
---
# Response fields

bool success
string error_message

# JSON-encoded data: {"topic_name": {"field": value, ...}, ...}
string data_json
33 changes: 33 additions & 0 deletions src/ros2_medkit_msgs/srv/ListEntities.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright 2026 mfaferek93
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ListEntities.srv - List SOVD entities from the gateway entity tree.
#
# Returns entities matching the requested type and parent filters.
# Used by VDA 5050 agent, BT.CPP, PlotJuggler, and other ROS 2 consumers
# to discover the SOVD entity tree without HTTP.

# Request fields

# Filter by entity type: "app", "component", "area", "function", "" (all)
string entity_type

# Filter by parent entity ID, "" for no filter (returns all entities)
string parent_id
---
# Response fields

bool success
string error_message
EntityInfo[] entities
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Copyright 2026 mfaferek93
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required(VERSION 3.8)
project(ros2_medkit_sovd_service_interface)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic -Wshadow -Wconversion)
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Shared cmake modules (multi-distro compat)
find_package(ros2_medkit_cmake REQUIRED)
include(ROS2MedkitCompat)

find_package(ament_cmake REQUIRED)
find_package(ros2_medkit_gateway REQUIRED)
find_package(ros2_medkit_msgs REQUIRED)
find_package(rclcpp REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(OpenSSL REQUIRED)

# cpp-httplib via multi-distro compatibility macro
medkit_find_cpp_httplib()

# Enable OpenSSL support for cpp-httplib
add_compile_definitions(CPPHTTPLIB_OPENSSL_SUPPORT)

# MODULE target: loaded via dlopen at runtime by PluginManager.
# Symbols from gateway_lib are resolved from the host process at runtime.
add_library(sovd_service_interface MODULE
src/sovd_service_interface.cpp
src/service_exports.cpp
)

target_include_directories(sovd_service_interface PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)

medkit_target_dependencies(sovd_service_interface
ros2_medkit_msgs
ros2_medkit_gateway
rclcpp
)

# Allow unresolved symbols - they resolve from the host process at runtime
target_link_options(sovd_service_interface PRIVATE
-Wl,--unresolved-symbols=ignore-all
)

target_link_libraries(sovd_service_interface
nlohmann_json::nlohmann_json
cpp_httplib_target
OpenSSL::SSL OpenSSL::Crypto
)

install(TARGETS sovd_service_interface
LIBRARY DESTINATION lib/${PROJECT_NAME}
)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# uncrustify/cpplint conflict with project-wide clang-format (120 cols vs 100)
list(APPEND AMENT_LINT_AUTO_EXCLUDE
ament_cmake_uncrustify
ament_cmake_cpplint
ament_cmake_clang_format
)
ament_lint_auto_find_test_dependencies()

find_package(ament_cmake_clang_format REQUIRED)
file(GLOB_RECURSE _format_files
"src/*.hpp" "src/*.cpp" "test/*.cpp"
)
ament_clang_format(${_format_files}
CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../../../.clang-format")

find_package(ament_cmake_gtest REQUIRED)

include(ROS2MedkitTestDomain)
medkit_init_test_domains(START 1 END 9)

ament_add_gtest(test_sovd_service_interface
test/test_sovd_service_interface.cpp
src/sovd_service_interface.cpp
)
target_include_directories(test_sovd_service_interface PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)
medkit_target_dependencies(test_sovd_service_interface
ros2_medkit_gateway
rclcpp
ros2_medkit_msgs
)
target_link_libraries(test_sovd_service_interface
nlohmann_json::nlohmann_json
cpp_httplib_target
OpenSSL::SSL OpenSSL::Crypto
)
medkit_set_test_domain(test_sovd_service_interface)
endif()

ament_package()
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ros2_medkit_sovd_service_interface

Gateway plugin exposing medkit entity data via ROS 2 services. Enables ROS 2 nodes (e.g. VDA 5050 agent, BT.CPP, PlotJuggler) to access SOVD diagnostics without HTTP.

## Services

| Service | Type | Description |
|---------|------|-------------|
| `/medkit/list_entities` | `ros2_medkit_msgs/srv/ListEntities` | List all discovered entities (apps, components, areas) |
| `/medkit/list_entity_faults` | `ros2_medkit_msgs/srv/ListFaultsForEntity` | Get faults for a specific entity |
| `/medkit/get_entity_data` | `ros2_medkit_msgs/srv/GetEntityData` | Get entity topic data (not yet implemented) |
| `/medkit/get_capabilities` | `ros2_medkit_msgs/srv/GetCapabilities` | Get SOVD capabilities for an entity |

Service prefix is configurable via `plugins.sovd_service_interface.service_prefix` parameter (default: `/medkit`).

## Usage

Load as a gateway plugin:

```bash
ros2 run ros2_medkit_gateway gateway_node --ros-args \
-p "plugins:=[\"sovd_service_interface\"]" \
-p "plugins.sovd_service_interface.path:=/path/to/libsovd_service_interface.so" \
-p "plugins.sovd_service_interface.service_prefix:=/medkit"
```

## Tests

```bash
colcon test --packages-select ros2_medkit_sovd_service_interface
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>ros2_medkit_sovd_service_interface</name>
<version>0.4.0</version>
<description>SOVD Service Interface plugin - exposes medkit entity tree and fault data via ROS 2 services</description>
<maintainer email="bartoszburda93@gmail.com">bburda</maintainer>
<maintainer email="mfaferek93@gmail.com">mfaferek93</maintainer>
<license>Apache-2.0</license>

<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>ros2_medkit_cmake</buildtool_depend>

<depend>rclcpp</depend>
<depend>ros2_medkit_msgs</depend>
<depend>ros2_medkit_gateway</depend>
<depend>nlohmann-json-dev</depend>
<depend>libcpp-httplib-dev</depend>
<depend>libssl-dev</depend>

<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>ament_cmake_clang_format</test_depend>
<test_depend>ament_cmake_gtest</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2026 mfaferek93
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "ros2_medkit_gateway/plugins/plugin_types.hpp"
#include "sovd_service_interface.hpp"

using namespace ros2_medkit_gateway;

extern "C" GATEWAY_PLUGIN_EXPORT int plugin_api_version() {
return PLUGIN_API_VERSION; // Must return 4 (exact match required)
}

extern "C" GATEWAY_PLUGIN_EXPORT GatewayPlugin * create_plugin() {
return new SovdServiceInterface();
}
Loading
Loading