From 89576e0810fb1a4cdc6bfdb626745aba97da2d4d Mon Sep 17 00:00:00 2001 From: Trishna Saeharaseelan <trishna.saeharaseelan@noc.ac.uk> Date: Wed, 25 Jan 2023 15:32:18 +0800 Subject: [PATCH] fix: openapi schemas implementing oneOf --- README.md | 2 + formats/__init__.py | 16 +- formats/acknowledgement.py | 12 +- formats/message_wrapper.py | 61 --- formats/mission_plan.py | 11 +- formats/observation.py | 58 ++- formats/planning_configuration.py | 10 +- formats/platform_status.py | 11 +- generate_schema_config.py | 93 ++++ generate_swagger.py | 133 ------ project/{ => soar}/SOAR_README.md | 0 project/soar/soar_protocol.json | 697 ++++++++++++++++++++++++++++++ 12 files changed, 844 insertions(+), 260 deletions(-) delete mode 100644 formats/message_wrapper.py create mode 100644 generate_schema_config.py delete mode 100644 generate_swagger.py rename project/{ => soar}/SOAR_README.md (100%) create mode 100644 project/soar/soar_protocol.json diff --git a/README.md b/README.md index 84c31a3..51a5ed9 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ This project repository is a collaborative workspace. It consists of all messages transferred into and out of the Communications Backbone. Message type schemas will be developed once reviewing each platform's data and statuses defined by each partner. +_# TODO: Add note on OpenAPI version used._ + # Message Types Each message below will be wrapped in a `message_wrapper`: * `mission_plan`: these would be two message types, i. encoded (platform-specific serialized message) and ii. parsed, human-readable message. diff --git a/formats/__init__.py b/formats/__init__.py index 5254584..1af1410 100644 --- a/formats/__init__.py +++ b/formats/__init__.py @@ -7,15 +7,7 @@ __all__ = [ if x.endswith(".py") and x != "__init__.py" ] -abstract_schema = { - "allOf": [{"$ref": "#/components/schemas/Metadata"}], - "type": "object", - "properties": { - "payload": {} - } -} - -message_metadata = { +message_header = { "type": "object", "discriminator": { "propertyName": "message_type", @@ -32,11 +24,6 @@ message_metadata = { "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", @@ -68,5 +55,4 @@ message_metadata = { "default": "publish", }, }, - "required": ["message_type"], } \ No newline at end of file diff --git a/formats/acknowledgement.py b/formats/acknowledgement.py index 9dd353e..cd2ce6e 100644 --- a/formats/acknowledgement.py +++ b/formats/acknowledgement.py @@ -2,11 +2,14 @@ schemas: Acknowledgement status sent by the surface platform to report receipt of message. """ -from formats import abstract_schema - acknowledgement_schema = { "type": "object", "properties": { + "message_type": { + "type": "string", + "description": "Type of message", + "example": "acknowledgement", + }, "acknowledged_message_ID": { "type": "string", "description": "Identifier of message received and executed with " @@ -23,8 +26,5 @@ acknowledgement_schema = { "example": "executed by platform", }, }, - "required": ["acknowledged_message_ID", "status"], + "required": ["message_type", "acknowledged_message_ID", "status"], } - -full_acknowledgement_schema = abstract_schema -full_acknowledgement_schema["properties"]["payload"] = acknowledgement_schema diff --git a/formats/message_wrapper.py b/formats/message_wrapper.py deleted file mode 100644 index 41d4a77..0000000 --- a/formats/message_wrapper.py +++ /dev/null @@ -1,61 +0,0 @@ -# """ -# 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"], -# } diff --git a/formats/mission_plan.py b/formats/mission_plan.py index 76eef55..7243547 100644 --- a/formats/mission_plan.py +++ b/formats/mission_plan.py @@ -3,7 +3,6 @@ sent to the respective platform's C2 to compile into a platform-specific mission plan. """ -from formats import abstract_schema action_schema = { "type": "object", @@ -66,6 +65,11 @@ action_schema = { mission_plan_schema = { "type": "object", "properties": { + "message_type": { + "type": "string", + "description": "Type of message", + "example": "mission_plan", + }, "autonomy_engine_plan_ID": { "type": "integer", "description": "Unique identifier for this plan" @@ -82,8 +86,5 @@ mission_plan_schema = { "items": action_schema, }, }, - "required": ["plan_ID", "platform_ID", "plan"], + "required": ["message_type", "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 45fb10c..3a49727 100644 --- a/formats/observation.py +++ b/formats/observation.py @@ -2,7 +2,6 @@ schema: Observation Message sent by platforms when points of interest are found. """ -from formats import abstract_schema hits_schema = { "type": "object", @@ -33,36 +32,33 @@ hits_schema = { observation_schema = { "type": "object", "properties": { - "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}, - }, - }, + "message_type": { + "type": "string", + "description": "Type of message", + "example": "observation", + }, + "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"], + "required": ["message_type", "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 1febb4f..b117b04 100644 --- a/formats/planning_configuration.py +++ b/formats/planning_configuration.py @@ -2,7 +2,6 @@ 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", @@ -160,6 +159,11 @@ squad_metadata_schema = { planning_configuration_schema = { "type": "object", "properties": { + "message_type": { + "type": "string", + "description": "Type of message", + "example": "planning_configuration", + }, "planning_config_ID": { "type": "integer", "description": "Unique identifier tagged to version of this" @@ -177,11 +181,9 @@ planning_configuration_schema = { }, }, "required": [ + "message_type", "config_ID", "squads", "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 222ebd7..30622f1 100644 --- a/formats/platform_status.py +++ b/formats/platform_status.py @@ -1,7 +1,6 @@ """ schema: platform-specific decoded status message """ -from formats import abstract_schema sensor_schema = { "type": "object", @@ -30,6 +29,11 @@ sensor_schema = { platform_status_message_schema = { "type": "object", "properties": { + "message_type": { + "type": "string", + "description": "Type of message", + "example": "platform_status", + }, "platform_ID": { "type": "integer", "description": "Identifier for platform", @@ -175,6 +179,7 @@ platform_status_message_schema = { "sensor_config": sensor_schema, }, "required": [ + "message_type", "platform_ID", "status_source", "platform_timestamp", @@ -182,7 +187,3 @@ 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_schema_config.py b/generate_schema_config.py new file mode 100644 index 0000000..2587f25 --- /dev/null +++ b/generate_schema_config.py @@ -0,0 +1,93 @@ +from formats import message_header +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 flasgger import Swagger +from flask import Flask + +app = Flask(__name__) + + +swagger_config = { + "openapi": "3.0.2", + "swagger_ui": True, + "specs_route": "/", + "info": { + "title": "SoAR Backbone Message Formats", + "version": "1.0", + "description": "SoAR message protocol in schemas" + }, + "specs": [ + { + "endpoint": "swagger", + "route": "/soar_protocol.json", + } + ], + "paths": {}, + "components": { + "schemas": { + "MESSAGE": { + "type": "object", + "description": "Full message definition with message-metadata in `header` and different message type schemas under `payload`", + "properties": { + "header": { + "$ref": "#/components/schemas/header", + }, + "payload": { + "$ref": "#/components/schemas/payload" + }, + }, + "required": ["header", "payload"], + }, + "payload": { + "discriminator": { + "propertyName": "message_type", + "mapping":{ + "MissionPlan": "#/components/schemas/mission_plan", + "Observation": "#/components/schemas/observation", + "PlanningConfiguration": "#/components/schemas/planning_configuration", + "PlatformStatus": "#/components/schemas/platform_status", + "Acknowledgement": "#/components/schemas/acknowledgement", + }, + }, + "oneOf":[ + { + "$ref": "#/components/schemas/" + + "acknowledgement" + }, + { + "$ref": "#/components/schemas/" + + "mission_plan" + }, + { + "$ref": "#/components/schemas/" + + "observation" + }, + { + "$ref": "#/components/schemas/" + + "planning_configuration" + }, + { + "$ref": "#/components/schemas/" + + "platform_status" + }, + ] + }, + "header": message_header, + "mission_plan": mission_plan_schema, + "observation": observation_schema, + "planning_configuration": planning_configuration_schema, + "platform_status": platform_status_message_schema, + "acknowledgement": acknowledgement_schema, + } + }, +} + +swag = Swagger(app, config=swagger_config, merge=True) + + +if __name__ == "__main__": + app.run(debug=True) \ No newline at end of file diff --git a/generate_swagger.py b/generate_swagger.py deleted file mode 100644 index a30a9f0..0000000 --- a/generate_swagger.py +++ /dev/null @@ -1,133 +0,0 @@ -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 - -app = Flask(__name__) - -swagger_config = { - "headers": [], - "openapi": "3.0.2", - "swagger_ui": True, - "specs_route": "/", - "info": { - "title": "Backbone Message Formats", - "version": "0.1", - "description": "SoAR message schemas (i.e. formats)", - }, - "specs": [ - { - "endpoint": "swagger", - "route": "/swagger.json", - "rule_filter": lambda rule: True, - "model_filter": lambda tag: True, - } - ], - "components": { - "schemas": { - "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": { - "get": { - "description": "Returns all messages from the system.", - "responses": { - "200": { - "description": "A list of messages.", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/" - + "Acknowledgement" - }, - { - "$ref": "#/components/schemas/" - + "MissionPlan" - }, - { - "$ref": "#/components/schemas/" - + "Observation" - }, - { - "$ref": "#/components/schemas/" - + "PlanningConfiguration" - }, - { - "$ref": "#/components/schemas/" - + "PlatformStatus" - }, - ], - "discriminator": { - "propertyName": "message_type", - }, - } - } - }, - } - }, - } - }, - }, - "produces": ["application/json"], - "consumes": ["application/json"], -} -message_types = [ - "Metadata", - # "Acknowledgement", - "MissionPlan", - "Observation", - "PlanningConfiguration", - "PlatformStatus", -] -for item in message_types: - swagger_config["paths"]["/" + str(item.lower())] = { - "get": { - "description": "Returns message for " + item, - "responses": { - "200": { - "description": item + " message.", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/" + item, - }, - ], - "discriminator": { - "propertyName": "message_type", - }, - } - } - }, - } - }, - } - } - -swag = Swagger(app, config=swagger_config, merge=True) - - -if __name__ == "__main__": - app.run(debug=True) - # print(validate_spec_url("http://127.0.0.1:5000/swagger.json")) - - # # If no exception is raised by validate_spec(), the spec is valid. - # validate_spec(swagger_config) - # print("000 Schema validation passed") - - # errors_iterator = openapi_v3_spec_validator.iter_errors(swagger_config) - # print(errors_iterator) diff --git a/project/SOAR_README.md b/project/soar/SOAR_README.md similarity index 100% rename from project/SOAR_README.md rename to project/soar/SOAR_README.md diff --git a/project/soar/soar_protocol.json b/project/soar/soar_protocol.json new file mode 100644 index 0000000..5367b43 --- /dev/null +++ b/project/soar/soar_protocol.json @@ -0,0 +1,697 @@ +{ + "openapi": "3.0.2", + "info": { + "description": "SoAR message protocol in schemas", + "title": "SoAR Backbone Message Formats", + "version": "1.0" + }, + "definitions": {}, + "paths": {}, + "components": { + "schemas": { + "acknowledgement": { + "properties": { + "acknowledged_message_ID": { + "description": "Identifier of message received and executed with success for mission plans sent by the Autonomy Engine.", + "example": "02125022255-7bc8-11ed-a1eb-0242ac999999", + "type": "string" + }, + "message_type": { + "description": "Type of message", + "example": "acknowledgement", + "type": "string" + }, + "status": { + "description": "Highest level of acknowledgement. I.e. `c2_received`: Received by C2, `operator_approved_and_sent` : Approved by operator and sent from C2->Platform, `executed`: Executed by platform", + "enum": [ + "c2_received", + "operator_approved_and_sent", + "executed" + ], + "example": "executed by platform", + "type": "string" + } + }, + "required": [ + "message_type", + "acknowledged_message_ID", + "status" + ], + "type": "object" + }, + "header": { + "discriminator": { + "propertyName": "message_type" + }, + "properties": { + "delivery_type": { + "default": "publish", + "description": "To publish or broadcast this message.", + "enum": [ + "broadcast", + "publish" + ], + "example": "publish", + "type": "string" + }, + "destination": { + "description": "Publisher topic; What is the destination of this message", + "example": "ah1", + "type": "string" + }, + "encoded": { + "description": "Indicate that message raw (encoded) or decoded. Options: encoded=True, decoded=False", + "example": false, + "type": "boolean" + }, + "message_ID": { + "description": "An identifier for the type of message received.", + "example": "b427003c-0000-11aa-a1eb-bvcdfghjgfdd", + "type": "string" + }, + "source": { + "description": "The sender; Where is this message from", + "example": "autonomy_engine", + "type": "string" + }, + "timestamp": { + "description": "Timestamp of message", + "example": "2022-11-16T00:00:00Z", + "format": "date-time", + "type": "string" + }, + "version": { + "description": "Version of comms backbone message format protocol", + "example": 2.0, + "format": "float", + "type": "number" + } + }, + "type": "object" + }, + "message": { + "properties": { + "header": { + "$ref": "#/components/schemas/header" + }, + "payload": { + "$ref": "#/components/schemas/payload" + } + }, + "required": [ + "header", + "payload" + ], + "type": "object" + }, + "mission_plan": { + "properties": { + "autonomy_engine_plan_ID": { + "description": "Unique identifier for this plangenerated by the Autonomy Engine", + "example": 3, + "type": "integer" + }, + "message_type": { + "description": "Type of message", + "example": "mission_plan", + "type": "string" + }, + "plan": { + "items": { + "properties": { + "action": { + "description": "Autonomy Engine's action from `move`, `payload`, `dive`, `send_hits`, `scanline`, `scanpoint`.", + "example": "move", + "type": "string" + }, + "activate_payload": { + "description": "To activate/deactivate sensor for Autosub Hover-1 --> `MBES` sensor and for EcoSUB --> `Sidescan`", + "example": true, + "type": "boolean" + }, + "altitude": { + "description": "Altitude of next action", + "example": 15.0, + "format": "float", + "type": "number" + }, + "depth": { + "description": "Depth of next action", + "example": 15.0, + "format": "float", + "type": "number" + }, + "flight_style": { + "description": "Platform-specific modes/flight styles to perform next action", + "example": "orbit", + "type": "string" + }, + "latitude_waypoint": { + "description": "Next waypoint, x-coordinate", + "example": -4.187143188645706, + "format": "float", + "type": "number" + }, + "longitude_waypoint": { + "description": "Next waypoint, y-coordinate", + "example": 50.37072283932642, + "format": "float", + "type": "number" + }, + "send_environmental_data": { + "description": "To trigger the platform to send list of observations if any found", + "example": false, + "type": "boolean" + } + }, + "required": [ + "latitude_waypoint", + "longitude_waypoint" + ], + "type": "object" + }, + "type": "array" + }, + "platform_ID": { + "description": "Unique identifier for this platform", + "example": 1, + "type": "integer" + } + }, + "required": [ + "message_type", + "plan_ID", + "platform_ID", + "plan" + ], + "type": "object" + }, + "observation": { + "properties": { + "additional_data": { + "description": "Placeholder field for any additional data", + "example": { + "sensor_payload": false + } + }, + "message_type": { + "description": "Type of message", + "example": "observation", + "type": "string" + }, + "platform_ID": { + "description": "ID of platform to sending observations", + "example": 2, + "type": "integer" + }, + "points_of_interest": { + "description": "Points from features of interest identified by platform if any found.", + "items": { + "properties": { + "latitude": { + "description": "Identified x-coordinate of point of interest", + "example": 178.2, + "format": "float", + "type": "number" + }, + "longitude": { + "description": "Identified y-coordinate of point of interest", + "example": -10.122, + "format": "float", + "type": "number" + }, + "quality_of_point": { + "description": "Quality/strength of points from features of interest identified by platform.", + "example": 0.98, + "format": "float", + "type": "number" + } + }, + "required": [ + "latitude", + "longitude" + ], + "type": "object" + }, + "type": "array" + }, + "region_surveyed": { + "description": "Region surveyed by given platform. GEOJSON", + "example": "", + "nullable": true + } + }, + "required": [ + "message_type", + "platform_ID" + ], + "type": "object" + }, + "payload": { + "discriminator": { + "mapping": { + "Acknowledgement": "#/components/schemas/acknowledgement", + "MissionPlan": "#/components/schemas/mission_plan", + "Observation": "#/components/schemas/observation", + "PlanningConfiguration": "#/components/schemas/planning_configuration", + "PlatformStatus": "#/components/schemas/platform_status" + }, + "propertyName": "message_type" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/acknowledgement" + }, + { + "$ref": "#/components/schemas/mission_plan" + }, + { + "$ref": "#/components/schemas/observation" + }, + { + "$ref": "#/components/schemas/planning_configuration" + }, + { + "$ref": "#/components/schemas/platform_status" + } + ] + }, + "planning_configuration": { + "properties": { + "exclusion_zones": { + "description": "Exclusion zones for all platforms", + "items": { + "description": "Using GEOJSON, exact 4-point region (rectangle shaped)", + "properties": { + "geometry_coordinates": { + "example": [ + [ + [ + -4.187143188645706, + 50.37072283932642 + ], + [ + -4.202697005964865, + 50.368816892405874 + ], + [ + -4.203156724702808, + 50.365640144076906 + ], + [ + -4.19449868846155, + 50.362267670845654 + ] + ] + ], + "type": "array" + } + }, + "required": [ + "geometry_coordinates" + ], + "type": "object" + }, + "type": "array" + }, + "message_type": { + "description": "Type of message", + "example": "planning_configuration", + "type": "string" + }, + "planning_config_ID": { + "description": "Unique identifier tagged to version of this configuration plan", + "example": 3, + "type": "integer" + }, + "squads": { + "items": { + "properties": { + "no_of_platforms": { + "description": "Number of platforms", + "example": 3, + "type": "integer" + }, + "platforms": { + "description": "Squad consists of these platforms", + "items": { + "properties": { + "additional_data": { + "description": "Any addition fields/data to be added here", + "example": { + "scan_type": "DVL", + "swath_width": 10.0 + }, + "type": "null" + }, + "emergency": { + "properties": { + "additional_data": { + "description": "Any addition fields/data to be added here", + "example": {}, + "type": "null" + }, + "latitude_waypoint": { + "description": "X-coordinate safe place for respective platform", + "example": -7.432, + "format": "float", + "type": "number" + }, + "longitude_waypoint": { + "description": "Y-coordinate safe place for respective platform", + "example": 50.365, + "format": "float", + "type": "number" + }, + "safe_command": { + "description": "Command/Action that is native to respective partner's platform/C2", + "enum": [ + "go_home", + "abort_now", + "stop_mission" + ], + "example": "go_home", + "type": "string" + }, + "target_depth": { + "description": "Z-coordinate safe place for respective platform . If platform to NOT stay at depth, key in `0.0`", + "example": 10, + "format": "float", + "type": "number" + } + }, + "required": [ + "latitude_waypoint", + "longitude_waypoint", + "target_depth" + ], + "type": "object" + }, + "max_velocity": { + "description": "Maximum altitude set for squad.", + "example": 0.9, + "format": "float", + "type": "number" + }, + "min_altitude": { + "description": "Minimum altitude set for squad.", + "example": 15.2, + "format": "float", + "type": "number" + }, + "min_velocity": { + "description": "Minimum velocity set for squad.", + "example": 0.1, + "format": "float", + "type": "number" + }, + "model": { + "example": "reav", + "type": "string" + }, + "platform_ID": { + "description": "Identifier for platform", + "example": 23, + "type": "integer" + }, + "serial": { + "description": "platform serial number", + "example": "reav-60", + "type": "string" + } + }, + "required": [ + "platform_ID", + "serial", + "model", + "emergency", + "min_altitude", + "min_velocity", + "max_velocity" + ], + "type": "object" + }, + "type": "array" + }, + "region_of_interest": { + "description": "Using GEOJSON, exact 4-point region (rectangle shaped)", + "properties": { + "geometry_coordinates": { + "example": [ + [ + [ + -4.187143188645706, + 50.37072283932642 + ], + [ + -4.202697005964865, + 50.368816892405874 + ], + [ + -4.203156724702808, + 50.365640144076906 + ], + [ + -4.19449868846155, + 50.362267670845654 + ] + ] + ], + "type": "array" + } + }, + "required": [ + "geometry_coordinates" + ], + "type": "object" + }, + "squad_ID": { + "description": "Identifier of given squad", + "example": 23, + "type": "integer" + }, + "squad_mission_type": { + "description": "Mission of given squad: `tracking`, `survey`, `inspection`", + "enum": [ + "tracking", + "survey", + "inspection" + ], + "example": "survey", + "type": "string" + }, + "squad_state": { + "description": "In execution, Waiting.. <define further>", + "example": false, + "type": "string" + } + }, + "required": [ + "squad_ID", + "no_of_platforms", + "platforms", + "squad_mission_type", + "squad_state", + "exclusion_zones" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "message_type", + "config_ID", + "squads", + "exclusion_zones" + ], + "type": "object" + }, + "platform_status": { + "properties": { + "active": { + "description": "When a platform is in deployment (executing a mission plan) this should be True", + "example": true, + "type": "boolean" + }, + "altitude": { + "description": "Target altitude in metres", + "example": 20, + "format": "float", + "type": "number" + }, + "autonomy_engine_plan_ID": { + "description": "Last mission plan ID (according to Autonomy Engine's mission plan number sent) executed by platform", + "example": 1, + "type": "integer" + }, + "battery_remaining_capacity": { + "description": "Battery remaining % provided by respective C2", + "example": 80.2, + "format": "float", + "type": "number" + }, + "current_pitch": { + "description": "Current pitch of platform", + "example": -4.0, + "format": "float", + "type": "number" + }, + "depth": { + "default": 0, + "description": "Target depth in metres", + "example": 50, + "format": "float", + "type": "number" + }, + "heading": { + "description": "Angular distance relative to north, usually 000\u00b0 at north, clockwise through 359\u00b0, in degrees", + "example": 124.3, + "format": "float", + "type": "number" + }, + "health_status": { + "description": "Health status extracted by respective platform if any diagnosis is available to check sensors", + "example": "Warning", + "type": "string" + }, + "latitude": { + "description": "Latitude in decimal degrees.", + "example": 178.2, + "format": "float", + "type": "number" + }, + "localisation_error": { + "description": "Localisation error at last USBL update.", + "example": 0.000129, + "format": "float", + "type": "number" + }, + "longitude": { + "description": "Longitude in decimal degrees.", + "example": -10.122, + "format": "float", + "type": "number" + }, + "message_type": { + "description": "Type of message", + "example": "platform_status", + "type": "string" + }, + "mission_action_ID": { + "description": "", + "example": 1, + "type": "integer" + }, + "mission_track_ID": { + "description": "Track number - stage in mission (e.g. 4 --> Waypoint 3 to Waypoint 4)", + "example": 4, + "type": "integer" + }, + "platform_ID": { + "description": "Identifier for platform", + "example": 1, + "type": "integer" + }, + "platform_state": { + "description": "Current state executed by platform. E.g. STOP, IDLE, ABORT.", + "example": "ABORT", + "type": "string" + }, + "platform_timestamp": { + "decription": "Timestamp for onboard platform status message", + "example": "2022-12-21T00:00:00Z", + "format": "date-time", + "type": "string" + }, + "range_to_go": { + "description": "Estimated distance to reach next waypoint", + "example": 124.3, + "format": "float", + "type": "number" + }, + "sensor_config": { + "description": "Scanning sensor on platform available to be controlled by the Autonomy Engine", + "properties": { + "additional_data": { + "description": "Any addition fields/data to be added here", + "example": { + "payload": [ + 1.2, + 434 + ] + }, + "type": "null" + }, + "sensor_on": { + "description": "Sensor switched on (True) or off (False)", + "example": true, + "type": "boolean" + }, + "sensor_serial": { + "description": "serial number of sensor", + "example": "mbes-002a", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "speed_over_ground": { + "description": "", + "example": 124.3, + "format": "float", + "type": "number" + }, + "status_source": { + "description": "Indicate if this status message is from the platform or USBL", + "enum": [ + "usbl", + "onboard_platform" + ], + "example": "usbl", + "type": "string" + }, + "thrust_applied": { + "description": "", + "example": 124.3, + "format": "float", + "type": "number" + }, + "transmission_mode": { + "description": "Mode in which status message was transmitted when on the surface (i.e. iridium/wifi) or underwater (i.e. acoustics)", + "enum": [ + "acoustics", + "iridium", + "wifi", + "starlink" + ], + "example": "wifi", + "type": "string" + }, + "usbl_fix_seconds_ago": { + "description": "USBL Fix received x second ago.", + "example": 10.0, + "format": "float", + "type": "number" + }, + "water_current_velocity": { + "description": "", + "example": 124.3, + "format": "float", + "type": "number" + } + }, + "required": [ + "message_type", + "platform_ID", + "status_source", + "platform_timestamp", + "latitude", + "longitude" + ], + "type": "object" + } + } + } + } \ No newline at end of file -- GitLab