async update plot

fix loosing csi packet caused by sync updating plot
This commit is contained in:
Miroslav Hutár 2024-04-22 13:33:33 +02:00
parent 9bb4fd74fa
commit 2086412fbf
5 changed files with 54 additions and 34 deletions

View File

@ -39,7 +39,7 @@ public:
private:
static int listenToCsiHandler(nl80211_state *state, nl_msg *msg, void *arg);
static int processListenToCsiHandler(nl_msg *msg, void *arg);
static void printDetail(Csi &c);
static void printDetail(Csi *c);
GnuPlot gnuPlot;
};

View File

@ -1,6 +1,6 @@
/*
* FeitCSI is the tool for extracting CSI information from supported intel NICs.
* Copyright (C) 2023 Miroslav Hutar.
* Copyright (C) 2023-2024 Miroslav Hutar.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -22,8 +22,8 @@
#include <gtkmm.h>
#include <gtkmm/socket.h>
#include <Csi.h>
#include <string>
#include <future>
class GnuPlot
{
@ -32,11 +32,14 @@ public:
void setWindow(uint64_t id);
void setBlank();
void reload();
void updateChart(Csi &csi);
void updateChartAsync(Csi *csi);
private:
inline static std::string lastCmd;
inline static FILE *gnuPlotPipe;
inline static std::future<void> runningAsyncEvent;
void updateChart(Csi *csi);
};
#endif

View File

@ -93,35 +93,35 @@ int WiFiCsiController::processListenToCsiHandler(struct nl_msg *msg, void *arg)
uint8_t *dataCsi = (uint8_t *)nla_data(attrs[IWL_MVM_VENDOR_ATTR_CSI_DATA]);
memcpy(rawCsi, dataCsi, dataLength);
Csi c;
c.loadFromMemory(header, dataCsi);
Csi *c = new Csi();
c->loadFromMemory(header, dataCsi);
if (
(c.channelWidth == RATE_MCS_CHAN_WIDTH_20 && Arguments::arguments.channelWidth == 20) ||
(c.channelWidth == RATE_MCS_CHAN_WIDTH_40 && Arguments::arguments.channelWidth == 40) ||
(c.channelWidth == RATE_MCS_CHAN_WIDTH_80 && Arguments::arguments.channelWidth == 80) ||
(c.channelWidth == RATE_MCS_CHAN_WIDTH_160 && Arguments::arguments.channelWidth == 160)
(c->channelWidth == RATE_MCS_CHAN_WIDTH_20 && Arguments::arguments.channelWidth == 20) ||
(c->channelWidth == RATE_MCS_CHAN_WIDTH_40 && Arguments::arguments.channelWidth == 40) ||
(c->channelWidth == RATE_MCS_CHAN_WIDTH_80 && Arguments::arguments.channelWidth == 80) ||
(c->channelWidth == RATE_MCS_CHAN_WIDTH_160 && Arguments::arguments.channelWidth == 160)
)
{
if (
(c.format == RATE_MCS_LEGACY_OFDM_MSK && Arguments::arguments.format == "NOHT") ||
(c.format == RATE_MCS_HT_MSK && Arguments::arguments.format == "HT") ||
(c.format == RATE_MCS_VHT_MSK && Arguments::arguments.format == "VHT") ||
(c.format == RATE_MCS_HE_MSK && Arguments::arguments.format == "HESU") ||
(c.format == RATE_MCS_EHT_MSK && Arguments::arguments.format == "EHT")
(c->format == RATE_MCS_LEGACY_OFDM_MSK && Arguments::arguments.format == "NOHT") ||
(c->format == RATE_MCS_HT_MSK && Arguments::arguments.format == "HT") ||
(c->format == RATE_MCS_VHT_MSK && Arguments::arguments.format == "VHT") ||
(c->format == RATE_MCS_HE_MSK && Arguments::arguments.format == "HESU") ||
(c->format == RATE_MCS_EHT_MSK && Arguments::arguments.format == "EHT")
)
{
if (Arguments::arguments.verbose) {
printDetail(c);
}
instance->gnuPlot.updateChart(c);
if ( MainController::getInstance()->udpSocket ) {
c.sendUDP(MainController::getInstance()->udpSocket);
c->sendUDP(MainController::getInstance()->udpSocket);
} else {
c.save();
c->save();
}
instance->gnuPlot.updateChartAsync(c); // also delete c
}
}
}
@ -130,13 +130,13 @@ int WiFiCsiController::processListenToCsiHandler(struct nl_msg *msg, void *arg)
return NL_SKIP;
}
void WiFiCsiController::printDetail(Csi &c)
void WiFiCsiController::printDetail(Csi *c)
{
Logger::log(info) << "Subcarrier count: " << c.rawHeaderData.numSubCarriers << ", ";
Logger::log(info, true) << "RX: " << +c.rawHeaderData.numRx << ", ";
Logger::log(info, true) << "TX: " << +c.rawHeaderData.numTx << ", ";
Logger::log(info) << "Subcarrier count: " << c->rawHeaderData.numSubCarriers << ", ";
Logger::log(info, true) << "RX: " << +c->rawHeaderData.numRx << ", ";
Logger::log(info, true) << "TX: " << +c->rawHeaderData.numTx << ", ";
switch (c.channelWidth)
switch (c->channelWidth)
{
case RATE_MCS_CHAN_WIDTH_20:
Logger::log(info, true) << "Channel width: 20, ";
@ -151,7 +151,7 @@ void WiFiCsiController::printDetail(Csi &c)
Logger::log(info, true) << "Channel width: 160, ";
break;
}
switch (c.format)
switch (c->format)
{
case RATE_MCS_CCK_MSK: // VERY OLD FORMAT
Logger::log(info, true) << "Format: CCK\n";

View File

@ -67,7 +67,7 @@ void CsiProcessingWindow::refresh()
if (!this->csiProcessor.csiData.empty())
{
gnuPlot.updateChart(*this->csiProcessor.csiData[this->currentIndex]);
gnuPlot.updateChartAsync(this->csiProcessor.csiData[this->currentIndex]);
}
}

View File

@ -64,13 +64,29 @@ void GnuPlot::setBlank()
fflush(this->gnuPlotPipe);
}
void GnuPlot::updateChart(Csi &csi)
void GnuPlot::updateChartAsync(Csi *csi)
{
if (!Arguments::arguments.plot)
{
return;
}
bool isEventRunning = false;
if (this->runningAsyncEvent.valid())
{
isEventRunning = this->runningAsyncEvent.wait_for(std::chrono::seconds(0)) != std::future_status::ready;
}
if (!isEventRunning)
{
std::future<void> tmpEvent = std::async(&GnuPlot::updateChart, this, csi);
this->runningAsyncEvent = std::move(tmpEvent);
}
}
void GnuPlot::updateChart(Csi *csi)
{
std::stringstream ss;
// ss << "set multiplot layout 2,1";
ss << R"(
@ -82,11 +98,11 @@ void GnuPlot::updateChart(Csi &csi)
)";
std::stringstream plotCmd;
plotCmd << "set xrange [1:" << csi.numSubCarriers << "]\n";
plotCmd << "set xrange [1:" << csi->numSubCarriers << "]\n";
plotCmd << "plot";
for (uint32_t tx = 0; tx < csi.numTx; tx++)
for (uint32_t tx = 0; tx < csi->numTx; tx++)
{
for (uint32_t rx = 0; rx < csi.numRx; rx++)
for (uint32_t rx = 0; rx < csi->numRx; rx++)
{
plotCmd << " '-' with lines title \"RX" << (rx + 1) << "TX" << (tx + 1) << "\", ";
}
@ -98,14 +114,14 @@ void GnuPlot::updateChart(Csi &csi)
std::stringstream dataPhase;
uint32_t index = 0;
for (uint32_t rx = 0; rx < csi.numRx; rx++)
for (uint32_t rx = 0; rx < csi->numRx; rx++)
{
for (uint32_t tx = 0; tx < csi.numTx; tx++)
for (uint32_t tx = 0; tx < csi->numTx; tx++)
{
for (uint32_t n = 0; n < csi.numSubCarriers; n++)
for (uint32_t n = 0; n < csi->numSubCarriers; n++)
{
dataMagnitude << (n + 1) << " " << csi.magnitude[index] << "\n";
dataPhase << (n + 1) << " " << csi.phase[index] << "\n";
dataMagnitude << (n + 1) << " " << csi->magnitude[index] << "\n";
dataPhase << (n + 1) << " " << csi->phase[index] << "\n";
index++;
}
dataMagnitude << "e\n";
@ -129,6 +145,7 @@ void GnuPlot::updateChart(Csi &csi)
this->lastCmd = ss.str();
fprintf(this->gnuPlotPipe, ss.str().c_str());
fflush(this->gnuPlotPipe);
delete csi;
}
void GnuPlot::reload()