From bc7486ed61aeb30a7cccc69cae44ebb6efb6dfd9 Mon Sep 17 00:00:00 2001 From: Trishna Saeharaseelan <trishna.saeharaseelan@noc.ac.uk> Date: Mon, 23 Jan 2023 19:01:36 +0800 Subject: [PATCH] refactor: schemas and added abstract message --- .../hydrosurv_adapter/acknowledgement.json | 2 +- formats/__init__.py | 64 ++++++++++ formats/acknowledgement.py | 11 +- formats/message_wrapper.py | 120 +++++++++--------- formats/mission_plan.py | 5 +- formats/observation.py | 51 +++++--- formats/planning_configuration.py | 5 +- formats/platform_status.py | 15 ++- generate_swagger.py | 80 ++++++------ 9 files changed, 222 insertions(+), 131 deletions(-) diff --git a/examples/hydrosurv_adapter/acknowledgement.json b/examples/hydrosurv_adapter/acknowledgement.json index 21ca73e..a9deaf6 100644 --- a/examples/hydrosurv_adapter/acknowledgement.json +++ b/examples/hydrosurv_adapter/acknowledgement.json @@ -8,5 +8,5 @@ "encoded": false, "message_type": "acknowledgement", "acknowledged_message_ID": "11111111-7bc8-11ed-a1eb-0242ac999999", - "status": "Approved and sent to platform" + "status": "c2_received" } \ No newline at end of file diff --git a/formats/__init__.py b/formats/__init__.py index 2253a07..79f2ec5 100644 --- a/formats/__init__.py +++ b/formats/__init__.py @@ -6,3 +6,67 @@ __all__ = [ for x in os.listdir(os.path.dirname(__file__)) if x.endswith(".py") and x != "__init__.py" ] + +abstract_schema = { + "allOf": [{"$ref": "#/definitions/Metadata"}], + "type": "object", + "properties": { + "payload": {} + } +} + +message_metadata = { + "type": "object", + "discriminator": { + "propertyName": "message_type", + }, + "properties": { + "message_ID": { + "type": "string", + "description": "An identifier for the type of message received.", + "example": "b427003c-0000-11aa-a1eb-bvcdfghjgfdd", + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "Timestamp of message", + "example": "2022-11-16T00:00:00Z", + }, + "message_type": { + "type": "string", + "description": "Type of message", + "example": "platform_status", + }, + "version": { + "type": "number", + "format": "float", + "description": "Version of comms backbone message format protocol", + "example": 2.0, + }, + "source": { + "type": "string", + "description": "The sender; Where is this message from", + "example": "autonomy_engine", + }, + "destination": { + "type": "string", + "description": "Publisher topic; What is the destination" + + " of this message", + "example": "ah1", + }, + "encoded": { + "type": "boolean", + "description": "Indicate that message raw (encoded) or decoded. " + + "Options: encoded=True, decoded=False", + "example": False, + }, + "delivery_type": { + "type": "string", + "description": "To publish or broadcast this message.", + "enum": ["broadcast", "publish"], + "example": "publish", + "default": "publish", + }, + }, + "required": ["message_type"], +} \ No newline at end of file diff --git a/formats/acknowledgement.py b/formats/acknowledgement.py index 23d1c9a..9dd353e 100644 --- a/formats/acknowledgement.py +++ b/formats/acknowledgement.py @@ -2,12 +2,9 @@ schemas: Acknowledgement status sent by the surface platform to report receipt of message. """ -# from openapi_schema_validator import validate -# from jsonschema import validate - +from formats import abstract_schema acknowledgement_schema = { - "allOf": [{"$ref": "#/components/schemas/Message"}], "type": "object", "properties": { "acknowledged_message_ID": { @@ -29,7 +26,5 @@ acknowledgement_schema = { "required": ["acknowledged_message_ID", "status"], } -# validate( -# {"acknowledged_message_ID": "string-type-id", "status": "c2_received"}, -# acknowledgement_schema, -# ) +full_acknowledgement_schema = abstract_schema +full_acknowledgement_schema["properties"]["payload"] = acknowledgement_schema diff --git a/formats/message_wrapper.py b/formats/message_wrapper.py index a7a92d0..41d4a77 100644 --- a/formats/message_wrapper.py +++ b/formats/message_wrapper.py @@ -1,61 +1,61 @@ -""" - schemas: Message Wrapper is used to wrap all message types that contain - details of where the message is coming from, which end client is its - destination and the type of message. -""" +# """ +# schemas: Message Wrapper is used to wrap all message types that contain +# details of where the message is coming from, which end client is its +# destination and the type of message. +# """ -message_wrapper_schema = { - "type": "object", - "discriminator": { - "propertyName": "message_type", - }, - "properties": { - "message_ID": { - "type": "string", - "description": "An identifier for the type of message received.", - "example": "b427003c-0000-11aa-a1eb-bvcdfghjgfdd", - }, - "timestamp": { - "type": "string", - "format": "date-time", - "description": "Timestamp of message", - "example": "2022-11-16T00:00:00Z", - }, - "message_type": { - "type": "string", - "description": "Type of message", - "example": "platform_status", - }, - "version": { - "type": "number", - "format": "float", - "description": "Version of comms backbone message format protocol", - "example": 2.0, - }, - "source": { - "type": "string", - "description": "The sender; Where is this message from", - "example": "autonomy_engine", - }, - "destination": { - "type": "string", - "description": "Publisher topic; What is the destination" - + " of this message", - "example": "ah1", - }, - "encoded": { - "type": "boolean", - "description": "Indicate that message raw (encoded) or decoded. " - + "Options: encoded=True, decoded=False", - "example": False, - }, - "delivery_type": { - "type": "string", - "description": "To publish or broadcast this message.", - "enum": ["broadcast", "publish"], - "example": "publish", - "default": "publish", - }, - }, - "required": ["message_type"], -} +# message_wrapper_schema = { +# "type": "object", +# "discriminator": { +# "propertyName": "message_type", +# }, +# "properties": { +# "message_ID": { +# "type": "string", +# "description": "An identifier for the type of message received.", +# "example": "b427003c-0000-11aa-a1eb-bvcdfghjgfdd", +# }, +# "timestamp": { +# "type": "string", +# "format": "date-time", +# "description": "Timestamp of message", +# "example": "2022-11-16T00:00:00Z", +# }, +# "message_type": { +# "type": "string", +# "description": "Type of message", +# "example": "platform_status", +# }, +# "version": { +# "type": "number", +# "format": "float", +# "description": "Version of comms backbone message format protocol", +# "example": 2.0, +# }, +# "source": { +# "type": "string", +# "description": "The sender; Where is this message from", +# "example": "autonomy_engine", +# }, +# "destination": { +# "type": "string", +# "description": "Publisher topic; What is the destination" +# + " of this message", +# "example": "ah1", +# }, +# "encoded": { +# "type": "boolean", +# "description": "Indicate that message raw (encoded) or decoded. " +# + "Options: encoded=True, decoded=False", +# "example": False, +# }, +# "delivery_type": { +# "type": "string", +# "description": "To publish or broadcast this message.", +# "enum": ["broadcast", "publish"], +# "example": "publish", +# "default": "publish", +# }, +# }, +# "required": ["message_type"], +# } diff --git a/formats/mission_plan.py b/formats/mission_plan.py index 0e6c975..76eef55 100644 --- a/formats/mission_plan.py +++ b/formats/mission_plan.py @@ -3,6 +3,7 @@ sent to the respective platform's C2 to compile into a platform-specific mission plan. """ +from formats import abstract_schema action_schema = { "type": "object", @@ -63,7 +64,6 @@ action_schema = { } mission_plan_schema = { - "allOf": [{"$ref": "#/components/schemas/Message"}], "type": "object", "properties": { "autonomy_engine_plan_ID": { @@ -84,3 +84,6 @@ mission_plan_schema = { }, "required": ["plan_ID", "platform_ID", "plan"], } + +full_mission_plan_schema = abstract_schema +full_mission_plan_schema["properties"]["payload"] = mission_plan_schema diff --git a/formats/observation.py b/formats/observation.py index d67ff38..45fb10c 100644 --- a/formats/observation.py +++ b/formats/observation.py @@ -2,6 +2,7 @@ schema: Observation Message sent by platforms when points of interest are found. """ +from formats import abstract_schema hits_schema = { "type": "object", @@ -30,30 +31,38 @@ hits_schema = { } observation_schema = { - "allOf": [{"$ref": "#/components/schemas/Message"}], "type": "object", "properties": { - "platform_ID": { - "type": "integer", - "description": "ID of platform to sending observations", - "example": 2, - }, - "points_of_interest": { - "type": "array", - "items": hits_schema, - "description": "Points from features of interest identified by" - + " platform if any found.", # TODO: DEFINE FORMAT. - }, - "region_surveyed": { - "type": "null", - "description": "Region surveyed by given platform." - + " GEOJSON", # TODO: DEFINE FORMAT. - "example": "", - }, - "additional_data": { - "description": "Placeholder field for any additional data", - "example": {"sensor_payload": False}, + "payload": { + "type": "object", + "properties": { + "platform_ID": { + "type": "integer", + "description": "ID of platform to sending observations", + "example": 2, + }, + "points_of_interest": { + "type": "array", + "items": hits_schema, + "description": "Points from features of interest identified by" + + " platform if any found.", # TODO: DEFINE FORMAT. + }, + "region_surveyed": { + # "type": "null", + "nullable": True, + "description": "Region surveyed by given platform." + + " GEOJSON", # TODO: DEFINE FORMAT. + "example": "", + }, + "additional_data": { + "description": "Placeholder field for any additional data", + "example": {"sensor_payload": False}, + }, + }, }, }, "required": ["platform_ID"], } + +full_observation_schema = abstract_schema +full_observation_schema["properties"]["payload"] = observation_schema diff --git a/formats/planning_configuration.py b/formats/planning_configuration.py index 50da184..1febb4f 100644 --- a/formats/planning_configuration.py +++ b/formats/planning_configuration.py @@ -2,6 +2,7 @@ schemas: configuration sent to Autonomy Engine (i.e. during an emergency, if a platform needs to be removed from the mission planning) """ +from formats import abstract_schema emergency_schema = { "type": "object", @@ -157,7 +158,6 @@ squad_metadata_schema = { } planning_configuration_schema = { - "allOf": [{"$ref": "#/components/schemas/Message"}], "type": "object", "properties": { "planning_config_ID": { @@ -182,3 +182,6 @@ planning_configuration_schema = { "exclusion_zones", ], } + +full_planning_configuration_schema = abstract_schema +full_planning_configuration_schema["properties"]["payload"] = planning_configuration_schema diff --git a/formats/platform_status.py b/formats/platform_status.py index 87853c6..222ebd7 100644 --- a/formats/platform_status.py +++ b/formats/platform_status.py @@ -1,6 +1,8 @@ """ schema: platform-specific decoded status message """ +from formats import abstract_schema + sensor_schema = { "type": "object", "description": "Scanning sensor on platform available" @@ -26,7 +28,6 @@ sensor_schema = { } platform_status_message_schema = { - "allOf": [{"$ref": "#/components/schemas/Message"}], "type": "object", "properties": { "platform_ID": { @@ -41,6 +42,14 @@ platform_status_message_schema = { + " platform or USBL", "example": "usbl", }, + "transmission_mode": { + "type": "string", + "enum": ["acoustics", "iridium", "wifi", "starlink"], + "description": "Mode in which status message was transmitted" + + " when on the surface (i.e. iridium/wifi) or underwater" + + " (i.e. acoustics)", + "example": "wifi", + }, "platform_timestamp": { "type": "string", "format": "date-time", @@ -173,3 +182,7 @@ platform_status_message_schema = { "longitude", ], } + +full_platform_status_message_schema = abstract_schema +full_platform_status_message_schema["properties"]["payload"] = platform_status_message_schema + diff --git a/generate_swagger.py b/generate_swagger.py index 29e3b43..5820cdc 100644 --- a/generate_swagger.py +++ b/generate_swagger.py @@ -1,9 +1,9 @@ -from formats.message_wrapper import message_wrapper_schema -from formats.mission_plan import mission_plan_schema -from formats.observation import observation_schema -from formats.planning_configuration import planning_configuration_schema -from formats.platform_status import platform_status_message_schema -from formats.acknowledgement import acknowledgement_schema +from formats import message_metadata +from formats.mission_plan import full_mission_plan_schema +from formats.observation import full_observation_schema +from formats.planning_configuration import full_planning_configuration_schema +from formats.platform_status import full_platform_status_message_schema +from formats.acknowledgement import full_acknowledgement_schema from flasgger import Swagger from flask import Flask @@ -28,15 +28,15 @@ swagger_config = { "model_filter": lambda tag: True, } ], - "components": { - "schemas": { - "Message": message_wrapper_schema, - "MissionPlan": mission_plan_schema, - "Observation": observation_schema, - "PlanningConfiguration": planning_configuration_schema, - "PlatformStatus": platform_status_message_schema, - "Acknowledgement": acknowledgement_schema, - } + # "components": { + "definitions": { + "Metadata": message_metadata, + "MissionPlan": full_mission_plan_schema, + "Observation": full_observation_schema, + "PlanningConfiguration": full_planning_configuration_schema, + "PlatformStatus": full_platform_status_message_schema, + "Acknowledgement": full_acknowledgement_schema, + # } }, "paths": { "/all_messages": { @@ -49,26 +49,30 @@ swagger_config = { "application/json": { "schema": { "oneOf": [ - { - "$ref": "#/components/schemas/" - + "Acknowledgement" - }, - { - "$ref": "#/components/schemas/" - + "MissionPlan" - }, - { - "$ref": "#/components/schemas/" - + "Observation" - }, - { - "$ref": "#/components/schemas/" - + "PlanningConfiguration" - }, - { - "$ref": "#/components/schemas/" - + "PlatformStatus" - }, + full_mission_plan_schema, + full_planning_configuration_schema, + full_platform_status_message_schema, + full_observation_schema, + # { + # "$ref": "#/definitions/" + # + "Acknowledgement" + # }, + # { + # "$ref": "#/definitions/" + # + "MissionPlan" + # }, + # { + # "$ref": "#/definitions/" + # + "Observation" + # }, + # { + # "$ref": "#/definitions/" + # + "PlanningConfiguration" + # }, + # { + # "$ref": "#/definitions/" + # + "PlatformStatus" + # }, ], "discriminator": { "propertyName": "message_type", @@ -85,8 +89,8 @@ swagger_config = { "consumes": ["application/json"], } message_types = [ - "Message", - "Acknowledgement", + "Metadata", + # "Acknowledgement", "MissionPlan", "Observation", "PlanningConfiguration", @@ -104,7 +108,7 @@ for item in message_types: "schema": { "allOf": [ { - "$ref": "#/components/schemas/" + item, + "$ref": "#/definitions/" + item, }, ], "discriminator": { -- GitLab