Skip to content

fix(opcua): run a fault manager in the OpenPLC tank demo - #683

Draft
bburda wants to merge 2 commits into
fix/persist-entity-freeze-framesfrom
fix/opcua-demo-runs-a-fault-manager
Draft

fix(opcua): run a fault manager in the OpenPLC tank demo#683
bburda wants to merge 2 commits into
fix/persist-entity-freeze-framesfrom
fix/opcua-demo-runs-a-fault-manager

Conversation

@bburda

@bburda bburda commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

The plugin's start.sh started OpenPLC and one gateway container and no fault manager, so the demo the README describes could not confirm a fault: GET /api/v1/faults answered 503 ListFaults service not available, and a PLC alarm waited in the plugin's report buffer for a service that never came.

start.sh now runs fault_manager_node in the gateway container before gateway_node, waits for /fault_manager/report_fault, and logs it to /var/lib/ros2_medkit/fault_manager.log. The fault manager's state sits under /var/lib/ros2_medkit, the named volume from #680, so faults, freeze frames and recordings survive stop.sh and start.sh together. The image is unchanged. test_all.sh, the test scripts and the CI workflow are untouched.

Stacked on #680.

Issue

Type

  • Bug fix
  • New feature or tests
  • Breaking change
  • Documentation only

Testing

Shell and docs only, so the evidence is the demo run, base against branch.

Base: start.sh, GET /api/v1/faults answers 503 ListFaults service not available. Driving tank_temperature to 95 raises the alarm on x-plc-status and the fault list stays empty, no faults.db on the volume.

Branch: GET /api/v1/faults answers 200. The same write confirms PLC_HIGH_TEMP within 2 s, and the fault detail carries a freeze_frame with tank_temperature at 95. After stop.sh and start.sh the same detail is served with the same captured_at while the live PLC reads 25 °C. After the documented purge the fault is gone and the list is empty.

Injected failure: a directory in place of faults.db makes the fault manager abort, and start.sh exits 1 naming the missing service and printing the log tail.

shellcheck and pre-commit pass.

Checklist

  • Breaking changes are clearly described (and announced in docs / changelog if needed)
  • Tests were added or updated if needed
  • Docs were updated if behavior or public API changed

The demo gateway had no fault manager, so every alarm the OPC-UA plugin
detected was reported into nothing and each /faults route answered 503
"ListFaults service not available". The demo could show live PLC values
and never a fault, which is the one thing the alarm-to-fault bridge is
there to demonstrate.

scripts/start.sh now starts fault_manager_node in the gateway container
before gateway_node, on the same ROS domain, and waits for
/fault_manager/report_fault to be advertised instead of sleeping a fixed
time. The wait is bounded and both the container and the host script
fail with a message naming the missing service, so a fault manager that
never came up is a loud failure rather than a 503 discovered later.

database_path is passed explicitly so faults.db lands on the named state
volume next to the entity freeze frames. A fault and the freeze frame it
carries now cross stop.sh and start.sh together, and rosbag storage
points at the same volume for when black-box capture is switched on.

The test scripts and the CI workflow are untouched. They start their own
containers, and run_alarm_tests.sh already ran a fault manager this way.
The previous wording claimed every /faults route answers 503 without a
fault manager. Only the global GET /api/v1/faults does. A plugin-owned
entity's list is served by the plugin's FaultProvider, and the context
contract is an empty array when the fault manager is unavailable, so
GET /api/v1/apps/tank_process/faults answers 200 with no items. The
demo symptom is the same, live PLC values and never a fault, but the
two routes fail differently and a reader chasing one will not see the
other.

Also correct the state comment in gateway_params.yaml. It said the test
scripts keep the frames and faults.db inside the container, which reads
as though they all run a fault manager. run_integration_tests.sh and
test_all.sh run none and have no faults.db, while run_alarm_tests.sh and
run_discovery_race_test.sh start one and keep it in the container.
@bburda bburda self-assigned this Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant