- `src` - contains source code for the Rapp
- `config.json` - configuration file for database, RAPP, and SME settings
- `sme_client.py` - Service Management Environment client for service discovery
+ - `ran_nssmf_client.py` - RAN Network Slice Subnet Management Function client
- `models/` - directory for trained AI/ML models and scalers
- `data_generator.py` - generates data for training and testing the model
- `Dockerfile` - contains instructions to build a Docker image for the Rapp
- `aefProfiles`: Application Exposure Function profiles
- `versions`: API version information
- `resources`: Available resources within each version
-- `interfaceDescriptions`: Network endpoint details (IP, port)
\ No newline at end of file
+- `interfaceDescriptions`: Network endpoint details (IP, port)
+
+## RAN NSSMF Client (`src/ran_nssmf_client.py`)
+
+The `ran_nssmf_client.py` module implements a client for interacting with the RAN Network Slice Subnet Management Function (NSSMF). This component enables the RAPP to communicate with RAN slice management services for resource optimization and slice lifecycle management.
+
+### Key Features
+
+- **Dynamic Service Discovery**: Uses SME to automatically discover RAN NSSMF endpoints
+- **Configuration-Driven**: Loads all settings from centralized config.json file
+- **O-RAN Integration**: Seamlessly integrates with O-RAN RAN architecture
+- **Flexible Endpoint Management**: Supports both static and dynamic endpoint configuration
+
+### RAN_NSSMF_CLIENT Class
+
+The main class provides the following functionality:
+
+#### Initialization
+```python
+client = RAN_NSSMF_CLIENT()
+```
+
+The client automatically loads configuration from `config.json` and initializes:
+- RAN NSSMF endpoint address from RAPP configuration
+- SME discovery parameters for dynamic endpoint resolution
+- Service identification credentials
+
+#### Service Discovery Integration
+
+The client integrates with the SME client for dynamic endpoint discovery:
+
+```python
+def get_url_from_sme(self):
+ sme_client = SMEClient(
+ invoker_id=self.invoker_id,
+ api_name=self.ran_nssmf_api_name,
+ resource_name=self.ran_nssmf_resource_name
+ )
+
+ self.ran_nssmf_address = sme_client.discover_service()
+```
+
+#### Configuration Parameters
+
+The client uses the following configuration sections from `config.json`:
+
+**RAPP Configuration:**
+```json
+{
+ "RAPP": {
+ "ran_nssmf_address": "http://localhost:8080", // Static fallback endpoint
+ "callback_uri": "http://localhost:8080/handleFileReadyNotification"
+ }
+}
+```
+
+**SME Configuration:**
+```json
+{
+ "SME": {
+ "invoker_id": "6a965002-ed7c-4f69-855c-ab9196f86e61",
+ "ran_nssmf_api_name": "", // API name for SME discovery
+ "ran_nssmf_resource_name": "" // Resource name for SME discovery
+ }
+}
+```
+
+#### Usage Example
+```python
+# Initialize RAN NSSMF client
+ran_client = RAN_NSSMF_CLIENT()
+
+# Discover service endpoint dynamically (if SME configured)
+ran_client.get_url_from_sme()
+
+# Use the discovered or configured endpoint
+if ran_client.ran_nssmf_address:
+ print(f"RAN NSSMF available at: {ran_client.ran_nssmf_address}")
+ # Make API calls to RAN NSSMF for slice management
+else:
+ print("RAN NSSMF endpoint not available")
+```
+
+### Integration with RAPP Architecture
+
+The RAN NSSMF client serves as a bridge between the PRB prediction system and the RAN slice management infrastructure:
+
+1. **Resource Optimization**: Provides interface to adjust slice resource allocations based on PRB predictions
+2. **Slice Lifecycle Management**: Enables programmatic control over slice creation, modification, and termination
+3. **Performance Monitoring**: Facilitates collection of real-time RAN performance metrics
+4. **Policy Enforcement**: Allows implementation of resource allocation policies based on ML predictions
+
+### Error Handling and Logging
+
+The client includes comprehensive error handling:
+- Configuration validation and error reporting
+- Service discovery failure handling with fallback to static endpoints
+- Detailed logging for debugging and monitoring
+- Graceful degradation when services are unavailable
+
+## Model Training (Jupyter Notebook)
+
+The `RAN_Slice_PRB_Prediction_Rapp_Model_Generator.ipynb` notebook provides a complete pipeline for training the LSTM model used for PRB prediction.
+
+### Training Pipeline
+
+1. **Data Fetching**: Retrieves NSSAI performance data from InfluxDB using Flux queries
+2. **Data Preprocessing**:
+ - One-hot encoding for slice types and NSSI IDs
+ - MinMax scaling for numerical features
+ - Time series sequence creation with sliding windows
+3. **Model Architecture**: LSTM neural network with dropout layers for time series prediction
+4. **Training Process**:
+ - Time-based train/validation split
+ - Early stopping and learning rate scheduling
+ - Model checkpointing for best performance
+5. **Evaluation**: Calculates MAE, RMSE, and R² scores with visualization
+6. **Artifact Saving**: Stores trained models, encoders, and scalers for deployment
+
+### Key Model Parameters
+
+- **Window Size**: 672 time steps (approximately 7 days at 15-minute intervals)
+- **Horizon**: 1-step ahead prediction
+- **Features**: One-hot encoded slice types/NSSI IDs + scaled PRB/data/RRC metrics
+- **Target**: PRB downlink usage percentage
+- **Loss Function**: Huber loss for robust training
+- **Optimizer**: Adam with learning rate scheduling
+
+### Model Artifacts
+
+After training, the following artifacts are saved to the `models/` directory:
+- `best_prb_lstm.keras`: Best performing model checkpoint
+- `final_prb_lstm.keras`: Final trained model
+- `slice_onehot.joblib`: Slice type encoder
+- `nssi_onehot.joblib`: NSSI ID encoder
+- `scaler_*.joblib`: Feature and target scalers
+- `meta.json`: Model metadata and configuration
+
+### Usage
+
+To train a new model:
+
+1. Ensure InfluxDB is running and contains performance data
+2. Update database connection parameters in the notebook
+3. Run all cells sequentially to execute the training pipeline
+4. Monitor training progress and evaluation metrics
+5. Use the saved artifacts for deployment in the RAPP
+
+## Deployment and Usage
+
+### Prerequisites
+
+- Python 3.8+
+- InfluxDB 2.x for time series data storage
+- TensorFlow/Keras for model inference
+- O-RAN Service Management Environment (optional for service discovery)
+
+### Running the Application
+
+1. **Generate Training Data**:
+ ```bash
+ python data_generator.py
+ ```
+
+2. **Train ML Model**:
+ ```bash
+ jupyter notebook RAN_Slice_PRB_Prediction_Rapp_Model_Generator.ipynb
+ ```
+
+3. **Configure Application**:
+ - Update `src/config.json` with your environment settings
+ - Configure InfluxDB connection parameters
+ - Set up SME endpoints if using service discovery
\ No newline at end of file
--- /dev/null
+import json
+import logging
+
+from sme_client import SMEClient
+
+
+logger = logging.getLogger(__name__)
+
+class RAN_NSSMF_CLIENT(object):
+
+ def __init__(self):
+ with open('config.json', 'r') as f:
+ config = json.load(f)
+
+ rapp_config = config.get("RAPP", {})
+ self.ran_nssmf_address = rapp_config.get("ran_nssmf_address")
+
+ # Load the SME configuration from the JSON file
+ sme_config = config.get("SME", {})
+ self.invoker_id = sme_config.get("invoker_id")
+ self.ran_nssmf_api_name = sme_config.get("ran_nssmf_api_name")
+ self.ran_nssmf_resource_name = sme_config.get("ran_nssmf_resource_name")
+
+ def get_url_from_sme(self):
+ sme_client = SMEClient(
+ invoker_id=self.invoker_id,
+ api_name=self.ran_nssmf_api_name,
+ resource_name=self.ran_nssmf_resource_name
+ )
+
+ self.ran_nssmf_address = sme_client.discover_service()
+
+ logger.info("RAN NSSMF URL: {}".format(self.ran_nssmf_address))
+
+ if self.ran_nssmf_address is not None:
+ self.address = self.ran_nssmf_address.rstrip('/')
+ logger.debug(f"InfluxDB Address: {self.address}")
+ else:
+ logger.error("Failed to discover RAN NSSMF URL from SME.")
+
\ No newline at end of file