Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_gateway at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-11 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- bburda
Authors
ros2_medkit_gateway
HTTP gateway node for the ros2_medkit diagnostics system.
Overview
The ROS 2 Medkit Gateway exposes ROS 2 system information and data through a RESTful HTTP API. It automatically discovers nodes in the ROS 2 system, organizes them into a SOVD-aligned entity hierarchy (Areas, Components, Apps, Functions), and provides endpoints to query and interact with them.
Key Features:
- Auto-discovery: Automatically detects ROS 2 nodes and topics
- SOVD entity model: Areas, Components (host-level), Apps (ROS 2 nodes), and Functions (namespace-based logical grouping)
- REST API: Standard HTTP/JSON interface
- Real-time updates: Configurable cache refresh for up-to-date system state
- Bulk Data Management: Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
- Resource Locking: SOVD-compliant entity locking with scoped access control, lock breaking, and automatic expiry
Endpoints
All endpoints are prefixed with /api/v1 for API versioning.
Discovery Endpoints
-
GET /api/v1/health- Health check endpoint (returns healthy status) -
GET /api/v1/- Gateway status and version information -
GET /api/v1/version-info- SOVD version info (supported SOVD versions and base URIs) -
GET /api/v1/areas- List all discovered areas (powertrain, chassis, body, root) -
GET /api/v1/areas/{area_id}- Get area capabilities -
GET /api/v1/areas/{area_id}/subareas- List sub-areas within an area -
GET /api/v1/areas/{area_id}/contains- List components contained in an area -
GET /api/v1/components- List all discovered components across all areas -
GET /api/v1/components/{component_id}- Get component capabilities -
GET /api/v1/components/{component_id}/subcomponents- List sub-components -
GET /api/v1/components/{component_id}/hosts- List apps hosted on a component -
GET /api/v1/components/{component_id}/depends-on- List component dependencies -
GET /api/v1/areas/{area_id}/components- List components within a specific area -
GET /api/v1/apps- List all discovered apps -
GET /api/v1/apps/{app_id}- Get app capabilities -
GET /api/v1/apps/{app_id}/is-located-on- Get the component hosting this app -
GET /api/v1/functions- List all discovered functions -
GET /api/v1/functions/{function_id}- Get function capabilities -
GET /api/v1/functions/{function_id}/hosts- List apps grouped by this function
Component Data Endpoints
-
GET /api/v1/components/{component_id}/data- Read all topic data from a component -
GET /api/v1/components/{component_id}/data/{topic_name}- Read specific topic data from a component -
PUT /api/v1/components/{component_id}/data/{topic_name}- Publish data to a topic
Operations Endpoints (Services & Actions)
-
GET /api/v1/components/{component_id}/operations- List all services and actions for a component -
GET /api/v1/components/{component_id}/operations/{operation_id}- Get operation details -
POST /api/v1/components/{component_id}/operations/{operation_id}/executions- Execute operation (call service or send action goal) -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions- List all executions for an operation -
GET /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Get execution status -
DELETE /api/v1/components/{component_id}/operations/{operation_id}/executions/{execution_id}- Cancel action execution
Configurations Endpoints (ROS 2 Parameters)
-
GET /api/v1/components/{component_id}/configurations- List all parameters for a component -
GET /api/v1/components/{component_id}/configurations/{param}- Get parameter value -
PUT /api/v1/components/{component_id}/configurations/{param}- Set parameter value -
DELETE /api/v1/components/{component_id}/configurations/{param}- Reset parameter to default value -
DELETE /api/v1/components/{component_id}/configurations- Reset all parameters to default values
Bulk Data Endpoints
-
GET /api/v1/{entity}/{id}/bulk-data- List bulk-data categories (rosbags + configured) -
GET /api/v1/{entity}/{id}/bulk-data/{category}- List bulk-data items in a category -
GET /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Download a bulk-data file -
POST /api/v1/{entity}/{id}/bulk-data/{category}- Upload bulk data (components/apps only) -
DELETE /api/v1/{entity}/{id}/bulk-data/{category}/{item_id}- Delete bulk data (components/apps only)
Logging Endpoints
-
GET /api/v1/components/{component_id}/logs- Query recent log entries for a component (all its nodes, prefix match) -
GET /api/v1/apps/{app_id}/logs- Query recent log entries for a specific app node (exact match) -
GET /api/v1/components/{component_id}/logs/configuration- Get log configuration for a component -
GET /api/v1/apps/{app_id}/logs/configuration- Get log configuration for an app -
PUT /api/v1/components/{component_id}/logs/configuration- Update log configuration for a component -
PUT /api/v1/apps/{app_id}/logs/configuration- Update log configuration for an app
Locking Endpoints
-
POST /api/v1/{components|apps}/{id}/locks- Acquire a lock on an entity -
GET /api/v1/{components|apps}/{id}/locks- List active locks on an entity -
GET /api/v1/{components|apps}/{id}/locks/{lock_id}- Get lock details -
PUT /api/v1/{components|apps}/{id}/locks/{lock_id}- Extend lock expiration -
DELETE /api/v1/{components|apps}/{id}/locks/{lock_id}- Release a lock
Trigger Endpoints
-
POST /api/v1/{entity}/{id}/triggers- Create a trigger with conditions -
GET /api/v1/{entity}/{id}/triggers- List active triggers -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}- Get trigger details -
PUT /api/v1/{entity}/{id}/triggers/{trigger_id}- Update trigger conditions -
DELETE /api/v1/{entity}/{id}/triggers/{trigger_id}- Delete a trigger -
GET /api/v1/{entity}/{id}/triggers/{trigger_id}/events- SSE stream of trigger events
Scripts Endpoints
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.5.0 (2026-06-08)
Breaking Changes:
- Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403) - Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403) -
SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403) - Synchronous operation-execution service-call failures
(
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403) -
GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider's free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin'svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403) - Entity responses (areas, components, apps, functions - list items
and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403) -
ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395) - Per-entity fault routes are now correctly scoped to the entity's
hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},
File truncated at 100 lines see the full file