/** * @file UDPStreamerClient.h * @brief Header file for class UDPStreamerClient * @date 24/06/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 UDPStreamerClient * with all of its public, protected and private members. * * The UDPStreamerClient is an input DataSource that receives signal data from * a UDPStreamer server over the network. It reuses the StreamHub hub's network * code base: transport, fragment reassembly, multicast and auto-reconnect are * delegated to the shared UDPSClient receiver, and this class only implements * the UDPSClientListener callbacks to validate the CONFIG and decode DATA into * the real-time signal memory. */ #ifndef UDPSTREAMERCLIENT_H_ #define UDPSTREAMERCLIENT_H_ /*---------------------------------------------------------------------------*/ /* Standard header includes */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Project header includes */ /*---------------------------------------------------------------------------*/ #include "EventSem.h" #include "FastPollingMutexSem.h" #include "MemoryDataSourceI.h" #include "StreamString.h" #include "TypeDescriptor.h" #include "UDPSClient.h" /*---------------------------------------------------------------------------*/ /* Class declaration */ /*---------------------------------------------------------------------------*/ namespace MARTe { /** * @brief Per-signal decode metadata resolved from the server CONFIG packet. */ struct UDPStreamerClientSignal { StreamString name; /**< Signal name (must match server). */ TypeDescriptor type; /**< MARTe2 destination type. */ uint8 quantType; /**< UDPS_QUANT_* code from CONFIG. */ uint32 numElements; /**< Element count (scalar = 1). */ float64 rangeMin; /**< Dequantisation lower bound. */ float64 rangeMax; /**< Dequantisation upper bound. */ uint32 srcByteSize; /**< Destination byte size for the signal. */ uint32 wireElemBytes; /**< Bytes per element on the wire. */ uint32 bufferOffset; /**< Offset of this signal in the flat buffer. */ }; /** * @brief A DataSource that receives signal data from a UDPStreamer server. * * @details This input DataSource owns a shared ::MARTe::UDPSClient (the same * receiver used by the StreamHub hub) which runs a background thread, connects * to the server, reassembles fragmented updates and auto-reconnects on silence. * The CONFIG and DATA payloads are delivered through the UDPSClientListener * callbacks; DATA is decoded into a double-buffered staging area which the * real-time thread copies into signal memory during Synchronise(). * * Two operating modes are selected by the presence or absence of MulticastGroup. * * @par Top-level configuration parameters * | Parameter | Type | Default | Description | * |-----------------|---------|--------------|-------------| * | ServerAddress | string | "127.0.0.1" | UDPStreamer server IP address. | * | Port | uint16 | 44500 | Server port (CONNECT/UDP unicast, TCP control multicast). | * | MulticastGroup | string | *(absent)* | Enables multicast mode. IPv4 multicast address. | * | DataPort | uint16 | Port+1 | UDP port for DATA datagrams in multicast mode. | * | MaxPayloadSize | uint32 | 1400 | Maximum payload bytes per datagram (excluding header). | * | CPUMask | uint32 | 0xFFFFFFFF | CPU affinity bitmask for the background thread. | * | StackSize | uint32 | 65536 | Stack size in bytes for the background thread. | * * The client's signal configuration must match the server's: signal count, * names and element counts are validated against the received CONFIG. */ class UDPStreamerClient : public MemoryDataSourceI, public UDPSClientListener { public: CLASS_REGISTER_DECLARATION() /** * @brief Constructor. Initialises all members to safe defaults. */ UDPStreamerClient(); /** * @brief Destructor. Stops the background receiver and frees memory. */ virtual ~UDPStreamerClient(); /** * @brief Parses top-level configuration and configures the UDPSClient. */ virtual bool Initialise(StructuredDataI &data); /** * @brief Validates signal types and builds the per-signal metadata array. */ virtual bool SetConfiguredDatabase(StructuredDataI &data); /** * @brief Allocates signal memory plus readyBuffer and scratchBuffer. */ virtual bool AllocateMemory(); /** * @brief Returns "MemoryMapSynchronisedInputBroker" for InputSignals. */ virtual const char8 *GetBrokerName(StructuredDataI &data, const SignalDirection direction); /** * @brief Copies the latest received data into signal memory. */ virtual bool Synchronise(); /** * @brief Starts the background receiver on the first state transition. */ virtual bool PrepareNextState(const char8 *const currentStateName, const char8 *const nextStateName); /* ---- UDPSClientListener callbacks (invoked from the receiver thread) ---- */ /** * @brief Validates a reassembled CONFIG payload against the local signals. */ virtual void OnUDPSConfig(const uint8 *payload, uint32 payloadSize); /** * @brief Decodes a reassembled DATA payload into the staging buffer. */ virtual void OnUDPSData(const uint8 *payload, uint32 payloadSize); /** * @brief Logs that the server connection is established. */ virtual void OnUDPSConnected(); /** * @brief Invalidates the CONFIG so stale data is not published. */ virtual void OnUDPSDisconnected(); private: /** * @brief Decodes a single snapshot from a DATA payload into @p dst. * @details Mirrors the StreamHub hub layout (UDPSourceSession): an 8-byte * HRT timestamp, an optional 4-byte sample count (Accumulate mode), then * per-signal data in CONFIG order. For accumulated scalars the most recent * sample is published. */ void DecodeSnapshot(const uint8 *payload, uint32 size, uint8 *dst); /* Configuration parameters */ StreamString serverAddress; /**< Server IP address. */ uint16 port; /**< Server port. */ uint32 maxPayloadSize; /**< Max payload bytes per datagram. */ uint32 cpuMask; /**< Background thread CPU affinity. */ uint32 stackSize; /**< Background thread stack size. */ StreamString multicastGroup; /**< Multicast group IP; empty = unicast. */ uint16 dataPort; /**< UDP port for DATA datagrams (multicast). */ bool useMulticast; /**< True when MulticastGroup is set. */ /* Signal metadata */ uint32 numSigs; /**< Number of signals. */ UDPStreamerClientSignal *signalInfos; /**< Per-signal metadata (heap). */ uint32 totalSrcBytes; /**< Total destination signal bytes. */ bool configValidated; /**< True after a valid CONFIG. */ uint8 publishMode; /**< UDPS_PUBLISH_* from CONFIG. */ /* Shared receiver (same code base as the StreamHub hub) */ UDPSClient client; /**< Transport, reassembly and reconnect. */ bool receiverUp; /**< True once the receiver thread is started. */ /* Double-buffering for RT safety */ uint8 *readyBuffer; /**< Protected copy of decoded signal data. */ uint8 *scratchBuffer; /**< Receiver-thread-private decode buffer. */ FastPollingMutexSem bufMutex; /**< Protects readyBuffer. */ EventSem dataSem; /**< Wakes the RT thread on new data. */ bool newDataReady; /**< Set when readyBuffer has fresh data. */ }; } /* namespace MARTe */ #endif /* UDPSTREAMERCLIENT_H_ */