Added tutorial and fixed issues on debugservice

This commit is contained in:
Martino Ferrari
2026-02-21 20:33:29 +01:00
parent 955eb02924
commit 817d7276b7
4 changed files with 118 additions and 18 deletions

View File

@@ -158,17 +158,20 @@ bool DebugService::Initialise(StructuredDataI & data) {
REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to Listen on port %u", controlPort); REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to Listen on port %u", controlPort);
return false; return false;
} }
printf("[DebugService] TCP Server listening on port %u\n", controlPort);
if (!udpSocket.Open()) { if (!udpSocket.Open()) {
REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to open UDP Socket"); REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to open UDP Socket");
return false; return false;
} }
printf("[DebugService] UDP Streamer socket opened\n");
if (!logServer.Open()) { if (!logServer.Open()) {
REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to open Log Server Socket"); REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to open Log Server Socket");
return false; return false;
} }
(void)logServer.Listen(logPort); (void)logServer.Listen(logPort);
printf("[DebugService] Log Server listening on port %u\n", logPort);
if (threadService.Start() != ErrorManagement::NoError) { if (threadService.Start() != ErrorManagement::NoError) {
REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to start Server thread"); REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to start Server thread");
@@ -182,6 +185,7 @@ bool DebugService::Initialise(StructuredDataI & data) {
REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to start LogStreamer thread"); REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to start LogStreamer thread");
return false; return false;
} }
printf("[DebugService] All worker threads started.\n");
} }
return true; return true;

56
TUTORIAL.md Normal file
View File

@@ -0,0 +1,56 @@
# Tutorial: High-Speed Observability with MARTe2 Debug GUI
This guide will walk you through the process of tracing and forcing signals in a real-time MARTe2 application using the native Rust GUI client.
## 1. Environment Setup
### Launch the MARTe2 Application
First, start your application using the provided debug runner. This script launches the standard `MARTeApp.ex` while injecting the debugging layer:
```bash
./run_debug_app.sh
```
*Note: You should see logs indicating the `DebugService` has started on port 8080.*
### Start the GUI Client
In a new terminal window, navigate to the client directory and run the GUI:
```bash
cd Tools/gui_client
cargo run --release
```
## 2. Exploring the Object Tree
Once connected, the left panel (**Application Tree**) displays the live hierarchy of your application.
1. **Navigate to Data:** Expand `Root` -> `App` -> `Data`.
2. **Inspect Nodes:** Click the ** Info** button next to any node (like `Timer` or `DDB`).
3. **View Metadata:** The bottom-left pane will display the full JSON configuration of that object, including its class, parameters, and signals.
## 3. Real-Time Signal Tracing (Oscilloscope)
Tracing allows you to see signal values exactly as they exist in the real-time memory map.
1. **Find a Signal:** In the tree, locate `Root.App.Data.Timer.Counter`.
2. **Activate Trace:** Click the **📈 Trace** button.
3. **Monitor the Scope:** The central **Oscilloscope** panel will begin plotting the signal.
4. **Verify Data Flow:** Check the **UDP Packets** counter in the top bar; it should be increasing rapidly, confirming high-speed data reception (Port 8081).
5. **Multi-Signal Trace:** You can click **📈 Trace** on other signals (like `Time`) to overlay multiple plots.
## 4. Signal Forcing (Manual Override)
Forcing allows you to bypass the framework logic and manually set a signal's value in memory.
1. **Locate Target:** Find a signal that is being written by a GAM, such as `Root.App.Data.DDB.Counter`.
2. **Open Force Dialog:** Click the **⚡ Force** button next to the signal.
3. **Inject Value:** In the popup dialog, enter a new value (e.g., `9999`) and click **Apply Force**.
4. **Observe Effect:** If you are tracing the same signal, the oscilloscope plot will immediately jump to and hold at `9999`.
5. **Release Control:** To stop forcing, click the **❌** button in the **Active Controls** (Right Panel) under "Forced Signals". The framework will resume writing its own values to that memory location.
## 5. Advanced Controls
### Global Pause
If you need to "freeze" the entire application to inspect a specific state:
- Click **⏸ Pause** in the top bar. The real-time threads will halt at the start of their next cycle.
- Click **▶ Resume** to restart the execution.
### Log Terminal
The bottom panel displays every `REPORT_ERROR` event from the C++ framework.
- **Regex Filter:** Type a keyword like `Timer` in the filter box to isolate relevant events.
- **Pause Logs:** Toggle **⏸ Pause Logs** to stop the scrolling view while data continues to be captured in the background.

View File

@@ -1,19 +1,4 @@
+DebugService = { $App = {
Class = DebugService
ControlPort = 8080
StreamPort = 8081
StreamIP = "127.0.0.1"
}
+LoggerService = {
Class = LoggerService
CPUs = 0x1
+DebugConsumer = {
Class = DebugService
}
}
+App = {
Class = RealTimeApplication Class = RealTimeApplication
+Functions = { +Functions = {
Class = ReferenceContainer Class = ReferenceContainer
@@ -23,7 +8,7 @@
Counter = { Counter = {
DataSource = Timer DataSource = Timer
Type = uint32 Type = uint32
Frequency = 10 Frequency = 1
} }
Time = { Time = {
DataSource = Timer DataSource = Timer
@@ -47,7 +32,7 @@
DefaultDataSource = DDB DefaultDataSource = DDB
+Timer = { +Timer = {
Class = LinuxTimer Class = LinuxTimer
SleepTime = 1000000 // 1 second SleepTime = 1000000 // 1 second cycle to reduce log spam
Signals = { Signals = {
Counter = { Counter = {
Type = uint32 Type = uint32
@@ -99,3 +84,18 @@
TimingDataSource = DAMS TimingDataSource = DAMS
} }
} }
+DebugService = {
Class = DebugService
ControlPort = 8080
UdpPort = 8081
StreamIP = "127.0.0.1"
}
+LoggerService = {
Class = LoggerService
CPUs = 0x1
+DebugConsumer = {
Class = DebugService
}
}

40
run_debug_app.sh Executable file
View File

@@ -0,0 +1,40 @@
#!/bin/bash
# run_debug_app.sh - Launch the MARTe2 Debugging Environment using standard MARTeApp.ex
# 1. Environment Setup
if [ -f "./env.sh" ]; then
source ./env.sh
else
echo "ERROR: env.sh not found. Ensure you are in the project root."
exit 1
fi
# 2. Paths
MARTE_EX="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex"
DEBUG_LIB="$(pwd)/Build/libmarte_dev.so"
# Component library base search path
COMPONENTS_BUILD_DIR="${MARTe2_Components_DIR}/Build/${TARGET}/Components"
# DYNAMICALLY FIND ALL COMPONENT DIRS
# MARTe2 Loader needs the specific directories containing .so files in LD_LIBRARY_PATH
ALL_COMPONENT_DIRS=$(find "$COMPONENTS_BUILD_DIR" -type d)
for dir in $ALL_COMPONENT_DIRS; do
if ls "$dir"/*.so >/dev/null 2>&1; then
export LD_LIBRARY_PATH="$dir:$LD_LIBRARY_PATH"
fi
done
# Ensure our build dir and core dir are included
export LD_LIBRARY_PATH="$(pwd)/Build:${MARTe2_DIR}/Build/${TARGET}/Core:${LD_LIBRARY_PATH}"
# 3. Cleanup
echo "Cleaning up lingering processes..."
pkill -9 MARTeApp.ex
sleep 1
# 4. Launch Application
echo "Launching standard MARTeApp.ex with debug_test.cfg..."
# PRELOAD ensures our DebugService class is available to the registry early
export LD_PRELOAD="${DEBUG_LIB}"
"$MARTE_EX" -f Test/Configurations/debug_test.cfg -l RealTimeLoader -s State1