Files
MARTe-Integrated-Components/Client/streamhub/Protocol.h
2026-06-14 14:09:51 +02:00

214 lines
7.4 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file Protocol.h
* @brief StreamHub wire protocol: binary frame parser + JSON builder/parser.
*/
#pragma once
#include "SignalBuffer.h"
#include <string>
#include <vector>
#include <functional>
#include <cstdint>
namespace StreamHubClient {
/* ── Signal metadata (mirrors UDPSSignalDescriptor fields used by UI) ─────── */
struct SignalMeta {
std::string name;
std::string unit;
int typeCode = 0;
int quantType = 0;
int timeMode = 0;
int timeSignalIdx = -1;
float samplingRate = 0.f;
double rangeMin = 0.0;
double rangeMax = 0.0;
uint32_t numRows = 1u;
uint32_t numCols = 1u;
uint32_t numElements = 1u; /* numRows × numCols */
};
/* ── Per-source statistics (hub "stats" broadcast, Go field names) ────────── */
struct SourceStats {
std::string state = "disconnected";
uint64_t totalReceived = 0;
uint64_t totalLost = 0;
double rateHz = 0.0;
double rateStdHz = 0.0;
double fragsPerCycle = 0.0;
double bytesPerCycle = 0.0;
double cycleAvgMs = 0.0;
double cycleStdMs = 0.0;
double cycleMinMs = 0.0;
double cycleMaxMs = 0.0;
double cycleHistMin = 0.0;
double cycleHistMax = 0.0;
double cycleHist[20] = {};
};
/* ── Source descriptor ────────────────────────────────────────────────────── */
struct SourceInfo {
std::string id;
std::string label;
std::string addr;
std::string state;
uint32_t port = 0;
};
/* ── Decoded push-frame signal data ──────────────────────────────────────── */
struct FrameSignal {
std::string name;
std::vector<double> t;
std::vector<double> v;
};
struct DataFrame {
std::string sourceId;
std::vector<FrameSignal> signals;
};
/* ── Zoom response ────────────────────────────────────────────────────────── */
struct ZoomSignal {
std::string name; /* full key "src:sig" */
std::vector<double> t;
std::vector<double> v;
};
struct ZoomResponse {
uint32_t reqId = 0;
std::vector<ZoomSignal> signals;
};
/* ── Trigger capture (binary frame version=2) ─────────────────────────────── */
struct CaptureSignal {
std::string key; /* full key "src:sig" */
std::vector<double> t;
std::vector<double> v;
};
struct CaptureFrame {
double trigTime = 0.0;
double preSec = 0.0;
double postSec = 0.0;
std::vector<CaptureSignal> signals;
};
/* ── Trigger state event ──────────────────────────────────────────────────── */
struct TriggerStateMsg {
std::string state; /* idle|armed|collecting|triggered */
std::string mode = "normal"; /* normal|single */
bool stopped = false;
bool hasTrigTime = false;
double trigTime = 0.0;
};
/*---------------------------------------------------------------------------*/
/* Binary frame parser */
/*---------------------------------------------------------------------------*/
/**
* @brief Parse one StreamHub binary push frame.
*
* Format:
* [1] version | [1] idLen | [idLen] sourceId | [4] numSignals
* per signal: [2] keyLen | [key] | [4] pairCount | [N×8] t | [N×8] v
*
* @return false if the frame is malformed.
*/
bool ParseBinaryFrame(const uint8_t* buf, size_t len, DataFrame& out);
/**
* @brief Parse a version=2 trigger-capture binary frame.
*
* Format:
* [1] version=2 | [8] trigTime | [8] preSec | [8] postSec | [4] nSig
* per signal: [2] keyLen | [key] | [4] N | [N×8] t | [N×8] v
*
* @return false if the frame is malformed or version != 2.
*/
bool ParseCaptureFrame(const uint8_t* buf, size_t len, CaptureFrame& out);
/*---------------------------------------------------------------------------*/
/* JSON command builders */
/*---------------------------------------------------------------------------*/
std::string BuildPing();
std::string BuildGetSources();
std::string BuildGetConfig(const std::string& sourceId);
std::string BuildGetStats();
std::string BuildAddSource(const std::string& label, const std::string& addr,
const std::string& multicastGroup = std::string(),
uint16_t dataPort = 0);
std::string BuildRemoveSource(const std::string& id);
std::string BuildArm();
std::string BuildDisarm();
std::string BuildRearm();
std::string BuildTrigStop(bool stopped);
std::string BuildSaveSources();
/** edge: "rising" | "falling" | "both"; mode: "normal" | "single". */
std::string BuildSetTrigger(const std::string& signalKey, const std::string& edge,
double threshold, double windowSec,
double prePercent, const std::string& mode);
/** signalsCsv: comma-separated full keys "src:sig,src:sig2"; n<=0 → raw. */
std::string BuildZoom(uint32_t reqId, double t0, double t1, int n,
const std::string& signalsCsv);
/** History zoom: same shape as zoom but reads from disk history. */
std::string BuildHistoryZoom(uint32_t reqId, double t0, double t1, int n,
const std::string& signalsCsv);
std::string BuildHistoryInfo();
std::string BuildSetMaxPoints(uint32_t n);
/*---------------------------------------------------------------------------*/
/* JSON event parsers */
/*---------------------------------------------------------------------------*/
/** @brief Extract the "type" field from a JSON text frame. */
std::string ParseType(const std::string& json);
/** @brief Parse a "sources" event. */
bool ParseSources(const std::string& json, std::vector<SourceInfo>& out);
/** @brief Parse a "config" event (one source). */
bool ParseConfig(const std::string& json, std::string& sourceId,
int& publishMode, std::vector<SignalMeta>& signals);
/** @brief Parse a "stats" event. */
bool ParseStats(const std::string& json,
std::vector<std::pair<std::string, SourceStats>>& out);
/** @brief Parse a "triggerState" event. */
bool ParseTriggerState(const std::string& json, TriggerStateMsg& out);
/** @brief Parse a "zoom" response. */
bool ParseZoom(const std::string& json, ZoomResponse& out);
/** @brief Parse a "historyInfo" event. */
struct HistorySignalRange {
std::string key;
double t0 = 0.0, t1 = 0.0;
uint32_t count = 0, capacity = 0;
};
struct HistoryInfoMsg {
bool enabled = false;
double durationHours = 0.0;
uint32_t decimation = 0;
std::vector<HistorySignalRange> signals;
};
bool ParseHistoryInfo(const std::string& json, HistoryInfoMsg& out);
/** @brief Parse a "maxPointsUpdated" event. */
bool ParseMaxPointsUpdated(const std::string& json, uint32_t& maxPoints);
} /* namespace StreamHubClient */