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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,23 @@ For more examples, see our [Postman collection](postman/).

## ✨ Features

- **🔍 Runtime Discovery** — Automatically discover what is actually running on your robot
- **🏗️ Entity Tree Model** — Organize diagnostics as Area → Component → Function → App
- **🔗 SOVD Compatible** — Align with Service-Oriented Vehicle Diagnostics standards
- **🌐 REST API Gateway** — HTTP interface for integration with external tools and UIs
- **📊 Health Modeling** — Track health state per entity for fleet-level observability
- **🔧 Easy Integration** — Works with existing ROS 2 nodes out of the box (Jazzy, Humble & Rolling)
- **📦 Bulk Data Management** — Upload, download, list, and delete bulk data files (calibration, firmware, etc.)
| Feature | Status | Description |
|---------|--------|-------------|
| 🔍 Discovery | **Available** | Automatically discover running nodes, topics, services, and actions |
| 📊 Data | **Available** | Read and write topic data via REST |
| ⚙️ Operations | **Available** | Call services and actions with execution tracking |
| 🔧 Configurations | **Available** | Read, write, and reset node parameters |
| 🚨 Faults | **Available** | Query, inspect, and clear faults with environment data and snapshots |
| 📦 Bulk Data | **Available** | Upload, download, and manage files (calibration, firmware, rosbags) |
| 📡 Subscriptions | **Available** | Stream live data and fault events via SSE |
| 🔄 Software Updates | **Available** | Async prepare/execute lifecycle with pluggable backends |
| 🔒 Authentication | **Available** | JWT-based RBAC (viewer, operator, configurator, admin) |
| 📋 Logs | Planned | Log sources, entries, and configuration |
| 🔁 Entity Lifecycle | Planned | Start, restart, shutdown control |
| 🔐 Modes & Locking | Planned | Target mode control and resource locking |
| 📝 Scripts | Planned | Diagnostic script upload and execution |
| 🧹 Clear Data | Planned | Clear cached and learned diagnostic data |
| 📞 Communication Logs | Planned | Protocol-level communication logging |

## 📖 Overview

Expand Down
140 changes: 140 additions & 0 deletions docs/api/rest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,145 @@ fault manager and cannot be deleted via this endpoint.
- **404 Not Found**: Entity, category, or bulk-data ID not found
- **405 Method Not Allowed**: Delete attempted on areas or functions

Software Updates
----------------

Manage software update packages with an async prepare/execute lifecycle.
The updates feature requires a backend plugin to be loaded (see :doc:`/config/server`).
Without a plugin, all endpoints return ``501 Not Implemented``.

``GET /api/v1/updates``
List all registered update packages.

**Query Parameters:**

- ``origin`` (optional): Filter by origin (``remote`` or ``proximity``)
- ``target-version`` (optional): Filter by target version

**Example Response (200 OK):**

.. code-block:: json

{
"items": ["firmware-v2.1", "calibration-update-3"]
}

``POST /api/v1/updates``
Register a new update package.

**Request Body:**

.. code-block:: json

{
"id": "firmware-v2.1",
"update_name": "Firmware Update v2.1",
"automated": true,
"origins": ["remote"],
"duration": 600,
"size": 52428800,
"updated_components": ["ecu_main"],
"affected_components": ["ecu_main", "ecu_secondary"]
}

**Response (201 Created):**

.. code-block:: json

{
"id": "firmware-v2.1"
}

**Response Headers:**

- ``Location``: ``/api/v1/updates/firmware-v2.1``

``GET /api/v1/updates/{id}``
Get full metadata for a specific update package.

**Response (200 OK):**

Returns the JSON metadata as registered.

- **404 Not Found:** Package does not exist

``DELETE /api/v1/updates/{id}``
Delete an update package.

- **204 No Content:** Package deleted
- **404 Not Found:** Package does not exist
- **409 Conflict:** Operation in progress for this package

``PUT /api/v1/updates/{id}/prepare``
Trigger preparation of an update (download, verify, check dependencies).
Runs asynchronously - poll the status endpoint for progress.

- **202 Accepted:** Preparation started
- **404 Not Found:** Package does not exist
- **409 Conflict:** Operation already in progress

**Response Headers:**

- ``Location``: ``/api/v1/updates/{id}/status``

``PUT /api/v1/updates/{id}/execute``
Trigger execution of a prepared update (install). Only succeeds after
prepare has completed.

- **202 Accepted:** Execution started
- **400 Bad Request:** Package not prepared
- **404 Not Found:** Package does not exist
- **409 Conflict:** Operation already in progress

**Response Headers:**

- ``Location``: ``/api/v1/updates/{id}/status``

``PUT /api/v1/updates/{id}/automated``
Trigger automated update (prepare + execute in one step). Only works
for packages that support automated mode.

- **202 Accepted:** Automated update started
- **400 Bad Request:** Package does not support automated mode
- **404 Not Found:** Package does not exist
- **409 Conflict:** Operation already in progress

**Response Headers:**

- ``Location``: ``/api/v1/updates/{id}/status``

``GET /api/v1/updates/{id}/status``
Get the current status and progress of an update operation.

**Example Response (200 OK):**

.. code-block:: json

{
"status": "inProgress",
"progress": 65,
"sub_progress": [
{"name": "download", "progress": 100},
{"name": "verify", "progress": 30}
]
}

**Status values:** ``pending``, ``inProgress``, ``completed``, ``failed``

When ``status`` is ``failed``, an ``error`` object is included:

.. code-block:: json

{
"status": "failed",
"error": {
"error_code": "internal-error",
"message": "Download failed: connection timeout"
}
}

- **404 Not Found:** No status available (package not found or no operation started)

Cyclic Subscriptions
--------------------

Expand Down Expand Up @@ -940,6 +1079,7 @@ The gateway implements a subset of the SOVD (Service-Oriented Vehicle Diagnostic
- Configurations (``/configurations``)
- Faults (``/faults``) with ``environment_data`` and SOVD status object
- Bulk Data (``/bulk-data``) for binary data downloads (rosbags, logs)
- Software Updates (``/updates``) with async prepare/execute lifecycle
- Cyclic Subscriptions (``/cyclic-subscriptions``) with SSE-based periodic data delivery

**ros2_medkit Extensions:**
Expand Down
8 changes: 7 additions & 1 deletion docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0
Added
~~~~~

* Software update management with pluggable backend architecture:

- 8 SOVD-compliant ``/updates`` endpoints (CRUD + prepare/execute/automated/status)
- Plugin system via dlopen for runtime backend loading
- Async lifecycle with progress tracking and status polling
- Feature gating via ``updates.enabled`` parameter

* SOVD bulk-data endpoints for all entity types:

- ``GET /{entity}/bulk-data`` - list available bulk-data categories
Expand Down Expand Up @@ -151,7 +158,6 @@ specification adapted for ROS 2:

Not yet implemented:

- Software updates
- Locks
- Triggers
- Communication logs
4 changes: 4 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,8 @@
linkcheck_ignore = [
r"http://localhost:\d+", # Ignore localhost URLs
r"http://127\.0\.0\.1:\d+",
# Auto-generated line-number links in verification.rst; skipped to
# avoid 395+ GitHub requests (rate-limiting) and anchor mismatches
# on branches where files differ from main.
r"https://github\.com/selfpatch/ros2_medkit/blob/.+#L\d+",
]
37 changes: 37 additions & 0 deletions docs/config/server.rst
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,43 @@ Example:
max_clients: 10
max_subscriptions: 100

Software Updates
----------------

Configure the software updates plugin system. Updates are disabled by default.

.. list-table::
:header-rows: 1
:widths: 25 15 15 45

* - Parameter
- Type
- Default
- Description
* - ``updates.enabled``
- bool
- ``false``
- Enable/disable software updates endpoints. When disabled, ``/updates`` routes are not registered.
* - ``updates.backend``
- string
- ``"none"``
- Backend type. ``"none"`` enables endpoints but returns 501. ``"plugin"`` loads a shared library.
* - ``updates.plugin_path``
- string
- ``""``
- Path to the ``.so`` plugin file. Required when ``backend`` is ``"plugin"``.

Example:

.. code-block:: yaml

ros2_medkit_gateway:
ros__parameters:
updates:
enabled: true
backend: "plugin"
plugin_path: "/opt/ros2_medkit/plugins/libmy_update_backend.so"

Complete Example
----------------

Expand Down
35 changes: 31 additions & 4 deletions docs/requirements/specs/updates.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,56 @@ Updates

.. req:: GET /updates
:id: REQ_INTEROP_082
:status: open
:status: verified
:tags: Updates

The endpoint shall list software update packages known to the SOVD server.

.. req:: POST /updates
:id: REQ_INTEROP_083
:status: open
:status: verified
:tags: Updates

The endpoint shall register a new software update package at the SOVD server using the provided parameters.

.. req:: DELETE /updates/{id}
:id: REQ_INTEROP_084
:status: open
:status: verified
:tags: Updates

The endpoint shall delete the addressed software update package from the SOVD server, if permitted (e.g. if no update is currently in execution).

.. req:: GET /updates/{id}
:id: REQ_INTEROP_085
:status: open
:status: verified
:tags: Updates

The endpoint shall return the details of the addressed software update package.

.. req:: PUT /updates/{id}/prepare
:id: REQ_INTEROP_091
:status: verified
:tags: Updates

The endpoint shall trigger preparation of the addressed software update package (download, integrity check, dependency validation) and return 202 Accepted with a Location header pointing to the status resource.

.. req:: PUT /updates/{id}/execute
:id: REQ_INTEROP_092
:status: verified
:tags: Updates

The endpoint shall begin the actual installation of a previously prepared software update package and return 202 Accepted with a Location header pointing to the status resource.

.. req:: PUT /updates/{id}/automated
:id: REQ_INTEROP_093
:status: verified
:tags: Updates

The endpoint shall trigger a fully automated update (prepare + execute) for packages where automated mode is supported and return 202 Accepted with a Location header pointing to the status resource.

.. req:: GET /updates/{id}/status
:id: REQ_INTEROP_094
:status: verified
:tags: Updates

The endpoint shall return the current progress and status of an update operation, including status value, progress percentage, and optional sub-progress details.
2 changes: 1 addition & 1 deletion docs/roadmap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ software updates, and authentication — completing the standard specification c
- Bulk Data (5 endpoints) — large data transfers
- Communication Logs (5 endpoints) — protocol-level logging
- Clear Data (5 endpoints) — cache and learned data management
- Updates (4 endpoints) — software update management
- Updates (8 endpoints) — software update management
- Auth (2 endpoints) — authorization and token management

`MS5 on GitHub <https://github.com/selfpatch/ros2_medkit/milestone/5>`_
Expand Down
Loading