This commit is contained in:
Martino Ferrari
2026-05-15 17:42:14 +02:00
commit e3389f932b
40 changed files with 7622 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
include Makefile.inc
+38
View File
@@ -0,0 +1,38 @@
#############################################################
#
# Copyright 2015 F4E | European Joint Undertaking for ITER
# and the Development of Fusion Energy ('Fusion for Energy')
#
# Licensed under the EUPL, Version 1.1 or - as soon they
# will be approved by the European Commission - subsequent
# versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the
# Licence.
# You may obtain a copy of the Licence at:
#
# http://ec.europa.eu/idabc/eupl
#
# Unless required by applicable law or agreed to in
# writing, software distributed under the Licence is
# distributed on an "AS IS" basis,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied.
# See the Licence for the specific language governing
# permissions and limitations under the Licence.
#
#############################################################
OBJSX=
SPB = UDPStreamer.x
PACKAGE=Components
ROOT_DIR=../../..
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
all: $(OBJS) $(SUBPROJ)
echo $(OBJS)
include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
@@ -0,0 +1 @@
include Makefile.inc
@@ -0,0 +1,57 @@
#############################################################
#
# Copyright 2015 F4E | European Joint Undertaking for ITER
# and the Development of Fusion Energy ('Fusion for Energy')
#
# Licensed under the EUPL, Version 1.1 or - as soon they
# will be approved by the European Commission - subsequent
# versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the
# Licence.
# You may obtain a copy of the Licence at:
#
# http://ec.europa.eu/idabc/eupl
#
# Unless required by applicable law or agreed to in
# writing, software distributed under the Licence is
# distributed on an "AS IS" basis,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied.
# See the Licence for the specific language governing
# permissions and limitations under the Licence.
#
#############################################################
OBJSX = UDPStreamerTest.x UDPStreamerGTest.x
PACKAGE=Components/DataSources
ROOT_DIR=../../../..
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
INCLUDES += -I.
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L2Objects
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Configuration
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L3Services
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4StateMachine
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Lib/gtest-1.7.0/include
INCLUDES += -I../../../../Source/Components/DataSources/UDPStreamer
all: $(OBJS) \
$(BUILD_DIR)/UDPStreamerTest$(LIBEXT)
echo $(OBJS)
include depends.$(TARGET)
include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
@@ -0,0 +1,187 @@
/**
* @file UDPStreamerGTest.cpp
* @brief Source file for class UDPStreamerGTest
* @date 13/05/2026
* @author Martino Ferrari
*
* @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
* the Development of Fusion Energy ('Fusion for Energy').
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence")
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
*
* @warning Unless required by applicable law or agreed to in writing,
* software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the Licence permissions and limitations under the Licence.
*
* @details This source file contains the GTest wrapper for all UDPStreamer tests.
*/
#define DLL_API
/*---------------------------------------------------------------------------*/
/* Standard header includes */
/*---------------------------------------------------------------------------*/
#include "gtest/gtest.h"
#include <limits.h>
/*---------------------------------------------------------------------------*/
/* Project header includes */
/*---------------------------------------------------------------------------*/
#include "UDPStreamerTest.h"
/*---------------------------------------------------------------------------*/
/* Method definitions */
/*---------------------------------------------------------------------------*/
TEST(UDPStreamerGTest, TestConstructor) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestConstructor());
}
TEST(UDPStreamerGTest, TestInitialise_Valid) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestInitialise_Valid());
}
TEST(UDPStreamerGTest, TestInitialise_DefaultPort) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestInitialise_DefaultPort());
}
TEST(UDPStreamerGTest, TestInitialise_InvalidMaxPayloadSize) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestInitialise_InvalidMaxPayloadSize());
}
TEST(UDPStreamerGTest, TestInitialise_ZeroStackSize) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestInitialise_ZeroStackSize());
}
TEST(UDPStreamerGTest, TestGetBrokerName_Output) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestGetBrokerName_Output());
}
TEST(UDPStreamerGTest, TestGetBrokerName_Input) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestGetBrokerName_Input());
}
TEST(UDPStreamerGTest, TestAllocateMemory) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestAllocateMemory());
}
TEST(UDPStreamerGTest, TestSetConfiguredDatabase_BasicSignals) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_BasicSignals());
}
TEST(UDPStreamerGTest, TestSetConfiguredDatabase_Quantized) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_Quantized());
}
TEST(UDPStreamerGTest, TestSetConfiguredDatabase_InvalidQuantOnInteger) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_InvalidQuantOnInteger());
}
TEST(UDPStreamerGTest, TestSetConfiguredDatabase_UnknownQuantType) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_UnknownQuantType());
}
TEST(UDPStreamerGTest, TestSetConfiguredDatabase_TimeModePacket) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_TimeModePacket());
}
TEST(UDPStreamerGTest, TestSetConfiguredDatabase_TimeModeFullArray) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_TimeModeFullArray());
}
TEST(UDPStreamerGTest, TestSetConfiguredDatabase_TimeModeFirstSample) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_TimeModeFirstSample());
}
TEST(UDPStreamerGTest, TestSetConfiguredDatabase_MissingSamplingRate) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_MissingSamplingRate());
}
TEST(UDPStreamerGTest, TestSetConfiguredDatabase_InvalidTimeSignal) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_InvalidTimeSignal());
}
TEST(UDPStreamerGTest, TestSetConfiguredDatabase_FullArrayMismatch) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_FullArrayMismatch());
}
TEST(UDPStreamerGTest, TestPrepareNextState) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestPrepareNextState());
}
TEST(UDPStreamerGTest, TestSynchronise_NoClient) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestSynchronise_NoClient());
}
TEST(UDPStreamerGTest, TestExecute_ConnectDataDisconnect) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestExecute_ConnectDataDisconnect());
}
TEST(UDPStreamerGTest, TestExecute_Fragmentation) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestExecute_Fragmentation());
}
TEST(UDPStreamerGTest, TestQuantization_Uint16Extremes) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestQuantization_Uint16Extremes());
}
TEST(UDPStreamerGTest, TestQuantization_Uint8Clamping) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestQuantization_Uint8Clamping());
}
TEST(UDPStreamerGTest, TestGetPort) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestGetPort());
}
TEST(UDPStreamerGTest, TestGetMaxPayloadSize) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestGetMaxPayloadSize());
}
TEST(UDPStreamerGTest, TestIsClientConnected_InitiallyFalse) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestIsClientConnected_InitiallyFalse());
}
TEST(UDPStreamerGTest, TestHighFrequency_AllocateMemory) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestHighFrequency_AllocateMemory());
}
TEST(UDPStreamerGTest, TestHighFrequency_Fragmentation) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestHighFrequency_Fragmentation());
}
TEST(UDPStreamerGTest, TestHighFrequency_DataIntegrity) {
UDPStreamerTest test;
ASSERT_TRUE(test.TestHighFrequency_DataIntegrity());
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,199 @@
/**
* @file UDPStreamerTest.h
* @brief Header file for class UDPStreamerTest
* @date 13/05/2026
* @author Martino Ferrari
*
* @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
* the Development of Fusion Energy ('Fusion for Energy').
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence")
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
*
* @warning Unless required by applicable law or agreed to in writing,
* software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the Licence permissions and limitations under the Licence.
*
* @details This header file contains the declaration of the class UDPStreamerTest
* with all of its public, protected and private members. It may also include
* definitions for inline methods which need to be visible to the compiler.
*/
#ifndef UDPSTREAMERTEST_H_
#define UDPSTREAMERTEST_H_
/*---------------------------------------------------------------------------*/
/* Standard header includes */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Project header includes */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Class declaration */
/*---------------------------------------------------------------------------*/
/**
* @brief Tests the UDPStreamer DataSource public methods.
*/
class UDPStreamerTest {
public:
/**
* @brief Tests the default constructor.
*/
bool TestConstructor();
/**
* @brief Tests Initialise with a fully valid configuration.
*/
bool TestInitialise_Valid();
/**
* @brief Tests that a missing Port uses the default (44500).
*/
bool TestInitialise_DefaultPort();
/**
* @brief Tests that MaxPayloadSize below the minimum is rejected.
*/
bool TestInitialise_InvalidMaxPayloadSize();
/**
* @brief Tests that StackSize = 0 is rejected.
*/
bool TestInitialise_ZeroStackSize();
/**
* @brief Tests GetBrokerName returns the correct broker for OutputSignals.
*/
bool TestGetBrokerName_Output();
/**
* @brief Tests GetBrokerName returns empty string for InputSignals.
*/
bool TestGetBrokerName_Input();
/**
* @brief Tests AllocateMemory allocates readyBuffer, scratchBuffer, wireBuffer.
*/
bool TestAllocateMemory();
/**
* @brief Tests SetConfiguredDatabase with basic signal types.
*/
bool TestSetConfiguredDatabase_BasicSignals();
/**
* @brief Tests SetConfiguredDatabase with a quantized float signal.
*/
bool TestSetConfiguredDatabase_Quantized();
/**
* @brief Tests that quantization on a non-float signal is rejected.
*/
bool TestSetConfiguredDatabase_InvalidQuantOnInteger();
/**
* @brief Tests that an unknown QuantizedType is rejected.
*/
bool TestSetConfiguredDatabase_UnknownQuantType();
/**
* @brief Tests TimeMode = PacketTime (default).
*/
bool TestSetConfiguredDatabase_TimeModePacket();
/**
* @brief Tests TimeMode = FullArray with a matching time signal.
*/
bool TestSetConfiguredDatabase_TimeModeFullArray();
/**
* @brief Tests TimeMode = FirstSample with a scalar time signal.
*/
bool TestSetConfiguredDatabase_TimeModeFirstSample();
/**
* @brief Tests that FirstSample without SamplingRate is rejected.
*/
bool TestSetConfiguredDatabase_MissingSamplingRate();
/**
* @brief Tests that TimeSignal pointing to a non-existent signal is rejected.
*/
bool TestSetConfiguredDatabase_InvalidTimeSignal();
/**
* @brief Tests that FullArray TimeMode with mismatched element counts is rejected.
*/
bool TestSetConfiguredDatabase_FullArrayMismatch();
/**
* @brief Tests PrepareNextState starts the thread and opens the socket.
*/
bool TestPrepareNextState();
/**
* @brief Tests Synchronise when no client is connected (must return true, no crash).
*/
bool TestSynchronise_NoClient();
/**
* @brief Tests the full CONNECT → CONFIG → DATA → DISCONNECT flow via loopback UDP.
*/
bool TestExecute_ConnectDataDisconnect();
/**
* @brief Tests that DATA packets are fragmented correctly for large payloads.
*/
bool TestExecute_Fragmentation();
/**
* @brief Tests uint16 quantization: verifies that 0 maps to 0 and max maps to 65535.
*/
bool TestQuantization_Uint16Extremes();
/**
* @brief Tests uint8 quantization: verifies clamping of out-of-range values.
*/
bool TestQuantization_Uint8Clamping();
/**
* @brief Tests the GetPort() accessor.
*/
bool TestGetPort();
/**
* @brief Tests the GetMaxPayloadSize() accessor.
*/
bool TestGetMaxPayloadSize();
/**
* @brief Tests that IsClientConnected() returns false before any CONNECT.
*/
bool TestIsClientConnected_InitiallyFalse();
/**
* @brief Tests AllocateMemory with 4 high-frequency int16[1000] packed channels (1 MSps).
*/
bool TestHighFrequency_AllocateMemory();
/**
* @brief Tests that 4 int16[1000] channels produce exactly 6 fragments at MaxPayloadSize=1400.
* Payload: 8 (HRT) + 8 (T0/uint64) + 4×2000 (int16[1000]) = 8016 bytes;
* chunk = 1383 bytes → ceil(8016/1383) = 6 fragments.
*/
bool TestHighFrequency_Fragmentation();
/**
* @brief Tests full CONNECT→DATA→DISCONNECT cycle with high-frequency packed signals.
* Reassembles all fragments and verifies the total payload size.
*/
bool TestHighFrequency_DataIntegrity();
};
#endif /* UDPSTREAMERTEST_H_ */
+6
View File
@@ -0,0 +1,6 @@
/depends.linux
/dependsRaw.linux
/depends.cov
/dependsRaw.cov
/cov/
/createLibrary
+29
View File
@@ -0,0 +1,29 @@
/*
* Main_TestAll.cpp
*
* Created on: 31/10/2016
* Author: Andre Neto
*/
#include "ErrorManagement.h"
#include "Object.h"
#include "StreamString.h"
#include "gtest/gtest.h"
#include <limits.h>
void MainGTestComponentsErrorProcessFunction(const MARTe::ErrorManagement::ErrorInformation& errorInfo,
const char* const errorDescription)
{
MARTe::StreamString errorCodeStr;
MARTe::ErrorManagement::ErrorCodeToStream(errorInfo.header.errorType, errorCodeStr);
printf("[%s - %s:%d]: %s\n", errorCodeStr.Buffer(), errorInfo.fileName, errorInfo.header.lineNumber, errorDescription);
}
int main(int argc, char** argv)
{
SetErrorProcessFunction(&MainGTestComponentsErrorProcessFunction);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
+34
View File
@@ -0,0 +1,34 @@
#############################################################
#
# Copyright 2015 F4E | European Joint Undertaking for ITER
# and the Development of Fusion Energy ('Fusion for Energy')
#
# Licensed under the EUPL, Version 1.1 or - as soon they
# will be approved by the European Commission - subsequent
# versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the
# Licence.
# You may obtain a copy of the Licence at:
#
# http://ec.europa.eu/idabc/eupl
#
# Unless required by applicable law or agreed to in
# writing, software distributed under the Licence is
# distributed on an "AS IS" basis,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied.
# See the Licence for the specific language governing
# permissions and limitations under the Licence.
#
#############################################################
include Makefile.inc
LIBRARIES += -L$(GTEST_DIR) -lgtest -lgtest_main -lpthread
LIBRARIES += -L$(MARTe2_LIB_DIR) -lMARTe2
LIBRARIES += -ldl
#Look for all the statically linked files
LIBRARIES_STATIC+=$(shell find $(ROOT_DIR)/Build/$(TARGET) -name "*.a")
+54
View File
@@ -0,0 +1,54 @@
#############################################################
#
# Copyright 2015 F4E | European Joint Undertaking for ITER
# and the Development of Fusion Energy ('Fusion for Energy')
#
# Licensed under the EUPL, Version 1.1 or - as soon they
# will be approved by the European Commission - subsequent
# versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the
# Licence.
# You may obtain a copy of the Licence at:
#
# http://ec.europa.eu/idabc/eupl
#
# Unless required by applicable law or agreed to in
# writing, software distributed under the Licence is
# distributed on an "AS IS" basis,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied.
# See the Licence for the specific language governing
# permissions and limitations under the Licence.
#
#############################################################
PACKAGE=
ROOT_DIR=../..
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L2Objects
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Configuration
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L3Services
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Lib/gtest-1.7.0/include
INCLUDES += -I../../Source/Components/DataSources/UDPStreamer
INCLUDES += -I../Components/DataSources/UDPStreamer
all: $(BUILD_DIR)/MainGTest$(EXEEXT)
include depends.$(TARGET)
include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
+289
View File
@@ -0,0 +1,289 @@
/**
* Test MARTe2 application for UDPStreamer DataSource.
*
* Generates scalar and high-frequency packed signals and streams them via UDPStreamer.
* Connect with the WebUI client (Client/WebUI) to visualise the signals.
*
* Signals produced (scalar, 10 kHz):
* Counter uint32 cycle counter from LinuxTimer
* Time uint32 time in microseconds from LinuxTimer
* Sine1 float32, 1 Hz sine, amplitude 10, quantised to uint16 on wire
* Sine2 float32, 0.3 Hz sine, amplitude 5, raw float32 on wire
*
* Signals produced (packed temporal arrays, 10 kHz × 1000 samples = 10 MSps):
* Ch1 float32[1000], 1 kHz sine, amplitude 1.0
* Ch2 float32[1000], 1 kHz sine, amplitude 0.5, phase π/2
* Both channels use TimeMode=FirstSample with Time as the anchor and
* SamplingRate=10000000 so the WebUI reconstructs the per-sample timestamps.
*/
$TestApp = {
Class = RealTimeApplication
+Functions = {
Class = ReferenceContainer
// ── Copy Counter + Time from LinuxTimer into the inter-GAM DDB ──────
+TimerGAM = {
Class = IOGAM
InputSignals = {
Counter = {
DataSource = Timer
Type = uint32
}
Time = {
Frequency = 1000
DataSource = Timer
Type = uint32
}
}
OutputSignals = {
Counter = {
DataSource = DDB
Type = uint32
}
Time = {
DataSource = DDB
Type = uint32
}
}
}
// ── 1 Hz sinusoidal signal ───────────────────────────────────────────
+SineGAM1 = {
Class = WaveformSin
Amplitude = 10.0
Frequency = 1.0
Phase = 0.0
Offset = 0.0
InputSignals = {
Time = {
DataSource = DDB
Type = uint32
}
}
OutputSignals = {
Sine1 = {
DataSource = DDB
Type = float32
}
}
}
// ── 0.3 Hz sinusoidal signal (phase-shifted) ─────────────────────────
+SineGAM2 = {
Class = WaveformSin
Amplitude = 5.0
Frequency = 0.3
Phase = 1.0472
Offset = 0.0
InputSignals = {
Time = {
DataSource = DDB
Type = uint32
}
}
OutputSignals = {
Sine2 = {
DataSource = DDB
Type = float32
}
}
}
// ── 1 kHz sine burst channel 1 (1000 samples/packet at 10 MSps) ──────
+SineGAM3 = {
Class = SineArrayGAM
Frequency = 1000.0
Amplitude = 1.0
Phase = 0.0
Offset = 0.0
SamplingRate = 1000000.0
OutputSignals = {
Ch1 = {
DataSource = DDB
Type = float32
NumberOfDimensions = 1
NumberOfElements = 1000
}
}
}
// ── 1 kHz sine burst channel 2 (phase-shifted by π/2) ──────────────
+SineGAM4 = {
Class = SineArrayGAM
Frequency = 1000.0
Amplitude = 0.5
Phase = 1.5708
Offset = 0.0
SamplingRate = 1000000.0
OutputSignals = {
Ch2 = {
DataSource = DDB
Type = float32
NumberOfDimensions = 1
NumberOfElements = 1000
}
}
}
// ── Route signals into UDPStreamer ────────────────────────────────────
+StreamerGAM = {
Class = IOGAM
InputSignals = {
Counter = {
DataSource = DDB
Type = uint32
}
Time = {
DataSource = DDB
Type = uint32
}
Sine1 = {
DataSource = DDB
Type = float32
}
Sine2 = {
DataSource = DDB
Type = float32
}
Ch1 = {
DataSource = DDB
Type = float32
NumberOfDimensions = 1
NumberOfElements = 1000
}
Ch2 = {
DataSource = DDB
Type = float32
NumberOfDimensions = 1
NumberOfElements = 1000
}
}
OutputSignals = {
Counter = {
DataSource = Streamer
Type = uint32
}
Time = {
DataSource = Streamer
Type = uint32
}
Sine1 = {
DataSource = Streamer
Type = float32
}
Sine2 = {
DataSource = Streamer
Type = float32
}
Ch1 = {
DataSource = Streamer
Type = float32
NumberOfDimensions = 1
NumberOfElements = 1000
}
Ch2 = {
DataSource = Streamer
Type = float32
NumberOfDimensions = 1
NumberOfElements = 1000
}
}
}
}
+Data = {
Class = ReferenceContainer
DefaultDataSource = DDB
// ── Inter-GAM data buffer ────────────────────────────────────────────
+DDB = {
Class = GAMDataSource
}
// ── Real-time clock / trigger source ─────────────────────────────────
+Timer = {
Class = LinuxTimer
SleepNature = "Default"
Signals = {
Counter = {
Type = uint32
}
Time = {
Type = uint32
}
}
}
// ── UDP Streamer DataSource ──────────────────────────────────────────
+Streamer = {
Class = UDPStreamer
Port = 44500
MaxPayloadSize = 1400
Signals = {
Counter = {
Type = uint32
}
Time = {
Type = uint32
Unit = "us"
}
Sine1 = {
Type = float32
Unit = "V"
RangeMin = -10.0
RangeMax = 10.0
QuantizedType = "uint16"
}
Sine2 = {
Type = float32
Unit = "V"
RangeMin = -5.0
RangeMax = 5.0
}
Ch1 = {
Type = float32
Unit = "V"
NumberOfDimensions = 1
NumberOfElements = 1000
TimeMode = FirstSample
TimeSignal = Time
SamplingRate = 1000000.0
}
Ch2 = {
Type = float32
Unit = "V"
NumberOfDimensions = 1
NumberOfElements = 1000
TimeMode = FirstSample
TimeSignal = Time
SamplingRate = 1000000.0
}
}
}
// ── Timing statistics ────────────────────────────────────────────────
+Timings = {
Class = TimingDataSource
}
}
+States = {
Class = ReferenceContainer
+Running = {
Class = RealTimeState
+Threads = {
Class = ReferenceContainer
+Thread1 = {
Class = RealTimeThread
CPUs = 0x1
Functions = {TimerGAM SineGAM1 SineGAM2 SineGAM3 SineGAM4 StreamerGAM}
}
}
}
}
+Scheduler = {
Class = GAMScheduler
TimingDataSource = Timings
}
}
+138
View File
@@ -0,0 +1,138 @@
#!/usr/bin/env bash
# run.sh Build UDPStreamer and launch the test MARTe2 application.
#
# Usage:
# ./run.sh # run MARTe2 app only
# ./run.sh --webui # also start the WebUI Go client in the background
# ./run.sh --help # show this message
#
# Prerequisites:
# - marte_env.sh must be present in the repo root (sets MARTe2_DIR, etc.)
# - MARTe2 and MARTe2-components must already be built
#
# The script resolves all paths relative to the repo root so it can be
# called from any working directory.
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
# ── Parse arguments ──────────────────────────────────────────────────────────
START_WEBUI=0
for arg in "$@"; do
case "$arg" in
--webui) START_WEBUI=1 ;;
--help|-h)
sed -n '2,12p' "$0"
exit 0
;;
esac
done
# ── Load MARTe2 environment ──────────────────────────────────────────────────
ENV_SCRIPT="${REPO_ROOT}/marte_env.sh"
if [ ! -f "${ENV_SCRIPT}" ]; then
echo "ERROR: ${ENV_SCRIPT} not found." >&2
exit 1
fi
# shellcheck source=/dev/null
source "${ENV_SCRIPT}"
if [ -z "${MARTe2_DIR}" ]; then
echo "ERROR: MARTe2_DIR is not set after sourcing marte_env.sh." >&2
exit 1
fi
# ── Build UDPStreamer ─────────────────────────────────────────────────────────
TARGET=x86-linux
UDPSTREAMER_SRC="${REPO_ROOT}/Source/Components/DataSources/UDPStreamer"
UDPSTREAMER_LIB="${REPO_ROOT}/Build/${TARGET}/Components/DataSources/UDPStreamer"
echo "==> Building UDPStreamer (TARGET=${TARGET})..."
make -C "${UDPSTREAMER_SRC}" \
-f Makefile.gcc \
TARGET="${TARGET}" \
2>&1 | tail -5
echo "==> Build done."
# ── Build WebUI binary (if requested and not already built) ──────────────────
WEBUI_DIR="${REPO_ROOT}/Client/WebUI"
WEBUI_BIN="${WEBUI_DIR}/udpstreamer-webui"
if [ "${START_WEBUI}" -eq 1 ] && [ ! -x "${WEBUI_BIN}" ]; then
echo "==> Building WebUI..."
(cd "${WEBUI_DIR}" && go build -o udpstreamer-webui ./...)
echo "==> WebUI build done."
fi
# ── Set LD_LIBRARY_PATH ───────────────────────────────────────────────────────
COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components"
export LD_LIBRARY_PATH="\
${UDPSTREAMER_LIB}:\
${MARTe2_DIR}/Build/${TARGET}/Core:\
${COMP}/DataSources/LinuxTimer:\
${COMP}/DataSources/LoggerDataSource:\
${COMP}/GAMs/IOGAM:\
${COMP}/GAMs/WaveformGAM:\
${LD_LIBRARY_PATH}"
echo "==> LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"
# ── Create class-name symlinks for MARTe2 auto-loader ────────────────────────
# MARTe2 looks for <ClassName>.so when a class is not yet registered.
# Some components bundle multiple classes into one .so (e.g. WaveformGAM.so
# contains WaveformSin, WaveformChirp, WaveformPointsDef). We need symlinks
# so dlopen("<ClassName>.so") succeeds.
WAVEFORM_DIR="${COMP}/GAMs/WaveformGAM"
for cls in WaveformSin WaveformChirp WaveformPointsDef; do
target="${WAVEFORM_DIR}/${cls}.so"
if [ ! -e "${target}" ]; then
ln -sf "${WAVEFORM_DIR}/WaveformGAM.so" "${target}"
fi
done
# SineArrayGAM is bundled inside UDPStreamer.so; create a symlink so MARTe2
# can dlopen("SineArrayGAM.so") before UDPStreamer has been registered.
SINE_LINK="${UDPSTREAMER_LIB}/SineArrayGAM.so"
if [ ! -e "${SINE_LINK}" ]; then
ln -sf "${UDPSTREAMER_LIB}/UDPStreamer.so" "${SINE_LINK}"
fi
# ── Optionally start WebUI ────────────────────────────────────────────────────
if [ "${START_WEBUI}" -eq 1 ]; then
echo "==> Starting WebUI on http://localhost:8080 (streamer at 127.0.0.1:44500)..."
"${WEBUI_BIN}" \
--streamer 127.0.0.1:44500 \
--listen :8080 \
--clientport 44900 &
WEBUI_PID=$!
echo "==> WebUI PID ${WEBUI_PID}"
fi
# ── Launch MARTe2 application ─────────────────────────────────────────────────
MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex"
CFG="${SCRIPT_DIR}/TestApp.cfg"
if [ ! -x "${MARTE_APP}" ]; then
echo "ERROR: MARTeApp.ex not found at ${MARTE_APP}" >&2
exit 1
fi
echo "==> Starting MARTe2 application (state=Running, 100 Hz)..."
echo "==> Press Ctrl+C to stop."
echo ""
cleanup() {
echo ""
echo "==> Stopping..."
if [ "${START_WEBUI}" -eq 1 ] && kill -0 "${WEBUI_PID}" 2>/dev/null; then
kill "${WEBUI_PID}"
fi
}
trap cleanup EXIT INT TERM
"${MARTE_APP}" \
-l RealTimeLoader \
-f "${CFG}" \
-s Running