LibreVNA TCP driver
This commit is contained in:
parent
80c5fc0ff6
commit
2c86cf1d6c
@ -420,6 +420,12 @@ bool LibreVNADriver::setExtRef(QString option_in, QString option_out)
|
|||||||
return SendPacket(p);
|
return SendPacket(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LibreVNADriver::registerTypes()
|
||||||
|
{
|
||||||
|
qRegisterMetaType<Protocol::PacketInfo>();
|
||||||
|
qRegisterMetaType<TransmissionResult>();
|
||||||
|
}
|
||||||
|
|
||||||
void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
|
void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
|
||||||
{
|
{
|
||||||
emit passOnReceivedPacket(packet);
|
emit passOnReceivedPacket(packet);
|
||||||
@ -533,7 +539,7 @@ void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int LibreVNADriver::getMaxAmplitudePoints() const
|
unsigned int LibreVNADriver::getMaxAmplitudePoints() const
|
||||||
{
|
{
|
||||||
return limits_maxAmplitudePoints;
|
return limits_maxAmplitudePoints;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool setExtRef(QString option_in, QString option_out) override;
|
virtual bool setExtRef(QString option_in, QString option_out) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers metatypes within the Qt Framework.
|
||||||
|
*
|
||||||
|
* If the device driver uses a queued signal/slot connection with custom data types, these types must be registered before emitting the signal.
|
||||||
|
* Register them within this function with qRegisterMetaType<Type>("Name");
|
||||||
|
*/
|
||||||
|
virtual void registerTypes();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
signals:
|
signals:
|
||||||
// Required for the compound device driver
|
// Required for the compound device driver
|
||||||
@ -149,7 +157,7 @@ public:
|
|||||||
virtual bool SendPacket(const Protocol::PacketInfo& packet, std::function<void(TransmissionResult)> cb = nullptr, unsigned int timeout = 500) = 0;
|
virtual bool SendPacket(const Protocol::PacketInfo& packet, std::function<void(TransmissionResult)> cb = nullptr, unsigned int timeout = 500) = 0;
|
||||||
bool sendWithoutPayload(Protocol::PacketType type, std::function<void(TransmissionResult)> cb = nullptr);
|
bool sendWithoutPayload(Protocol::PacketType type, std::function<void(TransmissionResult)> cb = nullptr);
|
||||||
|
|
||||||
int getMaxAmplitudePoints() const;
|
unsigned int getMaxAmplitudePoints() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void receivedAnswer(const LibreVNADriver::TransmissionResult &result);
|
void receivedAnswer(const LibreVNADriver::TransmissionResult &result);
|
||||||
@ -162,7 +170,7 @@ protected:
|
|||||||
bool connected;
|
bool connected;
|
||||||
QString serial;
|
QString serial;
|
||||||
Info info;
|
Info info;
|
||||||
int limits_maxAmplitudePoints;
|
unsigned int limits_maxAmplitudePoints;
|
||||||
|
|
||||||
Protocol::DeviceStatusV1 lastStatus;
|
Protocol::DeviceStatusV1 lastStatus;
|
||||||
|
|
||||||
@ -182,4 +190,8 @@ protected:
|
|||||||
bool VNAAdjustPowerLevel;
|
bool VNAAdjustPowerLevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Protocol::PacketInfo)
|
||||||
|
Q_DECLARE_METATYPE(LibreVNADriver::TransmissionResult)
|
||||||
|
|
||||||
|
|
||||||
#endif // LIBREVNADRIVER_H
|
#endif // LIBREVNADRIVER_H
|
||||||
|
@ -0,0 +1,357 @@
|
|||||||
|
#include "librevnatcpdriver.h"
|
||||||
|
|
||||||
|
#include "CustomWidgets/informationbox.h"
|
||||||
|
#include "../deviceusblog.h"
|
||||||
|
#include "Util/util.h"
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QNetworkInterface>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static const QString service_name = "urn:schemas-upnp-org:device:LibreVNA:1";
|
||||||
|
static constexpr int DataPort = 19544;
|
||||||
|
static constexpr int LogPort = 19545;
|
||||||
|
static auto SSDPaddress = QHostAddress("239.255.255.250");
|
||||||
|
static constexpr int SSDPport = 1900;
|
||||||
|
|
||||||
|
LibreVNATCPDriver::LibreVNATCPDriver()
|
||||||
|
: LibreVNADriver()
|
||||||
|
{
|
||||||
|
// dataSocket = nullptr;
|
||||||
|
// logSocket = nullptr;
|
||||||
|
connected = false;
|
||||||
|
m_receiveThread = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
auto interfaces = QNetworkInterface::allInterfaces();
|
||||||
|
for(auto i : interfaces) {
|
||||||
|
qDebug() << "Creating socket for interface" << i.name();
|
||||||
|
auto socket = new QUdpSocket();
|
||||||
|
socket->bind(QHostAddress::AnyIPv4, 0, QUdpSocket::ShareAddress);
|
||||||
|
socket->setMulticastInterface(i);
|
||||||
|
qDebug() << socket->joinMulticastGroup(SSDPaddress, i);
|
||||||
|
connect(socket, &QUdpSocket::readyRead, this, [=](){
|
||||||
|
SSDPreceived(socket);
|
||||||
|
});
|
||||||
|
ssdpSockets.push_back(socket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LibreVNATCPDriver::getDriverName()
|
||||||
|
{
|
||||||
|
return "LibreVNA/TCP";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<QString> LibreVNATCPDriver::GetAvailableDevices()
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
data.append("M-SEARCH * HTTP/1.1\r\n"
|
||||||
|
"HOST: 239.255.255.250:1900\r\n"
|
||||||
|
"MAN: \"ssdp:discover\"\r\n"
|
||||||
|
"MX: 1\r\n"
|
||||||
|
"ST: ");
|
||||||
|
data.append(service_name);
|
||||||
|
data.append("\r\n"
|
||||||
|
"\r\n");
|
||||||
|
|
||||||
|
pruneDetectedDevices();
|
||||||
|
for(auto s : ssdpSockets) {
|
||||||
|
s->writeDatagram(data.data(), SSDPaddress, SSDPport);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO need delay here while still processing events
|
||||||
|
SynSleep::sleep(100);
|
||||||
|
|
||||||
|
std::set<QString> serials;
|
||||||
|
for(auto d : detectedDevices) {
|
||||||
|
serials.insert(d.serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
return serials;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LibreVNATCPDriver::connectTo(QString serial)
|
||||||
|
{
|
||||||
|
if(connected) {
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if this device is actually available
|
||||||
|
DetectedDevice devInfo;
|
||||||
|
bool available = false;
|
||||||
|
for(auto d : detectedDevices) {
|
||||||
|
if(d.serial == serial) {
|
||||||
|
devInfo = d;
|
||||||
|
available = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!available) {
|
||||||
|
// no location information about this device available
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt to connect to the device
|
||||||
|
// dataSocket = new QTcpSocket();
|
||||||
|
// logSocket = new QTcpSocket();
|
||||||
|
|
||||||
|
dataSocket.connectToHost(devInfo.address, DataPort);
|
||||||
|
logSocket.connectToHost(devInfo.address, LogPort);
|
||||||
|
|
||||||
|
// check if connection succeeds
|
||||||
|
if(!dataSocket.waitForConnected(1000) || !logSocket.waitForConnected(1000)) {
|
||||||
|
// at least one socket failed
|
||||||
|
dataSocket.close();
|
||||||
|
logSocket.close();
|
||||||
|
// delete dataSocket;
|
||||||
|
// delete logSocket;
|
||||||
|
// dataSocket = nullptr;
|
||||||
|
// logSocket = nullptr;
|
||||||
|
InformationBox::ShowError("Error", "TCP connection timed out");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sockets are connected now
|
||||||
|
dataBuffer.clear();
|
||||||
|
logBuffer.clear();
|
||||||
|
connect(&dataSocket, qOverload<QAbstractSocket::SocketError>(&QTcpSocket::error), this, &LibreVNATCPDriver::ConnectionLost, Qt::QueuedConnection);
|
||||||
|
connect(&logSocket, qOverload<QAbstractSocket::SocketError>(&QTcpSocket::error), this, &LibreVNATCPDriver::ConnectionLost, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
qInfo() << "TCP connection established" << flush;
|
||||||
|
this->serial = serial;
|
||||||
|
connected = true;
|
||||||
|
|
||||||
|
connect(&dataSocket, &QTcpSocket::readyRead, this, &LibreVNATCPDriver::ReceivedData, Qt::UniqueConnection);
|
||||||
|
connect(&logSocket, &QTcpSocket::readyRead, this, &LibreVNATCPDriver::ReceivedLog, Qt::UniqueConnection);
|
||||||
|
connect(&transmissionTimer, &QTimer::timeout, this, &LibreVNATCPDriver::transmissionTimeout, Qt::UniqueConnection);
|
||||||
|
connect(this, &LibreVNATCPDriver::receivedAnswer, this, &LibreVNATCPDriver::transmissionFinished, static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));
|
||||||
|
connect(this, &LibreVNATCPDriver::receivedPacket, this, &LibreVNATCPDriver::handleReceivedPacket, static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));
|
||||||
|
transmissionTimer.setSingleShot(true);
|
||||||
|
transmissionActive = false;
|
||||||
|
|
||||||
|
sendWithoutPayload(Protocol::PacketType::RequestDeviceInfo);
|
||||||
|
sendWithoutPayload(Protocol::PacketType::RequestDeviceStatus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibreVNATCPDriver::disconnect()
|
||||||
|
{
|
||||||
|
if(connected) {
|
||||||
|
setIdle();
|
||||||
|
transmissionTimer.stop();
|
||||||
|
transmissionQueue.clear();
|
||||||
|
transmissionActive = false;
|
||||||
|
dataSocket.close();
|
||||||
|
logSocket.close();
|
||||||
|
// delete dataSocket;
|
||||||
|
// delete logSocket;
|
||||||
|
// dataSocket = nullptr;
|
||||||
|
// logSocket = nullptr;
|
||||||
|
connected = false;
|
||||||
|
serial = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibreVNATCPDriver::registerTypes()
|
||||||
|
{
|
||||||
|
qDebug() << "Registering meta type: " << qRegisterMetaType<Protocol::PacketInfo>();
|
||||||
|
qDebug() << "Registering meta type: " << qRegisterMetaType<TransmissionResult>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibreVNATCPDriver::SSDPreceived(QUdpSocket *sock)
|
||||||
|
{
|
||||||
|
while(sock->hasPendingDatagrams()) {
|
||||||
|
QHostAddress sender;
|
||||||
|
quint16 senderPort;
|
||||||
|
QByteArray buf(sock->pendingDatagramSize(), Qt::Uninitialized);
|
||||||
|
QDataStream str(&buf, QIODevice::ReadOnly);
|
||||||
|
sock->readDatagram(buf.data(), buf.size(), &sender, &senderPort);
|
||||||
|
|
||||||
|
QString ssdp_string = QString(buf);
|
||||||
|
auto lines = ssdp_string.split("\r\n");
|
||||||
|
|
||||||
|
QString location, st, serial, max_age;
|
||||||
|
|
||||||
|
if(lines[0] != "HTTP/1.1 200 OK") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(QString l : lines) {
|
||||||
|
if(l.startsWith("LOCATION:")) {
|
||||||
|
location = l.split(" ")[1];
|
||||||
|
} else if(l.startsWith("ST:")) {
|
||||||
|
st = l.split(" ")[1];
|
||||||
|
} else if(l.startsWith("LibreVNA-serial:")) {
|
||||||
|
serial = l.split(" ")[1];
|
||||||
|
} else if(l.startsWith("CACHE-CONTROL:")) {
|
||||||
|
max_age = l.split("=")[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(location.isEmpty() || st.isEmpty() || serial.isEmpty() || max_age.isEmpty()) {
|
||||||
|
// some required field is missing
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// new device
|
||||||
|
DetectedDevice d;
|
||||||
|
d.address = QHostAddress(location);
|
||||||
|
d.maxAgeSeconds = max_age.toUInt();
|
||||||
|
d.responseTime = QDateTime::currentDateTime();
|
||||||
|
d.serial = serial;
|
||||||
|
addDetectedDevice(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibreVNATCPDriver::ReceivedData()
|
||||||
|
{
|
||||||
|
dataBuffer.append(dataSocket.readAll());
|
||||||
|
Protocol::PacketInfo packet;
|
||||||
|
uint16_t handled_len;
|
||||||
|
// qDebug() << "Received data";
|
||||||
|
do {
|
||||||
|
// qDebug() << "Decoding" << dataBuffer->getReceived() << "Bytes";
|
||||||
|
handled_len = Protocol::DecodeBuffer((uint8_t*) dataBuffer.data(), dataBuffer.size(), &packet);
|
||||||
|
// qDebug() << "Handled" << handled_len << "Bytes, type:" << (int) packet.type;
|
||||||
|
if(handled_len > 0) {
|
||||||
|
auto &log = DeviceUSBLog::getInstance();
|
||||||
|
if(packet.type != Protocol::PacketType::None) {
|
||||||
|
log.addPacket(packet, serial);
|
||||||
|
} else {
|
||||||
|
log.addInvalidBytes((uint8_t*) dataBuffer.data(), handled_len, serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataBuffer.remove(0, handled_len);
|
||||||
|
switch(packet.type) {
|
||||||
|
case Protocol::PacketType::Ack:
|
||||||
|
emit receivedAnswer(TransmissionResult::Ack);
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::Nack:
|
||||||
|
emit receivedAnswer(TransmissionResult::Nack);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// pass on to LibreVNADriver class
|
||||||
|
emit receivedPacket(packet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (handled_len > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibreVNATCPDriver::ReceivedLog()
|
||||||
|
{
|
||||||
|
logBuffer.append(logSocket.readAll());
|
||||||
|
uint16_t handled_len;
|
||||||
|
do {
|
||||||
|
handled_len = 0;
|
||||||
|
auto firstLinebreak = (uint8_t*) memchr((uint8_t*) logBuffer.data(), '\n', logBuffer.size());
|
||||||
|
if(firstLinebreak) {
|
||||||
|
handled_len = firstLinebreak - (uint8_t*) logBuffer.data();
|
||||||
|
auto line = QString::fromLatin1(logBuffer.data(), handled_len - 1);
|
||||||
|
emit LogLineReceived(line);
|
||||||
|
logBuffer.remove(0, handled_len + 1);
|
||||||
|
}
|
||||||
|
} while(handled_len > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibreVNATCPDriver::transmissionFinished(LibreVNADriver::TransmissionResult result)
|
||||||
|
{
|
||||||
|
lock_guard<mutex> lock(transmissionMutex);
|
||||||
|
// remove transmitted packet
|
||||||
|
// qDebug() << "Transmission finsished (" << result << "), queue at " << transmissionQueue.size() << " Outstanding ACKs:"<<outstandingAckCount;
|
||||||
|
if(transmissionQueue.empty()) {
|
||||||
|
qWarning() << "transmissionFinished with empty transmission queue, stray Ack? Result:" << result;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto t = transmissionQueue.dequeue();
|
||||||
|
if(result == TransmissionResult::Timeout) {
|
||||||
|
qWarning() << "transmissionFinished with timeout, packettype:" << (int) t.packet.type << "Device:" << serial;
|
||||||
|
}
|
||||||
|
if(result == TransmissionResult::Nack) {
|
||||||
|
qWarning() << "transmissionFinished with NACK";
|
||||||
|
}
|
||||||
|
if(t.callback) {
|
||||||
|
t.callback(result);
|
||||||
|
}
|
||||||
|
transmissionTimer.stop();
|
||||||
|
bool success = false;
|
||||||
|
while(!transmissionQueue.isEmpty() && !success) {
|
||||||
|
success = startNextTransmission();
|
||||||
|
if(!success) {
|
||||||
|
// failed to send this packet
|
||||||
|
auto t = transmissionQueue.dequeue();
|
||||||
|
if(t.callback) {
|
||||||
|
t.callback(TransmissionResult::InternalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(transmissionQueue.isEmpty()) {
|
||||||
|
transmissionActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LibreVNATCPDriver::SendPacket(const Protocol::PacketInfo &packet, std::function<void (LibreVNADriver::TransmissionResult)> cb, unsigned int timeout)
|
||||||
|
{
|
||||||
|
Transmission t;
|
||||||
|
t.packet = packet;
|
||||||
|
t.timeout = timeout;
|
||||||
|
t.callback = cb;
|
||||||
|
lock_guard<mutex> lock(transmissionMutex);
|
||||||
|
transmissionQueue.enqueue(t);
|
||||||
|
// qDebug() << "Enqueued packet, queue at " << transmissionQueue.size();
|
||||||
|
if(!transmissionActive) {
|
||||||
|
startNextTransmission();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibreVNATCPDriver::addDetectedDevice(const LibreVNATCPDriver::DetectedDevice &d)
|
||||||
|
{
|
||||||
|
for(auto &e : detectedDevices) {
|
||||||
|
if(e.serial == d.serial) {
|
||||||
|
// replace entry
|
||||||
|
e = d;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// serial not already present, add
|
||||||
|
detectedDevices.push_back(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibreVNATCPDriver::pruneDetectedDevices()
|
||||||
|
{
|
||||||
|
for(unsigned int i=0;i<detectedDevices.size();i++) {
|
||||||
|
auto d = detectedDevices[i];
|
||||||
|
if(d.responseTime.secsTo(QDateTime::currentDateTime()) > d.maxAgeSeconds) {
|
||||||
|
// too old, remove
|
||||||
|
detectedDevices.erase(detectedDevices.begin()+i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LibreVNATCPDriver::startNextTransmission()
|
||||||
|
{
|
||||||
|
if(transmissionQueue.isEmpty() || !connected) {
|
||||||
|
// nothing more to transmit
|
||||||
|
transmissionActive = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
transmissionActive = true;
|
||||||
|
auto t = transmissionQueue.head();
|
||||||
|
unsigned char buffer[1024];
|
||||||
|
unsigned int length = Protocol::EncodePacket(t.packet, buffer, sizeof(buffer));
|
||||||
|
if(!length) {
|
||||||
|
qCritical() << "Failed to encode packet";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto &log = DeviceUSBLog::getInstance();
|
||||||
|
log.addPacket(t.packet);
|
||||||
|
auto ret = dataSocket.write((char*) buffer, length);
|
||||||
|
if(ret < 0) {
|
||||||
|
qCritical() << "Error sending TCP data";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
transmissionTimer.start(t.timeout);
|
||||||
|
// qDebug() << "Transmission started, queue at " << transmissionQueue.size();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
|||||||
|
#ifndef LIBREVNATCPDRIVER_H
|
||||||
|
#define LIBREVNATCPDRIVER_H
|
||||||
|
|
||||||
|
#include "librevnadriver.h"
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <thread>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include <QQueue>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QUdpSocket>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
class LibreVNATCPDriver : public LibreVNADriver
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
LibreVNATCPDriver();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the driver name. It must be unique across all implemented drivers and is used to identify the driver
|
||||||
|
* @return driver name
|
||||||
|
*/
|
||||||
|
virtual QString getDriverName() override;
|
||||||
|
/**
|
||||||
|
* @brief Lists all available devices by their serial numbers
|
||||||
|
* @return Serial numbers of detected devices
|
||||||
|
*/
|
||||||
|
virtual std::set<QString> GetAvailableDevices() override;
|
||||||
|
/**
|
||||||
|
* @brief Connects to a device, given by its serial number
|
||||||
|
* @param serial Serial number of device that should be connected to
|
||||||
|
* @return true if connection successful, otherwise false
|
||||||
|
*/
|
||||||
|
virtual bool connectTo(QString serial) override;
|
||||||
|
/**
|
||||||
|
* @brief Disconnects from device. Has no effect if no device was connected
|
||||||
|
*/
|
||||||
|
virtual void disconnect() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers metatypes within the Qt Framework.
|
||||||
|
*
|
||||||
|
* If the device driver uses a queued signal/slot connection with custom data types, these types must be registered before emitting the signal.
|
||||||
|
* Register them within this function with qRegisterMetaType<Type>("Name");
|
||||||
|
*/
|
||||||
|
virtual void registerTypes();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void SSDPreceived(QUdpSocket *sock);
|
||||||
|
void ReceivedData();
|
||||||
|
void ReceivedLog();
|
||||||
|
void transmissionTimeout() {
|
||||||
|
transmissionFinished(TransmissionResult::Timeout);
|
||||||
|
}
|
||||||
|
void transmissionFinished(TransmissionResult result);
|
||||||
|
private:
|
||||||
|
static constexpr int EP_Data_Out_Addr = 0x01;
|
||||||
|
static constexpr int EP_Data_In_Addr = 0x81;
|
||||||
|
static constexpr int EP_Log_In_Addr = 0x82;
|
||||||
|
|
||||||
|
virtual bool SendPacket(const Protocol::PacketInfo& packet, std::function<void(TransmissionResult)> cb = nullptr, unsigned int timeout = 500) override;
|
||||||
|
|
||||||
|
// Sockets for SSDP protocol
|
||||||
|
std::vector<QUdpSocket*> ssdpSockets;
|
||||||
|
class DetectedDevice {
|
||||||
|
public:
|
||||||
|
QString serial;
|
||||||
|
QHostAddress address;
|
||||||
|
QDateTime responseTime;
|
||||||
|
int maxAgeSeconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
void addDetectedDevice(const DetectedDevice &d);
|
||||||
|
// removes entries that are too old
|
||||||
|
void pruneDetectedDevices();
|
||||||
|
std::vector<DetectedDevice> detectedDevices;
|
||||||
|
|
||||||
|
// Connection sockets
|
||||||
|
QTcpSocket dataSocket;
|
||||||
|
QTcpSocket logSocket;
|
||||||
|
|
||||||
|
QByteArray dataBuffer;
|
||||||
|
QByteArray logBuffer;
|
||||||
|
|
||||||
|
class Transmission {
|
||||||
|
public:
|
||||||
|
Protocol::PacketInfo packet;
|
||||||
|
unsigned int timeout;
|
||||||
|
std::function<void(TransmissionResult)> callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::mutex transmissionMutex;
|
||||||
|
QQueue<Transmission> transmissionQueue;
|
||||||
|
bool startNextTransmission();
|
||||||
|
QTimer transmissionTimer;
|
||||||
|
bool transmissionActive;
|
||||||
|
|
||||||
|
std::thread *m_receiveThread;
|
||||||
|
|
||||||
|
std::mutex accessMutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LibreVNATCPDriver_H
|
@ -249,12 +249,6 @@ void LibreVNAUSBDriver::disconnect()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibreVNAUSBDriver::registerTypes()
|
|
||||||
{
|
|
||||||
qDebug() << "Registering meta type: " << qRegisterMetaType<Protocol::PacketInfo>();
|
|
||||||
qDebug() << "Registering meta type: " << qRegisterMetaType<TransmissionResult>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LibreVNAUSBDriver::ReceivedData()
|
void LibreVNAUSBDriver::ReceivedData()
|
||||||
{
|
{
|
||||||
Protocol::PacketInfo packet;
|
Protocol::PacketInfo packet;
|
||||||
|
@ -10,9 +10,6 @@
|
|||||||
#include <QQueue>
|
#include <QQueue>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Protocol::PacketInfo)
|
|
||||||
Q_DECLARE_METATYPE(LibreVNADriver::TransmissionResult)
|
|
||||||
|
|
||||||
class USBInBuffer : public QObject {
|
class USBInBuffer : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@ -66,14 +63,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void disconnect() override;
|
virtual void disconnect() override;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Registers metatypes within the Qt Framework.
|
|
||||||
*
|
|
||||||
* If the device driver uses a queued signal/slot connection with custom data types, these types must be registered before emitting the signal.
|
|
||||||
* Register them within this function with qRegisterMetaType<Type>("Name");
|
|
||||||
*/
|
|
||||||
virtual void registerTypes();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ReceivedData();
|
void ReceivedData();
|
||||||
void ReceivedLog();
|
void ReceivedLog();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "devicedriver.h"
|
#include "devicedriver.h"
|
||||||
|
|
||||||
DeviceDriver *DeviceDriver::activeDriver = nullptr;
|
DeviceDriver *DeviceDriver::activeDriver = nullptr;
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ public:
|
|||||||
class SAMeasurement {
|
class SAMeasurement {
|
||||||
public:
|
public:
|
||||||
// Number of point in the sweep
|
// Number of point in the sweep
|
||||||
int pointNum;
|
unsigned int pointNum;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
// for non-zero span
|
// for non-zero span
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>USB Log</string>
|
<string>Device Log</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
@ -19,6 +19,11 @@
|
|||||||
<property name="headerHidden">
|
<property name="headerHidden">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">1</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -23,6 +23,7 @@ HEADERS += \
|
|||||||
Device/LibreVNA/firmwareupdatedialog.h \
|
Device/LibreVNA/firmwareupdatedialog.h \
|
||||||
Device/LibreVNA/frequencycaldialog.h \
|
Device/LibreVNA/frequencycaldialog.h \
|
||||||
Device/LibreVNA/librevnadriver.h \
|
Device/LibreVNA/librevnadriver.h \
|
||||||
|
Device/LibreVNA/librevnatcpdriver.h \
|
||||||
Device/LibreVNA/librevnausbdriver.h \
|
Device/LibreVNA/librevnausbdriver.h \
|
||||||
Device/LibreVNA/manualcontroldialog.h \
|
Device/LibreVNA/manualcontroldialog.h \
|
||||||
Device/LibreVNA/receivercaldialog.h \
|
Device/LibreVNA/receivercaldialog.h \
|
||||||
@ -174,6 +175,7 @@ SOURCES += \
|
|||||||
Device/LibreVNA/firmwareupdatedialog.cpp \
|
Device/LibreVNA/firmwareupdatedialog.cpp \
|
||||||
Device/LibreVNA/frequencycaldialog.cpp \
|
Device/LibreVNA/frequencycaldialog.cpp \
|
||||||
Device/LibreVNA/librevnadriver.cpp \
|
Device/LibreVNA/librevnadriver.cpp \
|
||||||
|
Device/LibreVNA/librevnatcpdriver.cpp \
|
||||||
Device/LibreVNA/librevnausbdriver.cpp \
|
Device/LibreVNA/librevnausbdriver.cpp \
|
||||||
Device/LibreVNA/manualcontroldialog.cpp \
|
Device/LibreVNA/manualcontroldialog.cpp \
|
||||||
Device/LibreVNA/receivercaldialog.cpp \
|
Device/LibreVNA/receivercaldialog.cpp \
|
||||||
|
@ -527,7 +527,7 @@ void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
|
|||||||
UpdateAverageCount();
|
UpdateAverageCount();
|
||||||
markerModel->updateMarkers();
|
markerModel->updateMarkers();
|
||||||
}
|
}
|
||||||
static int lastPoint = 0;
|
static unsigned int lastPoint = 0;
|
||||||
if(m_avg.pointNum > 0 && m_avg.pointNum != lastPoint + 1) {
|
if(m_avg.pointNum > 0 && m_avg.pointNum != lastPoint + 1) {
|
||||||
qWarning() << "Got point" << m_avg.pointNum << "but last received point was" << lastPoint << "("<<(m_avg.pointNum-lastPoint-1)<<"missed points)";
|
qWarning() << "Got point" << m_avg.pointNum << "but last received point was" << lastPoint << "("<<(m_avg.pointNum-lastPoint-1)<<"missed points)";
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,44 @@
|
|||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
class SynSleep: public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SynSleep(){
|
||||||
|
needRunning=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void sleep(){
|
||||||
|
if (needRunning==1)
|
||||||
|
loop.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(){
|
||||||
|
needRunning=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void finish(){
|
||||||
|
needRunning=0;
|
||||||
|
loop.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sleep(int ms) {
|
||||||
|
QTimer tim;
|
||||||
|
tim.setSingleShot(true);
|
||||||
|
auto ss = SynSleep();
|
||||||
|
connect(&tim, &QTimer::timeout, &ss, &SynSleep::finish);
|
||||||
|
tim.start(ms);
|
||||||
|
ss.sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QEventLoop loop;
|
||||||
|
int needRunning;
|
||||||
|
};
|
||||||
|
|
||||||
namespace Util {
|
namespace Util {
|
||||||
template<typename T> T Scale(T value, T from_low, T from_high, T to_low, T to_high, bool log_from = false, bool log_to = false) {
|
template<typename T> T Scale(T value, T from_low, T from_high, T to_low, T to_high, bool log_from = false, bool log_to = false) {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "modehandler.h"
|
#include "modehandler.h"
|
||||||
#include "modewindow.h"
|
#include "modewindow.h"
|
||||||
#include "Device/LibreVNA/librevnausbdriver.h"
|
#include "Device/LibreVNA/librevnausbdriver.h"
|
||||||
|
#include "Device/LibreVNA/librevnatcpdriver.h"
|
||||||
|
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
@ -101,6 +102,7 @@ AppWindow::AppWindow(QWidget *parent)
|
|||||||
|
|
||||||
// Register device drivers
|
// Register device drivers
|
||||||
deviceDrivers.push_back(new LibreVNAUSBDriver());
|
deviceDrivers.push_back(new LibreVNAUSBDriver());
|
||||||
|
deviceDrivers.push_back(new LibreVNATCPDriver());
|
||||||
|
|
||||||
for(auto driver : deviceDrivers) {
|
for(auto driver : deviceDrivers) {
|
||||||
driver->registerTypes();
|
driver->registerTypes();
|
||||||
@ -240,7 +242,7 @@ void AppWindow::SetupMenu()
|
|||||||
});
|
});
|
||||||
|
|
||||||
// connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl);
|
// connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl);
|
||||||
connect(ui->actionUSB_log, &QAction::triggered, this, &AppWindow::ShowUSBLog);
|
connect(ui->actionDevice_log, &QAction::triggered, this, &AppWindow::ShowDeviceLog);
|
||||||
// connect(ui->actionFirmware_Update, &QAction::triggered, this, &AppWindow::StartFirmwareUpdateDialog);
|
// connect(ui->actionFirmware_Update, &QAction::triggered, this, &AppWindow::StartFirmwareUpdateDialog);
|
||||||
// connect(ui->actionSource_Calibration, &QAction::triggered, this, &AppWindow::SourceCalibrationDialog);
|
// connect(ui->actionSource_Calibration, &QAction::triggered, this, &AppWindow::SourceCalibrationDialog);
|
||||||
// connect(ui->actionReceiver_Calibration, &QAction::triggered, this, &AppWindow::ReceiverCalibrationDialog);
|
// connect(ui->actionReceiver_Calibration, &QAction::triggered, this, &AppWindow::ReceiverCalibrationDialog);
|
||||||
@ -369,12 +371,13 @@ bool AppWindow::ConnectToDevice(QString serial, DeviceDriver *driver)
|
|||||||
connect(device, &DeviceDriver::LogLineReceived, &deviceLog, &DeviceLog::addLine);
|
connect(device, &DeviceDriver::LogLineReceived, &deviceLog, &DeviceLog::addLine);
|
||||||
connect(device, &DeviceDriver::ConnectionLost, this, &AppWindow::DeviceConnectionLost);
|
connect(device, &DeviceDriver::ConnectionLost, this, &AppWindow::DeviceConnectionLost);
|
||||||
connect(device, &DeviceDriver::StatusUpdated, this, &AppWindow::DeviceStatusUpdated);
|
connect(device, &DeviceDriver::StatusUpdated, this, &AppWindow::DeviceStatusUpdated);
|
||||||
connect(device, &DeviceDriver::releaseControl, [=](){
|
connect(device, &DeviceDriver::FlagsUpdated, this, &AppWindow::DeviceFlagsUpdated);
|
||||||
|
connect(device, &DeviceDriver::releaseControl, this, [=](){
|
||||||
if(lastActiveMode) {
|
if(lastActiveMode) {
|
||||||
modeHandler->activate(lastActiveMode);
|
modeHandler->activate(lastActiveMode);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(device, &DeviceDriver::acquireControl, [=](){
|
connect(device, &DeviceDriver::acquireControl, this, [=](){
|
||||||
lastActiveMode = modeHandler->getActiveMode();
|
lastActiveMode = modeHandler->getActiveMode();
|
||||||
modeHandler->deactivate(lastActiveMode);
|
modeHandler->deactivate(lastActiveMode);
|
||||||
});
|
});
|
||||||
@ -440,6 +443,8 @@ void AppWindow::DisconnectDevice()
|
|||||||
ui->menuDevice->removeAction(a);
|
ui->menuDevice->removeAction(a);
|
||||||
}
|
}
|
||||||
device->disconnectDevice();
|
device->disconnectDevice();
|
||||||
|
disconnect(device, nullptr, &deviceLog, nullptr);
|
||||||
|
disconnect(device, nullptr, this, nullptr);
|
||||||
device = nullptr;
|
device = nullptr;
|
||||||
}
|
}
|
||||||
ui->actionDisconnect->setEnabled(false);
|
ui->actionDisconnect->setEnabled(false);
|
||||||
@ -465,7 +470,7 @@ void AppWindow::DisconnectDevice()
|
|||||||
void AppWindow::DeviceConnectionLost()
|
void AppWindow::DeviceConnectionLost()
|
||||||
{
|
{
|
||||||
DisconnectDevice();
|
DisconnectDevice();
|
||||||
InformationBox::ShowError("Disconnected", "The USB connection to the device has been lost");
|
InformationBox::ShowError("Disconnected", "The connection to the device has been lost");
|
||||||
UpdateDeviceList();
|
UpdateDeviceList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1084,7 +1089,7 @@ void AppWindow::UpdateReference()
|
|||||||
device->setExtRef(toolbars.reference.type->currentText(), toolbars.reference.outFreq->currentText());
|
device->setExtRef(toolbars.reference.type->currentText(), toolbars.reference.outFreq->currentText());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppWindow::ShowUSBLog()
|
void AppWindow::ShowDeviceLog()
|
||||||
{
|
{
|
||||||
auto d = new DeviceUSBLogView();
|
auto d = new DeviceUSBLogView();
|
||||||
if(AppWindow::showGUI()) {
|
if(AppWindow::showGUI()) {
|
||||||
|
@ -66,7 +66,7 @@ private slots:
|
|||||||
void UpdateReferenceToolbar();
|
void UpdateReferenceToolbar();
|
||||||
void UpdateReference();
|
void UpdateReference();
|
||||||
// void UpdateAcquisitionFrequencies();
|
// void UpdateAcquisitionFrequencies();
|
||||||
void ShowUSBLog();
|
void ShowDeviceLog();
|
||||||
// void StartFirmwareUpdateDialog();
|
// void StartFirmwareUpdateDialog();
|
||||||
// void DeviceNeedsUpdate(int reported, int expected);
|
// void DeviceNeedsUpdate(int reported, int expected);
|
||||||
void DeviceStatusUpdated();
|
void DeviceStatusUpdated();
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
<addaction name="actionDisconnect"/>
|
<addaction name="actionDisconnect"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionUSB_log"/>
|
<addaction name="actionDevice_log"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuWindow">
|
<widget class="QMenu" name="menuWindow">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -221,12 +221,12 @@
|
|||||||
<string>Preset</string>
|
<string>Preset</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionUSB_log">
|
<action name="actionDevice_log">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>View USB log</string>
|
<string>View Device Log</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionCreate_Debug_Data">
|
<action name="actionCreate_Debug_Data">
|
||||||
|
@ -29,6 +29,7 @@ SOURCES += \
|
|||||||
../LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.cpp \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/frequencycaldialog.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/frequencycaldialog.cpp \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp \
|
||||||
|
../LibreVNA-GUI/Device/LibreVNA/librevnatcpdriver.cpp \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/librevnausbdriver.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/librevnausbdriver.cpp \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialog.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialog.cpp \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/receivercaldialog.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/receivercaldialog.cpp \
|
||||||
@ -199,6 +200,7 @@ HEADERS += \
|
|||||||
../LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.h \
|
../LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.h \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/frequencycaldialog.h \
|
../LibreVNA-GUI/Device/LibreVNA/frequencycaldialog.h \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/librevnadriver.h \
|
../LibreVNA-GUI/Device/LibreVNA/librevnadriver.h \
|
||||||
|
../LibreVNA-GUI/Device/LibreVNA/librevnatcpdriver.h \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/librevnausbdriver.h \
|
../LibreVNA-GUI/Device/LibreVNA/librevnausbdriver.h \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialog.h \
|
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialog.h \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/receivercaldialog.h \
|
../LibreVNA-GUI/Device/LibreVNA/receivercaldialog.h \
|
||||||
|
Loading…
Reference in New Issue
Block a user