# How to develop a MEC application using the MEC Sandbox HTTP REST API
This tutorial introduces the step by step procedure to create a basic MEC appcation following ETSI MEC standards.
It uses the ETSI MEC Sandbox simulator.
<divclass="alert alert-block alert-danger">
<b>Note:</b> These source code examples are simplified and ignore return codes and error checks to a large extent. We do this to highlight how to use the MEC Sandbox API and the different MEC satndards and reduce unrelated code.
A real-world application will of course properly check every return value and exit correctly at the first serious error.
</div>
%% Cell type:markdown id: tags:
## What is a MEC application
See [The Wiki MEC web site](https://www.etsi.org/technologies/multi-access-edge-computing)
%% Cell type:markdown id: tags:
## The basics of developing a MEC application
The developement of a MEC application follows a strict process in order to access the ETSI MEC services and provides valuable services to the customers.
Mainly, this process can be split in several steps:
1. Global initializations (constant, variables...)
2. Create a new instance of a MEC Sandbox (Note that using an existing one could be a solution too (see Annex A)
2. Create a new instance of a MEC Sandbox (Note that using an existing one could be a solution too (see Annex A))
3. Activate a network scenario in order to access the ETSI MEC services
4. Create a new application identifier
5. Register our MEC application and subscribe to service termination (see MEC 011)
6. Use MEC services in order to provide valuable services to the customers
**Note:** Several application identifier can be created to address several MEC application.
## Use the MEC Sandbox HTTP REST API models and code
The MEC sandbox provides a piece of code (the python sub) that shall be used to develop the MEC application and interact with the MEC Sandbox. This piece of code mainly contains swagger models to serialize/deserialize JSON data structures and HTTP REST API call functions.
The openApi file is availabe [here](https://labs.etsi.org/rep/mec/etsi-mec-sandbox/-/blob/STF678_Task1_2_3_4/go-apps/meep-sandbox-api/api/swagger.yaml) and the [Swagger editor](https://editor-next.swagger.io/) is used to generate the python sub.
The openApi file is availabe [here](https://labs.etsi.org/rep/mec/etsi-mec-sandbox/-/blob/STF678_Task1_2_3_4/go-apps/meep-sandbox-api/api/swagger.yaml) and the [Swagger editor](https://editor-next.swagger.io/) is used to generate the python stub.
The project architecture is describe [here](images/project_arch.jpg).
The sandbox_api folder contains the python implementation of the HTTP REST API definitions introduced by the openApi [file](https://labs.etsi.org/rep/mec/etsi-mec-sandbox/-/blob/STF678_Task1_2_3_4/go-apps/meep-sandbox-api/api/swagger.yaml).
The model folder contains the python implementation of the data type definitions introduced by the openApi [file](https://labs.etsi.org/rep/mec/etsi-mec-sandbox/-/blob/STF678_Task1_2_3_4/go-apps/meep-sandbox-api/api/swagger.yaml).
%% Cell type:markdown id: tags:
Before going to create our MEC application skeleton, the following steps shall be done:
1) Change the working directory (see the project architecture)
%% Cell type:code id: tags:
``` python
importos
os.chdir(os.path.join(os.getcwd(),'../mecapp'))
print(os.getcwd())
```
%% Cell type:markdown id: tags:
2) Apply the python imports
%% Cell type:code id: tags:
``` python
from__future__importdivision# Import floating-point division (1/4=0.25) instead of Euclidian division (1/4=0)
nw_scenarios=[]# The list of available network scenarios
nw_scenario_idx=-1# The network scenario idx to activate (deactivate)
app_inst_id=None# The requested application instance identifier
```
%% Cell type:markdown id: tags:
## Create our first MEC application
The first step to develop a MEC application is to create the application skeleton which contains the minimum steps below:
- Login to instanciate a MEC Sandbox
- Logout to delete a existing MEC Sandbox
%% Cell type:markdown id: tags:
### First steps: the login/logout
Here is the first squeleton with the following sequence:
- Login
- Print sandbox identifier
- Logout
- Check that logout is effective
%% Cell type:markdown id: tags:
#### The login function
To log to the MEC Sandbox,
the login process is done in two step. In step 1, a user code is requested to GITHUB. In step 2, the user has to enter this user code to https://github.com/login/device and proceed to the authorization.
Please, pay attention to the log '=======================> DO AUTHORIZATION WITH CODE :' which indicates you the user code to use for the authorization.
It uses the HTTP POST request with the URL 'POST /sandbox-sandbox_api/v1/login?provide=github' (see PROVIDER constant).
%% Cell type:code id: tags:
``` python
# Login
defprocess_login()->str:
"""
Authenticate and create a new MEC Sandbox instance.
:return: The sandbox instance identifier on success, None otherwise
logger.error('Exception when calling AuthorizationApi->logout: %s\n'%e)
return-1
# End of function process_logout
```
%% Cell type:markdown id: tags:
Now, let put in action our Login/Logout functions:
%% Cell type:code id: tags:
``` python
defprocess_main():
"""
This is the skeleton of our MEC application:
- Login
- Print sandbox identifier
- Logout
- Check that logout is effective
This skeleton will be the bas of the next sprint in order to achieve a full implementation of a MEC application
"""
globallogger
logger.debug('Starting at '+time.strftime('%Y%m%d-%H%M%S'))
logger.debug('\t pwd= '+os.getcwd())
# Login
sandbox=process_login()
ifsandboxisNone:
return
# Print sandbox identifier
logger.info('Sandbox created: '+sandbox)
# Wait for the MEC Sandbox is running
time.sleep(STABLE_TIME_OUT)# Wait for k8s pods up and running
# Logout
process_logout(sandbox)
# Check that logout is effective
logger.debug('To check that logout is effective, verify on the MEC Sandbox server that the MEC Sandbox is removed (kubectl get pods -A)')
logger.debug('Stopped at '+time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if__name__=='__main__':
process_main()
```
%% Cell type:markdown id: tags:
### Second step: Retrieve the list of network scenarios
Let's go futhur and see how we can retrieve the list of the network scenarios available in order to activate one of them and access the MEC services exposed such as MEC 013 or MEC 030.
The sequence will be:
- Login
- Print sandbox identifier
- Print available network scenarios
- Logout
- Check that logout is effective
The login and logout functions are described in cell 3 and 4.
To retrieve the list of the network scenarios, let's create a new function called 'get_network_scenarios'. It uses the HTTP GET request with the URL '/sandbox-sandbox_api/v1/sandboxNetworkScenarios?sandbox_name={sandbox_name}'.
%% Cell type:code id: tags:
``` python
defget_network_scenarios(sandbox_name:str)->list:
"""
Retrieve the list of the available network scenarios.
:param sandbox_name: The MEC Sandbox instance to use
:return: The list of the available network scenarios on success, None otherwise
logger.info('nw_scenarios: No scenario available')
# Logout
process_logout(sandbox)
# Check that logout is effective
logger.debug('To check that logout is effective, verify on the MEC Sandbox server that the MEC Sandbox is removed (kubectl get pods -A)')
logger.debug('Stopped at '+time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if__name__=='__main__':
process_main()
```
%% Cell type:markdown id: tags:
### Third step: Activate and deactivate a network scenario
Having a list of network scenarion, the next step is to actvate (and deactivate) a network scenario. This step is mandatory to create a new application instance id and access the MEC services.
In this section, we will arbitrary activate the network scenario called '4g-5g-macro-v2x', which is at the index 0 of the nw_scenarios.
Select the network scenario to activate based of the provided list of criterias.
:param criterias_list: The list of criterias to select the correct network scenario
:return: 0 on success, -1 otherwise
"""
return0# The index of the '4g-5g-macro-v2x' network scenario - Hard coded
```
%% Cell type:markdown id: tags:
#### The activate function
The process to activate a scenario is based on an HTTP POST request with the URL '/sandboxNetworkScenarios/{sandbox_name}?network_scenario_id={network_scenario_id}'.
logger.error('Exception when calling SandboxNetworkScenariosApi->activate_network_scenario: %s\n'%e)
return-1
# End of function activate_network_scenario
```
%% Cell type:markdown id: tags:
#### The deactivate function
The process to deactivate a scenario is based on an HTTP DELETE request with the URL '/sandboxNetworkScenarios/{sandbox_name}?network_scenario_id={network_scenario_id}'.
time.sleep(2*STABLE_TIME_OUT)# Wait for k8s pods up and running
# Check that the network scenario is activated and the MEC services are running
logger.info('To check that the network scenario is activated, verify on the MEC Sandbox server that the MEC services are running (kubectl get pods -A)')
time.sleep(30)# Sleep for 30 seconds
# Deactivate a network scenario based on a list of criterias (hard coded!!!)
ifdeactivate_network_scenario(sandbox)==-1:
logger.error('Failed to deactivate network scenario')
logger.debug('To check that logout is effective, verify on the MEC Sandbox server that the MEC Sandbox is removed (kubectl get pods -A)')
logger.debug('Stopped at '+time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if__name__=='__main__':
process_main()
```
%% Cell type:markdown id: tags:
### Fourth step: Create and delete an appliction instance id
To enable our MEC application to be part of the activated network scenario, we need to request the MEC sandbox to create a new application instance identifier. Our MEC application will use this identifier to register to the MEC Sandbox according to MEC 011.
logger.debug('To check that logout is effective, verify on the MEC Sandbox server that the MEC Sandbox is removed (kubectl get pods -A)')
logger.debug('Stopped at '+time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if__name__=='__main__':
process_main()
```
%% Cell type:markdown id: tags:
## MEC Registration and the READY confirmation
Having an application instance identifier allows us to register with the MEC Sandbox and interact with it (e.g. to send service queries, to subscribe to events and to recieve notifications...).
The standard MEC 011 Clause 5.2.2 MEC application start-up describes the start up process. Basically, our MEC application has to:
1. Indicates that it is running by sending a Confirm Ready message
2. Retrieve the list of MEC services
To do so, a MEC application needs to be able to send requests but also to receive notifications (POST requests) and to reply to them.
%% Cell type:markdown id: tags:
### Fifth step: Send the READY confirmation
The MEC application instance confirms towards the MEC platform that it is up and running. It corresponds to step 4c described inETSI GS MEC 011 V3.2.1 (2024-04)11 Clause 5.2.2 MEC application start-up.
logger.error('Exception when calling call_api: %s\n'%e)
return-1
# End of function send_ready_confirmation
```
%% Cell type:markdown id: tags:
In addition, our MEC application is registering to AppTerminationNotificationSubscription and it needs to delete its subscription when terminating.
At this stage, it is important to note that all subscription deletion use the same format: <subscriptionURL>/<subscriptionidentifier> (see ETSI MEC GS 003 [16]).
In this case, it the AppTerminationNotificationSubscription is 'sub-1234', the URIs to do the susbscription and to delete it are:
So, it will be usefull to create a small function to extract the subscription identifier from either the HTTP Location header or from the Link field found into the reponse body data structure.
%% Cell type:markdown id: tags:
#### Subscribing to application termination
The purpose is to create a new subscription to
the MEC application termination notification as describe in ETSI GS MEC 011 V3.2.1 (2024-04) Clause 5.2.6b Receiving event notifications on MEC application instance
logger.debug('Stopped at '+time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if__name__=='__main__':
process_main()
```
%% Cell type:markdown id: tags:
## Create our second MEC application: how to use MEC Location Service
After doing the logging, network scenario activation, MEC application instance creation steps, we are ready to exploit the MEC services exposed by the MEC Sandbox.
In this clause, we use the following functionalities provided by MEC-013 LocationAPIs:
- Subscribe to the UE Location changes (ETSI GS MEC 030 Clause 5.3.4)
- Delete subscription
### First step: Getting UE location lookup
First of all, just create a function to request the location of a specific UE. The UE identifier depends of the network scenario which was activated. In our example, we are using the 4g-5g-macro-v2x network scenario and we will run our code with the high velocity UE (i.e., the cars such as 10.100.0.1).
logger.debug('Stopped at '+time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if__name__=='__main__':
process_main()
```
%% Cell type:markdown id: tags:
### Second step: Adding a subscription
%% Cell type:markdown id: tags:
## Create our third MEC application: how to use V2X MEC Services
After doing the logging, network scenario activation, MEC application instance creation steps, we are ready to exploit the MEC services exposed by the MEC Sandbox.
In this clause, we use the following functionalities provided by MEC-030:
logger.error('Exception when calling call_api: %s\n'%e)
returnNone
# End of function send_uu_unicast_provisioning_info
```
%% Cell type:markdown id: tags:
Let's create the our second MEC application.
The sequence is the following:
- Mec application setup
- Get UU unicast provisioning information
- Mec application termination
Note that the UU unicast provisioning information is returned as a JSON string. To de-serialized it into a Python data structure, please refer to clause [Subscribing to V2X message distribution server](#subscribing_to_v2x_message_distribution_server).
%% Cell type:code id: tags:
``` python
defprocess_main():
"""
This is the second sprint of our skeleton of our MEC application:
- Mec application setup
- Get UU unicast provisioning information
- Mec application termination
"""
globallogger,nw_scenarios
logger.debug('Starting at '+time.strftime('%Y%m%d-%H%M%S'))
logger.debug('\t pwd= '+os.getcwd())
# Setup the MEC application
(sandbox_name,app_inst_id,sub_id)=mec_app_setup()
# Get UU unicast provisioning information
ecgi="268708941961,268711972264"# List of ecgi spearated by a ','
logger.debug('Stopped at '+time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if__name__=='__main__':
process_main()
```
%% Cell type:markdown id: tags:
### Subscribing to V2X message distribution server
Here, we need to come back to the MEC 030 standard to create the type V2xMsgSubscription. It involves the creation of a set of basic types described below.
These new type shall be 'JSON' serializable. It means that they have to implement the following methods:
logger.error('Exception when calling call_api: %s\n'%e)
returnNone
# End of function subscribe_v2x_message
```
%% Cell type:markdown id: tags:
Here is a generic function to delete any MEC service subscription based on the subscription resource URL provided in the Location header of the subscription creation response.
logger.debug('Stopped at '+time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if__name__=='__main__':
process_main()
```
%% Cell type:markdown id: tags:
### Notification support
To recieve notifcation, our MEC application is required to support an HTTP listenener to recieve POST requests from the MEC Sandbox and reply to them: this is the notification mechanism.
This minimalistic HTTP server will also be used to implement the endpoints provided by our MEC application service: see chapter [Our third MEC application: how to create a new MEC Services](#our_third_mec_application_how_to_create_a_new_mec_services).
The class HTTPRequestHandler (see cell below) provides the suport of such mechanism.
logger.debug('Stopped at '+time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if__name__=='__main__':
process_main()
```
%% Cell type:markdown id: tags:
## Create our fourth MEC application: how to use V2X QoS Prediction
The MEC Sanbox V2X QoS Prediction is based on a grid Map of Monaco City where areas are categorized into residential, commercial and coastal.
PoAs (Point Of Access) are categorized depending on where they lie in each grid.
Each category has its own traffic load patterns which are pre-determin. The V2X QoS Prediction) will give more accurate values of RSRP and RSRQ based on the diurnal traffic patterns for each. The network scenario named "4g-5g-v2x-macro" must be used to get access to the V2X QoS Prediction feature.
**Note:** The MEC Sanbox V2X QoS Prediction is enabled when the PredictedQos.routes.routeInfo.time attribute is present in the request (see ETSI GS MEC 030 V3.2.1 (2024-02) Clause 6.2.6 Type: Preditecd QoS)
Limitations:
* The Location Granularity is currently not being validated as RSRP/RSRP calculations are done at the exact location provided by the user.
* Time Granularity is currently not supported by the Prediction Function (design limitations of the minimal, emulated, pre-determined traffic prediction)
* Upper limit on the number of elements (10 each) in the routes and routeInfo structures (arrays) to not affect user experience and respoy
%% Cell type:markdown id: tags:
The table below describes the excepted Qos with and without the prediction model in deiffrent area and at different time.
| Location | Time | PoA | Category | Status | QoS without Prediction Model | QoS with Prediction Model | Expected |
| | (Unix time in sec) | Standard (GMT) | | | | RSRP | RSRQ | RSRP | RSRQ | |
logger.debug('Stopped at ' + time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if __name__ == '__main__':
process_main()
```
%% Cell type:markdown id: tags:
## Our third MEC application: how to create a new MEC Services
The purpose of this MEC Service application is to provide a custom MEC service that can be use by other MEC applications. For the purpose of this tutorial, our MEC service is simulating some complex calculation based on a set of data provided by the MEC use.
We will use a second MEC application to exploit the features of our new MEC services.
In this clause, we use the following functionalities provided by MEC-011:
- Register a new service
- Retrieve the list of the MEC services exposed by the MEC platform
- Check that our new MEC service is present in the list of the MEC platform services
- Execute a request to the MEC service
- Delete the newly created service
**Note:** We will use a second MEC application to exploit the features of our new MEC services.
**Reference:** ETSI GS MEC 011 V3.2.1 (2024-04) Clause 5.2.4 Service availability update and new service registration
%% Cell type:markdown id: tags:
### Bases of the creation of a MEC service
#### Introduction
From the user perspective, a MEC service provides a set of endpoints which describe the interface of the MEC service (see [HTTP REST APIs
concepts](https://blog.postman.com/rest-api-examples/)). These endpoints come usually with a set of data structures used by the one or more endpoints.
Our service is really basic: it provide one endpoint:
- GET /statistic/v1/quantity: it computes statistical quantities of a set of data (such as average, max, min, standard deviation)
As described in ETSI GS MEC 011 Clause 5.2.4 Service availability update and new service registration, to create a new MEC service, the following information is required:
- A MEC Aplication instance: this is the MEC application providing the new MEC service (ETSI GS MEC 011 V3.2.1 Clause 8.2.6.3.4 POST)
- A ServiceInfo instance which describe the MEC service (ETSI GS MEC 011 V3.2.1 Clause 8.1.2.2 Type: ServiceInfo)
- As part of the ServiceInfo instance, a TransportInfo (ETSI GS MEC 011 V3.2.1 Clause 8.1.2.3 Type: TransportInfo) instance descibes the endpoints to use the MEC service
When created and available, all the other MEC applications are notified about the existance of this MEC service.
logger.debug('Stopped at ' + time.strftime('%Y%m%d-%H%M%S'))
# End of function process_main
if __name__ == '__main__':
process_main()
```
%% Cell type:markdown id: tags:
# Annexes
## Annex A: How to use an existing MEC sandbox instance
This case is used when the MEC Sandbox API is not used. The procedure is the following:
- Log to the MEC Sandbox using a WEB browser
- Select a network scenario
- Create a new application instance
When it is done, the newly created application instance is used by your application when required. This application instance is usually passed to your application in the command line or using a configuration file
%% Cell type:markdown id: tags:
### Bibliography
1. ETSI GS MEC 002 (V2.2.1) (01-2022): "Multi-access Edge Computing (MEC); Phase 2: Use Cases and Requirements".
2. ETSI GS MEC 010-1 (V1.1.1) (10-2017): "Mobile Edge Computing (MEC); Mobile Edge Management; Part 1: System, host and platform management".
3. ETSI GS MEC 010-2 (V2.2.1) (02-2022): "Multi-access Edge Computing (MEC); MEC Management; Part 2: Application lifecycle, rules and requirements management".