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: private:
static int listenToCsiHandler(nl80211_state *state, nl_msg *msg, void *arg); static int listenToCsiHandler(nl80211_state *state, nl_msg *msg, void *arg);
static int processListenToCsiHandler(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; GnuPlot gnuPlot;
}; };

View File

@ -1,6 +1,6 @@
/* /*
* FeitCSI is the tool for extracting CSI information from supported intel NICs. * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -22,8 +22,8 @@
#include <gtkmm.h> #include <gtkmm.h>
#include <gtkmm/socket.h> #include <gtkmm/socket.h>
#include <Csi.h> #include <Csi.h>
#include <string> #include <string>
#include <future>
class GnuPlot class GnuPlot
{ {
@ -32,11 +32,14 @@ public:
void setWindow(uint64_t id); void setWindow(uint64_t id);
void setBlank(); void setBlank();
void reload(); void reload();
void updateChart(Csi &csi); void updateChartAsync(Csi *csi);
private: private:
inline static std::string lastCmd; inline static std::string lastCmd;
inline static FILE *gnuPlotPipe; inline static FILE *gnuPlotPipe;
inline static std::future<void> runningAsyncEvent;
void updateChart(Csi *csi);
}; };
#endif #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]); uint8_t *dataCsi = (uint8_t *)nla_data(attrs[IWL_MVM_VENDOR_ATTR_CSI_DATA]);
memcpy(rawCsi, dataCsi, dataLength); memcpy(rawCsi, dataCsi, dataLength);
Csi c; Csi *c = new Csi();
c.loadFromMemory(header, dataCsi); c->loadFromMemory(header, dataCsi);
if ( if (
(c.channelWidth == RATE_MCS_CHAN_WIDTH_20 && Arguments::arguments.channelWidth == 20) || (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_40 && Arguments::arguments.channelWidth == 40) ||
(c.channelWidth == RATE_MCS_CHAN_WIDTH_80 && Arguments::arguments.channelWidth == 80) || (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_160 && Arguments::arguments.channelWidth == 160)
) )
{ {
if ( if (
(c.format == RATE_MCS_LEGACY_OFDM_MSK && Arguments::arguments.format == "NOHT") || (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_HT_MSK && Arguments::arguments.format == "HT") ||
(c.format == RATE_MCS_VHT_MSK && Arguments::arguments.format == "VHT") || (c->format == RATE_MCS_VHT_MSK && Arguments::arguments.format == "VHT") ||
(c.format == RATE_MCS_HE_MSK && Arguments::arguments.format == "HESU") || (c->format == RATE_MCS_HE_MSK && Arguments::arguments.format == "HESU") ||
(c.format == RATE_MCS_EHT_MSK && Arguments::arguments.format == "EHT") (c->format == RATE_MCS_EHT_MSK && Arguments::arguments.format == "EHT")
) )
{ {
if (Arguments::arguments.verbose) { if (Arguments::arguments.verbose) {
printDetail(c); printDetail(c);
} }
instance->gnuPlot.updateChart(c);
if ( MainController::getInstance()->udpSocket ) { if ( MainController::getInstance()->udpSocket ) {
c.sendUDP(MainController::getInstance()->udpSocket); c->sendUDP(MainController::getInstance()->udpSocket);
} else { } 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; return NL_SKIP;
} }
void WiFiCsiController::printDetail(Csi &c) void WiFiCsiController::printDetail(Csi *c)
{ {
Logger::log(info) << "Subcarrier count: " << c.rawHeaderData.numSubCarriers << ", "; Logger::log(info) << "Subcarrier count: " << c->rawHeaderData.numSubCarriers << ", ";
Logger::log(info, true) << "RX: " << +c.rawHeaderData.numRx << ", "; Logger::log(info, true) << "RX: " << +c->rawHeaderData.numRx << ", ";
Logger::log(info, true) << "TX: " << +c.rawHeaderData.numTx << ", "; Logger::log(info, true) << "TX: " << +c->rawHeaderData.numTx << ", ";
switch (c.channelWidth) switch (c->channelWidth)
{ {
case RATE_MCS_CHAN_WIDTH_20: case RATE_MCS_CHAN_WIDTH_20:
Logger::log(info, true) << "Channel 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, "; Logger::log(info, true) << "Channel width: 160, ";
break; break;
} }
switch (c.format) switch (c->format)
{ {
case RATE_MCS_CCK_MSK: // VERY OLD FORMAT case RATE_MCS_CCK_MSK: // VERY OLD FORMAT
Logger::log(info, true) << "Format: CCK\n"; Logger::log(info, true) << "Format: CCK\n";

View File

@ -67,7 +67,7 @@ void CsiProcessingWindow::refresh()
if (!this->csiProcessor.csiData.empty()) 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); fflush(this->gnuPlotPipe);
} }
void GnuPlot::updateChart(Csi &csi) void GnuPlot::updateChartAsync(Csi *csi)
{ {
if (!Arguments::arguments.plot) if (!Arguments::arguments.plot)
{ {
return; 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; std::stringstream ss;
// ss << "set multiplot layout 2,1"; // ss << "set multiplot layout 2,1";
ss << R"( ss << R"(
@ -82,11 +98,11 @@ void GnuPlot::updateChart(Csi &csi)
)"; )";
std::stringstream plotCmd; std::stringstream plotCmd;
plotCmd << "set xrange [1:" << csi.numSubCarriers << "]\n"; plotCmd << "set xrange [1:" << csi->numSubCarriers << "]\n";
plotCmd << "plot"; 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) << "\", "; plotCmd << " '-' with lines title \"RX" << (rx + 1) << "TX" << (tx + 1) << "\", ";
} }
@ -98,14 +114,14 @@ void GnuPlot::updateChart(Csi &csi)
std::stringstream dataPhase; std::stringstream dataPhase;
uint32_t index = 0; 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"; dataMagnitude << (n + 1) << " " << csi->magnitude[index] << "\n";
dataPhase << (n + 1) << " " << csi.phase[index] << "\n"; dataPhase << (n + 1) << " " << csi->phase[index] << "\n";
index++; index++;
} }
dataMagnitude << "e\n"; dataMagnitude << "e\n";
@ -129,6 +145,7 @@ void GnuPlot::updateChart(Csi &csi)
this->lastCmd = ss.str(); this->lastCmd = ss.str();
fprintf(this->gnuPlotPipe, ss.str().c_str()); fprintf(this->gnuPlotPipe, ss.str().c_str());
fflush(this->gnuPlotPipe); fflush(this->gnuPlotPipe);
delete csi;
} }
void GnuPlot::reload() void GnuPlot::reload()