diff --git a/include/WiFiCsiController.h b/include/WiFiCsiController.h index acee8ac..315851a 100644 --- a/include/WiFiCsiController.h +++ b/include/WiFiCsiController.h @@ -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; }; diff --git a/include/gui/GnuPlot.h b/include/gui/GnuPlot.h index 12524bb..7293095 100644 --- a/include/gui/GnuPlot.h +++ b/include/gui/GnuPlot.h @@ -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 #include #include - #include +#include 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 runningAsyncEvent; + + void updateChart(Csi *csi); }; #endif \ No newline at end of file diff --git a/src/WiFiCsiController.cpp b/src/WiFiCsiController.cpp index 374f823..8c44f37 100644 --- a/src/WiFiCsiController.cpp +++ b/src/WiFiCsiController.cpp @@ -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"; diff --git a/src/gui/CsiProcessingWindow.cpp b/src/gui/CsiProcessingWindow.cpp index 376391e..e6f085a 100644 --- a/src/gui/CsiProcessingWindow.cpp +++ b/src/gui/CsiProcessingWindow.cpp @@ -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]); } } diff --git a/src/gui/GnuPlot.cpp b/src/gui/GnuPlot.cpp index 0af3bcd..c135582 100644 --- a/src/gui/GnuPlot.cpp +++ b/src/gui/GnuPlot.cpp @@ -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 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()