From d0471178b3d9f4e4fc798327e5953320f3c7b1ff Mon Sep 17 00:00:00 2001 From: Andrea Lacava Date: Thu, 30 Jan 2025 23:40:59 +0000 Subject: [PATCH 1/4] trigger release workflow --- .github/workflows/tag-on-version-change.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tag-on-version-change.yml b/.github/workflows/tag-on-version-change.yml index 5b0afa3..fe9e8bf 100644 --- a/.github/workflows/tag-on-version-change.yml +++ b/.github/workflows/tag-on-version-change.yml @@ -1,4 +1,4 @@ -name: Auto-Tag on VERSION Change +name: Tag on VERSION change on: push: @@ -8,7 +8,7 @@ on: - 'VERSION' # Only trigger if VERSION file changes jobs: - tag_version: + create-tag: runs-on: ubuntu-latest steps: - name: Checkout repository @@ -30,10 +30,20 @@ jobs: echo "EXISTS=false" >> $GITHUB_ENV fi - - name: Create and push new tag + - name: Create and push tag if: env.EXISTS == 'false' run: | git tag $VERSION git push origin $VERSION env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Trigger Release Workflow + if: github.repository == 'wineslab/dApp-library' && env.EXISTS == 'false' + run: | + curl -X POST -H "Accept: application/vnd.github.v3+json" \ + -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + https://api.github.com/repos/${{ github.repository }}/actions/workflows/release.yml/dispatches \ + -d '{"ref": "main"}' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From a9ee04ee7c4f3dffb19cae891409d9facca95cf4 Mon Sep 17 00:00:00 2001 From: Andrea Lacava Date: Mon, 3 Feb 2025 16:02:46 -0500 Subject: [PATCH 2/4] Add the possibility to include a spectrum classifier in the dashboard * changes done by Noemi and Filippo * add new parameter for classification remove libiq internal dependency * improve GUI and codebase of dashboard * better visualization and sampling * renamed demogui into dashboard * fix classifier initialization --------- Co-authored-by: Filippo Olimpieri Co-authored-by: Noemi Giustini --- docs/gui_uml.txt | 4 +--- examples/spectrum_dapp.py | 2 +- src/spectrum/spectrum_dapp.py | 23 +++++++++++------------ src/visualization/dashboard.py | 14 +++++++++++--- src/visualization/templates/index.html | 19 +++++++++++++++++++ 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/docs/gui_uml.txt b/docs/gui_uml.txt index 73cb077..bbbddf3 100644 --- a/docs/gui_uml.txt +++ b/docs/gui_uml.txt @@ -34,7 +34,7 @@ class IQPlotter { + process_iq_data(iq_data) } -class DemoGui { +class Dashboard { -- Attributes -- - BUFFER_SIZE : int - iq_size : int @@ -49,6 +49,4 @@ class DemoGui { + stop() } -DemoGui --> IQPlotter : "contains" -DemoGui --> EnergyPlotter : "contains" @enduml \ No newline at end of file diff --git a/examples/spectrum_dapp.py b/examples/spectrum_dapp.py index 6ca0418..006a4a9 100644 --- a/examples/spectrum_dapp.py +++ b/examples/spectrum_dapp.py @@ -25,7 +25,7 @@ def main(args, time_to_wait: float = 60.0): # f.close() dapp = SpectrumSharingDApp(ota=args.ota, save_iqs=args.save_iqs, control=args.control, link=args.link, transport=args.transport, - energyGui=args.energy_gui, iqPlotterGui=args.iq_plotter_gui, demoGui=args.demo_gui) + energyGui=args.energy_gui, iqPlotterGui=args.iq_plotter_gui, dashboard=args.demo_gui) dapp.setup_connection() diff --git a/src/spectrum/spectrum_dapp.py b/src/spectrum/spectrum_dapp.py index 1a5ae63..49fe8b7 100644 --- a/src/spectrum/spectrum_dapp.py +++ b/src/spectrum/spectrum_dapp.py @@ -54,7 +54,7 @@ def __init__(self, id: int = 1, ota: bool = False, save_iqs: bool = False, contr self.energyGui = kwargs.get('energyGui', False) self.iqPlotterGui = kwargs.get('iqPlotterGui', False) - self.demoGui = kwargs.get('demoGui', False) + self.dashboard = kwargs.get('dashboard', False) self.control_count = 1 self.abs_iq_av = np.zeros(self.FFT_SIZE) @@ -70,11 +70,12 @@ def __init__(self, id: int = 1, ota: bool = False, save_iqs: bool = False, contr iq_size = self.FFT_SIZE * 2 # double the size of ofdm_symbol_size since real and imaginary parts are interleaved self.iqPlotter = IQPlotter(buffer_size=500, iq_size=iq_size, bw=self.bw, center_freq=self.center_freq) - if self.demoGui: - from visualization.dashboard import DemoGui + if self.dashboard: + from visualization.dashboard import Dashboard self.demo_queue = multiprocessing.Queue() iq_size = self.FFT_SIZE * 2 # double the size of ofdm_symbol_size since real and imaginary parts are interleaved - self.demo = DemoGui(buffer_size=100, iq_size=iq_size) + classifier = kwargs.get('classifier', None) + self.demo = Dashboard(buffer_size=100, iq_size=iq_size, classifier=classifier) def get_iqs_from_ran(self, data): dapp_logger.debug(f'Triggered callback') @@ -93,7 +94,7 @@ def get_iqs_from_ran(self, data): if self.iqPlotterGui: self.iq_queue.put(iq_arr) - if self.demoGui: + if self.dashboard: self.demo_queue.put(("iq_data", iq_arr)) if self.control: @@ -106,9 +107,6 @@ def get_iqs_from_ran(self, data): self.control_count += 1 dapp_logger.debug(f"Control count is: {self.control_count}") - if self.iqPlotterGui: - self.iq_queue.put(iq_arr) - if self.control_count == self.Average_over_frames: abs_iq_av_db = 20 * np.log10(1 + (self.abs_iq_av/(self.Average_over_frames))) abs_iq_av_db_offset_correct = np.append(abs_iq_av_db[self.First_carrier_offset:self.FFT_SIZE],abs_iq_av_db[0:self.First_carrier_offset]) @@ -119,7 +117,6 @@ def get_iqs_from_ran(self, data): # last_5_max_abs_iq_av_db_offset_correct = np.sort(abs_iq_av_db_offset_correct)[-20:] # dapp_logger.info(f'Last 20 max values (abs_iq_av_db_offset_correct): {last_5_max_abs_iq_av_db_offset_correct}') - # PRB blocking based on the noise floor threshold f_ind = np.arange(self.FFT_SIZE) blklist_sub_carrier = f_ind[abs_iq_av_db_offset_correct > self.Noise_floor_threshold] @@ -143,7 +140,7 @@ def get_iqs_from_ran(self, data): if self.energyGui: self.sig_queue.put(abs_iq_av_db) - if self.demoGui: + if self.dashboard: self.demo_queue.put(("prb_list", prb_blk_list)) # Reset the variables @@ -154,10 +151,12 @@ def _control_loop(self): if self.energyGui: abs_iq_av_db = self.sig_queue.get() self.energyPlotter.process_iq_data(abs_iq_av_db) + if self.iqPlotterGui: iq_data = self.iq_queue.get() self.iqPlotter.process_iq_data(iq_data) - if self.demoGui: + + if self.dashboard: message = self.demo_queue.get() self.demo.process_iq_data(message) @@ -165,5 +164,5 @@ def _stop(self): if self.save_iqs: self.iq_save_file.close() - if self.demoGui: + if self.dashboard: self.demo.stop() diff --git a/src/visualization/dashboard.py b/src/visualization/dashboard.py index ab2b6d3..3e0ca7e 100644 --- a/src/visualization/dashboard.py +++ b/src/visualization/dashboard.py @@ -13,8 +13,8 @@ exit(-1) import numpy as np -class DemoGui: - def __init__(self, buffer_size=100, iq_size=1536, bw=46.08e6, center_freq=3.6192e9): +class Dashboard: + def __init__(self, buffer_size=100, iq_size=1536, bw=46.08e6, center_freq=3.6192e9, classifier=None): # TODO double check killing conditions # Flask app setup self.app = Flask(__name__) @@ -30,6 +30,8 @@ def __init__(self, buffer_size=100, iq_size=1536, bw=46.08e6, center_freq=3.6192 # Route setup self.app.add_url_rule("/", view_func=self.index) + self.classifier = classifier if classifier is not None else None + # SocketIO event handlers self.socketio.on_event("connect", self.handle_initial_connection) self._initialize_plot() @@ -63,6 +65,7 @@ def handle_initial_connection(self): data_buffer = { "magnitude": np.zeros((self.BUFFER_SIZE, iqs_to_show)).tolist(), "num_prbs": num_prbs, + "predicted_label": self.classifier is not None } self.socketio.emit("initialize_plot", data_buffer) @@ -88,6 +91,11 @@ def process_iq_data(self, message): if self.sampling_counter >= self.sampling_threshold: magnitude_dB = self._process_iq_data(iq_data)[::-1].tolist() # visualization processing is delegated to client self.socketio.emit("update_plot", {"magnitude": magnitude_dB}) + + if self.classifier: + label = self.classifier.predict(iq_data) + self.socketio.emit("update_plot", {"predicted_label": label}) + self.sampling_counter = 0 elif plot == "prb_list": @@ -101,4 +109,4 @@ def stop(self): self.run_thread.join() if __name__ == "__main__": - server_app = DemoGui() + server_app = Dashboard() diff --git a/src/visualization/templates/index.html b/src/visualization/templates/index.html index 85b1fa2..f169e6c 100644 --- a/src/visualization/templates/index.html +++ b/src/visualization/templates/index.html @@ -11,6 +11,7 @@
+