dapps 0.0.4__tar.gz → 0.0.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. dapps-0.0.6/CONTRIBUTING.md +95 -0
  2. {dapps-0.0.4 → dapps-0.0.6}/PKG-INFO +112 -25
  3. dapps-0.0.6/README.md +156 -0
  4. dapps-0.0.6/VERSION +1 -0
  5. dapps-0.0.6/docs/dapp_uml.txt +210 -0
  6. dapps-0.0.6/examples/nvidia_dapp.py +43 -0
  7. dapps-0.0.6/examples/simple_dapp.py +123 -0
  8. {dapps-0.0.4 → dapps-0.0.6}/examples/spectrum_dapp.py +45 -14
  9. {dapps-0.0.4 → dapps-0.0.6}/pyproject.toml +9 -4
  10. dapps-0.0.6/src/dapp/dapp.py +186 -0
  11. dapps-0.0.6/src/e3interface/defs/e3.asn +105 -0
  12. dapps-0.0.6/src/e3interface/defs/e3.json +494 -0
  13. {dapps-0.0.4 → dapps-0.0.6}/src/e3interface/e3_connector.py +40 -24
  14. dapps-0.0.6/src/e3interface/e3_encoder.py +376 -0
  15. dapps-0.0.6/src/e3interface/e3_interface.py +467 -0
  16. {dapps-0.0.4 → dapps-0.0.6}/src/e3interface/e3_logging.py +4 -5
  17. dapps-0.0.6/src/iq_saver/__init__.py +3 -0
  18. dapps-0.0.6/src/iq_saver/iq_saver.py +424 -0
  19. dapps-0.0.6/src/nvidia/defs/e3sm_nvidia.asn +48 -0
  20. dapps-0.0.6/src/nvidia/defs/e3sm_nvidia.json +40 -0
  21. dapps-0.0.6/src/nvidia/nvidia_dapp.py +71 -0
  22. dapps-0.0.6/src/simple/__init__.py +4 -0
  23. dapps-0.0.6/src/simple/defs/e3sm_simple.asn +54 -0
  24. dapps-0.0.6/src/simple/simple_dapp.py +239 -0
  25. dapps-0.0.6/src/spectrum/defs/e3sm_spectrum.asn +76 -0
  26. dapps-0.0.6/src/spectrum/defs/e3sm_spectrum.json +137 -0
  27. dapps-0.0.6/src/spectrum/spectrum_dapp.py +542 -0
  28. dapps-0.0.6/src/visualization/__init__.py +4 -0
  29. {dapps-0.0.4 → dapps-0.0.6}/src/visualization/dashboard.py +5 -3
  30. dapps-0.0.6/tests/test_iq_saver.py +432 -0
  31. dapps-0.0.6/tools/README.md +117 -0
  32. dapps-0.0.6/tools/asntojson.py +335 -0
  33. dapps-0.0.6/tools/generate_sm.sh +1125 -0
  34. dapps-0.0.6/tools/read_recording.py +50 -0
  35. dapps-0.0.4/README.md +0 -70
  36. dapps-0.0.4/VERSION +0 -1
  37. dapps-0.0.4/docker/Dockerfile +0 -65
  38. dapps-0.0.4/docker/build.sh +0 -7
  39. dapps-0.0.4/docs/dapp_uml.txt +0 -128
  40. dapps-0.0.4/e3protocol/README.md +0 -10
  41. dapps-0.0.4/e3protocol/build_asn.sh +0 -27
  42. dapps-0.0.4/e3protocol/client/client.c +0 -164
  43. dapps-0.0.4/e3protocol/dump_packets.sh +0 -3
  44. dapps-0.0.4/e3protocol/server/server.py +0 -70
  45. dapps-0.0.4/e3protocol/wrapper/e3.c +0 -168
  46. dapps-0.0.4/e3protocol/wrapper/e3.h +0 -11
  47. dapps-0.0.4/src/dapp/dapp.py +0 -66
  48. dapps-0.0.4/src/e3interface/defs/e3.asn +0 -27
  49. dapps-0.0.4/src/e3interface/e3_interface.py +0 -187
  50. dapps-0.0.4/src/spectrum/spectrum_dapp.py +0 -170
  51. {dapps-0.0.4 → dapps-0.0.6}/.github/workflows/mirror.yml +0 -0
  52. {dapps-0.0.4 → dapps-0.0.6}/.github/workflows/tag-and-release.yml +0 -0
  53. {dapps-0.0.4 → dapps-0.0.6}/.gitignore +0 -0
  54. {dapps-0.0.4 → dapps-0.0.6}/LICENSE +0 -0
  55. {dapps-0.0.4 → dapps-0.0.6}/MANIFEST.in +0 -0
  56. {dapps-0.0.4 → dapps-0.0.6}/docs/gui_uml.txt +0 -0
  57. {dapps-0.0.4 → dapps-0.0.6}/src/dapp/__init__.py +0 -0
  58. {dapps-0.0.4 → dapps-0.0.6}/src/e3interface/__init__.py +0 -0
  59. {dapps-0.0.4/src/spectrum → dapps-0.0.6/src/nvidia}/__init__.py +0 -0
  60. {dapps-0.0.4/src/visualization → dapps-0.0.6/src/spectrum}/__init__.py +0 -0
  61. {dapps-0.0.4 → dapps-0.0.6}/src/visualization/energy.py +0 -0
  62. {dapps-0.0.4 → dapps-0.0.6}/src/visualization/grafana.py +0 -0
  63. {dapps-0.0.4 → dapps-0.0.6}/src/visualization/influx.py +0 -0
  64. {dapps-0.0.4 → dapps-0.0.6}/src/visualization/iq.py +0 -0
  65. {dapps-0.0.4 → dapps-0.0.6}/src/visualization/templates/index.html +0 -0
@@ -0,0 +1,95 @@
1
+ # Contributing
2
+
3
+ Thank you for considering contributing to this project! Please follow these guidelines to help us maintain a welcoming and productive environment.
4
+ When contributing to this repository, please first discuss the change you wish to make via issue,
5
+ email, or any other method with the original authors of this work.
6
+
7
+ Please note we have a code of conduct, please follow it in all your interactions with the project.
8
+
9
+ ## Pull Request Process
10
+
11
+ 1. Ensure any install or build dependencies are removed before the end of the layer when doing a
12
+ build.
13
+ 2. Update the README.md with details of changes to the interface, this includes new environment
14
+ variables, exposed ports, useful file locations and container parameters.
15
+ 3. Increase the version numbers in any examples files and the README.md to the new version that this
16
+ Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
17
+ This repository is part of a framework with a counterpart in OpenAirInterface written in C/C++.
18
+ We do not accept major patches that break or reduce compatibility with the twin repository.
19
+ 4. Submitted code must have been tested and should work with all the compatible configurations of the framework.
20
+ 5. Merging should always be performed via squash commits. Pull Requests must be updated through rebasing, without duplicating commits or altering the original branch history. Merges without prior approval are not allowed, and any accidental violations will result in the deletion of the merge commit.
21
+
22
+ ## Code of Conduct
23
+
24
+ ### Our Pledge
25
+
26
+ In the interest of fostering an open and welcoming environment, we as
27
+ contributors and maintainers pledge to making participation in our project and
28
+ our community a harassment-free experience for everyone, regardless of age, body
29
+ size, disability, ethnicity, gender identity and expression, level of experience,
30
+ nationality, personal appearance, race, religion, or sexual identity and
31
+ orientation.
32
+
33
+ ### Our Standards
34
+
35
+ Examples of behavior that contributes to creating a positive environment
36
+ include:
37
+
38
+ * Using welcoming and inclusive language
39
+ * Being respectful of differing viewpoints and experiences
40
+ * Gracefully accepting constructive criticism
41
+ * Focusing on what is best for the community
42
+ * Showing empathy towards other community members
43
+
44
+ Examples of unacceptable behavior by participants include:
45
+
46
+ * The use of sexualized language or imagery and unwelcome sexual attention or
47
+ advances
48
+ * Trolling, insulting/derogatory comments, and personal or political attacks
49
+ * Public or private harassment
50
+ * Publishing others' private information, such as a physical or electronic
51
+ address, without explicit permission
52
+ * Other conduct which could reasonably be considered inappropriate in a
53
+ professional setting
54
+
55
+ ### Our Responsibilities
56
+
57
+ Project maintainers are responsible for clarifying the standards of acceptable
58
+ behavior and are expected to take appropriate and fair corrective action in
59
+ response to any instances of unacceptable behavior.
60
+
61
+ Project maintainers have the right and responsibility to remove, edit, or
62
+ reject comments, commits, code, wiki edits, issues, and other contributions
63
+ that are not aligned to this Code of Conduct, or to ban temporarily or
64
+ permanently any contributor for other behaviors that they deem inappropriate,
65
+ threatening, offensive, or harmful.
66
+
67
+ ### Scope
68
+
69
+ This Code of Conduct applies both within project spaces and in public spaces
70
+ when an individual is representing the project or its community. Examples of
71
+ representing a project or community include using an official project e-mail
72
+ address, posting via an official social media account, or acting as an appointed
73
+ representative at an online or offline event. Representation of a project may be
74
+ further defined and clarified by project maintainers.
75
+
76
+ ### Enforcement
77
+
78
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
79
+ reported by contacting the project team. All
80
+ complaints will be reviewed and investigated and will result in a response that
81
+ is deemed necessary and appropriate to the circumstances. The project team is
82
+ obligated to maintain confidentiality with regard to the reporter of an incident.
83
+ Further details of specific enforcement policies may be posted separately.
84
+
85
+ Project maintainers who do not follow or enforce the Code of Conduct in good
86
+ faith may face temporary or permanent repercussions as determined by other
87
+ members of the project's leadership.
88
+
89
+ ### Attribution
90
+
91
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
92
+ available at [http://contributor-covenant.org/version/1/4][version]
93
+
94
+ [homepage]: http://contributor-covenant.org
95
+ [version]: http://contributor-covenant.org/version/1/4/
@@ -1,27 +1,28 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dapps
3
- Version: 0.0.4
3
+ Version: 0.0.6
4
4
  Summary: A library for creating and connecting dApps to Open RAN units.
5
5
  Project-URL: Homepage, https://openrangym.com/o-ran-frameworks/dapps
6
6
  Project-URL: Package, https://pypi.org/project/dapps/
7
7
  Project-URL: Source, https://github.com/wineslab/dApp-library
8
8
  Project-URL: Bug Tracker, https://github.com/wineslab/dApp-library/issues
9
9
  Author-email: Andrea Lacava <thecave003@gmail.com>
10
+ License-Expression: Apache-2.0
10
11
  License-File: LICENSE
11
12
  Keywords: 5G,O-RAN,cellular,dApps,networks
12
13
  Classifier: Development Status :: 4 - Beta
13
14
  Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3.8
15
- Classifier: Programming Language :: Python :: 3.9
16
15
  Classifier: Programming Language :: Python :: 3.10
17
16
  Classifier: Programming Language :: Python :: 3.11
18
17
  Classifier: Programming Language :: Python :: 3.12
19
18
  Classifier: Programming Language :: Python :: Implementation :: CPython
20
19
  Classifier: Programming Language :: Python :: Implementation :: PyPy
21
- Requires-Python: >=3.8
20
+ Requires-Python: >=3.10
22
21
  Requires-Dist: asn1tools
22
+ Requires-Dist: jsonschema>=4.18.0
23
23
  Requires-Dist: numpy
24
24
  Requires-Dist: pyzmq
25
+ Requires-Dist: sigmf
25
26
  Requires-Dist: typing-extensions
26
27
  Provides-Extra: all
27
28
  Requires-Dist: flask; extra == 'all'
@@ -62,7 +63,7 @@ Clone the repository and install it manually with:
62
63
 
63
64
  ```
64
65
  hatch build
65
- pip3 install dist/*.tar.gz
66
+ pip3 install "dist/*.tar.gz[all]"
66
67
  ```
67
68
 
68
69
  ### Launch the Spectrum Sharing dApp example
@@ -74,27 +75,43 @@ python3 examples/spectrum_dapp.py
74
75
  ```
75
76
 
76
77
  This dApp implements a spectrum sharing use case discussed in [our paper](https://doi.org/10.1016/j.comnet.2025.111342) ([here for the archive version](https://arxiv.org/pdf/2501.16502)).
77
- The dApp parameters can be controlled through the following command-line arguments:
78
-
79
- - `--link` (str, default: 'zmq', choices: [layer.value for layer in E3LinkLayer]): Specify the link layer to be used
80
- - `--transport` (str, default: 'ipc', choices: [layer.value for layer in E3TransportLayer]): Specify the transport layer to be used
81
- - `--save-iqs` (store_true, default: False): Specify if this is data collection run or not. In the first case I/Q samples will be saved
82
- - `--control` (store_true, default: False): Set whether to perform control of PRB
83
- - `--noise-floor-threshold` (int, default: None): Set the noise floor threshold for determining the presence of incumbents and for detecting the PRBs affected.
84
- - `--ota` (store_true, default: False): Specify if the setup used is OTA or on Colosseum for determining the noise floor threshold. If the `noise_floor_threshold` parameter is specified, this parameter is ignored
85
- - `--energy-gui` (store_true, default: False): Set whether to enable the energy GUI
86
- - `--iq-plotter-gui` (store_true, default: False): Set whether to enable the IQ Plotter GUI
87
- - `--demo-gui` (store_true, default: False): Set whether to enable the Demo GUI
88
- - `--num-prbs` (int, default: 106): Number of PRBs
89
- - `--num-subcarrier-spacing` (int, default: 30): Subcarrier spacing in kHz (FR1 is 30)
90
- - `--e` (store_true, default: False): Set if 3/4 sampling for FFT size is set on the gNB (-E option on OAI)
91
- - `--center-freq` (float, default: 3.6192e9): Center frequency in Hz
92
- - `--timed` (store_true, default: False): Run with a 5-minute time limit
93
- - `--model` (str, default: ''): Path to the CNN model file to be used
94
- - `--time-window` (int, default: 5): Number of input vectors to pass to the CNN model
95
- - `--moving-avg-window` (int, default: 30): Window size (in samples) for the moving average used to detect energy peaks in the spectrum
96
- - `--extraction-window` (int, default: 600): Number of samples to retain after detecting an energy peak
97
78
 
79
+ **Command-line arguments:**
80
+
81
+ **Connection Configuration:**
82
+ - `--link` - Specify the link layer to be used. Options: `zmq`, `posix` (default: `zmq`)
83
+ - `--transport` - Specify the transport layer to be used. Options: `ipc`, `tcp` (default: `ipc`)
84
+
85
+ **Data Collection and Control:**
86
+ - `--save-iqs` - Enable data collection mode. When set, I/Q samples will be saved to disk for later analysis using SigMF
87
+ - `--control` - Enable PRB control. When set, the dApp will actively control spectrum allocation based on detected interference. If not set, the dApp can still receive and implement control action from an external xApp
88
+
89
+ **Spectrum Sensing Configuration:**
90
+ - `--noise-floor-threshold` - Set the noise floor threshold (in dB) for determining the presence of incumbents and for detecting the PRBs affected. If not specified, will be auto-detected based on environment
91
+ - `--ota` - Specify if the setup is Over-The-Air (OTA) or on Colosseum testbed for using a precalculated noise floor threshold. If `--noise-floor-threshold` is specified, this parameter is ignored
92
+
93
+ **Visualization Options:**
94
+ - `--energy-gui` - Enable the energy spectrum visualization GUI
95
+ - `--iq-plotter-gui` - Enable the I/Q constellation plotter GUI
96
+ - `--demo-gui` - Enable the demonstration GUI showing real-time spectrum occupancy
97
+
98
+ **Radio Configuration:**
99
+ - `--num-prbs` - Number of Physical Resource Blocks in the channel (default: 106)
100
+ - `--num-subcarrier-spacing` - Subcarrier spacing in kHz. Use 30 for FR1 (sub-6 GHz) (default: 30)
101
+ - `--e` - Enable 3/4 FFT sampling mode. Set this flag if the gNB was started with the `-E` option
102
+ - `--center-freq` - Center frequency in Hz (default: 3.6192e9, which is 3.6192 GHz)
103
+
104
+ **Execution Control:**
105
+ - `--timed SECONDS` - Run the dApp with a time limit (in seconds). Set to 0 for no limit (default: 0)
106
+
107
+ **AI/ML Model Configuration:**
108
+ - `--model` - Path to a pre-trained CNN model file for spectrum classification. If not provided, uses rule-based detection
109
+ - `--time-window` - Number of consecutive spectrum vectors to use as input for the CNN model (default: 5)
110
+
111
+ **Signal Processing Parameters:**
112
+ - `--moving-avg-window` - Window size (in samples) for the moving average filter used to smooth energy measurements and detect peaks in the spectrum (default: 30)
113
+ - `--extraction-window` - Number of samples to retain after detecting an energy peak for further analysis (default: 600)
114
+ - `--sampling-threshold` - Down-sampling ratio applied to IQ sensing. An IQ vector will be delivered every Nth sensing (default: 5)
98
115
 
99
116
  If you use the dApp concept and/or the framework to develop your own dApps, please cite the following paper:
100
117
 
@@ -112,3 +129,73 @@ keywords = {Open RAN, dApps, Real-time control loops, Radio Resource Management
112
129
  abstract = {Open Radio Access Networks (RANs) leverage disaggregated and programmable RAN functions and open interfaces to enable closed-loop, data-driven radio resource management. This is performed through custom intelligent applications on the RAN Intelligent Controllers (RICs), optimizing RAN policy scheduling, network slicing, user session management, and medium access control, among others. In this context, we have proposed dApps as a key extension of the O-RAN architecture into the real-time and user-plane domains. Deployed directly on RAN nodes, dApps access data otherwise unavailable to RICs due to privacy or timing constraints, enabling the execution of control actions within shorter time intervals. In this paper, we propose for the first time a reference architecture for dApps, defining their life cycle from deployment by the Service Management and Orchestration (SMO) to real-time control loop interactions with the RAN nodes where they are hosted. We introduce a new dApp interface, E3, along with an Application Protocol (AP) that supports structured message exchanges and extensible communication for various service models. By bridging E3 with the existing O-RAN E2 interface, we enable dApps, xApps, and rApps to coexist and coordinate. These applications can then collaborate on complex use cases and employ hierarchical control to resolve shared resource conflicts. Finally, we present and open-source a dApp framework based on OpenAirInterface (OAI). We benchmark its performance in two real-time control use cases, i.e., spectrum sharing and positioning in a 5th generation (5G) Next Generation Node Base (gNB) scenario. Our experimental results show that standardized real-time control loops via dApps are feasible, achieving average control latency below 450microseconds and allowing optimal use of shared spectral resources.}
113
130
  }
114
131
  ```
132
+
133
+ ## E3 Service Model Generator
134
+
135
+ The `tools/generate_sm.sh` script helps you create skeleton code for new E3 Service Models. This automates the creation of boilerplate code for both the agent (OAI) and dApp sides.
136
+
137
+ ### Usage
138
+
139
+ **Interactive mode (recommended for first-time users):**
140
+ ```bash
141
+ cd tools
142
+ ./generate_sm.sh --interactive
143
+ ```
144
+
145
+ **Command-line mode:**
146
+ ```bash
147
+ ./generate_sm.sh -n <sm_name> -a <asn_file> [OPTIONS]
148
+ ```
149
+
150
+ **Options:**
151
+ - `-n, --name NAME` - Service Model name (required)
152
+ - `-a, --asn-file FILE` - ASN.1 definition file path (required)
153
+ - `-t, --target TARGET` - Target: `agent`, `dapp`, or `both` (default: both)
154
+ - `-r, --ran-functions IDS` - Comma-separated RAN function IDs (e.g., 2,3,4)
155
+ - `-f, --format FORMAT` - Encoding format: `asn1` or `json` (default: asn1)
156
+ - `--agent-root PATH` - Path to OAI repository (or set `AGENT_ROOT` env var)
157
+ - `-i, --interactive` - Interactive mode with prompts
158
+ - `-h, --help` - Show help message
159
+
160
+ **Examples:**
161
+ ```bash
162
+ # Generate both agent and dApp code for positioning SM
163
+ cd tools
164
+ ./generate_sm.sh -n positioning -a positioning.asn -r 2 --agent-root /path/to/spear-openairinterface5g
165
+
166
+ # Generate only dApp code for KPM SM
167
+ ./generate_sm.sh -n kpm -a kpm.asn -r 3,4 -t dapp
168
+
169
+ # Interactive mode
170
+ ./generate_sm.sh --interactive
171
+ ```
172
+
173
+ **Generated Structure:**
174
+
175
+ For agent-side (when `--target agent` or `both`):
176
+ ```
177
+ spear-openairinterface5g/openair2/E3AP/service_models/<sm_name>_sm/
178
+ ├── <sm_name>_sm.h # Main SM header
179
+ ├── <sm_name>_sm.c # Main SM implementation
180
+ ├── <sm_name>_enc.h/.c # Encoding functions
181
+ ├── <sm_name>_dec.h/.c # Decoding functions
182
+ ├── CMakeLists.txt # Build configuration
183
+ └── MESSAGES/
184
+ ├── CMakeLists.txt
185
+ └── ASN1/V1/
186
+ ├── e3sm_<sm_name>.asn
187
+ └── e3sm_<sm_name>.cmake
188
+ ```
189
+
190
+ For dApp-side (when `--target dapp` or `both`):
191
+ ```
192
+ spear-dApp/src/<sm_name>/
193
+ ├── __init__.py
194
+ ├── <sm_name>_dapp.py # Main dApp implementation
195
+ └── defs/
196
+ └── e3sm_<sm_name>.asn # ASN.1 schema
197
+ ```
198
+
199
+ ### Contributing
200
+
201
+ Contributions are welcome, but they must follow the guidelines in [CONTRIBUTING.md](./CONTRIBUTING.md)
dapps-0.0.6/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # dApp Library
2
+
3
+ A complete tutorial on how to deploy a dApp can be found on the [OpenRAN Gym website](https://openrangym.com/tutorials/dapps-oai). Please refer to that guide to instrument your system.
4
+
5
+ ## Installation
6
+
7
+ ### Python package installation (recommended)
8
+
9
+ ```
10
+ pip3 install dapps[all]
11
+ ```
12
+
13
+ The dApp can be found in the `examples` directory or it can be downloaded from this repository.
14
+
15
+ ### Manual installation (use only for library development)
16
+
17
+ Clone the repository and install it manually with:
18
+
19
+ ```
20
+ hatch build
21
+ pip3 install "dist/*.tar.gz[all]"
22
+ ```
23
+
24
+ ### Launch the Spectrum Sharing dApp example
25
+
26
+ OAI should start _before_ running the dApp
27
+
28
+ ```python
29
+ python3 examples/spectrum_dapp.py
30
+ ```
31
+
32
+ This dApp implements a spectrum sharing use case discussed in [our paper](https://doi.org/10.1016/j.comnet.2025.111342) ([here for the archive version](https://arxiv.org/pdf/2501.16502)).
33
+
34
+ **Command-line arguments:**
35
+
36
+ **Connection Configuration:**
37
+ - `--link` - Specify the link layer to be used. Options: `zmq`, `posix` (default: `zmq`)
38
+ - `--transport` - Specify the transport layer to be used. Options: `ipc`, `tcp` (default: `ipc`)
39
+
40
+ **Data Collection and Control:**
41
+ - `--save-iqs` - Enable data collection mode. When set, I/Q samples will be saved to disk for later analysis using SigMF
42
+ - `--control` - Enable PRB control. When set, the dApp will actively control spectrum allocation based on detected interference. If not set, the dApp can still receive and implement control action from an external xApp
43
+
44
+ **Spectrum Sensing Configuration:**
45
+ - `--noise-floor-threshold` - Set the noise floor threshold (in dB) for determining the presence of incumbents and for detecting the PRBs affected. If not specified, will be auto-detected based on environment
46
+ - `--ota` - Specify if the setup is Over-The-Air (OTA) or on Colosseum testbed for using a precalculated noise floor threshold. If `--noise-floor-threshold` is specified, this parameter is ignored
47
+
48
+ **Visualization Options:**
49
+ - `--energy-gui` - Enable the energy spectrum visualization GUI
50
+ - `--iq-plotter-gui` - Enable the I/Q constellation plotter GUI
51
+ - `--demo-gui` - Enable the demonstration GUI showing real-time spectrum occupancy
52
+
53
+ **Radio Configuration:**
54
+ - `--num-prbs` - Number of Physical Resource Blocks in the channel (default: 106)
55
+ - `--num-subcarrier-spacing` - Subcarrier spacing in kHz. Use 30 for FR1 (sub-6 GHz) (default: 30)
56
+ - `--e` - Enable 3/4 FFT sampling mode. Set this flag if the gNB was started with the `-E` option
57
+ - `--center-freq` - Center frequency in Hz (default: 3.6192e9, which is 3.6192 GHz)
58
+
59
+ **Execution Control:**
60
+ - `--timed SECONDS` - Run the dApp with a time limit (in seconds). Set to 0 for no limit (default: 0)
61
+
62
+ **AI/ML Model Configuration:**
63
+ - `--model` - Path to a pre-trained CNN model file for spectrum classification. If not provided, uses rule-based detection
64
+ - `--time-window` - Number of consecutive spectrum vectors to use as input for the CNN model (default: 5)
65
+
66
+ **Signal Processing Parameters:**
67
+ - `--moving-avg-window` - Window size (in samples) for the moving average filter used to smooth energy measurements and detect peaks in the spectrum (default: 30)
68
+ - `--extraction-window` - Number of samples to retain after detecting an energy peak for further analysis (default: 600)
69
+ - `--sampling-threshold` - Down-sampling ratio applied to IQ sensing. An IQ vector will be delivered every Nth sensing (default: 5)
70
+
71
+ If you use the dApp concept and/or the framework to develop your own dApps, please cite the following paper:
72
+
73
+ ```text
74
+ @article{LACAVA2025111342,
75
+ title = {{dApps: Enabling Real-Time AI-based Open RAN Control}},
76
+ journal = {Computer Networks},
77
+ pages = {111342},
78
+ year = {2025},
79
+ issn = {1389-1286},
80
+ doi = {https://doi.org/10.1016/j.comnet.2025.111342},
81
+ url = {https://www.sciencedirect.com/science/article/pii/S1389128625003093},
82
+ author = {Andrea Lacava and Leonardo Bonati and Niloofar Mohamadi and Rajeev Gangula and Florian Kaltenberger and Pedram Johari and Salvatore D’Oro and Francesca Cuomo and Michele Polese and Tommaso Melodia},
83
+ keywords = {Open RAN, dApps, Real-time control loops, Radio Resource Management (RRM), Spectrum sharing, Positioning, Integrated Sensing and Communication (ISAC)},
84
+ abstract = {Open Radio Access Networks (RANs) leverage disaggregated and programmable RAN functions and open interfaces to enable closed-loop, data-driven radio resource management. This is performed through custom intelligent applications on the RAN Intelligent Controllers (RICs), optimizing RAN policy scheduling, network slicing, user session management, and medium access control, among others. In this context, we have proposed dApps as a key extension of the O-RAN architecture into the real-time and user-plane domains. Deployed directly on RAN nodes, dApps access data otherwise unavailable to RICs due to privacy or timing constraints, enabling the execution of control actions within shorter time intervals. In this paper, we propose for the first time a reference architecture for dApps, defining their life cycle from deployment by the Service Management and Orchestration (SMO) to real-time control loop interactions with the RAN nodes where they are hosted. We introduce a new dApp interface, E3, along with an Application Protocol (AP) that supports structured message exchanges and extensible communication for various service models. By bridging E3 with the existing O-RAN E2 interface, we enable dApps, xApps, and rApps to coexist and coordinate. These applications can then collaborate on complex use cases and employ hierarchical control to resolve shared resource conflicts. Finally, we present and open-source a dApp framework based on OpenAirInterface (OAI). We benchmark its performance in two real-time control use cases, i.e., spectrum sharing and positioning in a 5th generation (5G) Next Generation Node Base (gNB) scenario. Our experimental results show that standardized real-time control loops via dApps are feasible, achieving average control latency below 450microseconds and allowing optimal use of shared spectral resources.}
85
+ }
86
+ ```
87
+
88
+ ## E3 Service Model Generator
89
+
90
+ The `tools/generate_sm.sh` script helps you create skeleton code for new E3 Service Models. This automates the creation of boilerplate code for both the agent (OAI) and dApp sides.
91
+
92
+ ### Usage
93
+
94
+ **Interactive mode (recommended for first-time users):**
95
+ ```bash
96
+ cd tools
97
+ ./generate_sm.sh --interactive
98
+ ```
99
+
100
+ **Command-line mode:**
101
+ ```bash
102
+ ./generate_sm.sh -n <sm_name> -a <asn_file> [OPTIONS]
103
+ ```
104
+
105
+ **Options:**
106
+ - `-n, --name NAME` - Service Model name (required)
107
+ - `-a, --asn-file FILE` - ASN.1 definition file path (required)
108
+ - `-t, --target TARGET` - Target: `agent`, `dapp`, or `both` (default: both)
109
+ - `-r, --ran-functions IDS` - Comma-separated RAN function IDs (e.g., 2,3,4)
110
+ - `-f, --format FORMAT` - Encoding format: `asn1` or `json` (default: asn1)
111
+ - `--agent-root PATH` - Path to OAI repository (or set `AGENT_ROOT` env var)
112
+ - `-i, --interactive` - Interactive mode with prompts
113
+ - `-h, --help` - Show help message
114
+
115
+ **Examples:**
116
+ ```bash
117
+ # Generate both agent and dApp code for positioning SM
118
+ cd tools
119
+ ./generate_sm.sh -n positioning -a positioning.asn -r 2 --agent-root /path/to/spear-openairinterface5g
120
+
121
+ # Generate only dApp code for KPM SM
122
+ ./generate_sm.sh -n kpm -a kpm.asn -r 3,4 -t dapp
123
+
124
+ # Interactive mode
125
+ ./generate_sm.sh --interactive
126
+ ```
127
+
128
+ **Generated Structure:**
129
+
130
+ For agent-side (when `--target agent` or `both`):
131
+ ```
132
+ spear-openairinterface5g/openair2/E3AP/service_models/<sm_name>_sm/
133
+ ├── <sm_name>_sm.h # Main SM header
134
+ ├── <sm_name>_sm.c # Main SM implementation
135
+ ├── <sm_name>_enc.h/.c # Encoding functions
136
+ ├── <sm_name>_dec.h/.c # Decoding functions
137
+ ├── CMakeLists.txt # Build configuration
138
+ └── MESSAGES/
139
+ ├── CMakeLists.txt
140
+ └── ASN1/V1/
141
+ ├── e3sm_<sm_name>.asn
142
+ └── e3sm_<sm_name>.cmake
143
+ ```
144
+
145
+ For dApp-side (when `--target dapp` or `both`):
146
+ ```
147
+ spear-dApp/src/<sm_name>/
148
+ ├── __init__.py
149
+ ├── <sm_name>_dapp.py # Main dApp implementation
150
+ └── defs/
151
+ └── e3sm_<sm_name>.asn # ASN.1 schema
152
+ ```
153
+
154
+ ### Contributing
155
+
156
+ Contributions are welcome, but they must follow the guidelines in [CONTRIBUTING.md](./CONTRIBUTING.md)
dapps-0.0.6/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.6
@@ -0,0 +1,210 @@
1
+ @startuml
2
+ !theme mars
3
+ skinparam defaultFontSize 20
4
+ skinparam classFontSize 22
5
+ skinparam backgroundColor transparent
6
+ left to right direction
7
+ skinparam linetype ortho
8
+ !define AbstractClass class
9
+ hide empty members
10
+ hide circles
11
+
12
+ class E3Interface {
13
+ -- Attributes --
14
+ - _instance : E3Interface
15
+ - _lock : threading.Lock
16
+ - callbacks : dict[int, list]
17
+ - stop_event : multiprocessing.Event
18
+ - initialized : bool
19
+ - _message_id_counter : int
20
+ - _message_id_lock : threading.Lock
21
+ - e3_connector : E3Connector
22
+ - encoder : E3Encoder
23
+ - outbound_queue : multiprocessing.Queue
24
+ - inbound_process : multiprocessing.Process
25
+ - outbound_process : multiprocessing.Process
26
+ -- Methods --
27
+ __new__()
28
+ __init__(encoder: E3Encoder, **kwargs)
29
+ Note: kwargs can include: link (str), transport (str)
30
+ + send_setup_request(dappId: int) : bool | list
31
+ + send_subscription_request(ranFunctionId: int, dappId: int, actionType: str) : bool
32
+ + send_message_ack(requestId: int, responseCode: str)
33
+ + setup_connections()
34
+ + add_callback(dapp_id: int, callback)
35
+ + remove_callback(dapp_id: int, callback=None)
36
+ + schedule_control(dappId: int, actionData: bytes)
37
+ + schedule_report(reportData: bytes)
38
+ + terminate_connections()
39
+ - _inbound_connection()
40
+ - _outbound_connection()
41
+ - _handle_incoming_data(dapp_identifier: int, data)
42
+ - _get_next_message_id() : int
43
+ }
44
+
45
+ AbstractClass SpectrumSharingDApp {
46
+ -- Attributes --
47
+ - spectrum_encoder : asn1tools.Compiler
48
+ - _sampling_threshold_control_callback : callable
49
+ - num_consecutive_subcarriers_for_prb : int
50
+ - num_prbs : int
51
+ - num_subcarrier_spacing : int
52
+ - ofdm_symbol_size : int
53
+ - bw : float
54
+ - center_freq : float
55
+ - fft_size : int
56
+ - first_carrier_offset : int
57
+ - prb_thrs : int
58
+ - average_over_frames : int
59
+ - noise_floor_threshold : int
60
+ - save_iqs : bool
61
+ - sampling_threshold : int
62
+ - iq_save_file : file
63
+ - save_counter : int
64
+ - limit_per_file : int
65
+ - control : bool
66
+ - energyGui : bool
67
+ - iqPlotterGui : bool
68
+ - dashboard : bool
69
+ - control_count : int
70
+ - abs_iq_av : np.ndarray
71
+ - sig_queue : multiprocessing.Queue (optional, if energyGui=True)
72
+ - energyPlotter : EnergyPlotter (optional, if energyGui=True)
73
+ - iq_queue : multiprocessing.Queue (optional, if iqPlotterGui=True)
74
+ - iqPlotter : IQPlotter (optional, if iqPlotterGui=True)
75
+ - demo_queue : multiprocessing.Queue (optional, if dashboard=True)
76
+ - demo : Dashboard (optional, if dashboard=True)
77
+ -- Methods --
78
+ __init__(id: int, link: str, transport: str, noise_floor_threshold: int, save_iqs: bool, control: bool, center_freq: float, num_prbs: int, num_subcarrier_spacing: int, e_sampling: bool, encoding_method: str, sampling_threshold: int, **kwargs)
79
+ Note: kwargs can include: energyGui, iqPlotterGui, dashboard, classifier
80
+ - _init_spectrum_encoder()
81
+ + set_sampling_threshold_control_logic(callback)
82
+ + create_prb_blacklist_control(blacklisted_prbs: bytes, prb_count: int, sampling_period_ms: int, action_definition: str) : bytes
83
+ + decode_iq_data_indication(data: bytes) : dict
84
+ + decode_config_control(data: bytes) : dict
85
+ + get_iqs_from_ran(dapp_identifier: int, data: bytes)
86
+ # _control_loop()
87
+ # _stop()
88
+ - _encode_spectrum_message(message_type: str, data: dict) : bytes
89
+ - _decode_spectrum_message(message_type: str, data: bytes) : dict
90
+ }
91
+
92
+
93
+ AbstractClass DApp {
94
+ -- Attributes --
95
+ - dapp_id : int
96
+ - encoding_method : str
97
+ - e3_interface : E3Interface
98
+ - stop_event : multiprocessing.Event
99
+ -- Methods --
100
+ __init__(id: int, link: str, transport: str, callbacks: list, encoding_method: str, **kwargs)
101
+ + setup_connection() : bool, list
102
+ + send_subscription_request(ranFunctionIds: list)
103
+ + control_loop()
104
+ + stop()
105
+ # _control_loop() : abstract
106
+ # _stop() : abstract
107
+ }
108
+
109
+ class E3LinkLayer {
110
+ -- Enumeration --
111
+ + ZMQ = "zmq"
112
+ + POSIX = "posix"
113
+ -- Methods --
114
+ + from_string(link_layer_str: str)
115
+ }
116
+
117
+ class E3TransportLayer {
118
+ -- Enumeration --
119
+ + SCTP = "sctp"
120
+ + TCP = "tcp"
121
+ + IPC = "ipc"
122
+ -- Methods --
123
+ + from_string(transport_layer_str: str)
124
+ }
125
+
126
+ AbstractClass E3Connector {
127
+ -- Attributes --
128
+ - VALID_CONFIGURATIONS : list
129
+ - E3_IPC_SETUP_PATH : str
130
+ - E3_IPC_SOCKET_PATH : str
131
+ - DAPP_IPC_SOCKET_PATH : str
132
+ -- Methods --
133
+ + setup_connector(link_layer: str, transport_layer: str)
134
+ + send_setup_request(payload: bytes)
135
+ + setup_inbound_connection()
136
+ + setup_outbound_connection()
137
+ + send(payload: bytes)
138
+ + receive() : bytes
139
+ + dispose()
140
+ }
141
+
142
+ class ZMQConnector {
143
+ -- Attributes --
144
+ - setup_context : zmq.Context
145
+ - inbound_context : zmq.Context
146
+ - outbound_context : zmq.Context
147
+ - transport_layer : E3TransportLayer
148
+ -- Methods --
149
+ + __init__(transport_layer: E3TransportLayer)
150
+ + send_setup_request(payload: bytes)
151
+ + setup_inbound_connection()
152
+ + setup_outbound_connection()
153
+ + send(payload: bytes)
154
+ + receive() : bytes
155
+ + dispose()
156
+ }
157
+
158
+ class POSIXConnector {
159
+ -- Attributes --
160
+ - transport_layer : E3TransportLayer
161
+ - CHUNK_SIZE : int
162
+ -- Methods --
163
+ + __init__(transport_layer: E3TransportLayer)
164
+ + send_setup_request(payload: bytes)
165
+ + setup_inbound_connection()
166
+ + setup_outbound_connection()
167
+ + send(payload: bytes)
168
+ + receive() : bytes
169
+ + dispose()
170
+ }
171
+
172
+ AbstractClass E3Encoder {
173
+ -- Attributes --
174
+ - encoding_type : str
175
+ -- Methods --
176
+ + encode_pdu(pdu_type: str, pdu_data: dict) : bytes
177
+ + decode_pdu(data: bytes) : tuple
178
+ + create_setup_request(dappId: int, ranFunctions: list, msgId: int, actionType: str) : bytes
179
+ + create_subscription_request(msgId: int, dappId: int, actionType: str, ranFunctionId: int) : bytes
180
+ + create_message_ack(msgId: int, requestId: int, responseCode: str) : bytes
181
+ + create_control_action(msgId: int, dappId: int, actionData: bytes) : bytes
182
+ + create_dapp_report(msgId: int, reportData: bytes) : bytes
183
+ + create_indication_message(msgId: int, protocolData: bytes) : bytes
184
+ }
185
+
186
+ class AsnE3Encoder {
187
+ -- Attributes --
188
+ - defs : asn1tools.Compiler
189
+ -- Methods --
190
+ + __init__(asn_file_path: str)
191
+ + encode_pdu(pdu_type: str, pdu_data: dict) : bytes
192
+ + decode_pdu(data: bytes) : tuple
193
+ + create_setup_request(dappId: int, ranFunctions: list, msgId: int, actionType: str) : bytes
194
+ + create_subscription_request(msgId: int, dappId: int, actionType: str, ranFunctionId: int) : bytes
195
+ + create_message_ack(msgId: int, requestId: int, responseCode: str) : bytes
196
+ + create_control_action(msgId: int, dappId: int, actionData: bytes) : bytes
197
+ + create_dapp_report(msgId: int, reportData: bytes) : bytes
198
+ + create_indication_message(msgId: int, protocolData: bytes) : bytes
199
+ }
200
+
201
+ DApp --> E3Interface
202
+ DApp <|-- SpectrumSharingDApp
203
+ E3Connector <|-- ZMQConnector
204
+ E3Connector <|-- POSIXConnector
205
+ E3Encoder <|-- AsnE3Encoder
206
+ E3Interface --* E3Connector
207
+ E3Interface --* E3Encoder
208
+ E3Connector --> E3LinkLayer
209
+ E3Connector --> E3TransportLayer
210
+ @enduml