SDNPublisher
Warning
The SDNPublisher DataSource is only available in CODAC Core System distributions.
The SDNPublisher DataSource can be used to stream application data over the ITER SDN network (based on UDP multicast).
Typical use cases include streaming data to a remote monitoring or control application.
One of the main differences between the SDNPublisher and the UDPSender DataSources is that SDN imposes a common header and offers the possibility of streaming over multicast. The multicast addresses are encoded in the so-called Topic names.
The SDN header includes built-in fields such as received and sent absolute timestamps, a counter, and the expected topic size and version. These features can be used by the receiving application to implement features such as data synchronisation, data integrity checks, and detection of stalled data.
In this section, the UDPSender from the previous section will be replaced by a SDNPublisher.
Given that the topic name is also dependent on the system configuration, the configuration file ../Configurations/MassSpring/RTApp-MassSpring-26-Publisher.cfg will be automatically updated from a Makefile.cfg, as in the previous example.
The Makefile will automatically call the script ./GenerateTopicNames.sh to generate a unique Topic name, which will then be used by the Makefile to update the variable TUTORIAL_TOPIC_NAME in the generated configuration file ../Configurations/MassSpring/RTApp-MassSpring-26-Publisher_Gen.cfg.
TUTORIAL_TOPIC_NAME, which is replaced by the Makefile.cfg. 1 +SDNPublisherReference = {
2 Class = SDN::SDNPublisher
3 Interface = lo
4 Topic = TUTORIAL_TOPIC_NAME_0
5 Signals = {
6 ReferencePosition = {
7 Type = float64
8 }
9 }
10 }
11 +UDPWriterStats = {
Note
Some output DataSources require a Trigger signal (see Signal properties) to be explicitly declared in the GAM that interfaces with the DataSource. This is the case for the SDNPublisher DataSource.
1 +GAMSDNPublisherRefPos = {
2 Class = IOGAM
3 InputSignals = {
4 ReferencePosition = {
5 DataSource = DDB1
6 Type = float64
7 }
8 }
9 OutputSignals = {
10 ReferencePosition = {
11 DataSource = SDNPublisherReference
12 Type = float64
13 Trigger = 1
14 }
15 }
16 }
Running the application
Start the application with:
make -C ../Configurations/MassSpring/ -f Makefile.cfg
./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-26-Publisher_Gen.cfg -l RealTimeLoader -s State1
Once the application is running, inspect the screen output and verify that the application is running without any issues. The log should show entries similar to the following:
$ [Warning - Threads.cpp:181]: Failed to change the thread priority (likely due to insufficient permissions)
$ [Information - RealTimeLoader.cpp:111]: Started application in state State1
$ [Information - MARTeApp.cpp:135]: Application starting
$ [Information - LoggerBroker.cpp:152]: Time [0:0]:0
$ [Information - LoggerBroker.cpp:152]: Time [0:0]:1000000
...
The CCS tool sdn-print will be used to monitor the SDN traffic and verify that the application is streaming data over the SDN network.
Open another console and generate the required .xml configuration files for sdn-print.
../Test/Integrated/GenerateSDNTopicFiles.sh
Export the required environment variables for the sdn-print tool and run it.
export SDN_TOPIC_PATH=../Test/Integrated
sdn-print -i lo -t mass-spring-0 -c -1
Notice that both MARTe2 and the sdn-print tool receive from the SDN topic source using multicast.
If everything is working correctly, you should see the SDN packets being printed to the console:
$ Using topic definition - <topic name="mass-spring-cabrian-1" version="1" size="8" mapping="239.0.50.191:52544"><dataType format="json">{"type":"mass-spring-cabrian-1","attributes":[{"ReferencePosition":{"type":"float64"}}]}</dataType></topic>
$ 2026-03-31T16:15:11.716842934 {"ReferencePosition":1.592}
$ 2026-03-31T16:15:11.726838572 {"ReferencePosition":1.588}
...
Exercises
Ex. 1: Stream the Stats signals over SDN.
Edit the file
../Configurations/MassSpring/RTApp-MassSpring-27-Publisher.cfgand modify the DataSourceUDPWriterStatsto stream the signals to the topic identified asTUTORIAL_TOPIC_NAME_1.Run
make -C ../Configurations/MassSpring/ -f Makefile.cfgto generate the configuration file with the correct topic names and UDP port numbers.Check that the application statistics are still being streamed over SDN to the topics identified as
TUTORIAL_TOPIC_NAMEandTUTORIAL_TOPIC_NAME_1.
make -C ../Configurations/MassSpring/ -f Makefile.cfg
./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-27-Publisher_Gen.cfg -l RealTimeLoader -s State1
../Test/Integrated/GenerateSDNTopicFiles.sh
export SDN_TOPIC_PATH=../Test/Integrated
sdn-print -i lo -t mass-spring-1 -c -1
export SDN_TOPIC_PATH=../Test/Integrated
sdn-print -i lo -t mass-spring-0 -c -1
Solution
The solution is to modify the configuration file ../Configurations/MassSpring/RTApp-MassSpring-27-Publisher.cfg and complete the necessary changes to the UDPWriterStats DataSource, making sure that a Trigger = 1 is also explicitly declared in one of the signals interfacing with the UDPWriterStats DataSource.
For the sake of clarity, the DataSource name should also be updated to reflect that it is now an SDNPublisher.
1 +SDNPublisherStats = {
2 Class = SDN::SDNPublisher
3 Interface = lo
4 Topic = TUTORIAL_TOPIC_NAME_1
5 Signals = {
6 Thread1CycleTime = {
7 Type = uint32
8 }
9 Thread1CycleTimeAverage = {
10 Type = uint32
11 }
12 Thread1CycleTimeStdDev = {
13 Type = uint32
14 }
15 Thread1CycleTimeMax = {
16 Type = uint32
17 }
18 Thread1CycleTimeMin = {
19 Type = uint32
20 }
21 Thread1CycleTimeHistogram = {
22 Type = uint32
23 NumberOfElements = 11
24 }
25 Thread1FreeTimeHistogram = {
26 Type = uint32
27 NumberOfElements = 11
28 }
29 GAMsExecutionTime = {
30 Type = uint32
31 }
32 }
33 }
Trigger = 1 property set in one of the signals interfacing with the DataSource. 1 +GAMWriterStats = {
2 Class = IOGAM
3 InputSignals = {
4 Thread1CycleTime = {
5 DataSource = DDB1
6 Type = uint32
7 }
8 Thread1CycleTimeAverage = {
9 OutputSignals = {
10 Thread1CycleTime = {
11 DataSource = SDNPublisherStats
12 Type = uint32
13 Trigger = 1
14 }
15 Thread1CycleTimeAverage = {