Files
2026-06-26 09:11:10 +02:00

126 lines
4.3 KiB
C++

/**
* @file Hub.h
* @brief Central controller: owns the WS client, the source model, trigger
* state, capture, zoom caches and history info. Translates StreamHub WS
* messages into model updates and emits Qt signals for the UI.
*/
#pragma once
#include "Model.h"
#include "WsClient.h"
#include "Protocol.h"
#include <QObject>
#include <QString>
#include <vector>
#include <string>
#include <cstdint>
namespace shq {
/** Hi-res zoom cache (per plot; mirrors the ImGui client's PlotZoomCache). */
struct PlotZoomCache {
bool valid = false;
bool pending = false;
uint32_t reqId = 0;
double t0 = 0.0, t1 = 0.0; /* range of valid data */
double reqT0 = 0.0, reqT1 = 0.0; /* range of pending request */
std::vector<StreamHubClient::ZoomSignal> pts;
};
class Hub : public QObject {
Q_OBJECT
public:
explicit Hub(QObject* parent = nullptr);
void start(const QString& host, uint16_t port);
void reconnect(const QString& host, uint16_t port);
/* ---- Model access (GUI thread only) -------------------------------- */
std::vector<Source>& sources() { return sources_; }
const std::vector<Source>& sources() const { return sources_; }
TriggerCfgState& trigger() { return trigger_; }
const StreamHubClient::HistoryInfoMsg& historyInfo() const { return historyInfo_; }
uint32_t maxPoints() const { return maxPoints_; }
bool isConnected() const { return ws_.isConnected(); }
WsClient& ws() { return ws_; }
const StreamHubClient::CaptureFrame* capture() const {
return hasCapture_ ? &capture_ : nullptr;
}
void clearCapture() { hasCapture_ = false; }
PlotZoomCache& zoomCache(int i) { return zoomCache_[i]; }
PlotZoomCache& histZoomCache(int i) { return histZoomCache_[i]; }
int findSource(const std::string& id) const;
int findSignal(const Source& src, const std::string& name) const;
std::string slotKey(const PlotAssignment& a) const;
/* ---- Commands ------------------------------------------------------ */
void sendGetSources();
void sendGetStats();
void sendGetConfig(const std::string& sourceId);
void sendAddSource(const std::string& label, const std::string& addr,
const std::string& mcast, uint16_t dataPort);
void sendRemoveSource(const std::string& id);
void sendSaveSources();
void sendSetMaxPoints(uint32_t n);
void sendSetTrigger(const std::string& key, const std::string& edge,
double threshold, double windowSec, double prePercent,
const std::string& mode);
void sendArm();
void sendDisarm();
void sendRearm();
void sendTrigStop(bool stopped);
void requestZoom(int plotIdx, double t0, double t1, const std::string& csv);
void requestHistoryZoom(int plotIdx, double t0, double t1, const std::string& csv);
void sendHistoryInfo();
Q_SIGNALS:
void connectedChanged(bool connected);
void sourcesChanged();
void configChanged(const QString& sourceId);
void statsChanged();
void triggerStateChanged();
void captureReceived();
void zoomReceived(int plotIdx);
void historyZoomReceived(int plotIdx);
void historyInfoChanged();
void maxPointsChanged(uint32_t n);
private Q_SLOTS:
void onConnected(bool connected);
void onText(const QString& json);
void onBinary(const QByteArray& data);
private:
void onSources(const std::string& json);
void onConfig(const std::string& json);
void onStats(const std::string& json);
void onTriggerState(const std::string& json);
void onZoom(const std::string& json);
void onHistoryZoom(const std::string& json);
void onHistoryInfo(const std::string& json);
void onMaxPointsUpdated(const std::string& json);
WsClient ws_;
std::vector<Source> sources_;
TriggerCfgState trigger_;
uint32_t maxPoints_ = 1000000u;
StreamHubClient::CaptureFrame capture_;
bool hasCapture_ = false;
StreamHubClient::HistoryInfoMsg historyInfo_;
PlotZoomCache zoomCache_[kMaxPlotSlots];
PlotZoomCache histZoomCache_[kMaxPlotSlots];
uint32_t nextZoomReqId_ = 1;
double lastHistInfoReqMs_ = 0.0;
};
} /* namespace shq */