diff --git a/docs/dvl/dvl-a50_a125-changelog.md b/docs/dvl/dvl-a50_a125-changelog.md index e20e4beb..e97c5e76 100644 --- a/docs/dvl/dvl-a50_a125-changelog.md +++ b/docs/dvl/dvl-a50_a125-changelog.md @@ -4,6 +4,15 @@ This page applies to DVL A50 and DVL A125. See [Software updates](./sw-update.md) for more information on software updates. +## 2.7.2 (2026-06) + +- Added an integration API for NTP configuration and status to provide tighter time synchronisation + - Users with a NTP configuration from prior versions must apply this configuration again +- Improve NTP status feedback in GUI +- Add get_version_info TCP JSON command +- Fix issue where velocity updates for water tracking mode are not included in 'WL - Serial V2' +- Move changelog to docs.waterlinked.com + ## 2.7.1 (2026-04) - Add water tracking support for DVL A125 diff --git a/docs/dvl/dvl-json-protocol.md b/docs/dvl/dvl-json-protocol.md index 6082f433..c649bfa5 100644 --- a/docs/dvl/dvl-json-protocol.md +++ b/docs/dvl/dvl-json-protocol.md @@ -13,7 +13,7 @@ The DVL TCP JSON API sends JSON messages over TCP on port 16171. This page appli ## Version -This document describes TCP JSON API versions `json_v3.1` and `json_v3.2` (major.minor): +This document describes TCP JSON API version `json_v3.3` (major.minor): - MAJOR version increments represent incompatible API changes - MINOR version increments represent additional backwards-compatible functionality @@ -22,6 +22,7 @@ This document describes TCP JSON API versions `json_v3.1` and `json_v3.2` (major | Software release | Ethernet protocol version | Main protocol improvements | | -- | -- | -- | +| 2.7.2 | json_v3.3 | Add TCP JSON time API | | 2.7.1 | json_v3.2 | Add water tracking mode and tracking mode field in velocity reports | | 2.6.1 | json_v3.1 | Serial baud rate configurable. Add PD4 format support in serial 'wcp' command. Some serial protocol names [changed](dvl-serial-protocol.md#change-serial-output-protocol-wcp). | | 2.5.2 | json_v3.1 | Add PD4 format support (experimental) @@ -140,7 +141,7 @@ Example of TCP report (indented for legibility) "velocity_valid": true, "status": 0, "tracking_mode": "bottom", - "format": "json_v3.2", + "format": "json_v3.3", "type": "velocity", "time_of_validity": 1638191471563017, "time_of_transmission": 1638191471752336 @@ -182,7 +183,7 @@ Example of a dead reckoning report. "yaw": 0.6173566579818726, "type": "position_local", "status": 0, - "format": "json_v3.1" + "format": "json_v3.3" } ``` @@ -203,7 +204,7 @@ If the request is successfully received the response will have 'success' set to "success": true, "error_message": "", "result": null, - "format": "json_v3.1", + "format": "json_v3.3", "type": "response" } ``` @@ -224,7 +225,7 @@ The response will be as follows if the calibration is successful. If unsuccessfu "success": true, "error_message": "", "result": null, - "format": "json_v3.1", + "format": "json_v3.3", "type": "response" } ``` @@ -247,7 +248,221 @@ The response will be as follows if the command is accepted. If the queue is full "success": true, "error_message": "", "result": null, - "format": "json_v3.1", + "format": "json_v3.3", + "type": "response" +} +``` + +### Time + +#### Setting NTP configuration + +Set [NTP configuration](./time.md#ntp-server-address-configuration-auto-or-custom) by issuing the `set_time_ntp` command with a `ntp_address` parameter. Set `ntp_address` either to the address of a NTP server, or as "auto". + +``` +{ + "command": "set_time_ntp", + "parameters": { + "ntp_address": "192.168.0.10" + } +} +``` + +A successful response looks like this: + +``` +{ + "response_to": "set_time_ntp", + "success": true, + "error_message": "", + "result": null, + "format": "json_v3.3", + "type": "response" +} +``` + +#### Getting NTP configuration + +Get [NTP configuration](./time.md#ntp-server-address-configuration-auto-or-custom) by issuing the `get_time_ntp` command. + +``` +{ + "command": "get_time_ntp" +} +``` + +A successful response looks like this: + +``` +{ + "response_to": "get_time_ntp", + "success": true, + "error_message": "", + "result": { + "ntp_address": "auto" + }, + "format": "json_v3.3", + "type": "response" +} +``` + +#### Setting manual time + +Set time manually by issuing the `set_time_manual` command with the `now` parameter as a RFC3339 timestamp string. + +For more information see [Setting manual time](./time.md#setting-manual-time). + +``` +{ + "command": "set_time_manual", + "parameters": { + "now": "2026-04-20T09:04:13Z" + } +} +``` + +A successful response looks like this: + +``` +{ + "response_to": "set_time_manual", + "success": true, + "error_message": "", + "result": null, + "format": "json_v3.3", + "type": "response" +} +``` + +In the event the DVL is already synchronized via NTP, the response will look like this: + +``` +{ + "response_to": "set_time_manual", + "success": false, + "error_message": "Manual time not allowed when NTP is synchronized", + "result": null, + "format": "json_v3.3", + "type": "response" +} +``` + +#### Getting time status + +Get [time status](./time.md#time-status) by issuing the `get_time_status` command. + +``` +{ + "command": "get_time_status" +} +``` + +The response contains the following fields: + +|Field|Description| +|-|-| +| `system_time` | system time in RFC3339 | +| `ntp_synced` | true if synchronized to NTP source, false otherwise | +| `ntp_synced_to` |address the sonar is synchronized to if NTP is synchronized, "" otherwise | +| `ntp_seconds_since_last_sync` | seconds since last NTP sync, or null if not synchronized | + +Here is an example response where the DVL is not synchornized with NTP: + +``` +{ + "response_to": "get_time_status", + "success": true, + "error_message": "", + "result": { + "system_time": "2026-04-20T08:48:25Z", + "ntp_synced": false, + "ntp_synced_to": "", + "ntp_seconds_since_last_sync": null + }, + "format": "json_v3.3", + "type": "response" +} +``` + +Here is an example response where the DVL has achieved sync with NTP: + +``` +{ + "response_to": "get_time_status", + "success": true, + "error_message": "", + "result": { + "system_time": "2026-04-20T08:48:25Z", + "ntp_synced": true, + "ntp_synced_to": "192.168.0.10", + "ntp_seconds_since_last_sync": 5 + }, + "format": "json_v3.3", + "type": "response" +} +``` + +#### Forcing NTP sync + +A [forced NTP sync](./time.md#ntp-force-sync) can be triggered by issuing the `force_sync_ntp` command with the `timeout_seconds` as an integer timeout in seconds. + +``` +{ + "command": "force_sync_ntp", + "parameters": { + "timeout_seconds": 10 + } +} +``` + +This will trigger a forced NTP sync in the DVL. The DVL will wait up to `timeout_seconds` for sync to be achieved, finally responding with the following fields: + +|Field|Description| +|-|-| +|`success`|true if NTP sync was achieved within timeout, false otherwise. Important: callers that want to achieve sync with a specific address should check the returned status| +|`message`|human-readable message| +|`status`|[time status response body](#getting-time-status)| + +Here is an example response where the DVL achieved NTP sync: + +``` +{ + "response_to": "force_sync_ntp", + "success": true, + "error_message": "", + "result": { + "success": true, + "message": "NTP force-sync successful", + "status": { + "system_time": "2026-04-20T09:04:13Z", + "ntp_synced": true, + "ntp_synced_to": "192.168.0.10", + "ntp_seconds_since_last_sync": 0 + } + }, + "format": "json_v3.3", + "type": "response" +} +``` + +Here is an example response where the DVL did not achieve NTP sync: + +``` +{ + "response_to": "force_sync_ntp", + "success": true, + "error_message": "", + "result": { + "success": false, + "message": "NTP force-sync not successful within timeout", + "status": { + "system_time": "2026-04-20T09:04:13Z", + "ntp_synced": false, + "ntp_synced_to": "", + "ntp_seconds_since_last_sync": null + } + }, + "format": "json_v3.3", "type": "response" } ``` @@ -289,7 +504,7 @@ If the configuration is successfully fetched, the response will be in the follow "range_mode":"auto", "periodic_cycling_enabled":true }, - "format":"json_v3.1", + "format":"json_v3.3", "type":"response" } ``` @@ -311,7 +526,7 @@ If the parameters are successfully set, the response will be in the following fo "success": true, "error_message": "", "result" :null, - "format": "json_v3.1", + "format": "json_v3.3", "type": "response" } ``` diff --git a/docs/dvl/dvl-serial-protocol.md b/docs/dvl/dvl-serial-protocol.md index 6aca5826..b2f9922c 100644 --- a/docs/dvl/dvl-serial-protocol.md +++ b/docs/dvl/dvl-serial-protocol.md @@ -23,6 +23,7 @@ This document describes serial protocol versions `2.6.x` and `2.7.x` (major.mino | Software release | Serial protocol version | Main protocol improvements | | -- | -- | -- | +| 2.7.2 | 2.8.0 | Add serial time API | | 2.7.1 | 2.7.0 | Add water tracking mode and tracking mode field in velocity reports | | 2.6.1 | 2.6.0 | Serial baud rate configurable. Add PD4 format support in serial 'wcp' command. Some serial protocol names [changed](#change-serial-output-protocol-wcp). | | 2.5.2 | 2.5.0 | Add PD4 format support (experimental) @@ -73,6 +74,11 @@ The commands in the table are shown without the checksum and without the mandato | `wcx` | Trigger ping | `wra` | Successfully queued a ping | | `wcg` | Calibrate gyro | `wra` | Successfully calibrated gyro | | `wcp` | Change serial output protocol | `wra` | Successfully changed output protocol | +| `wcn,`*[ntp_address]* | Set [NTP server configuration](./time.md#ntp-server-address-configuration-auto-or-custom). `ntp_address` is an address, or "auto" | `wra` | Successfully set NTP server | +| `wcN` | Get [NTP address configuration](./time.md#ntp-server-address-configuration-auto-or-custom) | `wrN,`*[ntp_address]* | Configured NTP server address, or "auto" | +| `wcm,`*[timestamp]* | Set [manual time](./time.md#setting-manual-time), where `timestamp` is UTC epoch time in microseconds | `wra` | Successfully set manual time | +| `wct` | Get [time status](./time.md#time-status) | `wrs,`*[details below]* | Time status | +| `wcT,`*[timeout_seconds]* | [Force NTP sync](./time.md#ntp-force-sync) within given timeout | `wrT,`*[success]* | Where `success` is y if sync was achieved within timeout, and n otherwise | | | | `wrz,`*[details below]* | Velocities calculated | | | | `wrs,`*[details below]* | Velocities calculated during water tracking | | | | `wru,`*[details below]* | Transducer information | @@ -83,7 +89,25 @@ The commands in the table are shown without the checksum and without the mandato | | | `wr!` | Malformed request: packet does not match the given checksum | | | | `wrn` | Not acknowledged (nack): an error occurred when handling the packet | +### Time status (wrs) +[Time status](./time.md#time-status) is returned by the command `wct`. + +The report has the following format: `wrs,`*[system_time],[ntp_synced],[ntp_synced_to],[ntp_seconds_since_last_sync]* + +| Variable | Description | +|----------|-------------| +| system_time | UTC epoch time in microseconds | +| ntp_synced | `y` if synchronized, `n` if not | +| ntp_synced_to | NTP server address the DVL is synced to | +| ntp_seconds_since_last_sync | Seconds since last sync if synced | + + +Examples: +``` +wrs,1776409079,0,, +wrs,1776409079,1,192.168.0.10,45 +``` ### Velocity report (wrz) diff --git a/docs/dvl/time.md b/docs/dvl/time.md new file mode 100644 index 00000000..577e0c9d --- /dev/null +++ b/docs/dvl/time.md @@ -0,0 +1,77 @@ +# Time + +The DVL continously attempts to synchronize time using the Network Time Protocol (NTP). +When not synchronized with NTP, it is also possible to set time manually. + +## Supported models + +|Model|Support| +|-|-| +|A50|Supported, starting with software release 2.7.2| +|A100|Planned. Not supported in 3.2.0| +|A125|Supported, starting with software release 2.7.2| +|A250|Planned. Not supported in 3.2.0| + +See [Software updates](sw-update.md) for update instructions. + +## Importance of setting time + +The DVL does know the current time when booting, and initial timestamps output from the DVL will be relative to some arbitrary time in the past. +It is recommended to synchronize the DVL's time before using its output. + +## NTP server address configuration: auto or custom + +The NTP server address can be configured as either "auto" or a specific server address. +When NTP server address is configured as "auto", the DVL will attempt to reach a default pool of internet time servers. +The configuration is persisted across reboots. + +## Setting manual time + +When the DVL has not yet achieved NTP sync it is possible to set time manually. +This is useful in deployment scenarios without a reachable NTP server, or as a fallback until an NTP server becomes available. +A manually set time will be disregarded if the DVL later achieves NTP sync. + +## Time status + +The DVL separates between NTP configuration and time status. +Time status consists of the following fields: + +|Field|Description| +|-|-| +| `system_time` | system time | +| `ntp_synced` | true if synchronized to NTP source, false otherwise | +| `ntp_synced_to` | address the sonar is synchronized to if NTP is synchronized, "" otherwise | +| `ntp_seconds_since_last_sync` | seconds since last NTP sync if NTP is synchronized | + +## NTP Force sync + +A NTP force sync operation can be triggered which will attempt to achieve NTP sync within a specified timeout. +Upon achieving sync, or when the timeout expires, the operation will respond with the following fields: + +|Field|Description| +|-|-| +|`success`|true if NTP sync was achieved within timeout, false otherwise| +|`message`|human-readable message| +|`status`|Time status as described [here](#time-status) | + +!!! warning + `success` true means the DVL acieved NTP sync. To assert the DVL is synchronized to a specific NTP server, check the returned status. + +!!! warning + The operation can cause abrupt jumps in system time, and is not recommended for use while reading DVL output. + +## Web GUI + +On supported models there is a "System time configuration" section in the Configuration page. + +## TCP JSON API + +Time configuration is available in TCP JSON API `json_v3.3` and up for supported models: + +* [DVL A50/A125 TCP JSON time API](./dvl-json-protocol.md#time) + +## Serial API + +Time configuration is available in serial protocol `2.8.0` and up for supported models: + +* [DVL A50/A125 Serial time API](./dvl-serial-protocol.md) \ No newline at end of file diff --git a/docs/dvl/water-tracking.md b/docs/dvl/water-tracking.md index a5d19ec8..f1ae0c6d 100644 --- a/docs/dvl/water-tracking.md +++ b/docs/dvl/water-tracking.md @@ -34,7 +34,7 @@ The diagnostic page still shows spatial velocity, per-transducer velocity, and v ## TCP JSON API -Water tracking is available in TCP JSON API `json_v3.2` for supported models. Use the TCP JSON API configuration method for your model: +Water tracking is available in TCP JSON API version `json_v3.2` and up for supported models. Use the TCP JSON API configuration method for your model: * [DVL A50/A125 TCP JSON API configuration](dvl-json-protocol.md#configuration-over-json) * DVL A100/A250 TCP JSON API configuration is planned for water tracking and is not available yet. diff --git a/docs/sonar-3d/sonar-3d-15-api-swagger/swagger.json b/docs/sonar-3d/sonar-3d-15-api-swagger/swagger.json index 82ad6dcc..d43833d5 100644 --- a/docs/sonar-3d/sonar-3d-15-api-swagger/swagger.json +++ b/docs/sonar-3d/sonar-3d-15-api-swagger/swagger.json @@ -323,6 +323,146 @@ } } }, + "/api/v1/integration/time/manual": { + "post": { + "description": "Set time manually. Not allowed if already synchronized. 409 is returned if time is already synchronized.", + "tags": [ + "integrationAPI", + "time" + ], + "parameters": [ + { + "description": " ", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/integrationapi.GinManualTimeRequest" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request" + }, + "409": { + "description": "Already synchronized" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/api/v1/integration/time/ntp": { + "get": { + "description": "Get the NTP configuration", + "tags": [ + "integrationAPI", + "time" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/integrationapi.GinNTPConfigurationPayload" + } + }, + "500": { + "description": "Internal Server Error" + } + } + }, + "post": { + "description": "Set the NTP configuration. Configuration is persisted. After setting configuration the sonar will attempt to reach the configured NTP server.", + "tags": [ + "integrationAPI", + "time" + ], + "parameters": [ + { + "description": " ", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/integrationapi.GinNTPConfigurationPayload" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/api/v1/integration/time/ntp/force-sync": { + "post": { + "description": "Attempt to force NTP sync within timeout. Return whether sync was achieved, the time status, and a human-readable message. 409 is returned if another force sync request is already ongoing", + "tags": [ + "integrationAPI", + "time" + ], + "parameters": [ + { + "description": " ", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/integrationapi.GinNTPForceSyncRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/integrationapi.GinNTPForceSyncResponse" + } + }, + "400": { + "description": "Bad Request" + }, + "409": { + "description": "Another force sync is already ongoing" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/api/v1/integration/time/status": { + "get": { + "description": "Get the current time synchronization status", + "tags": [ + "integrationAPI", + "time" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/integrationapi.GinTimeStatusResponse" + } + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, "/api/v1/integration/udp": { "get": { "description": "Get the current UDP configuration for how the Sonar outputs data.", @@ -397,6 +537,49 @@ } } }, + "integrationapi.GinManualTimeRequest": { + "type": "object", + "properties": { + "now": { + "description": "Current system time in RFC3339.", + "type": "string" + } + } + }, + "integrationapi.GinNTPConfigurationPayload": { + "type": "object", + "properties": { + "ntp_address": { + "description": "address or \"auto\"", + "type": "string" + } + } + }, + "integrationapi.GinNTPForceSyncRequest": { + "type": "object", + "properties": { + "timeout_seconds": { + "description": "number of seconds to wait for sync to be achieved before cancelling the force sync request with success == false", + "type": "number" + } + } + }, + "integrationapi.GinNTPForceSyncResponse": { + "type": "object", + "properties": { + "message": { + "description": "human-readable message", + "type": "string" + }, + "status": { + "$ref": "#/definitions/integrationapi.GinTimeStatusResponse" + }, + "success": { + "description": "true if NTP sync was achieved within timeout, false otherwise. Important: callers that want to achieve sync with a specific address should check the returned status", + "type": "boolean" + } + } + }, "integrationapi.GinStatusResponse": { "type": "object", "properties": { @@ -423,6 +606,14 @@ "$ref": "#/definitions/integrationapi.GinSystemStatusEntryResponse" } ] + }, + "time": { + "description": "Time is the status of system time", + "allOf": [ + { + "$ref": "#/definitions/integrationapi.GinSystemStatusEntryResponse" + } + ] } } }, @@ -487,6 +678,27 @@ } } }, + "integrationapi.GinTimeStatusResponse": { + "type": "object", + "properties": { + "ntp_seconds_since_last_sync": { + "description": "seconds since last NTP sync, or null if not synchronized", + "type": "integer" + }, + "ntp_synced": { + "description": "true if synchronized to NTP source, false otherwise", + "type": "boolean" + }, + "ntp_synced_to": { + "description": "address the sonar is synchronized to if NTP is synchronized, \"\" otherwise", + "type": "string" + }, + "system_time": { + "description": "system time in RFC3339", + "type": "string" + } + } + }, "integrationapi.RangeResponse": { "type": "object", "properties": { diff --git a/docs/sonar-3d/sonar-3d-15-software-changelog.md b/docs/sonar-3d/sonar-3d-15-software-changelog.md index cea2aab9..51286928 100644 --- a/docs/sonar-3d/sonar-3d-15-software-changelog.md +++ b/docs/sonar-3d/sonar-3d-15-software-changelog.md @@ -1,5 +1,14 @@ # Software Versions +## v1.7.1 (2026-05) + +- Added an integration API for NTP configuration and status to provide tighter time synchronisation + - Users with a NTP configuration from prior versions must apply this configuration again +- Improve NTP status feedback in GUI +- Fix LED not blinking in thermal shutdown +- Fix source IP of UDP multicast packets in integration API +- Improve Ethernet stability + ## v1.7.0 (2026-02) - Introduce high-frequency 2.4 MHz mode diff --git a/docs/sonar-3d/sonar-3d-15-time.md b/docs/sonar-3d/sonar-3d-15-time.md new file mode 100644 index 00000000..f506983b --- /dev/null +++ b/docs/sonar-3d/sonar-3d-15-time.md @@ -0,0 +1,64 @@ +# Time + +The sonar continously attempts to synchronize time using the Network Time Protocol (NTP). +When not synchronized with NTP, it is also possible to set time manually. + +## Supported versions + +Supported on Sonar 3D-15 starting with release 1.7.1 + +See [Software Updates](./sonar-3d-15-software-update.md) for update instructions. + +## Importance of setting time + +The sonar does know the current time when booting, and initial timestamps output from the sonar will be relative to some arbitrary time in the past. +It is recommended to synchronize the sonar's time before using its output. + +## NTP server address configuration: auto or custom + +The NTP server address can be configured as either "auto" or a specific server address. +When NTP server address is configured as "auto", the sonar will attempt to reach a default pool of internet time servers. +The configuration is persisted across reboots. + +## Setting manual time + +When the sonar has not yet achieved NTP sync it is possible to set time manually. +This is useful in deployment scenarios without a reachable NTP server, or as a fallback until an NTP server becomes available. +A manually set time will be disregarded if the sonar later achieves NTP sync. + +## Time status + +The sonar separates between NTP configuration and time status. +Time status consists of the following fields: + +|Field|Description| +|-|-| +| `system_time` | system time | +| `ntp_synced` | true if synchronized to NTP source, false otherwise | +| `ntp_synced_to` | address the sonar is synchronized to if NTP is synchronized, "" otherwise | +| `ntp_seconds_since_last_sync` | seconds since last NTP sync if NTP is synchronized | + +## NTP Force sync + +A NTP force sync operation can be triggered which will attempt to achieve NTP sync within a specified timeout. +Upon achieving sync, or when the timeout expires, the operation will respond with the following fields: + +|Field|Description| +|-|-| +|`success`|true if NTP sync was achieved within timeout, false otherwise| +|`message`|human-readable message| +|`status`|Time status as described [here](#time-status) | + +!!! warning + `success` true means the sonar acieved NTP sync. To assert the sonar is synchronized to a specific NTP server, check the returned status. + +!!! warning + The operation can cause abrupt jumps in system time, and is not recommended for use while reading sonar output. + +## Web GUI + +On supported versions there is a "Time" section in the Config page. + +## HTTP API + +The HTTP API allows configuration and inspection of time on the sonar. See [HTTP API](./sonar-3d-15-api.md#http-api). \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 838922a6..bb10d040 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -61,6 +61,7 @@ nav: - GUI: sonar-3d/sonar-3d-15-gui.md - Settings: sonar-3d/sonar-3d-15-config.md - Replay Sonar Data: sonar-3d/sonar-replay.md + - Time: sonar-3d/sonar-3d-15-time.md - API: sonar-3d/sonar-3d-15-api.md - Software update: sonar-3d/sonar-3d-15-software-update.md @@ -152,6 +153,7 @@ nav: - Axes: dvl/axes.md - Range mode: dvl/range-mode.md - Water tracking: dvl/water-tracking.md + - Time: dvl/time.md - Settings and configuration: dvl/configuration.md - Diagnostic log: dvl/diagnostic-log.md - Dead reckoning: dvl/dead-reckoning.md