diff --git a/simu/data/access_point_list.csv b/simu/data/access_point_list.csv new file mode 100644 index 0000000000000000000000000000000000000000..ce83101402e7d3ed5fce5e35b1d0b71d60474f63 --- /dev/null +++ b/simu/data/access_point_list.csv @@ -0,0 +1,7 @@ +accessPointId,zoneId,connectionType,operationStatus,numberOfUsers,interestRealm,resourceURL +001010000000000000000000000000001,zone01,Macro,Serviceable,5,LA,http://example.com/exampleAPI/location/v1/zones/zone01/accessPoints/ap001 +001010000000000000000000000000010,zone01,Macro,Unserviceable,0,DC,http://example.com/exampleAPI/location/v1/zones/zone01/accessPoints/ap002 +001010000000000000000000000000011,zone01,Macro,Serviceable,5,NJ,http://example.com/exampleAPI/location/v1/zones/zone01/accessPoints/ap003 +002010000000000000000000000000001,zone02,Macro,Serviceable,5,LA,http://example.com/exampleAPI/location/v1/zones/zone02/accessPoints/ap001 +002010000000000000000000000000010,zone02,Macro,Unserviceable,0,DC,http://example.com/exampleAPI/location/v1/zones/zone02/accessPoints/ap002 +002010000000000000000000000000011,zone02,Macro,Serviceable,5,NJ,http://example.com/exampleAPI/location/v1/zones/zone02/accessPoints/ap003 diff --git a/simu/data/associated.csv b/simu/data/associated.csv new file mode 100644 index 0000000000000000000000000000000000000000..f4f9131b32127d6baefe0a9f23bc5fa8fa156b90 --- /dev/null +++ b/simu/data/associated.csv @@ -0,0 +1,3 @@ +cellId,appInst,type,address +134217738,appInst01,1,192.0.0.1 +134217739,appInst02,1,192.0.0.2 diff --git a/simu/data/cells.csv b/simu/data/cells.csv new file mode 100644 index 0000000000000000000000000000000000000000..2ba84522be7378cfd898adfeea4b87fd110d7f4a --- /dev/null +++ b/simu/data/cells.csv @@ -0,0 +1,3 @@ +cellId,mcc,mnc,hoStatus,seconds,nanoseconds +134217738,1,1,COMPLETED,1577836800,0 +134217739,1,1,COMPLETED,1577836800,0 diff --git a/simu/data/location_info.csv b/simu/data/location_info.csv new file mode 100644 index 0000000000000000000000000000000000000000..06afa5bb1263ee4cd692de326648242f317039fd --- /dev/null +++ b/simu/data/location_info.csv @@ -0,0 +1,4 @@ +accessPointId,latitude,longitude,altitude,accuracy +001010000000000000000000000000001,90.123,80.123,10.0,0 +001010000000000000000000000000010,91.123,81.123,12.0,1 +001010000000000000000000000000011,93.123,83.123,16.0,3 diff --git a/simu/data/subscribers.csv b/simu/data/subscribers.csv new file mode 100644 index 0000000000000000000000000000000000000000..ab026929534cadb88b9221ccdb536f4df7594814 --- /dev/null +++ b/simu/data/subscribers.csv @@ -0,0 +1,6 @@ +id,address,accessPointId,zoneId,resourceURL,seconds,nanoSeconds,ueTag +toto1,acr:192.0.0.1,001010000000000000000000000000001,zone01,http://example.com/exampleAPI/location/v2/users?address:acr:192.0.0.1,1483231138,0,UeTagA +toto2,acr:192.0.2.2,001010000000000000000000000000001,zone01,http://example.com/exampleAPI/location/v1/users?address:acr:192.0.2.2,1483231138,0,UeTagB +toto3,acr:192.0.2.3,001010000000000000000000000000010,zone01,http://example.com/exampleAPI/location/v1/users?address:acr:192.0.2.3,1483231138,0,UeTagC +toto4,acr:192.0.2.4,001010000000000000000000000000001,zone02,http://example.com/exampleAPI/location/v1/users?address:acr:192.0.2.4,1483231138,0,UeTagD +toto5,acr:192.0.2.5,001010000000000000000000000000010,zone02,http://example.com/exampleAPI/location/v1/users?address:acr:192.0.2.5,1483231138,0,UeTagE diff --git a/simu/data/ue_information_list.csv b/simu/data/ue_information_list.csv new file mode 100644 index 0000000000000000000000000000000000000000..fbd902cbd9072dd2ab7df011783833d7346bfda7 --- /dev/null +++ b/simu/data/ue_information_list.csv @@ -0,0 +1,6 @@ +appInst,ueTag,address,state +appInst01,UeTagA,acr:192.0.0.1,UNREGISTERED +appInst01,UeTagC,acr:192.0.0.3,UNREGISTERED +appInst02,UeTagB,acr:192.0.0.2,UNREGISTERED +appInst03,UeTagD,acr:192.0.0.4,UNREGISTERED +appInst03,UeTagE,acr:192.0.0.5,UNREGISTERED diff --git a/simu/data/zones.csv b/simu/data/zones.csv new file mode 100644 index 0000000000000000000000000000000000000000..ebbbf6891a6dc0068dd5e93580f66dc5faba2296 --- /dev/null +++ b/simu/data/zones.csv @@ -0,0 +1,3 @@ +zoneId,numberOfAccessPoints,numberOfUnserviceableAccessPoints,numberOfUsers,resourceURL +zone01,3,1,10,http://example.com/exampleAPI/location/v1/zones/zone01 +zone02,12,0,36,http://example.com/exampleAPI/location/v1/zones/zone02 diff --git a/simu/mec_database.py b/simu/mec_database.py new file mode 100644 index 0000000000000000000000000000000000000000..bb38d31a2300b8744096eb893de27a30c7303a22 --- /dev/null +++ b/simu/mec_database.py @@ -0,0 +1,210 @@ +# Simulate MEC devices using Pandas database + +import pandas as pd +from datetime import datetime, time + +class mec_database: + """ Private properties """ + __path__ = "/Users/yanng/OneDrive/Documents/Python/Mec/data/" # To be updated according to the local settings + __subscribers__ = None + __registered_list__ = None + __zones__ = None + __ue_information_list__ = None + __access_point_list__ = None + __location_info__ = None + __cells__ = None + __associated__ = None + + def __init__(self): + """ Default ctor: Open Pandas database. """ + self.__zones__ = pd.DataFrame(pd.read_csv(self.__path__ + 'zones.csv', index_col = 'zoneId')) + self.__subscribers__ = pd.DataFrame(pd.read_csv(self.__path__ + 'subscribers.csv', index_col = 'address')) + self.__ue_information_list__ = pd.DataFrame(pd.read_csv(self.__path__ + 'ue_information_list.csv', index_col = ['appInst', 'ueTag'])) + self.__access_point_list__ = pd.DataFrame(pd.read_csv(self.__path__ + 'access_point_list.csv', index_col = 'accessPointId')) + self.__location_info__ = pd.DataFrame(pd.read_csv(self.__path__ + 'location_info.csv', index_col = 'accessPointId')) + self.__cells__ = pd.DataFrame(pd.read_csv(self.__path__ + 'cells.csv', encoding = 'utf-8', index_col = 'cellId')) + self.__associated__ = pd.DataFrame(pd.read_csv(self.__path__ + 'associated.csv', encoding = 'utf-8', index_col = 'cellId')) + #self.dump() + # End of __init__ + + def dump(self): + """ Dump database contents. For debug purpose only. """ + print("Subscribers: ", self.__subscribers__.head()) + print("Zones: ", self.__zones__.head()) + print("UEinformation", self.__ue_information_list__.head()) + print("AccessPoint: ", self.__access_point_list__.head()) + print("LocationInfo: ", self.__location_info__.head()) + print("Cells: ", self.__cells__.head()) + print("Associated: ", self.__associated__.head()) + # End of dump + + def __to_accessPoint__(self, p_access_point, p_location): + """ Build an AccessPointLocation Json message. """ + print(">>> __to_accessPoint__: ", p_access_point) + print("__to_accessPoint__: location= ", p_location['latitude'][0]) + i = 0.0 + resp = "{\"accessPointId\": \"" + p_access_point[0] + \ + "\",\"locationInfo\": {\"latitude\": " + str(p_location['latitude'][0]) + ",\"longitude\": " + str(p_location['longitude'][0]) + ",\"altitude\": " + str(p_location['altitude'][0]) + ",\"accuracy\": " + str(p_location['accuracy'][0]) + "}," \ + "\"connectionType\": \"" + p_access_point[2] + "\"," \ + "\"operationStatus\": \"" + p_access_point[3] + "\"," \ + "\"numberOfUsers\": " + str(p_access_point[4]) + "," \ + "\"interestRealm\": \"" + p_access_point[5] + "\"," \ + "\"resourceURL\": \"" + p_access_point[6] + "\"" \ + "}" + print("__to_accessPoint__: ", resp) + return resp + # End of __to_accessPoint__ + + def __to_zone__(self, p_zone): + """ Build a Zones Json message. """ + print(">>> __to_zone__: ", p_zone) + resp = "{\t\"zoneId\": \"" + p_zone[0] + "\",\t\"numberOfAccessPoints\": \"" + str(p_zone[1]) + "\",\t\"numberOfUnserviceableAccessPoints\": \"" + str(p_zone[2]) + "\",\t\"numberOfUsers\": \"" + str(p_zone[3]) + "\",\t\"resourceURL\": \"" + p_zone[4] + "\"}" + print("__to_zone__: ", resp) + return resp + # End of __to_zone__ + + def __to_userInfo__(self, p_subscriber, p_location = None, p_contextLocationInfo = None): + """ Build a UserInfo Json message. """ + print(">>> __to_userInfo__: ", p_subscriber) + resp = "{\t\"address\": \"" + p_subscriber[0] + "\",\t\"accessPointId\": \"" + p_subscriber[2] + "\",\t\"zoneId\": \"" + p_subscriber[3] + "\",\t\"resourceURL\": \"" + p_subscriber[4] + "\"}" + print("__to_userInfo__: ", resp) + return resp + # End of __to_userInfo__ + + def __to_ueIdentityTagInfo__(self, p_ue_identity_tag, p_ue): + """ Build a ueIdentityTagInfo Json message. """ + print(">>> __to_ueIdentityTagInfo__: ", p_ue_identity_tag, ", ", p_ue) + resp = "{\t\"ueIdentityTagInfo\": {\t\"ueIdentityTags\": [{\t\"ueIdentityTag\": \"" + p_ue_identity_tag + "\",\t\"state\": \"" + p_ue[1] + "\"}]}}" + print("__to_ueIdentityTagInfo__: ", resp) + return resp + # End of __to_ueIdentityTagInfo__ + + def getSubscriberList(self, p_uri): + """ Build a SubscriberList Json message. """ + print(">>> getSubscriberList") + resp = None + try: + resp = "{\"userList\": {\t\"user\": [\t" + for r in self.__subscribers__.itertuples(): + t = tuple(r) + resp += self.__to_userInfo__(t) + "," + # En of 'for' statement + resp = resp[: len(resp) - 1] + resp += "\t],\"resourceURL\": \"http://example.com" + p_uri + "\"}}" + print("getSubscriberList: ", resp) + except KeyError: + print("getSubscriberList: No subscriber list") + return resp + # End of getSubscriberList + + def getZoneList(self, p_uri): + print(">>> getZoneList") + resp = None + try: + resp = "{\"zoneList\": {\t\"zone\": [\t" + for r in self.__zones__.itertuples(): + t = tuple(r) + resp += self.__to_zone__(t) + "," + # En of 'for' statement + resp = resp[: len(resp) - 1] + resp += "\t],\"resourceURL\": \"http://example.com" + p_uri + "\"}}" + print("getZoneList: ", resp) + except KeyError: + print("getZoneList: No zones list") + return resp + # End of getZoneList + + def getAccessPointList(self, p_zone_id, p_uri): + print(">>> getAccessPointList") + resp = None + try: + + r = self.__access_point_list__.loc[self.__access_point_list__['zoneId'] == p_zone_id] + print("getAccessPointList: r= ", r) + resp = "{\"accessPointList\": {\t\"zoneId\": \"" + p_zone_id + "\",\t\"accessPoint\": [\t" + for i in r.itertuples(): + t = tuple(i) + location = self.__location_info__.loc[[t[0]]] + resp += self.__to_accessPoint__(t, location) + "," + # En of 'for' statement + resp = resp[: len(resp) - 1] + resp += "\t],\"resourceURL\": \"http://example.com" + p_uri + "\"}}" + print("getAccessPointList: ", resp) + except KeyError: + print("getAccessPointList: No access point list") + return resp + # End of method getAccessPointList + + def getSubscriptionLinkList(self, p_uri): + return "{\"SubscriptionLinkList\": {\"_links\": {\"self\": \"http://example.com" + p_uri + "\"},\"subscription\": [{\"href\": \"http://meAppClient.example.com/rni/v1/notifications/cell_change/77777\",\"subscriptionType\": \"CELL_CHANGE\"},{\"href\": \"http://meAppClient.example.com/rni/v1/notifications/MeasTa/77777\",\"subscriptionType\": \"MEAS_TIMING_ADVANCE\"}]}}" + # End of method getSubscriptionLinkList + + def getSubscriberFromAddress(self, p_ue_address): + print(">>> getSubscriberFromAddress: ", p_ue_address) + result = None + try: + r = tuple(self.__subscribers__.loc[[p_ue_address]].itertuples(index=True, name=''))[0] + print("getSubscriberFromAddress: Find subscriber with address ", p_ue_address, ": ", r) + result = "{\"userInfo\": " + self.__to_userInfo__(r) + "}" + except KeyError: + print("getSubscriberFromAddress: No subscriber with address ", p_ue_address) + return result + # End of method getSubscriberFromAddress + + def getSubscriberFromZoneId(self, p_zone_id, p_uri): + print(">>> getSubscriberFromZoneId: ", p_zone_id) + resp = None + try: + r = self.__subscribers__.loc[self.__subscribers__['zoneId'] == p_zone_id] + resp = "{\"userList\": {\t\"user\": [\t" + for i in r.itertuples(): + t = tuple(i) + resp += self.__to_userInfo__(t) + "," + # En of 'for' statement + resp = resp[: len(resp) - 1] + resp += "\t],\"resourceURL\": \"http://example.com" + p_uri + "\"}}" + print("getSubscriberFromZoneId: ", resp) + except KeyError: + print("getSubscriberFromZoneId: No subscriber in zone ", p_zone_id) + return resp + # End of method getSubscriberFromAddress + + def getUEidentityTagInfo(self, p_app_inst, p_ue_identity_tag): + print(">>> getUEidentityTagInfo: ", p_app_inst, ", ", p_ue_identity_tag) + resp = None + try: + r = tuple(self.__ue_information_list__.loc[p_app_inst, p_ue_identity_tag]) + print("getUEidentityTagInfo: Find zoneId for appInst: ", p_app_inst, ", r= ", r) + resp = self.__to_ueIdentityTagInfo__(p_ue_identity_tag, r) + print("getUEidentityTagInfo: ", resp) + except KeyError: + print("getUEidentityTagInfo: No UE for appInst ", p_app_inst) + return resp + # End of method getUEidentityTagInfo + + def registerUEidentity(self, p_app_inst, p_json_msg): + print(">>> registerUEidentity", p_json_msg) + if p_json_msg["state"] != "REGISTERED" and p_json_msg["state"] != "UNREGISTERED": + return None + resp = None + try: + # Check the record exists + r = tuple(self.__ue_information_list__.loc[p_app_inst, p_json_msg["ueIdentityTag"]]) + print("registerUEidentity: Find zoneId for appInst: ", p_app_inst, ", r= ", r) + self.__ue_information_list__.loc[p_app_inst, p_json_msg["ueIdentityTag"]]['state'] = p_json_msg["state"] + l = (p_json_msg["ueIdentityTag"], p_json_msg["state"]) + resp = self.__to_ueIdentityTagInfo__(p_json_msg["ueIdentityTag"], l) + except KeyError: + print("registerUEidentity: No appInst/UE ", p_app_inst, "/", p_ue_identity_tag) + return resp + # End of method registerUEidentity + + def getBwAllocationAppInst(self, p_app_inst, p_ue_identity_tag): + print(">>> getBwAllocationAppInst: ", p_app_inst, ", ", p_ue_identity_tag) + resp = None + resp = "{\"bwInfo\": {\"timeStamp\": {\"seconds\": 0,\"nanoSeconds\": 0},\"appInsId\": \"string\",\"requestType\": \"APPLICATION_SPECIFIC_BW_ALLOCATION\",\"sessionFilter\": [{\"sourceIp\": \"string\",\"sourcePort\": [\"string\"],\"dstAddress\": \"string\",\"dstPort\": [\"string\"],\"protocol\": \"string\"}],\"fixedBWPriority\": \"not defined in the present document\",\"fixedAllocation\": \"string\",\"allocationDirection\": \"00 = Downlink (towards the UE)\"}}" + print("getBwAllocationAppInst: ", resp) + return resp + # End of method getBwAllocationAppInst + +# End of class mec_database diff --git a/simu/mec_http_server.py b/simu/mec_http_server.py new file mode 100644 index 0000000000000000000000000000000000000000..65e16662509b4dfd5375de1d536200f7d52fb29c --- /dev/null +++ b/simu/mec_http_server.py @@ -0,0 +1,278 @@ +import http.server +import json +from mec_database import mec_database + +# This class will handles any incoming request from the browser +class myHandler(http.server.BaseHTTPRequestHandler): + __db__ = mec_database() + + # Handler for the GET requests + def do_GET(self): + print(">>> do_GET: ", self.path) + self.protocol_version = self.request_version + # Check HTTP end_headers + if self.__check_http_headers__() == False: + resp = "{\"problemDetails\": {\t\"type\": \"Bad Request\",\t\"title\": \"N/A\",\t\"status\": 400,\t\"detail\": \"Wrong headers\",\t\"instance\": \"N/A\"}}" + self.send_response(400, 'Bad Request') + self.send_header('Host', self.headers.get('Host')) + self.send_header('Authorization', self.headers.get('Authorization')) + self.send_header('Content-Type', "application/problem+json") + l = len(resp) + self.send_header('Content-Length', str(l)) + self.end_headers() + self.wfile.write(bytes(resp, 'utf-8')) + return + + resp, content_type = self.__process__() + print("do_GET: resp= ", resp, ", Content_Type= ", content_type) + if (resp == None): + self.send_response(404, 'Not Found') + self.send_header('Host', self.headers.get('Host')) + self.send_header('Authorization', self.headers.get('Authorization')) + self.send_header('Content-Type', content_type) + self.send_header('Content-Length', '0') + self.end_headers() + else: + if resp.find('Not Found') != -1: + self.send_response(404, 'Not Found') + elif resp.find('Forbidden') != -1: + self.send_response(403, 'Forbidden') + elif resp.find('Bad Request') != -1: + self.send_response(400, 'Bad Request') + else: + self.send_response(200, 'OK') + self.send_header('Host', self.headers.get('Host')) + self.send_header('Authorization', self.headers.get('Authorization')) + self.send_header('Content-Type', content_type) + l = len(resp) + self.send_header('Content-Length', str(l)) + self.end_headers() + self.wfile.write(bytes(resp, 'utf-8')) + # End of do_GET + + # Handler for the POST requests + def do_POST(self): + print(">>> do_POST: ", self.path) + self.protocol_version = self.request_version + # Check HTTP end_headers + if self.__check_http_headers__() == False: + resp = "{\"problemDetails\": {\t\"type\": \"Bad Request\",\t\"title\": \"N/A\",\t\"status\": 400,\t\"detail\": \"Wrong headers\",\t\"instance\": \"N/A\"}}" + self.protocol_version = self.request_version + self.send_response(400, 'Bad Request') + self.send_header('Host', self.headers.get('Host')) + self.send_header('Authorization', self.headers.get('Authorization')) + self.send_header('Content-Type', "application/problem+json") + l = len(resp) + self.send_header('Content-Length', str(l)) + self.end_headers() + self.wfile.write(bytes(resp, 'utf-8')) + return + + resp, content_type = self.__process__() + print("do_POST: resp= ", resp, ", Content_Type= ", content_type) + if (resp == None): + self.send_response(404, 'Not Found') + self.send_header('Host', self.headers.get('Host')) + self.send_header('Authorization', self.headers.get('Authorization')) + self.send_header('Content-Type', content_type) + self.send_header('Content-Length', '0') + self.end_headers() + else: + if resp.find('Not Found') != -1: + self.send_response(404, 'Not Found') + elif resp.find('Forbidden') != -1: + self.send_response(403, 'Forbidden') + elif resp.find('Bad Request') != -1: + self.send_response(400, 'Bad Request') + else: + self.send_response(200, 'OK') + self.send_header('Host', self.headers.get('Host')) + self.send_header('Content-Type', content_type) + self.send_header('Authorization', self.headers.get('Authorization')) + self.send_header('Content-Type', content_type) + l = len(resp) + self.send_header('Content-Length', str(l)) + self.end_headers() + self.wfile.write(bytes(resp, 'utf-8')) + # End of do_POST + + # Check HTTP headers + def __check_http_headers__(self): + print (">>> __check_http_headers__") + result = True + host = self.headers.get('Host') + if host == None: + print("__check_http_headers__: Failed to parse 'Host' header") + result = False + content_type = self.headers.get('Content-Type') + if content_type != "application/json": + print("__check_http_headers__: Failed to parse 'Content-Type' header") + result = False + auth = self.headers.get('Authorization') + if auth == None: + print("__check_http_headers__: Failed to parse 'Authorization' header") + result = False + return result + # End of __check_http_headers__ + + # Process the request + def __process__(self): + s = self.path.split('/') + print (">>> __process__: ", s) + if s[1] != 'exampleAPI': + return None, "application/json" + # TODO Check HTTP headers + if s[2] == 'location' and ((s[3] == 'v1') or (s[3] == 'v2')): + return self.__process__location__api__(s) + elif s[2] == 'ui' and ((s[3] == 'v1') or (s[3] == 'v2')): + return self.__process__ue__identity__api__(s) + elif s[2] == 'rni' and ((s[3] == 'v1') or (s[3] == 'v2')): + return self.__process__rnis__api__(s) + elif s[2] == 'bwm' and ((s[3] == 'v1') or (s[3] == 'v2')): + return self.__process__bwm__api__(s) + else: + return None, "application/json" + # End of __process__ + + # Process the LocationAPI request + def __process__location__api__(self, p_split): + print (">>> __process__location__api__: ", p_split) + resp = None + content_type = "application/json" + if p_split[4].startswith('users'): # E.g. users?zoneId=zone01 + s = p_split[4].split('?') + if s.__len__() == 1: # Users list requested + resp = self.__db__.getSubscriberList(self.path) + elif s.__len__() == 2: # E.g. zoneId=zone01 + s = s[1].split('=') + if s[0] == 'zoneId': # Users list into a specific zoneId requested + resp = self.__db__.getSubscriberFromZoneId(s[1], self.path) + elif s[0] == 'address': + resp = self.__db__.getSubscriberFromAddress(s[1]) + elif p_split[4] == 'zones': + if p_split.__len__() == 5: + s = p_split[4].split('?') + print("__process__location__api__: ", s) + if s.__len__() == 1: # A list requested + if s[0] == 'zones': + resp = self.__db__.getZoneList(self.path) + else: + resp = "{\"Unsupported zone request\"}" + elif s.__len__() == 2: # E.g. ? + resp = "{\"Unsupported zone request\"}" + else: + resp = "{\"Unsupported " + p_split[4] + " request\"}" + elif p_split.__len__() == 7: + if p_split[6] == 'accessPoints': + resp = self.__db__.getAccessPointList(p_split[5], self.path) + else: + resp = "{\"Unsupported " + p_split[5] + " request\"}" + else: + resp = "{\"Unsupported " + p_split[4] + " request\"}" + else: + resp = "{\"Unsupported " + p_split[4] + " request\"}" + + print ("<<< __process__location__api__: ", resp, ", ", content_type) + return resp, content_type + # End of __process__location__api__ + + # Process the ue_identityAPI request + def __process__ue__identity__api__(self, p_split): + print (">>> __process__ue__identity__api__: ", p_split) + resp = None + content_type = "application/json" + if p_split[4] == 'appInst98': # Used for unknown application, e.g. TC_MEC_PLAT_UETAG_003_BI + resp = "{\"problemDetails\": {\t\"type\": \"Not Authorized\",\t\"title\": \"UEidentityAPI\",\t\"status\": 403,\t\"detail\": \"Forbidden\",\t\"instance\": \"AppInst98\"}}" + else: + if p_split[5].startswith('ue_identity_tag_info'): # E.g. ue_identity_tag_info?ueIdentityTag=UeTagA + s = p_split[5].split('?') + if s[0] != 'ue_identity_tag_info': + resp = "{\"problemDetails\": {\t\"type\": \"Bad Request\",\t\"title\": \"UEidentityAPI\",\t\"status\": 400,\t\"detail\": \"Wrong parameters\",\t\"instance\": \"string\"}}" + elif s.__len__() == 1: # ue_identity_tag_info, POST + # Register/Unregister operation + body = None + # Extract the body if any + content_len = int(self.headers.get('Content-Length')) + if (content_len != 0): + body = self.rfile.read(content_len) + json_msg = self.__decode__json__body__(body) + if (json_msg == None): + resp = "{\"problemDetails\": {\t\"type\": \"Body processing not supported\",\t\"title\": \"UEidentityAPI\",\t\"status\": 400,\t\"detail\": \"Unknown request\",\t\"instance\": \"string\"}}" + else: + resp = self.__db__.registerUEidentity(p_split[4], json_msg) + elif s.__len__() == 2: # E.g. ueIdentityTag=UeTagA + s = s[1].split('=') + if s[0] == 'ueIdentityTag': # Users list into a specific zoneId requested + resp = self.__db__.getUEidentityTagInfo(p_split[4], s[1]) + if (resp == None): + resp = "{\"problemDetails\": {\t\"type\": \"Not Found\",\t\"title\": \"UEidentityAPI\",\t\"status\": 404,\t\"detail\": \"Wrong parameters\",\t\"instance\": \"string\"}}" + content_type = "application/problem+json" + if (resp == None): + resp = "{\"problemDetails\": {\t\"type\": \"Bad Request\",\t\"title\": \"UEidentityAPI\",\t\"status\": 400,\t\"detail\": \"Wrong parameters\",\t\"instance\": \"string\"}}" + content_type = "application/problem+json" + elif resp.find('problemDetails') != -1: + content_type = "application/problem+json" + + print ("<<< __process__ue__identity__api__: ", resp, ", ", content_type) + return resp, content_type + # End of __process__ue__identity__api__ + + # Process the RnisAPI request + def __process__rnis__api__(self, p_split): + print (">>> __process__rnis__api__: ", p_split) + resp = None + content_type = "application/json" + if p_split[4].startswith('subscriptions'): + if p_split.__len__() == 6: + if p_split[5] == '': + resp = self.__db__.getSubscriptionLinkList(self.path) + if (resp == None): + resp = "{\"problemDetails\": {\t\"type\": \"Not supported\",\t\"title\": \"RnisAPI\",\t\"status\": 400,\t\"detail\": \"Wrong parameters\",\t\"instance\": \"string\"}}" + content_type = "application/problem+json" + + print ("<<< __process__rnis__api__: ", resp, ", ", content_type) + return resp, content_type + # End of __process__rnis__api__ + + # Process the BwManagementAPI request + def __process__bwm__api__(self, p_split): + print (">>> __process__bwm__api__: ", p_split) + resp = None + content_type = "application/json" + if p_split[4].startswith('bw_allocations'): # E.g. bw_allocation?app_instance_id=InstApp01 + s = p_split[4].split('?') + if s.__len__() == 1: # ue_identity_tag_info, POST + # Register/Unregister operation + body = None + # Extract the body if any + content_len = int(self.headers.get('Content-Length')) + if (content_len != 0): + body = self.rfile.read(content_len) + json_msg = self.__decode__json__body__(body) + if (json_msg == None): + resp = "{\"problemDetails\": {\t\"type\": \"Body processing not supported\",\t\"title\": \"BwManagementAPI\",\t\"status\": 400,\t\"detail\": \"Unknown request\",\t\"instance\": \"string\"}}" + content_type = "application/problem+json" + else: + resp = self.__db__.bwAllocation(json_msg) + elif s.__len__() == 2: # E.g. app_instance_id=InstApp01 + s = s[1].split('=') + if s[0] == 'app_instance_id': + resp = self.__db__.getBwAllocationAppInst(p_split[4], s[1]) + if (resp == None): + resp = "{\"problemDetails\": {\t\"type\": \"Not supported\",\t\"title\": \"BwManagementAPI\",\t\"status\": 400,\t\"detail\": \"Wrong parameters\",\t\"instance\": \"string\"}}" + content_type = "application/problem+json" + + print ("<<< __process__bwm__api__: ", resp, ", ", content_type) + return resp, content_type + # End of __process__bwm__api__ + + # Decode a Json HTTP body message + def __decode__json__body__(self, p_body): + json_msg = json.loads(p_body) + print("__decode__json__body__: ", type(json_msg)) + if ("ueIdentityTags" in json_msg.keys()) == False: + return None + return json_msg.get("ueIdentityTags")[0] + # End of __decode__json__body__ + +# End of class SimpleHTTPRequestHandler diff --git a/simu/mec_simulator.py b/simu/mec_simulator.py new file mode 100644 index 0000000000000000000000000000000000000000..7540eda59936b85bd62c8dd14622e1e56a640eb7 --- /dev/null +++ b/simu/mec_simulator.py @@ -0,0 +1,46 @@ +# Very basic MEC PLAT simulator + +import http.server +import socketserver +import mec_http_server +import threading +import sys, os, time +import msvcrt + +# MEC simulator IPv4 address +#ADDRESS_BINDING = '172.28.4.87' +#ADDRESS_BINDING = '192.168.1.21' +ADDRESS_BINDING = '192.168.0.5' +#ADDRESS_BINDING = '127.0.0.1' +# MEC simulator IPv4 listening port +PORT_NUMBER = 8081 + +# TODO Add Linux support for detecting keyboard input from the terminal? +def getch(): + """ Capture keybord entry. """ + return msvcrt.getch() +# End of function getch + +if __name__ == '__main__': + exit = False + try: + # Create a web server and define the handler to manage the incoming request + server = socketserver.TCPServer((ADDRESS_BINDING, PORT_NUMBER), mec_http_server.myHandler) + print ('Started httpserver on port ' , PORT_NUMBER) + # Wait forever for incoming http requests in background + #server.serve_forever() + threading.Thread(target=server.serve_forever).start() + # Use keybord entries to trigger notifications + while exit == False: + ch = getch() + if ch == b'\x03': + exit = True + else: + print(">>> ch= ", ch) + server.shutdown() + server.socket.close() + except KeyboardInterrupt: + print ('^C received, shutting down the web server') + server.shutdown() + server.socket.close() +# End of __main__