Source
...
Target
Commits (15)
__pycache__/
*.pyc
tests/test_swagger.json
\ No newline at end of file
......@@ -2,6 +2,7 @@ include:
- project: communications-backbone-system/backbone-infrastructure-config
ref: master
file: gitlab/all.yml
- local: /gitlab/test-js.yml
variables:
DOCKER_IMAGE_NAME: backbone-message-format
......
......@@ -10,11 +10,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Changed
- Updated README to run tests against JS dependencies
- Use discover to find all unit tests
- Run tests against current format definitions
- Test that formats match saved schema
- Run python and javascript tests in CI
- Refactor schema script to remove invalid definitions object automatically
- Refactor generate_schema_config script to output file on -f flag
### Added
## [v0.2.0] - 2024-02-06
- Emergency flag in mission plan schemas
### Added
- New alert message definition
- Emergency flag in mission plan schemas
- Added additional battery and fuel fields to platform status for SPINE project
## [v0.1.0] - 2023-03-24
......@@ -32,5 +41,6 @@ JSON schema definitions for the SoAR project
Example messages matching the schema for each partner
[unreleased]: https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/compare/v0.2.0...dev
[v0.2.0]: https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/compare/v0.1.0...v0.2.0
[v0.1.0]: https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/compare/9e6ce245...v0.1.0
[unreleased]: https://git.noc.ac.uk/communications-backbone-system/backbone-message-format/compare/v0.1.0...dev
......@@ -72,22 +72,28 @@ eg
## Run Docs & Save Schema When Updating Message Formats
1. Run the command below and go to `http://127.0.0.1:5000`
```
python3 generate_schema_config.py
python3 generate_schema_config.py -f
```
2. Copy the schema generated `http://127.0.0.1:5000/soar_protocol.json` into the `backbone-message-format/project/<project_name>/swagger.json`
3. In the json copied, remove the key `"definitions"` from the schema and save this.
2. Commit any changes to the `backbone-message-format/project/<project_name>/swagger.json`
## Run Tests
We have found slightly different behaviour between the OpenAPI validators in python and javascript.
By running tests in both languages we should protect against messages that pass validation in
one client but fail in another.
Run both tests below:
1. Test 1
1. Test 1 - Use python validators
```
python3 -m unittest tests/test_schemas.py
python3 -m unittest discover
```
2. Test 2
2. Test 2 - Use javascript validators
```
cd tests-js/docker; docker compose up --build
# Compile schema and run javascript validation tests in docker
python3 test-js.py
```
## Quick Links
......
......@@ -12,4 +12,4 @@ services:
- PYTHONDONTWRITEBYTECODE=1
volumes:
- ../:/app
command: "python3 -m unittest tests/test_schemas.py"
\ No newline at end of file
command: "python3 -m unittest discover"
......@@ -14,11 +14,19 @@ from formats.alert import alert_schema
from flasgger import Swagger
from flask import Flask
import argparse
import json
import os
app = Flask(__name__)
url_prefix = os.getenv("URL_PREFIX", "")
# Enable running on domain sub-path
URL_PREFIX = os.getenv("URL_PREFIX", "")
# Allow env override of default host
FLASK_HOST = os.getenv("FLASK_HOST", "localhost")
# Allow env override of default port
FLASK_PORT = os.getenv("FLASK_PORT", 5000)
# Switch on debug mode if env var is truthy
FLASK_DEBUG = os.getenv("FLASK_DEBUG", "False").lower() in ("true", "1", "t")
swagger_config = {
"openapi": "3.0.2",
......@@ -35,7 +43,7 @@ swagger_config = {
"route": "/soar_protocol.json",
}
],
"url_prefix": url_prefix,
"url_prefix": URL_PREFIX,
"paths": {},
"components": {
"schemas": {
......@@ -103,11 +111,125 @@ swagger_config = {
},
}
swag = Swagger(app, config=swagger_config, merge=True)
flask_host = os.getenv(
"FLASK_HOST", "localhost"
) # Sets to whatever FLASK_HOST is, or defaults to localhost
def configure_flask(swagger_config):
"""
Setup a flask app, load flasgger
and then patch to remove invalid
definitions:{} object
"""
app = Flask(__name__)
Swagger(app, config=swagger_config, merge=True)
# Replace schema route to remove invalid
# definitions: {}
# Should be fixed if Flassger 0.9.7 is released
#
# The last release of flasgger was Aug 2020
# This bug was fixed in Nov 2021
# There is a pre-release from May 2023
# Until the fix gets released we have to
# remove the invalid definitions object
# from the spec
@app.after_request
def after_request_decorator(response):
"""
I didn't want to mess with flasgger so
this blunt workaround that runs on every
route and then checks whether it's required
"""
is_response = type(response).__name__ == "Response"
is_json = is_response and response.content_type == "application/json"
if is_json:
parsed = response.json
if "definitions" in parsed:
del parsed["definitions"]
response.data = json.dumps(parsed)
return response
return app
def serve(swagger_config):
"""
Run as local flask app on FLASK_PORT|5000
"""
app = configure_flask(swagger_config)
app.run(debug=FLASK_DEBUG, host=FLASK_HOST, port=FLASK_PORT)
def compile_schema(swagger_config):
"""Extract the output schema from flasgger
The only way I have found to do this is to
use a test client to make the GET request
for the page
The function that returns the definition
can't be called outside the flask app context
"""
app = configure_flask(swagger_config)
route = swagger_config["specs"][0]["route"]
client = app.test_client()
response = client.get(route)
spec = response.json
return spec
def write_schema(swagger_config, file_path):
"""
Dump schema to specified file
"""
spec = compile_schema(swagger_config)
json_schema = json.dumps(spec, indent=2)
with open(file_path, "w") as f:
f.write(json_schema)
def get_options():
"""
Parse script arguments
"""
parser = argparse.ArgumentParser(
description="Generate the schema",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"-s",
"--serve",
dest="run_flask",
action="store_true",
help="Run flask app",
default=False,
)
parser.add_argument(
"-f",
"--file",
dest="output_file",
action="store_true",
help="Save output to schema file",
default=False,
)
parser.add_argument("filename", nargs="?", default="project/soar/swagger.json")
args = parser.parse_args()
config = vars(args)
# If no flag is specified default to running the flask server
if all(v is False for v in config.values()):
config["run_flask"] = True
return config
if __name__ == "__main__":
app.run(debug=False, host=flask_host)
# Parse script args
config = get_options()
# Output compiled schema
if config.get("output_file"):
write_schema(swagger_config, config.get("filename"))
# Run flask app
if config.get("run_flask"):
serve(swagger_config)
test-js:
stage: test
script:
- cd tests-js/docker
- docker compose up --build
tags:
- shell
rules:
- if: '$CI_SKIP_TESTS == "1"'
when: never
- if: '$CI_IGNORE_TESTS == "1"'
allow_failure: true
- when: on_success
......@@ -1150,10 +1150,10 @@
}
}
},
"info": {
"description": "SoAR message protocol in schemas",
"title": "SoAR Backbone Message Formats",
"version": "1.0"
"info":{
"description":"SoAR message protocol in schemas",
"title":"SoAR Backbone Message Formats",
"version":"0.2"
},
"openapi": "3.0.2",
"paths": {}
......
......@@ -2,7 +2,7 @@ from setuptools import setup
setup(
version="0.1.0",
version="0.2.0",
name="backbone_message_format",
python_requires=">=3.8",
packages=["backbone_formats", "soar_schema"],
......
FROM node:18.7.0-alpine
FROM python:3.9.16-alpine
# Add node for running JS validator tests
RUN apk add --update nodejs npm
WORKDIR /app/tests-js
COPY tests-js/package.json /app/tests-js/package.json
RUN npm install -g yarn
RUN yarn install
WORKDIR /app
COPY . /app
# compile test schema from message
RUN pip install -r requirements.txt
RUN python generate_schema_config.py -f tests/test_swagger.json
WORKDIR /app/tests-js
CMD [ 'yarn', 'test' ]
......@@ -3,7 +3,7 @@ const Validator = require('swagger-model-validator');
const OpenAPISchemaValidator = require('openapi-schema-validator').default;
const getSchema = () => {
const schema = require(`${__dirname}/../project/soar/swagger.json`);
const schema = require(`${__dirname}/../tests/test_swagger.json`);
return schema;
};
......
{
"components": {
"schemas": {
"MESSAGE": {
"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"
],
"type": "object"
},
"acknowledgement": {
"properties": {
"approved": {
"description": "Human-in-the-loop approval.1 - Plan approved; 0 - Plan Rejected",
"type": "boolean"
},
"autonomy_engine_plan_ID": {
"description": "Mission plan ID (according to Autonomy Engine's mission plan number sent) executed by platform",
"example": 1,
"type": "integer"
},
"message_type": {
"description": "Type of message",
"enum": [
"acknowledgement"
],
"example": "acknowledgement",
"type": "string"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "reav-x-1",
"type": "string"
}
},
"required": [
"message_type",
"autonomy_engine_plan_ID",
"platform_ID",
"approved"
],
"type": "object"
},
"alert": {
"properties": {
"code": {
"description": "Alert code",
"example": 345,
"type": "integer"
},
"details": {
"description": "Detailed reason for the alert ",
"example": "Discrepancy between rudder and actuator positions : Rudder Pos=10.31\u00b0, Steering Actuator Pos=28.65\u00b0, Discrepancy=18.33\u00b0",
"type": "string"
},
"message_type": {
"description": "Type of message",
"enum": [
"alert"
],
"example": "alert",
"type": "string"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "usvdecibel",
"type": "string"
},
"platform_timestamp": {
"description": "Timestamp for onboard platform status message",
"example": "2022-12-21T00:00:00Z",
"format": "date-time",
"type": "string"
},
"severity": {
"description": "Severity level of alert",
"enum": [
"Emergency",
"Alarm",
"Warning",
"Caution"
],
"example": "Alarm",
"type": "string"
},
"subsystem": {
"description": "System that generated the alert",
"example": "Onboard Fault Monitor",
"type": "string"
},
"summary": {
"description": "High level description of the alert",
"example": "Steering Damage - Port Side",
"type": "string"
}
},
"required": [
"message_type",
"platform_ID",
"code",
"severity"
],
"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"
},
"mission_plan": {
"properties": {
"autonomy_engine_plan_ID": {
"description": "Unique identifier for this plangenerated by the Autonomy Engine",
"example": 3,
"type": "integer"
},
"emergency": {
"default": false,
"description": "To indicate if this is an emergency. true = emergency and false = no emergency",
"example": false,
"type": "boolean"
},
"message_type": {
"description": "Type of message",
"enum": [
"mission_plan"
],
"example": "mission_plan",
"type": "string"
},
"plan": {
"items": {
"properties": {
"action": {
"description": "Autonomy Engine's action from `move`, `payload`, `dive`, `send_hits`, `scanline`, `scanpoint`.",
"enum": [
"move",
"payload",
"dive",
"send_hits",
"scanline",
"scanpoint",
"go_home",
"surface_now",
"stop_mission",
"abort_now"
],
"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"
},
"start_point_latitude": {
"description": "Start point, y-coordinate",
"example": 50.37072283932642,
"format": "float",
"type": "number"
},
"start_point_longitude": {
"description": "Start point, x-coordinate",
"example": -4.187143188645706,
"format": "float",
"type": "number"
},
"target_waypoint_latitude": {
"description": "Target waypoint, y-coordinate",
"example": 50.37072283932642,
"format": "float",
"type": "number"
},
"target_waypoint_longitude": {
"description": "Target waypoint, x-coordinate",
"example": -4.187143188645706,
"format": "float",
"type": "number"
},
"timeout": {
"description": "Timeout set to perform action",
"example": 1800.0,
"format": "float",
"type": "number"
}
},
"required": [
"target_waypoint_latitude",
"target_waypoint_longitude"
],
"type": "object"
},
"type": "array"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "reav-x-1",
"type": "string"
}
},
"required": [
"message_type",
"autonomy_engine_plan_ID",
"platform_ID",
"plan"
],
"type": "object"
},
"mission_plan_encoded": {
"properties": {
"data": {
"description": "encoded string. E.g. Base64 encoded",
"example": "SDQke4uwyP/YQQAgAhA2AND/nu8nvQAAAAAAAAAACtejPa5HHUGkcBAAAAIAAAAQAAAAAAAAAA9P2cP166ab+9cg==",
"type": "string"
},
"file_name": {
"description": "Name of file",
"example": "ah1-0238126349247372.bin",
"type": "string"
},
"is_binary": {
"description": "true if the data field contains binary format data encoded as base64. false if the data field contains ascii content such as NMEA.",
"example": true,
"type": "boolean"
},
"message_type": {
"description": "Type of message",
"enum": [
"mission_plan_encoded"
],
"example": "mission_plan_encoded",
"type": "string"
},
"mime_type": {
"description": "MIME type",
"example": "application/gzip",
"type": "string"
}
},
"required": [
"data",
"is_binary"
],
"type": "object"
},
"observation": {
"properties": {
"additional_data": {
"description": "Placeholder field for any additional data",
"example": {
"sensor_payload": false
}
},
"message_type": {
"description": "Type of message",
"enum": [
"observation"
],
"example": "observation",
"type": "string"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "reav-x-1",
"type": "string"
},
"points_of_interest": {
"description": "Points from features of interest identified by platform if any found.",
"items": {
"properties": {
"latitude": {
"description": "Identified y-coordinate of point of interest",
"example": 178.2,
"format": "float",
"type": "number"
},
"longitude": {
"description": "Identified x-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"
},
"observation_encoded": {
"properties": {
"data": {
"description": "encoded string. E.g. Base64 encoded",
"example": "SDQke4uwyP/YQQAgAhA2AND/nu8nvQAAAAAAAAAACtejPa5HHUGkcBAAAAIAAAAQAAAAAAAAAA9P2cP166ab+9cg==",
"type": "string"
},
"file_name": {
"description": "Name of file",
"example": "ah1-0238126349247372.bin",
"type": "string"
},
"is_binary": {
"description": "true if the data field contains binary format data encoded as base64. false if the data field contains ascii content such as NMEA.",
"example": true,
"type": "boolean"
},
"message_type": {
"description": "Type of message",
"enum": [
"observation_encoded"
],
"example": "observation_encoded",
"type": "string"
},
"mime_type": {
"description": "MIME type",
"example": "application/gzip",
"type": "string"
}
},
"required": [
"data",
"is_binary"
],
"type": "object"
},
"payload": {
"discriminator": {
"mapping": {
"acknowledgement": "#/components/schemas/acknowledgement",
"alert": "#/components/schemas/alert",
"mission_plan": "#/components/schemas/mission_plan",
"mission_plan_encoded": "#/components/schemas/mission_plan_encoded",
"observation": "#/components/schemas/observation",
"observation_encoded": "#/components/schemas/observation_encoded",
"planning_configuration": "#/components/schemas/planning_configuration",
"platform_status": "#/components/schemas/platform_status",
"platform_status_encoded": "#/components/schemas/platform_status_encoded",
"survey": "#/components/schemas/survey",
"survey_encoded": "#/components/schemas/survey_encoded"
},
"propertyName": "message_type"
},
"oneOf": [
{
"$ref": "#/components/schemas/alert"
},
{
"$ref": "#/components/schemas/acknowledgement"
},
{
"$ref": "#/components/schemas/mission_plan"
},
{
"$ref": "#/components/schemas/mission_plan_encoded"
},
{
"$ref": "#/components/schemas/observation"
},
{
"$ref": "#/components/schemas/observation_encoded"
},
{
"$ref": "#/components/schemas/planning_configuration"
},
{
"$ref": "#/components/schemas/platform_status"
},
{
"$ref": "#/components/schemas/platform_status_encoded"
},
{
"$ref": "#/components/schemas/survey"
},
{
"$ref": "#/components/schemas/survey_encoded"
}
]
},
"planning_configuration": {
"properties": {
"exclusion_zones": {
"description": "Exclusion zones for all platforms",
"items": {
"description": "Using GEOJSON, exact 4-point region (rectangle shaped - 5 points)",
"properties": {
"geometry_coordinates": {
"example": [
[
[
-4.1777839187560915,
50.34173405662855
],
[
-4.1777839187560915,
50.33820949229701
],
[
-4.143667777943875,
50.33820949229701
],
[
-4.143667777943875,
50.34173405662855
],
[
-4.1777839187560915,
50.34173405662855
]
]
],
"type": "array"
}
},
"type": "object"
},
"type": "array"
},
"message_type": {
"description": "Type of message",
"enum": [
"planning_configuration"
],
"example": "planning_configuration",
"type": "string"
},
"planning_config_ID": {
"description": "Unique identifier tagged to version of this configuration plan",
"example": 3,
"type": "integer"
},
"region_of_interest": {
"description": "Region of interest for the entire operation",
"items": {
"description": "Using GEOJSON, exact 4-point region (rectangle shaped - 5 points)",
"properties": {
"geometry_coordinates": {
"example": [
[
[
-4.1777839187560915,
50.34173405662855
],
[
-4.1777839187560915,
50.33820949229701
],
[
-4.143667777943875,
50.33820949229701
],
[
-4.143667777943875,
50.34173405662855
],
[
-4.1777839187560915,
50.34173405662855
]
]
],
"type": "array"
}
},
"type": "object"
},
"type": "array"
},
"squads": {
"items": {
"properties": {
"no_of_platforms": {
"description": "Number of platforms",
"example": 3,
"type": "integer"
},
"platforms": {
"description": "Squad consists of these platforms",
"items": {
"properties": {
"active": {
"description": "If platform is active = True, and inactive = False",
"example": true,
"type": "boolean"
},
"additional_data": {
"description": "Any addition fields/data to be added here",
"example": {
"new_sensor_a": "test_sensor",
"range": 10.0
},
"type": "object"
},
"beacon_ID": {
"description": "Unique identifier (number) for the beacon associated to this platform",
"example": 2407,
"type": "number"
},
"emergency": {
"properties": {
"safe_command": {
"description": "Command/Action that is native to respective partner's platform/C2",
"enum": [
"go_home",
"abort_now",
"stop_now",
"surface_now"
],
"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.0,
"format": "float",
"type": "number"
},
"target_waypoint_latitude": {
"description": "Y-coordinate safe place for respective platform",
"example": 50.365,
"format": "float",
"type": "number"
},
"target_waypoint_longitude": {
"description": "X-coordinate safe place for respective platform",
"example": -7.432,
"format": "float",
"type": "number"
}
},
"required": [
"target_waypoint_latitude",
"target_waypoint_longitude",
"target_depth"
],
"type": "object"
},
"endurance_relative_to_water_speed": {
"properties": {
"avg_battery_rating": {
"description": "Battery endurance rating during standard operational speed usage (m/s)",
"example": 1.9,
"format": "float",
"type": "number"
},
"max_battery_rating": {
"description": "Battery endurance rating during maximum speed usage (m/s)",
"example": 1.23,
"format": "float",
"type": "number"
},
"min_battery_rating": {
"description": "Battery endurance rating during maximum speed usage (m/s)",
"example": 3.32,
"format": "float",
"type": "number"
}
},
"type": "object"
},
"max_velocity": {
"description": "Maximum velocity set for platform",
"example": 0.9,
"format": "float",
"type": "number"
},
"min_altitude": {
"description": "Minimum altitude set for platform",
"example": 15.2,
"format": "float",
"type": "number"
},
"min_velocity": {
"description": "Minimum velocity set for platform",
"example": 0.1,
"format": "float",
"type": "number"
},
"model": {
"example": "reav",
"type": "string"
},
"operator": {
"description": "Operator of platform",
"example": "noc",
"type": "string"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "reav-x-1",
"type": "string"
},
"scan_sensor": {
"properties": {
"angle": {
"description": "Angle of range of swath width (in degrees)",
"example": 140.0,
"format": "float",
"type": "number"
},
"frequency": {
"description": "Frequency of scanning sensor (in kHz)",
"example": 700.0,
"format": "float",
"type": "number"
},
"sensor_type": {
"description": "Unique identifier for this platform",
"enum": [
"SIDESCAN",
"MBES"
],
"example": "MBES",
"type": "string"
},
"swath_width": {
"description": "Function of `target_altitude` for the platform's swath width (in metres)",
"example": 38.0,
"format": "float",
"type": "number"
},
"warmup_time": {
"description": "Warmup time (seconds) for sensor to start up.",
"example": 180.0,
"format": "float",
"type": "number"
}
},
"type": "object"
},
"target_altitude": {
"description": "Target altitude set for platform. This affects swath width",
"example": 15.0,
"format": "float",
"type": "number"
},
"turning_radius": {
"description": "Turning radius of platform (in metres)",
"example": 1.0,
"format": "float",
"type": "number"
}
},
"required": [
"operator",
"platform_ID",
"active",
"model"
],
"type": "object"
},
"type": "array"
},
"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"
}
},
"required": [
"squad_ID",
"no_of_platforms",
"platforms",
"squad_mission_type"
],
"type": "object"
},
"type": "array"
}
},
"required": [
"message_type",
"planning_config_ID",
"squads",
"exclusion_zones",
"region_of_interest"
],
"type": "object"
},
"platform_status": {
"properties": {
"altitude": {
"description": "Target altitude in metres",
"example": 20.0,
"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_output": {
"description": "Battery output in kW",
"example": 80.2,
"format": "float",
"type": "number"
},
"battery_remaining_capacity": {
"description": "Battery remaining % provided by respective C2",
"example": 80.2,
"format": "float",
"type": "number"
},
"depth": {
"default": 0.0,
"description": "Target depth in metres",
"example": 50.0,
"format": "float",
"type": "number"
},
"endurance": {
"description": "Estimate of hours of operation remaining based on present output or performance",
"example": 7.4,
"format": "float",
"type": "number"
},
"fuel_remaining_capacity": {
"description": "Percentage remaining capacity",
"example": 80.2,
"format": "float",
"type": "number"
},
"fuel_volume": {
"description": "Litres of liquid fuel",
"example": 12.5,
"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 where 0 is OK, 1 is platform has an ERROR",
"example": false,
"type": "boolean"
},
"latitude": {
"description": "Latitude (Y-coordinate) in decimal degrees.",
"example": 178.2,
"format": "float",
"type": "number"
},
"localisation_east_error": {
"description": "Difference in EAST between deadreckoningand USBL update.",
"example": 0.000129,
"format": "float",
"type": "number"
},
"localisation_north_error": {
"description": "Difference in NORTH between deadreckoning and USBL update.",
"example": 0.000129,
"format": "float",
"type": "number"
},
"longitude": {
"description": "Longitude (X-coordinate) in decimal degrees.",
"example": -10.122,
"format": "float",
"type": "number"
},
"message_type": {
"description": "Type of message",
"enum": [
"platform_status"
],
"example": "platform_status",
"type": "string"
},
"mission_plan_ID": {
"description": "Mission plan ID according to platform-C2 system",
"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": "Unique identifier for this platform",
"example": "reav-x-1",
"type": "string"
},
"platform_state": {
"description": "Current state executed by platform. E.g. STOP, IDLE, ABORT.",
"example": "ABORT",
"type": "string"
},
"platform_timestamp": {
"description": "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": "object"
},
"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"
}
},
"type": "object"
},
"speed_over_ground": {
"description": "Speed over ground",
"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": "Thrust applied",
"example": 124.3,
"format": "float",
"type": "number"
},
"transmission_mode": {
"description": "Mode in which status message was transmitted when on the surface (e.g. iridium/wifi) or underwater (e.g. 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": "Water current magnitude and direction",
"example": "124.3NE",
"type": "string"
}
},
"required": [
"message_type",
"platform_ID",
"status_source",
"platform_timestamp",
"latitude",
"longitude"
],
"type": "object"
},
"platform_status_encoded": {
"properties": {
"data": {
"description": "encoded string. E.g. Base64 encoded",
"example": "SDQke4uwyP/YQQAgAhA2AND/nu8nvQAAAAAAAAAACtejPa5HHUGkcBAAAAIAAAAQAAAAAAAAAA9P2cP166ab+9cg==",
"type": "string"
},
"file_name": {
"description": "Name of file",
"example": "ah1-0238126349247372.bin",
"type": "string"
},
"is_binary": {
"description": "true if the data field contains binary format data encoded as base64. false if the data field contains ascii content such as NMEA.",
"example": true,
"type": "boolean"
},
"message_type": {
"description": "Type of message",
"enum": [
"platform_status_encoded"
],
"example": "platform_status_encoded",
"type": "string"
},
"mime_type": {
"description": "MIME type",
"example": "application/gzip",
"type": "string"
}
},
"required": [
"data",
"is_binary"
],
"type": "object"
},
"survey": {
"properties": {
"latitude_A": {
"description": "Latitude of point A(intersection of normal)from waypoint A to survey line",
"example": 178.2,
"format": "float",
"type": "number"
},
"latitude_B": {
"description": "Latitude of point B(intersection of normal)from waypoint B to survey line",
"example": 178.2,
"format": "float",
"type": "number"
},
"latitude_C": {
"description": "Latitude of point C(intersection of normal)from waypoint C to survey line",
"example": 178.2,
"format": "float",
"type": "number"
},
"latitude_D": {
"description": "Latitude of point D(intersection of normal)from waypoint D to survey line",
"example": 178.2,
"format": "float",
"type": "number"
},
"latitude_E": {
"description": "Latitude of point E(intersection of normal)from waypoint E to survey line",
"example": 178.2,
"format": "float",
"type": "number"
},
"longitude_A": {
"description": "Longitude of point A(intersection of normal)from waypoint A to survey line",
"example": -10.122,
"format": "float",
"type": "number"
},
"longitude_B": {
"description": "Longitude of point B(intersection of normal)from waypoint B to survey line",
"example": -10.122,
"format": "float",
"type": "number"
},
"longitude_C": {
"description": "Longitude of point C(intersection of normal)from waypoint C to survey line",
"example": -10.122,
"format": "float",
"type": "number"
},
"longitude_D": {
"description": "Longitude of point D(intersection of normal)from waypoint D to survey line",
"example": -10.122,
"format": "float",
"type": "number"
},
"longitude_E": {
"description": "Longitude of point E(intersection of normal)from waypoint E to survey line",
"example": -10.122,
"format": "float",
"type": "number"
},
"message_type": {
"description": "Type of message",
"enum": [
"survey"
],
"example": "survey",
"type": "string"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "ecosub-2",
"type": "string"
},
"timestamp": {
"description": "Timestamp for onboard message",
"example": "2022-12-21T00:00:00Z",
"format": "date-time",
"type": "string"
},
"track_ID": {
"description": "Track number of action(s) currently executed by platform",
"example": 1,
"type": "integer"
}
},
"required": [
"latitude_A",
"longitude_A",
"latitude_B",
"longitude_B",
"platform_ID"
],
"type": "object"
},
"survey_encoded": {
"properties": {
"data": {
"description": "encoded string. E.g. Base64 encoded",
"example": "SDQke4uwyP/YQQAgAhA2AND/nu8nvQAAAAAAAAAACtejPa5HHUGkcBAAAAIAAAAQAAAAAAAAAA9P2cP166ab+9cg==",
"type": "string"
},
"file_name": {
"description": "Name of file",
"example": "ah1-0238126349247372.bin",
"type": "string"
},
"is_binary": {
"description": "true if the data field contains binary format data encoded as base64. false if the data field contains ascii content such as NMEA.",
"example": true,
"type": "boolean"
},
"message_type": {
"description": "Type of message",
"enum": [
"survey_encoded"
],
"example": "survey_encoded",
"type": "string"
},
"mime_type": {
"description": "MIME type",
"example": "application/gzip",
"type": "string"
}
},
"required": [
"data",
"is_binary"
],
"type": "object"
}
}
},
"info": {
"description": "SoAR message protocol in schemas",
"title": "SoAR Backbone Message Formats",
"version": "1.0"
},
"openapi": "3.0.2",
"paths": {}
"components": {
"schemas": {
"MESSAGE": {
"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"
],
"type": "object"
},
"acknowledgement": {
"properties": {
"approved": {
"description": "Human-in-the-loop approval.1 - Plan approved; 0 - Plan Rejected",
"type": "boolean"
},
"autonomy_engine_plan_ID": {
"description": "Mission plan ID (according to Autonomy Engine's mission plan number sent) executed by platform",
"example": 1,
"type": "integer"
},
"message_type": {
"description": "Type of message",
"enum": [
"acknowledgement"
],
"example": "acknowledgement",
"type": "string"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "reav-x-1",
"type": "string"
}
},
"required": [
"message_type",
"autonomy_engine_plan_ID",
"platform_ID",
"approved"
],
"type": "object"
},
"alert": {
"properties": {
"code": {
"description": "Alert code",
"example": 345,
"type": "integer"
},
"details": {
"description": "Detailed reason for the alert ",
"example": "Discrepancy between rudder and actuator positions : Rudder Pos=10.31\u00b0, Steering Actuator Pos=28.65\u00b0, Discrepancy=18.33\u00b0",
"type": "string"
},
"message_type": {
"description": "Type of message",
"enum": [
"alert"
],
"example": "alert",
"type": "string"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "usvdecibel",
"type": "string"
},
"platform_timestamp": {
"description": "Timestamp for onboard platform status message",
"example": "2022-12-21T00:00:00Z",
"format": "date-time",
"type": "string"
},
"severity": {
"description": "Severity level of alert",
"enum": [
"Emergency",
"Alarm",
"Warning",
"Caution"
],
"example": "Alarm",
"type": "string"
},
"subsystem": {
"description": "System that generated the alert",
"example": "Onboard Fault Monitor",
"type": "string"
},
"summary": {
"description": "High level description of the alert",
"example": "Steering Damage - Port Side",
"type": "string"
}
},
"required": [
"message_type",
"platform_ID",
"code",
"severity"
],
"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"
},
"mission_plan": {
"properties": {
"autonomy_engine_plan_ID": {
"description": "Unique identifier for this plangenerated by the Autonomy Engine",
"example": 3,
"type": "integer"
},
"emergency": {
"default": false,
"description": "To indicate if this is an emergency. true = emergency and false = no emergency",
"example": false,
"type": "boolean"
},
"message_type": {
"description": "Type of message",
"enum": [
"mission_plan"
],
"example": "mission_plan",
"type": "string"
},
"plan": {
"items": {
"properties": {
"action": {
"description": "Autonomy Engine's action from `move`, `payload`, `dive`, `send_hits`, `scanline`, `scanpoint`.",
"enum": [
"move",
"payload",
"dive",
"send_hits",
"scanline",
"scanpoint",
"go_home",
"surface_now",
"stop_mission",
"abort_now"
],
"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"
},
"start_point_latitude": {
"description": "Start point, y-coordinate",
"example": 50.37072283932642,
"format": "float",
"type": "number"
},
"start_point_longitude": {
"description": "Start point, x-coordinate",
"example": -4.187143188645706,
"format": "float",
"type": "number"
},
"target_waypoint_latitude": {
"description": "Target waypoint, y-coordinate",
"example": 50.37072283932642,
"format": "float",
"type": "number"
},
"target_waypoint_longitude": {
"description": "Target waypoint, x-coordinate",
"example": -4.187143188645706,
"format": "float",
"type": "number"
},
"timeout": {
"description": "Timeout set to perform action",
"example": 1800.0,
"format": "float",
"type": "number"
}
},
"required": [
"target_waypoint_latitude",
"target_waypoint_longitude"
],
"type": "object"
},
"type": "array"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "reav-x-1",
"type": "string"
}
},
"required": [
"message_type",
"autonomy_engine_plan_ID",
"platform_ID",
"plan"
],
"type": "object"
},
"mission_plan_encoded": {
"properties": {
"data": {
"description": "encoded string. E.g. Base64 encoded",
"example": "SDQke4uwyP/YQQAgAhA2AND/nu8nvQAAAAAAAAAACtejPa5HHUGkcBAAAAIAAAAQAAAAAAAAAA9P2cP166ab+9cg==",
"type": "string"
},
"file_name": {
"description": "Name of file",
"example": "ah1-0238126349247372.bin",
"type": "string"
},
"is_binary": {
"description": "true if the data field contains binary format data encoded as base64. false if the data field contains ascii content such as NMEA.",
"example": true,
"type": "boolean"
},
"message_type": {
"description": "Type of message",
"enum": [
"mission_plan_encoded"
],
"example": "mission_plan_encoded",
"type": "string"
},
"mime_type": {
"description": "MIME type",
"example": "application/gzip",
"type": "string"
}
},
"required": [
"data",
"is_binary"
],
"type": "object"
},
"observation": {
"properties": {
"additional_data": {
"description": "Placeholder field for any additional data",
"example": {
"sensor_payload": false
}
},
"message_type": {
"description": "Type of message",
"enum": [
"observation"
],
"example": "observation",
"type": "string"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "reav-x-1",
"type": "string"
},
"points_of_interest": {
"description": "Points from features of interest identified by platform if any found.",
"items": {
"properties": {
"latitude": {
"description": "Identified y-coordinate of point of interest",
"example": 178.2,
"format": "float",
"type": "number"
},
"longitude": {
"description": "Identified x-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"
},
"observation_encoded": {
"properties": {
"data": {
"description": "encoded string. E.g. Base64 encoded",
"example": "SDQke4uwyP/YQQAgAhA2AND/nu8nvQAAAAAAAAAACtejPa5HHUGkcBAAAAIAAAAQAAAAAAAAAA9P2cP166ab+9cg==",
"type": "string"
},
"file_name": {
"description": "Name of file",
"example": "ah1-0238126349247372.bin",
"type": "string"
},
"is_binary": {
"description": "true if the data field contains binary format data encoded as base64. false if the data field contains ascii content such as NMEA.",
"example": true,
"type": "boolean"
},
"message_type": {
"description": "Type of message",
"enum": [
"observation_encoded"
],
"example": "observation_encoded",
"type": "string"
},
"mime_type": {
"description": "MIME type",
"example": "application/gzip",
"type": "string"
}
},
"required": [
"data",
"is_binary"
],
"type": "object"
},
"payload": {
"discriminator": {
"mapping": {
"acknowledgement": "#/components/schemas/acknowledgement",
"alert": "#/components/schemas/alert",
"mission_plan": "#/components/schemas/mission_plan",
"mission_plan_encoded": "#/components/schemas/mission_plan_encoded",
"observation": "#/components/schemas/observation",
"observation_encoded": "#/components/schemas/observation_encoded",
"planning_configuration": "#/components/schemas/planning_configuration",
"platform_status": "#/components/schemas/platform_status",
"platform_status_encoded": "#/components/schemas/platform_status_encoded",
"survey": "#/components/schemas/survey",
"survey_encoded": "#/components/schemas/survey_encoded"
},
"propertyName": "message_type"
},
"oneOf": [
{
"$ref": "#/components/schemas/alert"
},
{
"$ref": "#/components/schemas/acknowledgement"
},
{
"$ref": "#/components/schemas/mission_plan"
},
{
"$ref": "#/components/schemas/mission_plan_encoded"
},
{
"$ref": "#/components/schemas/observation"
},
{
"$ref": "#/components/schemas/observation_encoded"
},
{
"$ref": "#/components/schemas/planning_configuration"
},
{
"$ref": "#/components/schemas/platform_status"
},
{
"$ref": "#/components/schemas/platform_status_encoded"
},
{
"$ref": "#/components/schemas/survey"
},
{
"$ref": "#/components/schemas/survey_encoded"
}
]
},
"planning_configuration": {
"properties": {
"exclusion_zones": {
"description": "Exclusion zones for all platforms",
"items": {
"description": "Using GEOJSON, exact 4-point region (rectangle shaped - 5 points)",
"properties": {
"geometry_coordinates": {
"example": [
[
[
-4.1777839187560915,
50.34173405662855
],
[
-4.1777839187560915,
50.33820949229701
],
[
-4.143667777943875,
50.33820949229701
],
[
-4.143667777943875,
50.34173405662855
],
[
-4.1777839187560915,
50.34173405662855
]
]
],
"type": "array"
}
},
"type": "object"
},
"type": "array"
},
"message_type": {
"description": "Type of message",
"enum": [
"planning_configuration"
],
"example": "planning_configuration",
"type": "string"
},
"planning_config_ID": {
"description": "Unique identifier tagged to version of this configuration plan",
"example": 3,
"type": "integer"
},
"region_of_interest": {
"description": "Region of interest for the entire operation",
"items": {
"description": "Using GEOJSON, exact 4-point region (rectangle shaped - 5 points)",
"properties": {
"geometry_coordinates": {
"example": [
[
[
-4.1777839187560915,
50.34173405662855
],
[
-4.1777839187560915,
50.33820949229701
],
[
-4.143667777943875,
50.33820949229701
],
[
-4.143667777943875,
50.34173405662855
],
[
-4.1777839187560915,
50.34173405662855
]
]
],
"type": "array"
}
},
"type": "object"
},
"type": "array"
},
"squads": {
"items": {
"properties": {
"no_of_platforms": {
"description": "Number of platforms",
"example": 3,
"type": "integer"
},
"platforms": {
"description": "Squad consists of these platforms",
"items": {
"properties": {
"active": {
"description": "If platform is active = True, and inactive = False",
"example": true,
"type": "boolean"
},
"additional_data": {
"description": "Any addition fields/data to be added here",
"example": {
"new_sensor_a": "test_sensor",
"range": 10.0
},
"type": "object"
},
"beacon_ID": {
"description": "Unique identifier (number) for the beacon associated to this platform",
"example": 2407,
"type": "number"
},
"emergency": {
"properties": {
"safe_command": {
"description": "Command/Action that is native to respective partner's platform/C2",
"enum": [
"go_home",
"abort_now",
"stop_now",
"surface_now"
],
"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.0,
"format": "float",
"type": "number"
},
"target_waypoint_latitude": {
"description": "Y-coordinate safe place for respective platform",
"example": 50.365,
"format": "float",
"type": "number"
},
"target_waypoint_longitude": {
"description": "X-coordinate safe place for respective platform",
"example": -7.432,
"format": "float",
"type": "number"
}
},
"required": [
"target_waypoint_latitude",
"target_waypoint_longitude",
"target_depth"
],
"type": "object"
},
"endurance_relative_to_water_speed": {
"properties": {
"avg_battery_rating": {
"description": "Battery endurance rating during standard operational speed usage (m/s)",
"example": 1.9,
"format": "float",
"type": "number"
},
"max_battery_rating": {
"description": "Battery endurance rating during maximum speed usage (m/s)",
"example": 1.23,
"format": "float",
"type": "number"
},
"min_battery_rating": {
"description": "Battery endurance rating during maximum speed usage (m/s)",
"example": 3.32,
"format": "float",
"type": "number"
}
},
"type": "object"
},
"max_velocity": {
"description": "Maximum velocity set for platform",
"example": 0.9,
"format": "float",
"type": "number"
},
"min_altitude": {
"description": "Minimum altitude set for platform",
"example": 15.2,
"format": "float",
"type": "number"
},
"min_velocity": {
"description": "Minimum velocity set for platform",
"example": 0.1,
"format": "float",
"type": "number"
},
"model": {
"example": "reav",
"type": "string"
},
"operator": {
"description": "Operator of platform",
"example": "noc",
"type": "string"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "reav-x-1",
"type": "string"
},
"scan_sensor": {
"properties": {
"angle": {
"description": "Angle of range of swath width (in degrees)",
"example": 140.0,
"format": "float",
"type": "number"
},
"frequency": {
"description": "Frequency of scanning sensor (in kHz)",
"example": 700.0,
"format": "float",
"type": "number"
},
"sensor_type": {
"description": "Unique identifier for this platform",
"enum": [
"SIDESCAN",
"MBES"
],
"example": "MBES",
"type": "string"
},
"swath_width": {
"description": "Function of `target_altitude` for the platform's swath width (in metres)",
"example": 38.0,
"format": "float",
"type": "number"
},
"warmup_time": {
"description": "Warmup time (seconds) for sensor to start up.",
"example": 180.0,
"format": "float",
"type": "number"
}
},
"type": "object"
},
"target_altitude": {
"description": "Target altitude set for platform. This affects swath width",
"example": 15.0,
"format": "float",
"type": "number"
},
"turning_radius": {
"description": "Turning radius of platform (in metres)",
"example": 1.0,
"format": "float",
"type": "number"
}
},
"required": [
"operator",
"platform_ID",
"active",
"model"
],
"type": "object"
},
"type": "array"
},
"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"
}
},
"required": [
"squad_ID",
"no_of_platforms",
"platforms",
"squad_mission_type"
],
"type": "object"
},
"type": "array"
}
},
"required": [
"message_type",
"planning_config_ID",
"squads",
"exclusion_zones",
"region_of_interest"
],
"type": "object"
},
"platform_status": {
"properties": {
"altitude": {
"description": "Target altitude in metres",
"example": 20.0,
"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_output": {
"description": "Battery output in kW",
"example": 80.2,
"format": "float",
"type": "number"
},
"battery_remaining_capacity": {
"description": "Battery remaining % provided by respective C2",
"example": 80.2,
"format": "float",
"type": "number"
},
"depth": {
"default": 0.0,
"description": "Target depth in metres",
"example": 50.0,
"format": "float",
"type": "number"
},
"endurance": {
"description": "Estimate of hours of operation remaining based on present output or performance",
"example": 7.4,
"format": "float",
"type": "number"
},
"fuel_remaining_capacity": {
"description": "Percentage remaining capacity",
"example": 80.2,
"format": "float",
"type": "number"
},
"fuel_volume": {
"description": "Litres of liquid fuel",
"example": 12.5,
"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 where 0 is OK, 1 is platform has an ERROR",
"example": false,
"type": "boolean"
},
"latitude": {
"description": "Latitude (Y-coordinate) in decimal degrees.",
"example": 178.2,
"format": "float",
"type": "number"
},
"localisation_east_error": {
"description": "Difference in EAST between deadreckoningand USBL update.",
"example": 0.000129,
"format": "float",
"type": "number"
},
"localisation_north_error": {
"description": "Difference in NORTH between deadreckoning and USBL update.",
"example": 0.000129,
"format": "float",
"type": "number"
},
"longitude": {
"description": "Longitude (X-coordinate) in decimal degrees.",
"example": -10.122,
"format": "float",
"type": "number"
},
"message_type": {
"description": "Type of message",
"enum": [
"platform_status"
],
"example": "platform_status",
"type": "string"
},
"mission_plan_ID": {
"description": "Mission plan ID according to platform-C2 system",
"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": "Unique identifier for this platform",
"example": "reav-x-1",
"type": "string"
},
"platform_state": {
"description": "Current state executed by platform. E.g. STOP, IDLE, ABORT.",
"example": "ABORT",
"type": "string"
},
"platform_timestamp": {
"description": "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": "object"
},
"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"
}
},
"type": "object"
},
"speed_over_ground": {
"description": "Speed over ground",
"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": "Thrust applied",
"example": 124.3,
"format": "float",
"type": "number"
},
"transmission_mode": {
"description": "Mode in which status message was transmitted when on the surface (e.g. iridium/wifi) or underwater (e.g. 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": "Water current magnitude and direction",
"example": "124.3NE",
"type": "string"
}
},
"required": [
"message_type",
"platform_ID",
"status_source",
"platform_timestamp",
"latitude",
"longitude"
],
"type": "object"
},
"platform_status_encoded": {
"properties": {
"data": {
"description": "encoded string. E.g. Base64 encoded",
"example": "SDQke4uwyP/YQQAgAhA2AND/nu8nvQAAAAAAAAAACtejPa5HHUGkcBAAAAIAAAAQAAAAAAAAAA9P2cP166ab+9cg==",
"type": "string"
},
"file_name": {
"description": "Name of file",
"example": "ah1-0238126349247372.bin",
"type": "string"
},
"is_binary": {
"description": "true if the data field contains binary format data encoded as base64. false if the data field contains ascii content such as NMEA.",
"example": true,
"type": "boolean"
},
"message_type": {
"description": "Type of message",
"enum": [
"platform_status_encoded"
],
"example": "platform_status_encoded",
"type": "string"
},
"mime_type": {
"description": "MIME type",
"example": "application/gzip",
"type": "string"
}
},
"required": [
"data",
"is_binary"
],
"type": "object"
},
"survey": {
"properties": {
"latitude_A": {
"description": "Latitude of point A(intersection of normal)from waypoint A to survey line",
"example": 178.2,
"format": "float",
"type": "number"
},
"latitude_B": {
"description": "Latitude of point B(intersection of normal)from waypoint B to survey line",
"example": 178.2,
"format": "float",
"type": "number"
},
"latitude_C": {
"description": "Latitude of point C(intersection of normal)from waypoint C to survey line",
"example": 178.2,
"format": "float",
"type": "number"
},
"latitude_D": {
"description": "Latitude of point D(intersection of normal)from waypoint D to survey line",
"example": 178.2,
"format": "float",
"type": "number"
},
"latitude_E": {
"description": "Latitude of point E(intersection of normal)from waypoint E to survey line",
"example": 178.2,
"format": "float",
"type": "number"
},
"longitude_A": {
"description": "Longitude of point A(intersection of normal)from waypoint A to survey line",
"example": -10.122,
"format": "float",
"type": "number"
},
"longitude_B": {
"description": "Longitude of point B(intersection of normal)from waypoint B to survey line",
"example": -10.122,
"format": "float",
"type": "number"
},
"longitude_C": {
"description": "Longitude of point C(intersection of normal)from waypoint C to survey line",
"example": -10.122,
"format": "float",
"type": "number"
},
"longitude_D": {
"description": "Longitude of point D(intersection of normal)from waypoint D to survey line",
"example": -10.122,
"format": "float",
"type": "number"
},
"longitude_E": {
"description": "Longitude of point E(intersection of normal)from waypoint E to survey line",
"example": -10.122,
"format": "float",
"type": "number"
},
"message_type": {
"description": "Type of message",
"enum": [
"survey"
],
"example": "survey",
"type": "string"
},
"platform_ID": {
"description": "Unique identifier for this platform",
"example": "ecosub-2",
"type": "string"
},
"timestamp": {
"description": "Timestamp for onboard message",
"example": "2022-12-21T00:00:00Z",
"format": "date-time",
"type": "string"
},
"track_ID": {
"description": "Track number of action(s) currently executed by platform",
"example": 1,
"type": "integer"
}
},
"required": [
"latitude_A",
"longitude_A",
"latitude_B",
"longitude_B",
"platform_ID"
],
"type": "object"
},
"survey_encoded": {
"properties": {
"data": {
"description": "encoded string. E.g. Base64 encoded",
"example": "SDQke4uwyP/YQQAgAhA2AND/nu8nvQAAAAAAAAAACtejPa5HHUGkcBAAAAIAAAAQAAAAAAAAAA9P2cP166ab+9cg==",
"type": "string"
},
"file_name": {
"description": "Name of file",
"example": "ah1-0238126349247372.bin",
"type": "string"
},
"is_binary": {
"description": "true if the data field contains binary format data encoded as base64. false if the data field contains ascii content such as NMEA.",
"example": true,
"type": "boolean"
},
"message_type": {
"description": "Type of message",
"enum": [
"survey_encoded"
],
"example": "survey_encoded",
"type": "string"
},
"mime_type": {
"description": "MIME type",
"example": "application/gzip",
"type": "string"
}
},
"required": [
"data",
"is_binary"
],
"type": "object"
}
}
},
"info":{
"description":"SoAR message protocol in schemas",
"title":"SoAR Backbone Message Formats",
"version":"0.2"
},
"openapi": "3.0.2",
"paths": {}
}
\ No newline at end of file
......@@ -5,12 +5,28 @@ from jsonschema.validators import RefResolver
import unittest
import json
import os
from generate_schema_config import write_schema, swagger_config
SCHEMA_DIR = "project/soar/swagger.json"
MOCK_DATA_DIR = "examples/"
class SchemaTestCase(unittest.TestCase):
def load_schema(self, file_path=None):
if file_path:
schema_path = file_path
else:
schema_path = os.getenv("SCHEMA_PATH")
schema, _ = read_from_filename(schema_path)
return schema
@classmethod
def setUpClass(cls):
test_schema_path = "tests/test_swagger.json"
os.environ["SCHEMA_PATH"] = test_schema_path
write_schema(swagger_config, test_schema_path)
class SchemaError(Exception):
"""
Test config specs of swagger.json for projects
......@@ -19,26 +35,37 @@ class SchemaError(Exception):
def __init__(self, exception_type, message):
self.type = exception_type
self.message = message
super().__init__(self.message)
super().__init__(message)
class TestSpecs(unittest.TestCase):
class TestCompiledSoarSpec(SchemaTestCase):
"""
Test the saved version of the compiled schema has been updated
"""
def test_compiled_spec_matches_definitions(self):
print("TEST: definitions match project/soar/swagger.json")
derived_schema = self.load_schema()
saved_schema = self.load_schema("project/soar/swagger.json")
self.assertEqual(saved_schema, derived_schema)
class TestSpecs(SchemaTestCase):
def test_swagger_specs(self):
"""
Test specs (swagger.json generated from generate_schema_config.py)
"""
schema, spec_url = read_from_filename("tests/fixtures/swagger.json")
print("TEST: compiled schema matches openapi v3 spec")
schema = self.load_schema()
self.assertIsNone(openapi_v30_spec_validator.validate(schema))
class TestAllMessageExamples(unittest.TestCase):
class TestAllMessageExamples(SchemaTestCase):
def test_schema_specs(self):
"""
Test specs (swagger.json generated from generate_schema_config.py)
"""
schema_ref = open(SCHEMA_DIR)
schema = json.load(schema_ref)
schema_ref.close()
schema = self.load_schema()
partner_dir_list = os.listdir(MOCK_DATA_DIR)
......@@ -70,8 +97,6 @@ class TestAllMessageExamples(unittest.TestCase):
f.close()
print("Done.")
schema_ref.close()
if __name__ == "__main__":
unittest.main()