added streaming servers

This commit is contained in:
Jan Käberich 2024-06-20 15:56:38 +02:00
parent 2ba954537b
commit 6ca54547bb
11 changed files with 457 additions and 12 deletions

View file

@ -155,6 +155,7 @@ HEADERS += \
preferences.h \
savable.h \
scpi.h \
streamingserver.h \
tcpserver.h \
touchstone.h \
unit.h
@ -301,6 +302,7 @@ SOURCES += \
preferences.cpp \
savable.cpp \
scpi.cpp \
streamingserver.cpp \
tcpserver.cpp \
touchstone.cpp \
unit.cpp

View file

@ -530,6 +530,8 @@ void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
}
}
window->addStreamingData(m_avg, AppWindow::SADataType::Raw);
if(normalize.measuring) {
if(average.currentSweep() == averages) {
// this is the last averaging sweep, use values for normalization
@ -561,6 +563,8 @@ void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
}
}
window->addStreamingData(m_avg, AppWindow::SADataType::Normalized);
traceModel.addSAData(m_avg, settings);
emit dataChanged();
if(m_avg.pointNum == DeviceDriver::SApoints() - 1) {

View file

@ -931,6 +931,9 @@ void VNA::NewDatapoint(DeviceDriver::VNAMeasurement m)
}
m_avg = average.process(m_avg);
window->addStreamingData(m_avg, AppWindow::VNADataType::Raw);
if(average.settled()) {
setOperationPending(false);
}
@ -955,6 +958,8 @@ void VNA::NewDatapoint(DeviceDriver::VNAMeasurement m)
cal.correctMeasurement(m_avg);
window->addStreamingData(m_avg, AppWindow::VNADataType::Calibrated);
TraceMath::DataType type;
if(settings.zerospan) {
type = TraceMath::DataType::TimeZeroSpan;
@ -983,6 +988,9 @@ void VNA::NewDatapoint(DeviceDriver::VNAMeasurement m)
deembedding.Deembed(m_avg);
traceModel.addVNAData(m_avg, type, true);
}
window->addStreamingData(m_avg, AppWindow::VNADataType::Deembedded);
emit dataChanged();
if(m_avg.pointNum == settings.npoints - 1) {
UpdateAverageCount();

View file

@ -70,6 +70,11 @@ AppWindow::AppWindow(QWidget *parent)
, deviceActionGroup(new QActionGroup(this))
, ui(new Ui::MainWindow)
, server(nullptr)
, streamVNARawData(nullptr)
, streamVNACalibratedData(nullptr)
, streamVNADeembeddedData(nullptr)
, streamSARawData(nullptr)
, streamSANormalizedData(nullptr)
, appVersion(APP_VERSION)
, appGitHash(APP_GIT_HASH)
{
@ -97,6 +102,8 @@ AppWindow::AppWindow(QWidget *parent)
Preferences::getInstance().load();
}
auto &p = Preferences::getInstance();
device = nullptr;
// vdevice = nullptr;
modeHandler = nullptr;
@ -109,9 +116,25 @@ AppWindow::AppWindow(QWidget *parent)
port = Preferences::getInstance().SCPIServer.port;
}
StartTCPServer(port);
Preferences::getInstance().manualTCPport();
} else if(Preferences::getInstance().SCPIServer.enabled) {
StartTCPServer(Preferences::getInstance().SCPIServer.port);
p.manualTCPport();
} else if(p.SCPIServer.enabled) {
StartTCPServer(p.SCPIServer.port);
}
if(p.StreamingServers.VNARawData.enabled) {
streamVNARawData = new StreamingServer(p.StreamingServers.VNARawData.port);
}
if(p.StreamingServers.VNACalibratedData.enabled) {
streamVNACalibratedData = new StreamingServer(p.StreamingServers.VNACalibratedData.port);
}
if(p.StreamingServers.VNADeembeddedData.enabled) {
streamVNADeembeddedData = new StreamingServer(p.StreamingServers.VNADeembeddedData.port);
}
if(p.StreamingServers.SARawData.enabled) {
streamSARawData = new StreamingServer(p.StreamingServers.SARawData.port);
}
if(p.StreamingServers.SANormalizedData.enabled) {
streamSANormalizedData = new StreamingServer(p.StreamingServers.SANormalizedData.port);
}
ui->setupUi(this);
@ -1019,6 +1042,25 @@ void AppWindow::preferencesChanged()
StopTCPServer();
StartTCPServer(p.SCPIServer.port);
}
auto updateStreamingServer = [](StreamingServer **server, bool enabled, int port) {
if(*server && !enabled) {
delete *server;
*server = nullptr;
} else if(!*server && enabled) {
*server = new StreamingServer(port);
} else if(*server && (*server)->getPort() != port) {
delete *server;
*server = new StreamingServer(port);
}
};
updateStreamingServer(&streamVNARawData, p.StreamingServers.VNARawData.enabled, p.StreamingServers.VNARawData.port);
updateStreamingServer(&streamVNACalibratedData, p.StreamingServers.VNACalibratedData.enabled, p.StreamingServers.VNACalibratedData.port);
updateStreamingServer(&streamVNADeembeddedData, p.StreamingServers.VNADeembeddedData.enabled, p.StreamingServers.VNADeembeddedData.port);
updateStreamingServer(&streamSARawData, p.StreamingServers.SARawData.enabled, p.StreamingServers.SARawData.port);
updateStreamingServer(&streamSANormalizedData, p.StreamingServers.SANormalizedData.enabled, p.StreamingServers.SANormalizedData.port);
// averaging mode may have changed, update for all relevant modes
for (auto m : modeHandler->getModes())
{
@ -1055,6 +1097,33 @@ SCPI* AppWindow::getSCPI()
return &scpi;
}
void AppWindow::addStreamingData(const DeviceDriver::VNAMeasurement &m, VNADataType type)
{
StreamingServer *server = nullptr;
switch(type) {
case VNADataType::Raw: server = streamVNARawData; break;
case VNADataType::Calibrated: server = streamVNACalibratedData; break;
case VNADataType::Deembedded: server = streamVNADeembeddedData; break;
}
if(server) {
server->addData(m);
}
}
void AppWindow::addStreamingData(const DeviceDriver::SAMeasurement &m, SADataType type)
{
StreamingServer *server = nullptr;
switch(type) {
case SADataType::Raw: server = streamSARawData; break;
case SADataType::Normalized: server = streamSANormalizedData; break;
}
if(server) {
server->addData(m);
}
}
void AppWindow::setModeStatus(QString msg)
{
lModeInfo.setText(msg);

View file

@ -10,6 +10,7 @@
#include "preferences.h"
#include "scpi.h"
#include "tcpserver.h"
#include "streamingserver.h"
#include "Device/devicedriver.h"
#include <QWidget>
@ -52,6 +53,21 @@ public:
SCPI* getSCPI();
enum class VNADataType {
Raw = 0,
Calibrated = 1,
Deembedded = 2,
};
void addStreamingData(const DeviceDriver::VNAMeasurement &m, VNADataType type);
enum class SADataType {
Raw = 0,
Normalized = 1,
};
void addStreamingData(const DeviceDriver::SAMeasurement &m, SADataType type);
public slots:
void setModeStatus(QString msg);
@ -143,6 +159,11 @@ private:
SCPI scpi;
TCPServer *server;
StreamingServer *streamVNARawData;
StreamingServer *streamVNACalibratedData;
StreamingServer *streamVNADeembeddedData;
StreamingServer *streamSARawData;
StreamingServer *streamSANormalizedData;
QString appVersion;
QString appGitHash;

View file

@ -320,6 +320,17 @@ void PreferencesDialog::setInitialGUIState()
ui->SCPIServerEnabled->setChecked(p->SCPIServer.enabled);
ui->SCPIServerPort->setValue(p->SCPIServer.port);
ui->streamingServerVNArawEnabled->setChecked(p->StreamingServers.VNARawData.enabled);
ui->streamingServerVNArawPort->setValue(p->StreamingServers.VNARawData.port);
ui->streamingServerVNAcalibratedEnabled->setChecked(p->StreamingServers.VNACalibratedData.enabled);
ui->streamingServerVNAcalibratedPort->setValue(p->StreamingServers.VNACalibratedData.port);
ui->streamingServerVNAdeembeddedEnabled->setChecked(p->StreamingServers.VNADeembeddedData.enabled);
ui->streamingServerVNAdeembeddedPort->setValue(p->StreamingServers.VNADeembeddedData.port);
ui->streamingServerSArawEnabled->setChecked(p->StreamingServers.SARawData.enabled);
ui->streamingServerSArawPort->setValue(p->StreamingServers.SARawData.port);
ui->streamingServerSAnormalizedEnabled->setChecked(p->StreamingServers.SANormalizedData.enabled);
ui->streamingServerSAnormalizedPort->setValue(p->StreamingServers.SANormalizedData.port);
ui->DebugMaxUSBlogSize->setValue(p->Debug.USBlogSizeLimit);
ui->DebugSaveTraceData->setChecked(p->Debug.saveTraceData);
@ -420,6 +431,17 @@ void PreferencesDialog::updateFromGUI()
p->SCPIServer.enabled = ui->SCPIServerEnabled->isChecked();
p->SCPIServer.port = ui->SCPIServerPort->value();
p->StreamingServers.VNARawData.enabled = ui->streamingServerVNArawEnabled->isChecked();
p->StreamingServers.VNARawData.port = ui->streamingServerVNArawPort->value();
p->StreamingServers.VNACalibratedData.enabled = ui->streamingServerVNAcalibratedEnabled->isChecked();
p->StreamingServers.VNACalibratedData.port = ui->streamingServerVNAcalibratedPort->value();
p->StreamingServers.VNADeembeddedData.enabled = ui->streamingServerVNAdeembeddedEnabled->isChecked();
p->StreamingServers.VNADeembeddedData.port = ui->streamingServerVNAdeembeddedPort->value();
p->StreamingServers.SARawData.enabled = ui->streamingServerSArawEnabled->isChecked();
p->StreamingServers.SARawData.port = ui->streamingServerSArawPort->value();
p->StreamingServers.SANormalizedData.enabled = ui->streamingServerSAnormalizedEnabled->isChecked();
p->StreamingServers.SANormalizedData.port = ui->streamingServerSAnormalizedPort->value();
p->Debug.USBlogSizeLimit = ui->DebugMaxUSBlogSize->value();
p->Debug.saveTraceData = ui->DebugSaveTraceData->isChecked();

View file

@ -163,6 +163,28 @@ public:
bool enabled;
int port;
} SCPIServer;
struct {
struct {
bool enabled;
int port;
} VNARawData;
struct {
bool enabled;
int port;
} VNACalibratedData;
struct {
bool enabled;
int port;
} VNADeembeddedData;
struct {
bool enabled;
int port;
} SARawData;
struct {
bool enabled;
int port;
} SANormalizedData;
} StreamingServers;
struct {
double USBlogSizeLimit;
bool saveTraceData;
@ -273,6 +295,16 @@ private:
{&Marker.symbolStyle, "Marker.symbolStyle", MarkerSymbolStyle::EmptyNumberAbove},
{&SCPIServer.enabled, "SCPIServer.enabled", true},
{&SCPIServer.port, "SCPIServer.port", 19542},
{&StreamingServers.VNARawData.enabled, "StreamingServers.VNARawData.enabled", false},
{&StreamingServers.VNARawData.port, "StreamingServers.VNARawData.port", 19000},
{&StreamingServers.VNACalibratedData.enabled, "StreamingServers.VNACalibratedData.enabled", false},
{&StreamingServers.VNACalibratedData.port, "StreamingServers.VNACalibratedData.port", 19001},
{&StreamingServers.VNADeembeddedData.enabled, "StreamingServers.VNADeembeddedData.enabled", false},
{&StreamingServers.VNADeembeddedData.port, "StreamingServers.VNADeembeddedData.port", 19002},
{&StreamingServers.SARawData.enabled, "StreamingServers.sARawData.enabled", false},
{&StreamingServers.SARawData.port, "StreamingServers.sARawData.port", 19100},
{&StreamingServers.SANormalizedData.enabled, "StreamingServers.SANormalizedData.enabled", false},
{&StreamingServers.SANormalizedData.port, "StreamingServers.SANormalizedData.port", 19101},
{&Debug.USBlogSizeLimit, "Debug.USBlogSizeLimit", 10000000.0},
{&Debug.saveTraceData, "Debug.saveTraceData", false},
}};

View file

@ -68,6 +68,11 @@
<string>SCPI Server</string>
</property>
</item>
<item>
<property name="text">
<string>Streaming Servers</string>
</property>
</item>
<item>
<property name="text">
<string>Debug</string>
@ -93,7 +98,7 @@
</size>
</property>
<property name="currentIndex">
<number>3</number>
<number>5</number>
</property>
<widget class="QWidget" name="Startup">
<layout class="QHBoxLayout" name="horizontalLayout_4">
@ -698,8 +703,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>697</width>
<height>563</height>
<width>565</width>
<height>477</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_21">
@ -939,8 +944,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>683</width>
<height>1058</height>
<width>553</width>
<height>1075</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_22">
@ -1779,8 +1784,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>168</width>
<height>127</height>
<width>697</width>
<height>563</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
@ -1857,6 +1862,199 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="StreamingServers">
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<layout class="QVBoxLayout" name="verticalLayout_23">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_32">
<property name="text">
<string>VNA raw data:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="streamingServerVNArawEnabled">
<property name="text">
<string>Enabled</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_33">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="streamingServerVNArawPort">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_55">
<property name="text">
<string>VNA calibrated data:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="streamingServerVNAcalibratedEnabled">
<property name="text">
<string>Enabled</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_34">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QSpinBox" name="streamingServerVNAcalibratedPort">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_57">
<property name="text">
<string>VNA de-embedded data:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="streamingServerVNAdeembeddedEnabled">
<property name="text">
<string>Enabled</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_56">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QSpinBox" name="streamingServerVNAdeembeddedPort">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_59">
<property name="text">
<string>SA raw data:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="streamingServerSArawEnabled">
<property name="text">
<string>Enabled</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_58">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QSpinBox" name="streamingServerSArawPort">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_61">
<property name="text">
<string>SA normalized data:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="streamingServerSAnormalizedEnabled">
<property name="text">
<string>Enabled</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLabel" name="label_60">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QSpinBox" name="streamingServerSAnormalizedPort">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_8">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>316</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="Debug">
<layout class="QVBoxLayout" name="verticalLayout_29">
<item>
@ -1869,8 +2067,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>215</width>
<height>168</height>
<width>697</width>
<height>563</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_19">

View file

@ -0,0 +1,60 @@
#include "streamingserver.h"
#include "json.hpp"
StreamingServer::StreamingServer(int port)
{
this->port = port;
server.listen(QHostAddress::Any, port);
connect(&server, &QTcpServer::newConnection, [&](){
auto socket = server.nextPendingConnection();
sockets.insert(socket);
connect(socket, &QTcpSocket::stateChanged, [this, socket](QAbstractSocket::SocketState state){
if (state == QAbstractSocket::UnconnectedState)
{
sockets.erase(socket);
socket->deleteLater();
}
});
});
}
void StreamingServer::addData(const DeviceDriver::VNAMeasurement &m)
{
nlohmann::json j;
j["pointNum"] = m.pointNum;
j["frequency"] = m.frequency;
j["dBm"] = m.dBm;
j["Z0"] = m.Z0;
nlohmann::json jp;
for(auto const &p : m.measurements) {
jp[QString(p.first+"_real").toStdString()] = p.second.real();
jp[QString(p.first+"_imag").toStdString()] = p.second.imag();
}
j["measurements"] = jp;
std::string toSend = j.dump();
for(auto s : sockets) {
if(s->isOpen()) {
s->write(QByteArray::fromStdString(toSend+'\n'));
}
}
}
void StreamingServer::addData(const DeviceDriver::SAMeasurement &m)
{
nlohmann::json j;
j["pointNum"] = m.pointNum;
j["frequency"] = m.frequency;
nlohmann::json jp;
for(auto const &p : m.measurements) {
jp[p.first.toStdString()] = p.second;
}
j["measurements"] = jp;
std::string toSend = j.dump();
for(auto s : sockets) {
if(s->isOpen()) {
s->write(QByteArray::fromStdString(toSend+'\n'));
}
}
}

View file

@ -0,0 +1,27 @@
#ifndef STREAMINGSERVER_H
#define STREAMINGSERVER_H
#include <QTcpServer>
#include <QTcpSocket>
#include <set>
#include "Device/devicedriver.h"
class StreamingServer : public QObject
{
Q_OBJECT
public:
StreamingServer(int port);
void addData(const DeviceDriver::VNAMeasurement &m);
void addData(const DeviceDriver::SAMeasurement &m);
int getPort() {return port;}
private:
int port;
QTcpServer server;
std::set<QTcpSocket*> sockets;
};
#endif // STREAMINGSERVER_H

View file

@ -147,6 +147,7 @@ SOURCES += \
../LibreVNA-GUI/savable.cpp \
../LibreVNA-GUI/scpi.cpp \
../LibreVNA-GUI/tcpserver.cpp \
../LibreVNA-GUI/streamingserver.cpp \
../LibreVNA-GUI/touchstone.cpp \
../LibreVNA-GUI/unit.cpp \
main.cpp \
@ -338,6 +339,7 @@ HEADERS += \
../LibreVNA-GUI/savable.h \
../LibreVNA-GUI/scpi.h \
../LibreVNA-GUI/tcpserver.h \
../LibreVNA-GUI/streamingserver.h \
../LibreVNA-GUI/touchstone.h \
../LibreVNA-GUI/unit.h \
parametertests.h \