FIWARE / NGSI-LD and DDS Mapping Reference
==========================================
This page is the standalone interface reference for ROBIN's FIWARE,
NGSI-LD, and DDS integration. It documents the current data model,
the DDS Enabler configuration, validation commands, and known mapping
limitations so users do not need to infer the interface from source code.
Runtime Components
------------------
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - Component
- Local endpoint or file
- Role
* - Orion-LD
- ``http://localhost:1026``
- NGSI-LD context broker and DDS ingestion endpoint.
* - MongoDB
- ``localhost:27017``
- Orion-LD document persistence.
* - TimescaleDB / TROE
- ``localhost:5433``
- Temporal attribute store used by Orion-LD.
* - Mintaka
- ``http://localhost:9090``
- Temporal query API over TROE history.
* - Process Intelligence API
- ``http://localhost:8001``
- FastAPI layer for process lifecycle, measurements, deviation checks,
alerts, recommendations, and dashboard-facing reads.
* - ROBIN Dashboard
- ``http://localhost:5174``
- Browser UI for live monitoring, alerts, model controls, and history CSV
export.
* - DDS Enabler configuration
- ``config-dds.json``
- Orion-LD DDS mapping configuration mounted by ``docker-compose.yaml``.
Default local Compose configuration does not set ``NGSILD_TENANT`` for the API
or DDS path. If a deployment enables tenants, use the same ``NGSILD-Tenant``
header consistently for Orion-LD, Mintaka, and API-side requests.
End-to-End Data Flow
--------------------
.. mermaid::
graph LR
SRC["ROS 2 robot / sensor topics"]
AGG["telemetry_aggregator_node"]
DDS["/robin/telemetry
ProcessTelemetry"]
ORION["Orion-LD
DDS Enabler"]
PROCESS["urn:ngsi-ld:Process:ros_bridge
urn:robin:processTelemetry"]
TSDB[("TimescaleDB / TROE")]
MINTAKA["Mintaka temporal API"]
API["Process Intelligence API"]
UI["ROBIN Dashboard"]
SRC --> AGG
AGG --> DDS
DDS --> ORION
ORION --> PROCESS
PROCESS --> TSDB
TSDB --> MINTAKA
MINTAKA --> API
ORION --> API
API --> UI
The primary DDS path is:
``ROS 2 topic -> DDS Enabler -> Orion-LD -> Mintaka/history -> API/dashboard``.
The API/demo path can also write directly to Orion-LD through REST. That path
creates ``Measurement`` entities and patches scalar measurement attributes onto
the related ``Process`` entity so TROE/Mintaka can store history.
Entity Model Summary
--------------------
.. mermaid::
erDiagram
PROCESS ||--o{ MEASUREMENT : "processId"
PROCESS ||--o| GEOMETRY_TARGET : "processId"
PROCESS ||--o{ ALERT : "processId"
PROCESS ||--o{ AI_RECOMMENDATION : "processId"
PROCESS {
string id
string type
string processStatus
string operationMode
object inputParams
object pendingIntent
object processTelemetry
}
MEASUREMENT {
string id
string type
relationship processId
number measuredHeight
number measuredWidth
number measuredSpeed
number measuredCurrent
number measuredVoltage
}
GEOMETRY_TARGET {
string id
string type
relationship processId
number targetHeight
number targetWidth
}
ALERT {
string id
string type
relationship processId
string deviationType
object expectedValue
object measuredValue
number deviationPercentage
}
AI_RECOMMENDATION {
string id
string type
relationship processId
object recommendedParams
number confidence
string modelVersion
}
.. list-table::
:header-rows: 1
:widths: 18 28 27 27
* - Entity
- Entity ID pattern
- Main properties / relationships
- Producer and consumer
* - ``Process``
- ``urn:ngsi-ld:Process:PROCESS_ID``
- ``processStatus``, ``operationMode``, ``startedAt``,
``stoppedAt``, ``stopReason``, ``inputParams``,
``pendingIntent``, ``simulationProgress``, ``processTelemetry`` or
``urn:robin:processTelemetry``, scalar measured attributes.
- Created by API/CLI. Read by API, dashboard, Orion-LD, Mintaka, and
ROS/FIWARE intent bridge paths.
* - ``Measurement``
- ``urn:ngsi-ld:Measurement:MEASUREMENT_ID``
- ``processId`` relationship, ``measuredHeight``, ``measuredWidth``,
``measuredSpeed``, ``measuredCurrent``, ``measuredVoltage``,
``inputParams``. Measurement properties carry ``observedAt``.
- Created by API/CLI demo path. Used as Orion fallback when Mintaka
history is not available.
* - ``GeometryTarget``
- ``urn:ngsi-ld:GeometryTarget:PROCESS_ID``
- ``processId`` relationship, ``targetHeight``, ``targetWidth``.
- Created or patched by ``POST /process/{process_id}/target`` and used
by geometry-driven deviation checks.
* - ``Alert``
- ``urn:ngsi-ld:Alert:PROCESS_ID-TIMESTAMP``
- ``processId`` relationship, ``deviationType``, ``expectedValue``,
``measuredValue``, ``deviationPercentage``, ``recommendedActions``,
``timestamp``.
- Created by deviation checks. Read by ``GET /process/{id}/alerts`` and
the dashboard History / Reports export.
* - ``AIRecommendation``
- ``urn:ngsi-ld:AIRecommendation:PROCESS_ID-TIMESTAMP``
- ``processId`` relationship, ``recommendedParams``, ``confidence``,
``modelVersion``, ``timestamp``.
- Created by ``POST /ai-recommendation`` and stored as advisory evidence.
Type URNs used by the current implementation:
.. code-block:: text
urn:robin:Process
urn:robin:Measurement
urn:robin:GeometryTarget
urn:robin:Alert
urn:robin:AIRecommendation
Implementation evidence:
* API endpoints and response shaping: ``robin/alert_engine.py``.
* FIWARE client and entity creation helpers: ``robin/cli.py``.
* Dashboard API types and fetch helpers:
``robin-dashboard/src/hooks/useRobinAPI.ts``.
* CSV export implementation:
``robin-dashboard/src/components/features/history/HistoryTab.tsx``.
Example NGSI-LD Payloads
------------------------
Process entity:
.. code-block:: json
{
"id": "urn:ngsi-ld:Process:reviewer_demo_process",
"type": "urn:robin:Process",
"processStatus": {
"type": "Property",
"value": "active"
},
"operationMode": {
"type": "Property",
"value": "parameter_driven"
},
"inputParams": {
"type": "Property",
"value": {
"wire_feed_speed_mpm_model_input": 10.5,
"travel_speed_mps_model_input": 0.021,
"arc_length_correction_mm_model_input": 1.5
}
}
}
Measurement entity, created by the API/CLI demo path:
.. code-block:: json
{
"id": "urn:ngsi-ld:Measurement:reviewer_demo_process-001",
"type": "urn:robin:Measurement",
"processId": {
"type": "Relationship",
"object": "urn:ngsi-ld:Process:reviewer_demo_process"
},
"measuredHeight": {
"type": "Property",
"value": 2.95,
"unitCode": "MMT",
"observedAt": "2026-06-16T12:01:05+00:00"
},
"measuredWidth": {
"type": "Property",
"value": 7.48,
"unitCode": "MMT",
"observedAt": "2026-06-16T12:01:05+00:00"
},
"measuredCurrent": {
"type": "Property",
"value": 234.9,
"unitCode": "A",
"observedAt": "2026-06-16T12:01:05+00:00"
},
"measuredVoltage": {
"type": "Property",
"value": 26.7,
"unitCode": "V",
"observedAt": "2026-06-16T12:01:05+00:00"
}
}
Geometry target entity:
.. code-block:: json
{
"id": "urn:ngsi-ld:GeometryTarget:reviewer_demo_process",
"type": "urn:robin:GeometryTarget",
"processId": {
"type": "Relationship",
"object": "urn:ngsi-ld:Process:reviewer_demo_process"
},
"targetHeight": {
"type": "Property",
"value": 3.2,
"unitCode": "MMT"
},
"targetWidth": {
"type": "Property",
"value": 7.0,
"unitCode": "MMT"
}
}
Alert entity:
.. code-block:: json
{
"id": "urn:ngsi-ld:Alert:reviewer_demo_process-1781611265000",
"type": "urn:robin:Alert",
"processId": {
"type": "Relationship",
"object": "urn:ngsi-ld:Process:reviewer_demo_process"
},
"deviationType": {
"type": "Property",
"value": "geometry"
},
"expectedValue": {
"type": "Property",
"value": {
"height": 3.2,
"width": 7.0
}
},
"measuredValue": {
"type": "Property",
"value": {
"height": 2.95,
"width": 7.48
}
},
"deviationPercentage": {
"type": "Property",
"value": 7.8125,
"unitCode": "P1"
}
}
AI recommendation entity:
.. code-block:: json
{
"id": "urn:ngsi-ld:AIRecommendation:reviewer_demo_process-1781611265",
"type": "urn:robin:AIRecommendation",
"processId": {
"type": "Relationship",
"object": "urn:ngsi-ld:Process:reviewer_demo_process"
},
"recommendedParams": {
"type": "Property",
"value": {
"wire_feed_speed_mpm_model_input": 10.8,
"travel_speed_mps_model_input": 0.019,
"arc_length_correction_mm_model_input": 1.1,
"confidence": 0.88
}
},
"confidence": {
"type": "Property",
"value": 0.88
},
"modelVersion": {
"type": "Property",
"value": "v2.1"
}
}
DDS Enabler Configuration
-------------------------
The DDS Enabler mapping is defined in ``config-dds.json`` and mounted into
the Orion-LD container by ``docker-compose.yaml``:
.. code-block:: yaml
volumes:
- ./config-dds.json:/root/.orionld
command: -dbhost 127.0.0.1 -logLevel DEBUG -troe -wip dds
Relevant ``config-dds.json`` excerpt:
.. code-block:: json
{
"dds": {
"ddsmodule": {
"dds": {
"domain": 0,
"allowlist": [
{
"name": "rt/robin/telemetry"
}
]
},
"topics": {
"name": "*",
"qos": {
"durability": "VOLATILE",
"reliability": "BEST_EFFORT",
"history-depth": 5000
}
}
},
"ngsild": {
"topics": {
"rt/robin/telemetry": {
"entityType": "urn:robin:Process",
"entityId": "urn:ngsi-ld:Process:ros_bridge",
"attribute": "urn:robin:processTelemetry"
}
}
}
}
}
Field meaning:
.. list-table::
:header-rows: 1
:widths: 28 72
* - Field
- Meaning
* - ``dds.ddsmodule.dds.domain``
- DDS domain used by Orion-LD. Must match the ROS 2 publisher domain.
The Compose baseline uses ``ROS_DOMAIN_ID=0``.
* - ``allowlist``
- Limits Orion-LD DDS discovery to ``rt/robin/telemetry``.
* - ``topics.qos``
- DDS QoS used by the Orion-LD DDS module. Current baseline is
``VOLATILE`` and ``BEST_EFFORT`` with history depth ``5000``.
* - ``ngsild.topics.rt/robin/telemetry.entityType``
- NGSI-LD entity type created or updated by the DDS topic.
* - ``ngsild.topics.rt/robin/telemetry.entityId``
- Fixed NGSI-LD entity receiving DDS telemetry in the current baseline.
* - ``ngsild.topics.rt/robin/telemetry.attribute``
- Compound NGSI-LD attribute that stores the ``ProcessTelemetry`` fields.
ROS 2 Message to NGSI-LD Attribute Mapping
------------------------------------------
The DDS publisher uses
``vulcanexus_ws/src/robin_interfaces/msg/ProcessTelemetry.msg``:
.. list-table::
:header-rows: 1
:widths: 25 25 50
* - ROS 2 field
- NGSI-LD location
- Notes
* - ``current``
- ``urn:robin:processTelemetry.value.current``
- Welding current in ampere for the reference profile.
* - ``voltage``
- ``urn:robin:processTelemetry.value.voltage``
- Arc voltage for the reference profile.
* - ``speed``
- ``urn:robin:processTelemetry.value.speed``
- Wire feed speed in the reference profile.
* - ``width``
- ``urn:robin:processTelemetry.value.width``
- Measured bead or process width.
* - ``height``
- ``urn:robin:processTelemetry.value.height``
- Measured bead height or coating thickness equivalent.
* - ``cross_sectional_area``
- ``urn:robin:processTelemetry.value.cross_sectional_area``
- Preserved in DDS payload when present. Not all dashboard views use it.
API Endpoints and Expected Responses
------------------------------------
The API is served on host port ``8001`` in the local Compose stack.
Representative response fixtures are kept in ``media/api-responses/``.
.. list-table::
:header-rows: 1
:widths: 32 43 25
* - Purpose
- Command
- Expected response marker
* - Health check
- ``curl http://localhost:8001/health``
- ``"status": "healthy"``
* - Create process
- ``curl -X POST http://localhost:8001/create-process -H "Content-Type: application/json" -d @media/api-responses/create-process-request.json``
- ``"status": "success"``
* - Set geometry target
- ``curl -X POST http://localhost:8001/process/reviewer_demo_process/target -H "Content-Type: application/json" -d "{\"height\":3.2,\"width\":7.0}"``
- ``"mode_set": "geometry_driven"``
* - Read measurements
- ``curl "http://localhost:8001/process/reviewer_demo_process/measurements?last=5"``
- ``"debug_info": {"source": "mintaka"}`` when Mintaka has data.
* - Read alerts
- ``curl "http://localhost:8001/process/reviewer_demo_process/alerts"``
- ``"status": "success"``
* - Check deviation
- ``curl -X POST http://localhost:8001/check-deviation -H "Content-Type: application/json" -d @media/api-responses/check-deviation-request.json``
- ``"deviation_percentage"`` and ``"recommended_actions"``.
* - Request AI recommendation
- ``curl -X POST http://localhost:8001/ai-recommendation -H "Content-Type: application/json" -d @media/api-responses/ai-recommendation-request.json``
- ``"status": "success"``, ``"recommendation"``.
The response examples in ``media/api-responses/`` are illustrative evidence.
The quickstart can refresh or confirm them from a clean-clone run.
History and CSV Export
----------------------
History is API-backed:
* ``GET /process/{process_id}/measurements`` reads Mintaka first, then falls
back to Orion ``Measurement`` entities, then TROE SQL fallback.
* ``GET /process/{process_id}/alerts`` reads persisted ``Alert`` entities from
Orion-LD.
* The dashboard History / Reports tab combines those two responses into a CSV.
CSV export implementation:
``robin-dashboard/src/components/features/history/HistoryTab.tsx``.
Representative CSV evidence:
``media/exports/reviewer_demo_process-history-2026-06-16T12-02-00-000Z.csv``.
CSV rows use:
.. code-block:: text
record_type,process_id,timestamp,alert_id,measurement_height_mm,
measurement_width_mm,measurement_input_params_json,alert_severity,
alert_deviation_type,alert_deviation_percentage,alert_expected_height_mm,
alert_expected_width_mm,alert_measured_height_mm,alert_measured_width_mm,
alert_recommended_actions,raw_payload_json,source
Validation Commands
-------------------
Validate the DDS configuration file:
.. code-block:: bash
python -m json.tool config-dds.json >/dev/null && echo "config-dds.json OK"
Expected output:
.. code-block:: text
config-dds.json OK
Validate local services:
.. code-block:: bash
docker compose up -d
docker compose ps
curl http://localhost:1026/version
curl http://localhost:9090/health
curl http://localhost:8001/health
Expected output:
* Compose lists ``orion-ld``, ``vulcanexus``, ``mongo-db``, ``timescaledb``,
``mintaka``, ``alert-processor``, ``lichtblick``, and
``robin-dashboard`` as running or healthy.
* Orion returns version metadata.
* Mintaka returns a health response.
* API health returns ``"status": "healthy"`` when Orion-LD and Mintaka are
reachable.
Validate API/demo history path:
.. code-block:: bash
PROCESS_ID=reviewer_demo_process
python demo/profiles/welding_profile.py \
--process-id "$PROCESS_ID" \
--mode both \
--duration 60 \
--interval 1 \
--no-prompt
curl -s "http://localhost:8001/process/${PROCESS_ID}/measurements?last=5" \
| jq '.status, .count, .debug_info.source'
Expected output after a successful run:
.. code-block:: text
"success"
5
"mintaka"
If Mintaka is not ready, the API may return ``"orion"`` or ``"troe"`` as the
debug source. That is a fallback path, not the preferred steady-state path.
Validate DDS topic and Orion-LD mapping on a Linux ROS 2/Vulcanexus setup:
.. code-block:: bash
docker exec vulcanexus-bridge bash -lc \
'source /workspace/ros2_packages/ws_setup.sh && ros2 topic list | grep /robin/telemetry'
curl -s \
"http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:Process:ros_bridge" \
| jq '.id, .type, ."urn:robin:processTelemetry" // .processTelemetry'
Expected output:
* ``/robin/telemetry`` is listed after the telemetry aggregator is running.
* Orion returns ``urn:ngsi-ld:Process:ros_bridge`` with type
``urn:robin:Process``.
* The telemetry attribute contains the current ``ProcessTelemetry`` values.
Validate temporal history for DDS data:
.. code-block:: bash
curl -s \
"http://localhost:9090/temporal/entities/urn:ngsi-ld:Process:ros_bridge?attrs=urn:robin:processTelemetry,processTelemetry&timerel=between&timeAt=1970-01-01T00:00:00Z&endTimeAt=2035-01-01T00:00:00Z&timeproperty=observedAt&options=temporalValues&lastN=5" \
| jq
Expected output:
* A JSON array with the ``ros_bridge`` process entity after DDS telemetry has
been published and TROE has indexed it.
* An empty array means no DDS telemetry has been stored yet, or the time
property/domain mapping does not match the running stack.
Known Limitations and Assumptions
---------------------------------
* ``config-dds.json`` maps ``rt/robin/telemetry`` to the fixed entity
``urn:ngsi-ld:Process:ros_bridge``. Per-run or per-profile DDS entity IDs
require changing or templating the DDS mapping.
* The DDS path expects ROS 2 publishers, Orion-LD, and Vulcanexus to use the
same DDS domain. The local Compose baseline uses domain ``0``.
* DDS QoS is ``BEST_EFFORT``. This is suitable for telemetry visualization but
should not be treated as guaranteed delivery for safety-critical control.
* The local macOS override is useful for API/FIWARE/dashboard checks, but full
DDS discovery validation is best done on Linux with host networking.
* Tenant handling is disabled by default in the Compose baseline to keep DDS and
TROE history aligned. Deployments that enable ``NGSILD_TENANT`` must apply
the same tenant consistently across Orion-LD, Mintaka, API calls, and tests.
* The ``Measurement`` entity path and scalar Process attributes support API/demo
runs. The DDS path stores a compound telemetry attribute on the Process
entity instead.
* The committed API response and CSV files are representative examples. Final
release verification should refresh or confirm them from the approved
quickstart/demo run.