From b3cb1899dc29d335e82dab4431dae2d324eb741f Mon Sep 17 00:00:00 2001 From: piscione Date: Fri, 12 Jan 2024 18:50:36 +0100 Subject: [PATCH] MEC013 v3.1.1 UETESTNOT Draft TCs available --- .../UETESTNOT/PlatUeTestSubscription.robot | 101 ++++ MEC013/SRV/UETESTNOT/README.md | 0 .../SRV/UETESTNOT/environment/variables.txt | 21 + .../SRV/UETESTNOT/jsons/TestNotification.json | 8 + .../UETESTNOT/jsons/UserAreaNotification.json | 12 + .../UETESTNOT/jsons/UserAreaSubscription.json | 29 + .../jsons/UserLocationEventSubscription.json | 7 + MEC013/SRV/UETESTNOT/libraries/Server.py | 149 +++++ .../schemas/TestNotification.schema.json | 43 ++ .../schemas/UserAreaNotification.schema.json | 539 ++++++++++++++++++ 10 files changed, 909 insertions(+) create mode 100644 MEC013/SRV/UETESTNOT/PlatUeTestSubscription.robot create mode 100644 MEC013/SRV/UETESTNOT/README.md create mode 100644 MEC013/SRV/UETESTNOT/environment/variables.txt create mode 100644 MEC013/SRV/UETESTNOT/jsons/TestNotification.json create mode 100644 MEC013/SRV/UETESTNOT/jsons/UserAreaNotification.json create mode 100644 MEC013/SRV/UETESTNOT/jsons/UserAreaSubscription.json create mode 100644 MEC013/SRV/UETESTNOT/jsons/UserLocationEventSubscription.json create mode 100644 MEC013/SRV/UETESTNOT/libraries/Server.py create mode 100644 MEC013/SRV/UETESTNOT/schemas/TestNotification.schema.json create mode 100644 MEC013/SRV/UETESTNOT/schemas/UserAreaNotification.schema.json diff --git a/MEC013/SRV/UETESTNOT/PlatUeTestSubscription.robot b/MEC013/SRV/UETESTNOT/PlatUeTestSubscription.robot new file mode 100644 index 0000000..a2f1324 --- /dev/null +++ b/MEC013/SRV/UETESTNOT/PlatUeTestSubscription.robot @@ -0,0 +1,101 @@ +*** Settings *** + +Documentation +... A test suite for validating UE Test Notification (UETESTNOT) operations. + +Resource ../../../GenericKeywords.robot +Resource ../../../pics.txt +Resource environment/variables.txt +Library REST ${SCHEMA}://${HOST}:${PORT} ssl_verify=false +Library OperatingSystem +Library String +Library libraries/Server.py +Default Tags TC_MEC_SRV_UELOCSUB + + +*** Test Cases *** +TC_MEC_MEC013_SRV_UETESTNOT_001_OK + [Documentation] + ... Check that the IUT provides a test notification when requested by a MEC Application + ... + ... ETSI GS MEC 013 3.1.1 Clause 5.3.4 + ... ETSI GS MEC 013 3.1.1 Clause 6.3.4 + ... ETSI GS MEC 013 3.1.1 Clause 6.4.3 + ... ETSI GS MEC 013 3.1.1 Clause 7.5.3.4 + [Tags] PIC_MEC_PLAT PIC_SERVICES + [Setup] Create an UserLocationEvent subscription and get sub id UserLocationEventSubscription + Spawn Notification Server TestNotification + Validate Json TestNotification.schema.json ${payload_notification} + [TearDown] Remove an UserLocationEvent subscription ${SUB_ID} + + +TC_MEC_MEC013_SRV_UETESTNOT_002_OK + [Documentation] + ... Check that the IUT terminates notifications after time expiration + ... + ... ETSI GS MEC 013 3.1.1 Clause 5.3.11 + ... ETSI GS MEC 013 3.1.1 Clause 6.3.8 + ... ETSI GS MEC 013 3.1.1 Clause 6.4.8 + ... ETSI GS MEC 013 3.1.1 Clause 7.16.3.4 + [Tags] PIC_MEC_PLAT PIC_SERVICES + [Setup] Create an UserArea subscription and get sub id UserAreaSubscription + Spawn Notification Server UserAreaNotification + Validate Json UserAreaNotification.schema.json ${payload_notification} + [TearDown] Remove an UserArea subscription ${SUB_ID} + + +*** Keywords *** +Create an UserLocationEvent subscription and get sub id + [Arguments] ${content} + Set Headers {"Accept":"application/json"} + Set Headers {"Authorization":"${TOKEN}"} + Set Headers {"Authorization":"${TOKEN}"} + ${file}= Catenate SEPARATOR= jsons/ ${content} .json + ${body}= Get File ${file} + Post ${apiRoot}/${apiName}/${apiVersion}/subscriptions/users ${body} + ${output}= Output response + Set Suite Variable ${response} ${output} + ${elements} = Split String ${response['headers']['Location']} / + Set Suite Variable ${SUB_ID} ${elements[3]} + +Create an UserArea subscription and get sub id + [Arguments] ${content} + Set Headers {"Accept":"application/json"} + Set Headers {"Authorization":"${TOKEN}"} + Set Headers {"Authorization":"${TOKEN}"} + ${file}= Catenate SEPARATOR= jsons/ ${content} .json + ${body}= Get File ${file} + Post ${apiRoot}/${apiName}/${apiVersion}/subscriptions/area ${body} + ${output}= Output response + Set Suite Variable ${response} ${output} + ${elements} = Split String ${response['headers']['Location']} / + Set Suite Variable ${SUB_ID} ${elements[3]} + +Remove an UserLocationEvent subscription + [Arguments] ${subscription_id} + Set Headers {"Accept":"application/json"} + Set Headers {"Authorization":"${TOKEN}"} + Set Headers {"Authorization":"${TOKEN}"} + Delete ${apiRoot}/${apiName}/${apiVersion}/subscriptions/users/${subscription_id} + ${output}= Output response + Set Suite Variable ${response} ${output} + +Remove an UserArea subscription + [Arguments] ${subscription_id} + Set Headers {"Accept":"application/json"} + Set Headers {"Authorization":"${TOKEN}"} + Set Headers {"Authorization":"${TOKEN}"} + Delete ${apiRoot}/${apiName}/${apiVersion}/subscriptions/area/${subscription_id} + ${output}= Output response + Set Suite Variable ${response} ${output} + + + +Spawn Notification Server + [Arguments] ${payload_notification} + ${output} Spawn Web Server ${NOTIFICATION_SERVER_IP} ${NOTIFICATION_SERVER_PORT} ${NOTIFICATION_SERVER_TIMEOUT} ${NOTIFICATION_SERVER_HTTP_METHOD} ${NOTIFICATION_SERVER_URI} ${payload_notification} + ${length} = Get Length ${output} + Set Suite Variable ${payload_notification} ${output} + Run Keyword If ${length} == 0 Skip + + \ No newline at end of file diff --git a/MEC013/SRV/UETESTNOT/README.md b/MEC013/SRV/UETESTNOT/README.md new file mode 100644 index 0000000..e69de29 diff --git a/MEC013/SRV/UETESTNOT/environment/variables.txt b/MEC013/SRV/UETESTNOT/environment/variables.txt new file mode 100644 index 0000000..50c62aa --- /dev/null +++ b/MEC013/SRV/UETESTNOT/environment/variables.txt @@ -0,0 +1,21 @@ +*** Variables *** +# Generic variables +${SCHEMA} http +${HOST} 127.0.0.1 +${PORT} 8081 +${response} {} +${TOKEN} Basic YWxhZGRpbjpvcGVuc2VzYW1l +${apiRoot} +${apiName} location +${apiVersion} v3 + +${SUB_ID} +${NON_EXISTENT_SUBSCRIPTION_ID} NON_EXISTENT_SUBSCRIPTION_ID + + +##Notification Server variables +${NOTIFICATION_SERVER_IP} 127.0.0.1 +${NOTIFICATION_SERVER_PORT} 8888 +${NOTIFICATION_SERVER_HTTP_METHOD} POST +${NOTIFICATION_SERVER_URI} /callback_url +${NOTIFICATION_SERVER_TIMEOUT} 5 diff --git a/MEC013/SRV/UETESTNOT/jsons/TestNotification.json b/MEC013/SRV/UETESTNOT/jsons/TestNotification.json new file mode 100644 index 0000000..75ae598 --- /dev/null +++ b/MEC013/SRV/UETESTNOT/jsons/TestNotification.json @@ -0,0 +1,8 @@ +{ + "_links": { + "self": { + "href": "https://someurl.com/subscriptions/users/subscriptionId" + } + }, + "notificationType": "TestNotification" +} \ No newline at end of file diff --git a/MEC013/SRV/UETESTNOT/jsons/UserAreaNotification.json b/MEC013/SRV/UETESTNOT/jsons/UserAreaNotification.json new file mode 100644 index 0000000..21d73f3 --- /dev/null +++ b/MEC013/SRV/UETESTNOT/jsons/UserAreaNotification.json @@ -0,0 +1,12 @@ +{ + "notificationType": "UserAreaNotification", + "callbackReference":"127.0.0.1:8888/callback_uri", + "address": "http://someuri.com/123", + "civicInfo": { + "country": "A1" + }, + "userLocationEvent": "ENTERING_AREA_EVENT", + "_links": { + "subscription": "someuri" + } +} \ No newline at end of file diff --git a/MEC013/SRV/UETESTNOT/jsons/UserAreaSubscription.json b/MEC013/SRV/UETESTNOT/jsons/UserAreaSubscription.json new file mode 100644 index 0000000..accbfc3 --- /dev/null +++ b/MEC013/SRV/UETESTNOT/jsons/UserAreaSubscription.json @@ -0,0 +1,29 @@ +{ + "subscriptionType": "userAreaSubscription", + "clientCorrelator": "0123", + "callbackReference": "http://my.callback.com/area_notification/some-id", + "_links": { + "self": { + "href": "http://meAppServer.example.com/location/v2/subscriptions/area/subscription123" + } + }, + "areaDefine": { + "shape": 1, + "points": [ + { + "latitude": -80.86302, + "longitude": 41.277306 + } + ], + "radius": null + }, + "addressList": [ + "acr:10.0.0.1", + "acr:10.0.0.2" + ], + "trackingAccuracy": 10.99, + "expiryDeadline": { + "seconds": 1973507343, + "nanoSeconds\"": 0 + } +} \ No newline at end of file diff --git a/MEC013/SRV/UETESTNOT/jsons/UserLocationEventSubscription.json b/MEC013/SRV/UETESTNOT/jsons/UserLocationEventSubscription.json new file mode 100644 index 0000000..843f42f --- /dev/null +++ b/MEC013/SRV/UETESTNOT/jsons/UserLocationEventSubscription.json @@ -0,0 +1,7 @@ +{ + "subscriptionType": "UserLocationEventSubscription", + "clientCorrelator":"someCorrelator", + "address": "acr:10.0.0.1", + "callbackReference": "http://10.3.0.0.8:8888", + "requestTestNotification":"true" +} \ No newline at end of file diff --git a/MEC013/SRV/UETESTNOT/libraries/Server.py b/MEC013/SRV/UETESTNOT/libraries/Server.py new file mode 100644 index 0000000..ce79b6f --- /dev/null +++ b/MEC013/SRV/UETESTNOT/libraries/Server.py @@ -0,0 +1,149 @@ +#!/usr/bin/python3 + +from http.server import BaseHTTPRequestHandler, HTTPServer +import json, os +import logging + +# Library version +__version__ = '0.0.1' + +def import_notification_json(subscription_type): + notification_type = subscription_type.split("Subscription")[0] + file_path = "./jsons/"+notification_type+".json" + logging.info(file_path) + logging.info(os.listdir()) + try: + with open(file_path, 'r') as json_file: + # Load the JSON data + data = json.load(json_file) + logging.info(data) + return data + except FileNotFoundError: + logging.error(f"Error: File not found at {file_path}") + + +class Server ( object ): + + ROBOT_LIBRARY_VERSION = '0.0.1' + + def spawn_web_server (self, host="127.0.0.1", port=8080, timeout=15, method="POST", endpoint="/callback_url", resp_body=None): + + class GET_Server(BaseHTTPRequestHandler): + + def __call__(self, *args, **kwargs): + """Handle a request.""" + super().__init__(*args, **kwargs) + + def __init__(self, endpoint, resp_body): + self.resp_body = resp_body + self.endpoint = endpoint + + def do_GET(self): + self.send_response(200) + self.send_header('Content-Type', 'application/json') + self.end_headers() + if self.path == self.endpoint: + self.wfile.write(json.dumps(self.resp_body).encode(encoding='utf_8')) + else: + self.wfile.write(json.dumps("wrong endpoint").encode(encoding='utf_8')) + + class POST_Server(BaseHTTPRequestHandler): + + def __call__(self, *args, **kwargs): + """Handle a request.""" + super().__init__(*args, **kwargs) + + def __init__(self, endpoint, resp_body): + self.resp_body = resp_body + self.endpoint = endpoint + self.req_body = None + + + def do_POST(self): + self.send_response(200) + self.send_header('Content-Type', 'application/json') + self.end_headers() + + #if self.path == self.endpoint: + # self.wfile.write(json.dumps(self.resp_body).encode(encoding='utf_8')) + #else: + # self.wfile.write(json.dumps("wrong endpoint").encode(encoding='utf_8')) + + content_len = int(self.headers.get('Content-Length')) + post_body = self.rfile.read(content_len) + self.req_body=post_body + + def get_req_body(self): + return self.req_body + + def get_resp_body(self): + return self.resp_body + + + class PUT_Server(BaseHTTPRequestHandler): + + def __call__(self, *args, **kwargs): + """Handle a request.""" + super().__init__(*args, **kwargs) + + def __init__(self, endpoint, resp_body): + self.resp_body = resp_body + self.endpoint = endpoint + + def do_PUT(self): + self.send_response(200) + self.send_header('Content-Type', 'application/json') + self.end_headers() + if self.path == self.endpoint: + self.wfile.write(json.dumps(self.resp_body).encode(encoding='utf_8')) + else: + self.wfile.write(json.dumps("wrong endpoint").encode(encoding='utf_8')) + + class DELETE_Server(BaseHTTPRequestHandler): + + def __call__(self, *args, **kwargs): + """Handle a request.""" + super().__init__(*args, **kwargs) + + def __init__(self, endpoint, resp_body): + self.resp_body = resp_body + self.endpoint = endpoint + + def do_DELETE(self): + self.send_response(200) + self.send_header('Content-Type', 'application/json') + self.end_headers() + if self.path == self.endpoint: + self.wfile.write(json.dumps(self.resp_body).encode(encoding='utf_8')) + else: + self.wfile.write(json.dumps("wrong endpoint").encode(encoding='utf_8')) + + if method == "GET": + self.handler = GET_Server(endpoint, resp_body) + elif method == "POST": + self.handler = POST_Server(endpoint, resp_body) + elif method == "PUT": + self.handler = PUT_Server(endpoint, resp_body) + elif method == "DELETE": + self.handler = DELETE_Server(endpoint, resp_body) + else: + logging.info("Error, unknown endpoint") + exit(1) + + self.app = HTTPServer((host, int(port)), self.handler) + self.app.timeout = int(timeout) + + + self.app.handle_request() + self.app.server_close() + logging.info(self.handler.get_resp_body()) + ## If a notification is received, then is returned. Otherwise an empty dictionary. + if(self.handler.get_req_body()!=None): + return json.loads(self.handler.get_req_body().decode("windows-1252")) + + ##OLD mechanism commented: if no response is received, then read the Notification JSON file and return it. + + notification_json= import_notification_json(self.handler.get_resp_body()) + #return notification_json + return {} + diff --git a/MEC013/SRV/UETESTNOT/schemas/TestNotification.schema.json b/MEC013/SRV/UETESTNOT/schemas/TestNotification.schema.json new file mode 100644 index 0000000..af01800 --- /dev/null +++ b/MEC013/SRV/UETESTNOT/schemas/TestNotification.schema.json @@ -0,0 +1,43 @@ +{ + "properties": { + "_links": { + "description": "Hyperlink related to the resource. This shall be only included in the HTTP responses and in HTTP PUT requests.", + "properties": { + "self": { + "properties": { + "href": { + "description": "URI referring to a resource.", + "format": "uri", + "type": "string", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Uri" + } + }, + "required": [ + "href" + ], + "type": "object", + "x-etsi-ref": "6.7.2" + } + }, + "required": [ + "self" + ], + "type": "object", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "Structure (inlined)" + }, + "notificationType": { + "description": "Shall be set to \"TestNotification\".", + "type": "string", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "String" + } + }, + "required": [ + "notificationType", + "_links" + ], + "type": "object", + "x-etsi-ref": "6.4.3" + } \ No newline at end of file diff --git a/MEC013/SRV/UETESTNOT/schemas/UserAreaNotification.schema.json b/MEC013/SRV/UETESTNOT/schemas/UserAreaNotification.schema.json new file mode 100644 index 0000000..ea82b65 --- /dev/null +++ b/MEC013/SRV/UETESTNOT/schemas/UserAreaNotification.schema.json @@ -0,0 +1,539 @@ +{ + "properties": { + "_links": { + "description": "Hyperlink related to the resource. This shall be only included in the HTTP responses and in HTTP PUT requests.", + "properties": { + "subscription": { + "description": "URI referring to a resource.", + "format": "uri", + "type": "string", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Uri" + } + }, + "required": [ + "subscription" + ], + "type": "object", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "Structure (inlined)" + }, + "address": { + "description": "Address of user (e.g. ‘sip’ URI, ‘tel’ URI, ‘acr’ URI).", + "format": "uri", + "type": "string", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Uri" + }, + "civicInfo": { + "description": "Indicates a Civic address", + "type": "object", + "required": [ + "country" + ], + "properties": { + "country": { + "description": "The two-letter ISO 3166 country code in capital ASCII letters, e.g., DE or US", + "type": "string", + "x-etsi-mec-cardinality": 1, + "x-etsi-mec-origin-type": "String" + }, + "A1": { + "description": "National subdivisions (state, canton, region, province, prefecture)", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "A2": { + "description": "County, parish, gun (JP), district (IN)", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "A3": { + "description": "City, township, shi (JP)", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "A4": { + "description": "City division, borough, city district, ward, chou (JP)", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "A5": { + "description": "Neighbourhood, block", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "A6": { + "description": "Group of streets below the neighbourhood level", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "PRD": { + "description": "Leading street direction", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "POD": { + "description": "Trailing street suffix", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "STS": { + "description": "Street suffix or type", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "HNO": { + "description": "House number", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "HNS": { + "description": "House number suffix", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "LMK": { + "description": "Landmark or vanity address", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "LOC": { + "description": "Additional location information", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "NAM": { + "description": "Name (residence and office occupant)", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "PC": { + "description": "Postal/zip code", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "BLD": { + "description": "Building (structure)", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "UNIT": { + "description": "Unit (apartment, suite)", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "FLR": { + "description": "Floor", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "ROOM": { + "description": "Room", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "PLC": { + "description": "Place-type", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "PCN": { + "description": "Postal community name", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "POBOX": { + "description": "Post office box (P.O. box)", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "ADDCODE": { + "description": "Additional code", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "SEAT": { + "description": "Seat (desk, cubicle, workstation)", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "RD": { + "description": "Primary road or street", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "RDSEC": { + "description": "Road clause", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "RDBR": { + "description": "Road branch", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "RDSUBBR": { + "description": "Road sub-branch", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "PRM": { + "description": "Road pre-modifier", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "POM": { + "description": "Road post-modifier", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "usageRules": { + "description": "When present, this IE shall carry the value of \"usagerules\" Element of the PIDL-LO XML document, with UTF-8 encoding.", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "method": { + "description": "When present, this IE shall contain the method token, carried by the \"method\" Element of the PIDLLO XML document.", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + }, + "providedBy": { + "description": "When present, this IE shall carry the value of \"provided-by\" Element of the PIDL-LO XML document, with UTF-8 encoding.", + "type": "string", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "String" + } + } + }, + "locationInfo": { + "properties": { + "accuracy": { + "description": "Horizontal accuracy/(semi-major) uncertainty of location provided in meters, as defined in [14]. Present only if \"shape\" equals 4, 5 or 6.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "accuracyAltitude": { + "description": "Altitude accuracy/uncertainty of location provided in meters, as defined in [14]. Present only if \"shape\" equals 3 or 4.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "accuracySemiMinor": { + "description": "Horizontal accuracy/(semi-major) uncertainty of location provided in meters, as defined in [14]. Present only if \"shape\" equals 4, 5 or 6.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "altitude": { + "description": "Location altitude relative to the WGS84 ellipsoid surface.", + "format": "float", + "type": "number", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "Float" + }, + "confidence": { + "description": "Confidence by which the position of a target entity is known to be within the shape description, expressed as a percentage and defined in [14]. Present only if \"shape\" equals 1, 4 or 6.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "includedAngle": { + "description": "Present only if \"shape\" equals 6.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "innerRadius": { + "description": "Present only if \"shape\" equals 6.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "latitude": { + "description": "Location latitude, expressed in the range -90° to +90°. Cardinality greater than one only if \"shape\" equals 7.", + "format": "float", + "items": { + "type": "number" + }, + "minItems": 1, + "type": "array", + "x-etsi-mec-cardinality": "1..N", + "x-etsi-mec-origin-type": "Float" + }, + "longitude": { + "description": "Location longitude, expressed in the range -180° to +180°. Cardinality greater than one only if \"shape\" equals 7.", + "format": "float", + "items": { + "type": "number" + }, + "minItems": 1, + "type": "array", + "x-etsi-mec-cardinality": "1..N", + "x-etsi-mec-origin-type": "Float" + }, + "offsetAngle": { + "description": "Present only if \"shape\" equals 6.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "orientationMajorAxis": { + "description": "Angle of orientation of the major axis, expressed in the range 0° to 180°, as defined in [14]. Present only if \"shape\" equals 4 or 6.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "shape": { + "description": "Shape information, as detailed in [14], associated with the reported location coordinate: 1 = Ellipsoid_Arc 2 = ellipsoid_Point 3 = ellipsoid_Point_Altitude 4 = ellipsoid_Point_Altitude_Uncert_Ellipsoid 5 = ellipsoid_Point_Uncert_Circle 6 = ellipsoid_Point_Uncert_Ellipse 7 = polygon", + "enum": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ], + "type": "integer", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Enum_inlined" + }, + "uncertaintyRadius": { + "description": "Present only if \"shape\" equals 6.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "velocity": { + "description": "Structure with attributes relating to the target entity’s velocity, as defined in [14].", + "properties": { + "bearing": { + "description": "Bearing, expressed in the range 0° to 360°, as defined in [14].", + "type": "integer", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "horizontalSpeed": { + "description": "Horizontal speed, expressed in km/h and defined in [14].", + "type": "integer", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "uncertainty": { + "description": "Horizontal uncertainty, as defined in [14]. Present only if \"velocityType\" equals 3 or 4.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + }, + "velocityType": { + "description": "Velocity information, as detailed in [14], associated with the reported location coordinate: 1 = Horizontal 2 = Horizontal_Vertical 3 = Horizontal_Uncert 4 = Horizontal_Vertical_Uncert", + "enum": [ + 1, + 2, + 3, + 4 + ], + "type": "integer", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Enum_inlined" + }, + "verticalSpeed": { + "description": "Vertical speed, expressed in km/h and defined in [14]. Present only if \"velocityType\" equals 2 or 4.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "Int" + }, + "verticalUncertainty": { + "description": "Vertical uncertainty, as defined in [14]. Present only if \"velocityType\" equals 4.", + "type": "integer", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "UnsignedInt" + } + }, + "required": [ + "velocityType", + "bearing", + "horizontalSpeed" + ], + "type": "object", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "Structure (inlined)" + } + }, + "required": [ + "latitude", + "longitude", + "shape" + ], + "type": "object", + "x-etsi-ref": "6.5.3" + }, + "notificationType": { + "description": "Shall be set to \"UserAreaNotification\".", + "type": "string", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "String" + }, + "relativeLocationInfo": { + "properties": { + "X": { + "description": "Indicates the value (in the unit of meters) on x-axis of the relative location in the Cartesian system. Positive value represents easting from origin.", + "format": "float", + "type": "number", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Float" + }, + "Y": { + "description": "Indicates the value (in the unit of meters) on y-axis of the relative location in the Cartesian system. Positive value represents northing from origin.", + "format": "float", + "type": "number", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Float" + }, + "Z": { + "description": "Indicates the value (in the unit of meters) on z-axis of the relative location in the Cartesian system for a 3DPoint. Positive value represents height above origin.", + "format": "float", + "type": "number", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "Float" + }, + "mapInfo": { + "properties": { + "ancillaryMapInfo": { + "description": "Ancillary map information may be used to convert coordinates between different coordinate systems.", + "type": "object", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "Not_specified" + }, + "mapId": { + "description": "Indicates the ID of the map. ", + "type": "string", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "String" + }, + "origin": { + "description": "Indicates the location of the map origin in the local Cartesian coordinate system.", + "properties": { + "altitude": { + "description": "Location altitude relative to the WGS84 ellipsoid surface.", + "format": "float", + "type": "number", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "Float" + }, + "latitude": { + "description": "Location latitude, expressed in the range -90° to +90°.", + "format": "float", + "type": "number", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Float" + }, + "longitude": { + "description": "Location longitude, expressed in the range -180° to +180°.", + "format": "float", + "type": "number", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Float" + } + }, + "required": [ + "latitude", + "longitude" + ], + "type": "object", + "x-etsi-mec-cardinality": "0..1", + "x-etsi-mec-origin-type": "Structure(inlined)" + } + }, + "required": [ + "mapId" + ], + "type": "object", + "x-etsi-ref": "6.2.4" + } + }, + "required": [ + "mapInfo", + "X", + "Y" + ], + "type": "object", + "x-etsi-ref": "6.2.3" + }, + "timeStamp": { + "properties": { + "nanoSeconds": { + "description": "The nanoseconds part of the time. Time is defined as Unix-time since January 1, 1970, 00:00:00 UTC.", + "format": "uint32", + "type": "integer", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Uint32" + }, + "seconds": { + "description": "The seconds part of the time. Time is defined as Unix-time since January 1, 1970, 00:00:00 UTC.", + "format": "uint32", + "type": "integer", + "x-etsi-mec-cardinality": "1", + "x-etsi-mec-origin-type": "Uint32" + } + }, + "required": [ + "seconds", + "nanoSeconds" + ], + "type": "object", + "x-etsi-ref": "6.5.2" + }, + "userLocationEvent": { + "description": "This type represents specified event types for UE location report.", + "enum": [ + "ENTERING_AREA_EVENT", + "LEAVING_AREA_EVENT" + ], + "type": "string" + } + }, + "required": [ + "notificationType", + "address", + "userLocationEvent", + "_links" + ], + "type": "object", + "x-etsi-notes": "NOTE 1:\tAs specified in [17], clause 6.1.6.2.14.\nNOTE 2:\tAt least one of these attributes shall be present only when reportingLocationReq is set to TRUE in the UserAreaSubscription.", + "x-etsi-ref": "6.4.8" +} \ No newline at end of file -- GitLab