Package Summary
| Version | 0.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
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.7.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-09-01 |
| 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
-
Incremental entity cache: Discovery refresh diffs add/remove/change and performs zero structural allocations in the cache layer at steady state (object-pool backed, fixed capacity reserved at init via
entity_cache.capacity) - 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 (empty for a service, which leaves no execution resource) -
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
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_gateway
0.7.0 (2026-08-27)
- Rosbag bulk-data is addressed by recording id instead of fault code,
so a fault holding several recordings can expose each one.
GET /{entity}/bulk-data/rosbagsnow emits one descriptor per recording rather than one per fault - a burst that shares a bag used to appear as several entries each reporting the full bag size - and the covered faults move intox-medkit.fault_codes(was the scalarx-medkit.fault_code). Old URLs keep working: an id that is not a recording is resolved as a fault code and serves that fault's newest recording, which is what it returned before. Authorization is unchanged in effect - a download is allowed when any fault the recording covers is in the entity's source scope, which is exactly the set that could reach it previously (#623, #620) - Manual asset inventory: a manifest
assets:list and a newdiscovery.inventory.csv_pathparameter declare assets that no protocol layer can describe (or fully describe). Both paths recognize the canonical namesid, manufacturer, model, serial, hardware_rev, firmware, endpoint, role, areaplus the shared aliases (serial_number,hardware_revision/hw_rev,firmware_version/fw) and keep any other column / key as an extra; RFC-4180-style quoting is honored. Each asset becomes a Component withsource = "inventory"and a structured asset identity carrying per-field provenance, appended to the base manifest on every load / reload and merged into the tree by id alongside protocol-discovered structure;areaplaces the asset under an Area, without it the asset appears only in the flat component list. CSV rows never fail the load: rows without anidare skipped with a warning, for duplicate ids the first row wins, a row whose id is already a manifest component keeps the manifest definition (the row's identity is folded in as gap-fill), and an unknownareais dropped with a warning. The CSV is size-capped at 1 MiB before being read; a missing file is skipped with a warning (mirrorsfragments_dir), while an unreadable or malformed one fails the load / reload. Requires a manifest-backed discovery mode (manifest_only/hybridwithdiscovery.manifest_pathset); empty = disabled (default) (#493, #490) -
Breaking: the lifecycle status
operationIdvalues were singularized -getAppStatusandputAppStatusRestartrather than the plural collection forms they were built from before - so a generated client gets renamed methods for those operations (#497) - Aggregation now separates the time budget for reading metadata from
the budget for real work. One
aggregation.timeout_mswas applied as both the connect and the read timeout for every call, so a synchronous service call on a peer got two seconds end to end while the peer's own budget for the same call was ten; a large resource fanned out to a peer could not finish inside it either. The write timeout, which was never set and stayed at the cpp-httplib default, now follows the configured budget, and the timeout values are validated and reported rather than silently clamped (#638, #528) - A request that ran out of time is reported as a timeout. A peer that
did not answer in the budget returns
504withERR_NOT_RESPONDINGinstead of502claiming the peer is unavailable - which it did while that peer was answering the same request - a fanned-out collection carries the per-peer failure reason instead of only a boolean, and an operation that exceeds its own service-call budget says so rather than returning a generic failure (#638, #612) -
GET /faults/streamon an aggregating gateway relays its peers' fault events. It previously returned200with an open stream that only ever sent keepalive comments, which is indistinguishable from a healthy system - and on a deployment where the aggregator is the only reachable port, it was the only fault stream available (#638, #611) - One addressing model for an aggregating entity's resources, so the aggregator no longer refuses or 404s work its peers can serve (#626, #613)
- Nested
plugins.<name>.*parameters are rebuilt into a nested object instead of a flat dotted key, so nested plugin configuration reaches the plugin again (#518, #520) - Discovery configuration is read from the documented top-level
config:key. It was only ever read fromdiscovery.config, so the documented form was dropped without a word and unmanifested nodes leaked into the tree in hybrid mode (#609, #529) - Every startup parameter that is coerced or refused is reported. A
clamped thread count or keep-alive timeout used to change the value
and log nothing, leaving the configuration file and the running
process in silent disagreement. Integer parameters are read as the
int64 a ROS parameter holds and validated before narrowing, so a
value past
INT_MAXcan no longer wrap back into the legal band and pass its own range check, and range checks are written so that NaN is refused rather than accepted (#607, #603)
File truncated at 100 lines see the full file