diff --git a/docs/sonar-3d/sonar-3d-15-api-swagger/swagger.json b/docs/sonar-3d/sonar-3d-15-api-swagger/swagger.json new file mode 100644 index 0000000..65cd9bc --- /dev/null +++ b/docs/sonar-3d/sonar-3d-15-api-swagger/swagger.json @@ -0,0 +1,390 @@ +{ + "swagger": "2.0", + "info": { + "contact": {} + }, + "paths": { + "/api/v1/integration/about": { + "get": { + "description": "Get system version", + "tags": [ + "about", + "integrationAPI" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/integrationapi.GinSystemVersion" + } + } + } + } + }, + "/api/v1/integration/acoustics/enabled": { + "get": { + "description": "Get whether acoustics is enabled or disabled", + "tags": [ + "acoustics", + "integrationAPI" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "boolean" + } + }, + "204": { + "description": "No Content" + } + } + }, + "post": { + "description": "Enable/disable acoustic imaging", + "tags": [ + "acoustics", + "integrationAPI" + ], + "parameters": [ + { + "description": " ", + "name": "request", + "in": "body", + "required": true, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request" + }, + "408": { + "description": "Request Timeout" + }, + "409": { + "description": "Conflict" + } + } + } + }, + "/api/v1/integration/acoustics/range": { + "get": { + "description": "Get range", + "tags": [ + "acoustics", + "integrationAPI" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/integrationapi.RangeResponse" + } + } + } + }, + "post": { + "description": "Set range", + "tags": [ + "acoustics", + "integrationAPI" + ], + "parameters": [ + { + "description": " ", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/integrationapi.RangeResponse" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request" + }, + "409": { + "description": "Conflict" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/api/v1/integration/acoustics/speed_of_sound": { + "get": { + "description": "Get speed of sound", + "tags": [ + "acoustics", + "integrationAPI" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "number" + } + }, + "204": { + "description": "No Content" + } + } + }, + "post": { + "description": "Set speed of sound", + "tags": [ + "acoustics", + "integrationAPI" + ], + "parameters": [ + { + "description": " ", + "name": "request", + "in": "body", + "required": true, + "schema": { + "type": "number", + "example": 1500 + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request" + }, + "408": { + "description": "Request Timeout" + }, + "409": { + "description": "Conflict" + } + } + } + }, + "/api/v1/integration/status": { + "get": { + "description": "Get the status of the system", + "tags": [ + "status", + "integrationAPI" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/integrationapi.GinStatusResponse" + } + } + } + } + }, + "/api/v1/integration/temperature": { + "get": { + "description": "Get the internal temperature of the Sonar in degrees Celsius", + "tags": [ + "status", + "integrationAPI" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "number" + } + } + } + } + }, + "/api/v1/integration/udp": { + "get": { + "description": "Get the current UDP configuration for how the Sonar outputs data.", + "tags": [ + "integrationAPI" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/integrationapi.GinHandleUdpConfigPayload" + } + }, + "500": { + "description": "Internal Server Error" + } + } + }, + "post": { + "description": "Set UDP configuration for how the Sonar should output data.", + "tags": [ + "integrationAPI" + ], + "parameters": [ + { + "description": " ", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/integrationapi.GinHandleUdpConfigPayload" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request" + }, + "500": { + "description": "Internal Server Error" + } + } + } + } + }, + "definitions": { + "integrationapi.GinHandleUdpConfigPayload": { + "type": "object", + "properties": { + "mode": { + "description": "Must be \"multicast\", \"unicast\" or \"disabled\"\n\nIf mode is \"disabled\", no UDP packets will be sent\n\nIf mode is \"multicast\", UDP packets will be sent on multicast\n\nIf mode is \"unicast\", UDP packets will be sent to the destination\nIP and port", + "type": "string", + "enum": [ + "multicast", + "unicast", + "disabled" + ], + "example": "multicast" + }, + "unicast_destination_ip": { + "description": "The destination IP address if mode is \"unicast\".\nIf mode is \"unicast\", this must be a valid IP address.\nOtherwise, this must be a valid IP adddress or empty string.", + "type": "string", + "example": "192.168.1.100" + }, + "unicast_destination_port": { + "description": "The destination port if mode is \"unicast\".\nIf mode is \"unicast\", this must be a valid port.\nOtherwise, this must be a valid port or 0.", + "type": "integer", + "example": 12345 + } + } + }, + "integrationapi.GinStatusResponse": { + "type": "object", + "properties": { + "api": { + "description": "IntegrationAPI is the status of the UDP IntegrationAPI for external communication", + "allOf": [ + { + "$ref": "#/definitions/integrationapi.GinSystemStatusEntryResponse" + } + ] + }, + "calibration": { + "description": "Calibration is the status of the Sonar calibration", + "allOf": [ + { + "$ref": "#/definitions/integrationapi.GinSystemStatusEntryResponse" + } + ] + }, + "temperature": { + "description": "Temperature is the status of the Sonar temperature", + "allOf": [ + { + "$ref": "#/definitions/integrationapi.GinSystemStatusEntryResponse" + } + ] + } + } + }, + "integrationapi.GinSystemStatusEntryResponse": { + "type": "object", + "properties": { + "id": { + "description": "Unique ID for the status message", + "type": "string", + "example": "api-normal" + }, + "message": { + "description": "Message is a human readable message describing the status", + "type": "string", + "example": "Integration API is operational" + }, + "operational": { + "description": "Operational is true if the system is functional, false if it is not", + "type": "boolean", + "example": true + }, + "severity": { + "description": "Severity is the severity of the status message: info, warning, error", + "type": "string", + "example": "info" + } + } + }, + "integrationapi.GinSystemVersion": { + "type": "object", + "properties": { + "chipid": { + "type": "string", + "example": "0x12345678" + }, + "hardware_revision": { + "type": "integer", + "example": 6 + }, + "is_ready": { + "type": "boolean", + "example": true + }, + "product_id": { + "type": "integer", + "example": 21045 + }, + "product_name": { + "type": "string", + "example": "Sonar 3D-15" + }, + "variant": { + "type": "string" + }, + "version": { + "type": "string", + "example": "1.5.1 (v1.3.0-26-gedccab6.2025-07-11T06:14:03.837365)" + }, + "version_short": { + "type": "string", + "example": "1.5.1" + } + } + }, + "integrationapi.RangeResponse": { + "type": "object", + "properties": { + "max": { + "type": "number", + "example": 15 + }, + "min": { + "type": "number", + "example": 0 + } + } + } + } +} \ No newline at end of file diff --git a/docs/sonar-3d/sonar-3d-15-api.md b/docs/sonar-3d/sonar-3d-15-api.md index 972e3fd..c0b8e5f 100644 --- a/docs/sonar-3d/sonar-3d-15-api.md +++ b/docs/sonar-3d/sonar-3d-15-api.md @@ -1,7 +1,9 @@ # Integration API Sonar 3D-15 ## Introduction -The **Water Linked Sonar 3D-15** provides real-time 3D views of underwater environments using a low-bandwidth **Range Image Protocol (RIP1)**. This protocol efficiently transmits data such as 3D points or grayscale bitmaps over UDP multicast, enabling live visualization, analysis, or archival for later use. +The **Water Linked Sonar 3D-15** provides real-time 3D views of underwater environments using a low-bandwidth **Range Image Protocol (RIP1)**. This protocol efficiently transmits data such as 3D points or grayscale bitmaps over UDP, enabling live visualization, analysis, or archival for later use. + +The Sonar 3D-15 also exposes a HTTP API for configuration and inspection of system state. A Python example implementation of the Sonar API is available on [github](https://github.com/waterlinked/Sonar-3D-15-api-example). @@ -25,12 +27,14 @@ RIP1 is a compact format for range and bitmap images, designed for <10 Mbit ba --- -## Network -By default, the Sonar 3D-15 uses **UDP Multicast** (`224.0.0.96:4747`), so any device on the local network can receive data without knowing the sonar’s IP. +### Network +By default, the Sonar 3D-15 uses **UDP Multicast** (`224.0.0.96:4747`), so any device on the local network can receive RIP1 packets without knowing the sonar’s IP. + +The Sonar can also be configured for UDP unicast, or to disable sending of UDP packets. See HTTP API. --- -## Image Sizes and Update Rates +### Image Sizes and Update Rates | **Mode** | **Resolution (W×H)** | **FOV (H×V)** | **Rate** | |---------------|----------------------|--------------|---------| | Low Frequency | 256 × 64 | 90° × 40° | 5 Hz | @@ -38,21 +42,21 @@ By default, the Sonar 3D-15 uses **UDP Multicast** (`224.0.0.96:4747`), so any d --- -## Message Types +### Message Types RIP1 supports several Protobuf-encoded messages, including: -### `BitmapImageGreyscale8` +#### `BitmapImageGreyscale8` - 8-bit grayscale; each pixel = signal strength or shaded depth. - `type` enum differentiates **signal strength** vs. **shaded**. -### `RangeImage` +#### `RangeImage` - Each pixel represents distance (radius) to the strongest reflection. - `0` = no valid data. - `radius = pixelValue * imagePixelScale`. --- -## Coordinate and Image Conventions +### Coordinate and Image Conventions **Axes** (right-handed): - **x**: forward @@ -91,7 +95,7 @@ z = -radius * sin(pitch); // z is downward --- -## `.proto` File (Excerpt) +### `.proto` File (Excerpt) ```protobuf // Water Linked Sonar 3D-15 protocol syntax = "proto3"; @@ -173,7 +177,12 @@ message RangeImage { - Decoders should ignore unrecognized messages. - Major breaking changes will involve a new protocol identifier. +Refer to the full protocol specification and `.proto` file shown above for more information. + +## HTTP API + +The Sonar 3D-15 exposes a HTTP API for configuration and inspection of system state. The HTTP API is exposed on port 80 and uses paths rooted at `/api/v1/integration/`. JSON is used for request and response bodies. The HTTP API is documented with a [swagger.json](./sonar-3d-15-api-swagger/swagger.json) file. This file can be opened in a compatible viewer such as [this one](https://petstore.swagger.io/?url=https://docs.waterlinked.com/sonar-3d/sonar-3d-15-api/sonar-3d-15-api-swagger/swagger.json). Example code using the HTTP API exists on [github](https://github.com/waterlinked/Sonar-3D-15-api-example). + --- **Thank you for using the Water Linked Sonar 3D-15!** -Refer to the full protocol specification and `.proto` file shown above for more information. diff --git a/mkdocs.yml b/mkdocs.yml index 7e17494..258957b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -40,12 +40,12 @@ nav: - Wiring: sonar-3d/sonar-3d-15-wiring.md - LED: sonar-3d/sonar-3d-15-led.md - GUI: sonar-3d/sonar-3d-15-gui.md + - API: sonar-3d/sonar-3d-15-api.md - Integration: - DeepTrekker Pivot: sonar-3d/sonar-3d-15-deep-trekker-rov.md - Blueye X3: sonar-3d/sonar-3d-15-blueye-rov.md - BlueROV2: sonar-3d/sonar-3d-15-bluerov-integration.md - Chasing M2 PRO MAX: sonar-3d/sonar-3d-15-chasing-rov.md - - API: sonar-3d/sonar-3d-15-api.md - Software Updates: sonar-3d/sonar-3d-15-software-update.md - Settings: sonar-3d/sonar-3d-15-config.md - Networking: sonar-3d/sonar-3d-15-networking.md