Implemented client datasource

This commit is contained in:
Martino Ferrari
2026-06-25 00:45:45 +02:00
parent dca4872976
commit 0412c20edd
28 changed files with 3448 additions and 618 deletions
@@ -0,0 +1,204 @@
/**
* @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_ */