Skip to content

Commit ca25969

Browse files
committed
Startup and communication bugfixes
- reduce amount of mode switched when starting and loading setups - improve logging for errors during HIL tests - fix small USB communication bugs
1 parent 733d0ff commit ca25969

File tree

14 files changed

+148
-44
lines changed

14 files changed

+148
-44
lines changed

Software/Integrationtests/Integrationtest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import unittest
2+
import glob, os
23

34
testmodules = [
45
'tests.TestUpdate', # Must go first because it updates the connected VNA to the firwmare which should be tested
@@ -16,6 +17,12 @@
1617

1718
suite = unittest.TestSuite()
1819

20+
# Clean up potential error logs from previous test runs
21+
for f in glob.glob("errorlog_*"):
22+
os.remove(f)
23+
for f in glob.glob("packetlog_*"):
24+
os.remove(f)
25+
1926
for t in testmodules:
2027
try:
2128
# If the module defines a suite() function, call it to get the suite.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
0.027: [debug] Application start
2+
0.045: [info] Listening on port 19544
3+
0.060: [debug] Activating mode "Vector Network Analyzer"
4+
0.068: [debug] Updated device list, found 1
5+
0.068: [debug] Trying to connect to "208A367A4B42"
6+
0.068: [debug] Attempting to connect to device...
7+
0.075: [info] USB connection established
8+
0.075: [debug] Receive thread started
9+
0.075: [debug] Transmission started (packet type 15 ), queue at 1
10+
0.078: [info] Connected to "208A367A4B42"
11+
0.079: [debug] Transmission started (packet type 26 ), queue at 1
12+
0.082: [debug] No default calibration file set for this device
13+
0.082: [debug] Transmission started (packet type 11 ), queue at 1
14+
0.187: [debug] Transmission started (packet type 2 ), queue at 1
15+
0.533: [debug] Attempting to open calibration from file "LIBRECAL.cal"
16+
0.533: [debug] Associated calibration kit expected in "LIBRECAL.calkit"
17+
0.533: [debug] Opening calkit to file "LIBRECAL.calkit"
18+
0.533: [debug] Parsing of calibration kit failed while opening calibration file: Unable to open file (ignore for calibration format >= 3)
19+
0.899: [debug] Transmission started (packet type 2 ), queue at 1
20+
1.007: [debug] Deactivated mode "Vector Network Analyzer"
21+
1.007: [debug] Transmission started (packet type 20 ), queue at 1
22+
1.050: [debug] Disconnected, receive thread exiting

Software/Integrationtests/packetlog_20250106173310.vnalog

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

Software/Integrationtests/tests/TestBase.py

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,72 @@
44
import subprocess
55
import time
66
import select
7+
import os
78
from signal import SIGINT
89

910
class TestBase(unittest.TestCase):
1011
def setUp(self):
11-
self.gui = subprocess.Popen([defs.GUI_PATH, '-p', '19544', '--reset-preferences', '--no-gui', '-platform', 'offscreen'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
12+
f = open("log.txt", "w")
13+
self.gui = subprocess.Popen([defs.GUI_PATH, '-p', '19544', '--reset-preferences', '--no-gui', '-platform', 'offscreen'], stdout=f, stderr=subprocess.STDOUT)
1214

1315
# wait for the SCPI server to become available
1416
timeout = time.time() + 3;
15-
poll_obj = select.poll()
16-
poll_obj.register(self.gui.stdout, select.POLLIN)
17+
fread = open("log.txt", "r")
1718
while True:
18-
poll_result = poll_obj.poll(0)
19-
if poll_result:
20-
line = self.gui.stdout.readline().decode().strip()
21-
if "Listening on port 19544" in line:
22-
break
19+
text = fread.read()
20+
if text and "Listening on port 19544" in text:
21+
break
2322
if time.time() >= timeout:
2423
self.tearDown()
2524
raise AssertionError("Timed out waiting for SCPI server")
2625

2726
self.vna = libreVNA('localhost', 19544, timeout=4)
2827
try:
29-
self.vna.cmd("*CLS;:DEV:CONN")
28+
self.vna.cmd("*CLS")
3029
except Exception as e:
3130
self.tearDown()
3231
raise e
3332
if self.vna.query(":DEV:CONN?") == "Not connected":
3433
self.tearDown()
3534
raise AssertionError("Not connected")
36-
35+
36+
3737
def tearDown(self):
38+
if hasattr(self._outcome, 'errors'):
39+
# Python 3.4 - 3.10 (These two methods have no side effects)
40+
result = self.defaultTestResult()
41+
self._feedErrorsToResult(result, self._outcome.errors)
42+
else:
43+
# Python 3.11+
44+
result = self._outcome.result
45+
ok = all(test != self for test, text in result.errors + result.failures)
46+
47+
if not ok:
48+
try:
49+
# Try to grab the packet log and save it
50+
packetlog = self.vna.query(":DEV:PACKETLOG?", timeout=5)
51+
f = open("packetlog_"+time.strftime("%Y%m%d%H%M%S.vnalog"), "w")
52+
f.write(packetlog)
53+
f.close()
54+
except:
55+
pass
56+
3857
# make sure the GUI did not crash during the test
39-
self.assertEqual(self.gui.poll(), None)
58+
crashed = self.gui.poll() is not None
4059
self.gui.send_signal(SIGINT)
4160
try:
4261
self.gui.wait(timeout = 3)
4362
except subprocess.TimeoutExpired:
4463
self.gui.kill()
4564

65+
66+
if ok and not crashed:
67+
# remove log file
68+
os.remove("log.txt")
69+
else:
70+
os.rename("log.txt", "errorlog_"+time.strftime("%Y%m%d%H%M%S.txt"))
71+
72+
if(crashed):
73+
raise Exception("GUI crashed")
74+
4675

Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/Compound/compounddriver.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ CompoundDriver::CompoundDriver()
2929
p.load(d->driverSpecificSettings());
3030
}
3131

32-
specificSettings.push_back(Savable::SettingDescription(&compoundJSONString, "compoundDriver.compoundDeviceJSON", ""));
32+
specificSettings.push_back(Savable::SettingDescription(&compoundJSONString, "compoundDriver.compoundDeviceJSON", "{}"));
3333
specificSettings.push_back(Savable::SettingDescription(&captureRawReceiverValues, "compoundDriver.captureRawReceiverValues", false));
3434
specificSettings.push_back(Savable::SettingDescription(&preservePhase, "compoundDriver.preservePhase", false));
3535
}
@@ -488,6 +488,10 @@ void CompoundDriver::parseCompoundJSON()
488488
{
489489
try {
490490
configuredDevices.clear();
491+
if(compoundJSONString.isEmpty()) {
492+
// empty string will fail JSON parsing. Abort now instead of running into the exception
493+
return;
494+
}
491495
nlohmann::json jc = nlohmann::json::parse(compoundJSONString.toStdString());
492496
for(auto j : jc) {
493497
auto cd = new CompoundDevice();

Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,11 @@ LibreVNADriver::LibreVNADriver()
251251
}
252252
return SCPI::getResultName(SCPI::Result::Empty);
253253
}, nullptr));
254+
255+
specificSCPIcommands.push_back(new SCPICommand("DEVice:PACKETLOG", nullptr, [=](QStringList) -> QString {
256+
auto &log = DevicePacketLog::getInstance();
257+
return QString::fromStdString(log.toJSON().dump());
258+
}));
254259
}
255260

256261
std::set<DeviceDriver::Flag> LibreVNADriver::getFlags()
@@ -407,6 +412,7 @@ QStringList LibreVNADriver::availableVNAMeasurements()
407412
bool LibreVNADriver::setVNA(const DeviceDriver::VNASettings &s, std::function<void (bool)> cb)
408413
{
409414
if(!supports(Feature::VNA)) {
415+
qDebug() << "VNA does not support features \"VNA\" (has the DeviceInfo been received?)";
410416
return false;
411417
}
412418
if(s.excitedPorts.size() == 0) {

Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnausbdriver.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "devicepacketlog.h"
55

66
#include <QTimer>
7+
#include <QThread>
78

89
using namespace std;
910

@@ -166,9 +167,9 @@ void LibreVNAUSBDriver::ReceivedData()
166167
uint16_t handled_len;
167168
// qDebug() << "Received data";
168169
do {
169-
// qDebug() << "Decoding" << dataBuffer->getReceived() << "Bytes";
170+
// qDebug() << "Decoding" << dataBuffer->getReceived() << "Bytes";
170171
handled_len = Protocol::DecodeBuffer(dataBuffer->getBuffer(), dataBuffer->getReceived(), &packet);
171-
// qDebug() << "Handled" << handled_len << "Bytes, type:" << (int) packet.type;
172+
// qDebug() << "Handled" << handled_len << "Bytes, type:" << (int) packet.type;
172173
if(handled_len > 0) {
173174
auto &log = DevicePacketLog::getInstance();
174175
if(packet.type != Protocol::PacketType::None) {
@@ -185,6 +186,8 @@ void LibreVNAUSBDriver::ReceivedData()
185186
case Protocol::PacketType::Nack:
186187
emit receivedAnswer(TransmissionResult::Nack);
187188
break;
189+
case Protocol::PacketType::None:
190+
break;
188191
default:
189192
// pass on to LibreVNADriver class
190193
emit receivedPacket(packet);
@@ -220,12 +223,12 @@ void LibreVNAUSBDriver::transmissionFinished(LibreVNADriver::TransmissionResult
220223
{
221224
lock_guard<mutex> lock(transmissionMutex);
222225
// remove transmitted packet
223-
// qDebug() << "Transmission finsished (" << result << "), queue at " << transmissionQueue.size() << " Outstanding ACKs:"<<outstandingAckCount;
224226
if(transmissionQueue.empty()) {
225227
qWarning() << "transmissionFinished with empty transmission queue, stray Ack? Result:" << result;
226228
return;
227229
}
228230
auto t = transmissionQueue.dequeue();
231+
// qDebug() << "Transmission finsished (packet type" << (int) t.packet.type <<",result" << result << "), queue at " << transmissionQueue.size();
229232
if(result == TransmissionResult::Timeout) {
230233
qWarning() << "transmissionFinished with timeout, packettype:" << (int) t.packet.type << "Device:" << serial;
231234
}
@@ -374,6 +377,6 @@ bool LibreVNAUSBDriver::startNextTransmission()
374377
return false;
375378
}
376379
transmissionTimer.start(t.timeout);
377-
// qDebug() << "Transmission started, queue at " << transmissionQueue.size();
380+
qDebug() << "Transmission started (packet type" << (int) t.packet.type << "), queue at " << transmissionQueue.size();
378381
return true;
379382
}

Software/PC_Application/LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,10 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
340340

341341
void SpectrumAnalyzer::deactivate()
342342
{
343-
setOperationPending(false);
344343
StoreSweepSettings();
345344
configurationTimer.stop();
346345
Mode::deactivate();
346+
setOperationPending(false);
347347
}
348348

349349
void SpectrumAnalyzer::initializeDevice()
@@ -588,7 +588,11 @@ void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
588588

589589
void SpectrumAnalyzer::SettingsChanged()
590590
{
591-
if(window->getDevice()) {
591+
if(!running) {
592+
// not running, no need for any communication
593+
return;
594+
}
595+
if(isActive && window->getDevice()) {
592596
setOperationPending(true);
593597
}
594598
configurationTimer.start(100);
@@ -695,10 +699,15 @@ void SpectrumAnalyzer::SetSingleSweep(bool single)
695699
{
696700
if(singleSweep != single) {
697701
singleSweep = single;
702+
if(single) {
703+
Run();
704+
}
698705
emit singleSweepChanged(single);
699-
}
700-
if(single) {
701-
Run();
706+
} else {
707+
// if already set to single, a second single command triggers a new sweep
708+
if(single && !running) {
709+
Run();
710+
}
702711
}
703712
}
704713

@@ -734,7 +743,9 @@ void SpectrumAnalyzer::SetAveraging(unsigned int averages)
734743
average.setAverages(averages);
735744
emit averagingChanged(averages);
736745
UpdateAverageCount();
737-
setOperationPending(!average.settled());
746+
if(isActive && window->getDevice()) {
747+
setOperationPending(!average.settled());
748+
}
738749
}
739750

740751
void SpectrumAnalyzer::SetTGEnabled(bool enabled)
@@ -871,6 +882,7 @@ void SpectrumAnalyzer::Stop()
871882
{
872883
running = false;
873884
ConfigureDevice();
885+
setOperationPending(false);
874886
}
875887

876888
void SpectrumAnalyzer::ConfigureDevice()
@@ -920,9 +932,6 @@ void SpectrumAnalyzer::ConfigureDevice()
920932

921933
void SpectrumAnalyzer::ResetLiveTraces()
922934
{
923-
if(window->getDevice()) {
924-
setOperationPending(true);
925-
}
926935
average.reset(DeviceDriver::SApoints());
927936
traceModel.clearLiveData();
928937
UpdateAverageCount();

Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -745,10 +745,10 @@ QString VNA::getCalToolTip()
745745

746746
void VNA::deactivate()
747747
{
748-
setOperationPending(false);
749748
StoreSweepSettings();
750749
configurationTimer.stop();
751750
Mode::deactivate();
751+
setOperationPending(false);
752752
}
753753

754754
static void SetComboBoxItemEnabled(QComboBox * comboBox, int index, bool enabled)
@@ -939,9 +939,8 @@ void VNA::NewDatapoint(DeviceDriver::VNAMeasurement m)
939939
}
940940

941941
// Calculate sweep time
942-
if(m.pointNum == 0) {
942+
if(m.pointNum == 0 && lastPoint > 0) {
943943
// new sweep started
944-
static auto lastStart = QDateTime::currentDateTimeUtc();
945944
auto now = QDateTime::currentDateTimeUtc();
946945
auto sweepTime = lastStart.msecsTo(now);
947946
lastStart = now;
@@ -1042,7 +1041,6 @@ void VNA::NewDatapoint(DeviceDriver::VNAMeasurement m)
10421041
markerModel->updateMarkers();
10431042
}
10441043

1045-
static unsigned int lastPoint = 0;
10461044
if(m_avg.pointNum > 0 && m_avg.pointNum != lastPoint + 1) {
10471045
qWarning() << "Got point" << m_avg.pointNum << "but last received point was" << lastPoint << "("<<(m_avg.pointNum-lastPoint-1)<<"missed points)";
10481046
}
@@ -1065,7 +1063,11 @@ void VNA::UpdateAverageCount()
10651063

10661064
void VNA::SettingsChanged(bool resetTraces, int delay)
10671065
{
1068-
if(window->getDevice()) {
1066+
if(!running) {
1067+
// not running, no need for any communication
1068+
return;
1069+
}
1070+
if(isActive && window->getDevice()) {
10691071
setOperationPending(true);
10701072
}
10711073
configurationTimer.start(delay);
@@ -1317,7 +1319,9 @@ void VNA::SetAveraging(unsigned int averages)
13171319
average.setAverages(averages);
13181320
emit averagingChanged(averages);
13191321
UpdateAverageCount();
1320-
setOperationPending(!average.settled());
1322+
if(isActive && window->getDevice()) {
1323+
setOperationPending(!average.settled());
1324+
}
13211325
}
13221326

13231327
void VNA::ExcitationRequired()
@@ -1880,10 +1884,15 @@ void VNA::SetSingleSweep(bool single)
18801884
{
18811885
if(singleSweep != single) {
18821886
singleSweep = single;
1887+
if(single) {
1888+
Run();
1889+
}
18831890
emit singleSweepChanged(single);
1884-
}
1885-
if(single) {
1886-
Run();
1891+
} else {
1892+
// if already set to single, a second single command triggers a new sweep
1893+
if(single && !running) {
1894+
Run();
1895+
}
18871896
}
18881897
}
18891898

@@ -1897,6 +1906,7 @@ void VNA::Stop()
18971906
{
18981907
running = false;
18991908
ConfigureDevice(false);
1909+
setOperationPending(false);
19001910
}
19011911

19021912
void VNA::ConfigureDevice(bool resetTraces, std::function<void(bool)> cb)
@@ -1976,6 +1986,8 @@ void VNA::ConfigureDevice(bool resetTraces, std::function<void(bool)> cb)
19761986
cb(res);
19771987
}
19781988
changingSettings = false;
1989+
lastStart = QDateTime::currentDateTimeUtc();
1990+
lastPoint = -1;
19791991
});
19801992
emit sweepStarted();
19811993
} else {
@@ -2004,7 +2016,7 @@ void VNA::ResetLiveTraces()
20042016
traceModel.clearLiveData();
20052017
UpdateAverageCount();
20062018
UpdateCalWidget();
2007-
if(window->getDevice()) {
2019+
if(isActive && window->getDevice()) {
20082020
setOperationPending(true);
20092021
}
20102022
}

0 commit comments

Comments
 (0)