Sonardyne API Overview
The Sonardyne API allows supported devices to be programmatically controlled.
The underlying technologies are gRPC and Protocol Buffers (Protobuf), which support a number of programming languages. The examples in this documentation are written in Python and make use of the wrappers which are packaged up with the Sonardyne API Python library.
The API supports gRPC as a transport mechanism, as well as supporting two non-gRPC alternatives detailed below.
- The API supports sending and receiving messages using the Framed protocol, which encodes serialised Protobuf messages using Consistent Overhead Byte Stuffing (COBS). One reason to use the Framed protocol is that it removes gRPC as a dependency, which may be preferable in some use cases. For more information on the Framed protocol, see Using Non-gRPC Modes.
- The API also supports sending and receiving messages as JSON. This is not only useful for debugging (as JSON messages are human-readable), but it also removes both gRPC and Protobuf as dependencies. Each example has a "Raw JSON" version which demonstrates how these messages could be sent and received without Protobuf or gRPC.
Services
The API provides services which all follow a regular pattern.
| Service | Sends and receives | Envelope contains | What is this for? |
|---|---|---|---|
ConfigurationService |
ConfigurationEnvelope |
[name]Configuration |
Set/Get e.g. set lever arms |
CommandService |
CommandEnvelope |
[name]Command |
Run Task e.g. reset INS |
ObservationService |
ObservationEnvelope |
[name]Observation |
In/Out stream of data e.g. GNSS received |
CommsService |
CommsEnvelope |
[name]Comms |
In/Out stream of comms data e.g. write to serial |
Configuration Service
The configuration service is used for setting and getting configurations. For each configuration sent in an envelope, we can expect the same configuration types returned in the same order. Configurations contain a result to signify the success of the configuration application.
The configuration service provides a ConfigurationStream, which outputs any configurations
which change. Listening on the ConfigurationStream is an efficient way to track the entire
state of the product you are connected to.
Typically, all fields in a configuration are optional. This allows the application of
partial configurations.
Command Service
The command service is for command and control. Whereas the configuration service is used to configure the state of a product (typically at startup), the command service is used to perform actions (typically throughout runtime) such as algorithm resets, triggering acoustics or commanding the system to shut down.
Observation Service
The observation service provides a bidirectional stream, allowing us to send and listen to observations. An observation is a piece of structured data e.g. a GNSS observation containing latitude and longitude fields, unlike comms which is unstructured data, containing a variable number of raw bytes.
Example use cases for the observation services are streaming data from a pressure sensor, streaming GNSS readings from a GNSS source, and streaming navigation solutions from a navigation module.
For information on subscribing to observation streams, see Subscribing to Streams.
Comms Service
The comms service allows bidirectional communication with data ports e.g. ethernet ports and serial ports. This allows monitoring of incoming and outgoing data over a port, or the sending of data out over a port.
An example comms message as JSON:
{
"@type": "type.googleapis.com/sonardyne.api.services.comms_service.CommsEnvelope",
"comms_messages": [
{
"@type": "type.googleapis.com/sonardyne.api.common.ports.DataPortComms",
"uid": {
"value": "1518954244",
"name": "TCP-8110"
},
"timestamp": {
"common_time_seconds": 1765206239.1132329,
"instrument_time_seconds": 251542.067792193
},
"data_direction": "DATA_DIRECTION_OUTPUT",
"data": "SGVsbG8gV29ybGQhIDUw"
}
]
}
CommsEnvelope containing a DataPortComms message with bytes to output over a TCP port named TCP-8110.
Note that although these bytes are not human-readable in the serialised JSON, they do deserialise to a human-readable string.
Message Types
The API makes use of message suffixes which give information on how a message may be used.
- There are messages which represent a component of the device.
- There are messages which represent a reference to a component.
- There are common messages which represent commonly used concepts (e.g. ethernet ports) and have no required suffix.
Component Messages
A product can be considered as a collection of components. These components are modules, algorithms, sources, and port lists.
| Component | Message name must be | Can be combined with service names e.g. |
|---|---|---|
Module |
[name]Module |
[name]ModuleConfiguration |
Algorithm |
[name]Algorithm |
[name]AlgorithmCommand |
Source |
[name]Source |
[name]SourceObservation |
Sensor |
[name]Sensor |
[name]SensorObservation |
Port List |
[name]PortList |
[name]PortListComms |
Modules
The Module component represents non-algorithm, non-sensor, non-data source components e.g. a BatteryModule is responsible for managing a battery and enabling/disabling charging. Another example module is the NetworkModule.
BatteryModuleAllows battery management e.g. enabling charging.DeviceInstallationModuleAllows configuration of the device's lever arms & mounting angles relative to the vessel.DeviceModuleAllows reading of product name and serial number as well as sending of shutdown & factory reset commands.ExternalLoggingModuleAllows configuration of logging to an external client via a TCP server.NavigationModuleAllows streaming of navigation solutions, in SPRINT this is the combined result of the AHRS & INS algorithm.NetworkModuleAllows configuration of the device's network interface e.g. changing the device IP address.OutputMessageModuleAllows configuration of output messages over data ports e.g. outputting GGA messages on a serial port.PortLinkModuleAllows bidirectional routing between a serial and ethernet port.RemotePointsModuleAllows configuration of remote points on the vessel, the navigation module can output data valid at these remote points.SprintModuleAllows reading of SPRINT-specific device information.TimeModuleAllows selection of time input sources in order to set UTC and instrument time.
An example request and response sent as JSON:
{
"@type": "type.googleapis.com/sonardyne.api.common.envelope.RequestEnvelope",
"uid": 1,
"requests": [
{
"@type": "type.googleapis.com/sonardyne.api.services.configuration_service.SetConfigurationRequest",
"configuration": {
"@type": "type.googleapis.com/sonardyne.api.modules.battery_module.BatteryModuleConfiguration",
"isBatteryChargingEnabled": false
}
}
]
}
{
"@type": "type.googleapis.com/sonardyne.api.common.envelope.ResponseEnvelope",
"uid": 1,
"responses": [
{
"@type": "type.googleapis.com/sonardyne.api.services.configuration_service.SetConfigurationResponse",
"timestamp": {
"common_time_seconds": 1765193736.1050346,
"instrument_time_seconds": 239039.059659313
},
"configuration": {
"@type": "type.googleapis.com/sonardyne.api.modules.battery_module.BatteryModuleConfiguration",
"uid": {
"value": "2388163018",
"name": "Output Message Module"
},
"is_battery_charging_enabled": false
},
"result": {
"success": "OUTCOME_SUCCESS"
}
}
]
}
Algorithms
The Algorithm component represents internal algorithms e.g. an INS algorithm.
AhrsAlgorithmAllows sending of reset commands and configuring AHRS coarse latitude and longitude.InsAlgorithmAllows sending of reset commands and configuring INS aiding.DvlAlgorithmAllows configuration of DVL algorithm settings e.g. max ping rate & trigger inputs.
An example request and response sent as JSON:
{
"@type": "type.googleapis.com/sonardyne.api.common.envelope.RequestEnvelope",
"uid": 2,
"requests": [
{
"@type": "type.googleapis.com/sonardyne.api.services.configuration_service.SetConfigurationRequest",
"configuration": {
"@type": "type.googleapis.com/sonardyne.api.algorithms.ins_algorithm.InsAlgorithmConfiguration",
"isGnssEnabled": true,
"isXposEnabled": false
}
}
]
}
{
"@type": "type.googleapis.com/sonardyne.api.common.envelope.ResponseEnvelope",
"uid": 2,
"responses": [
{
"@type": "type.googleapis.com/sonardyne.api.services.configuration_service.SetConfigurationResponse",
"timestamp": {
"common_time_seconds": 1765193984.8364909,
"instrument_time_seconds": 239287.79105141
},
"configuration": {
"@type": "type.googleapis.com/sonardyne.api.algorithms.ins_algorithm.InsAlgorithmConfiguration",
"uid": {
"value": "3646079212",
"name": "INS Algorithm"
},
"is_gnss_enabled": true,
"is_susbl_enabled": true,
"is_xpos_enabled": false
},
"result": {
"success": "OUTCOME_SUCCESS"
}
}
]
}
Sources
The Source component represents "aiding" or "input" sources e.g. GNSS or Time. These sources typically have configurable lever arms. The SPRINT Nav has a pressure sensor and a depth source. The depth source selects either a data port (receiving depth messages e.g. PSONPD) or a built-in pressure sensor for use as the source of depth.
DepthSourceAllows configuration of a data port or pressure sensor for deriving depth.GnssSourceAllows configuration of a data port for a GNSS input (receiving GGA & GST messages).SoundVelocitySourceAllows configuration of a manual value, data port, or derived sound velocity.SusblSourceAllows configuration of a data port for an SUSBL input (receiving PSIMSSB messages).NtpTimeSourceAllows configuration of a connection to an NTP server.ZdaTimeSourceAllows configuration of a data port for a ZDA input (receiving ZDA messages).PpsTimeSourceAllows configuration of a trigger port for a 1-pulse-per-second time input.XposSourceAllows configuration of a data port for an XPOS input (receiving XPOS messages).
Many of the sources support observation streaming, which allows the monitoring of data received by these sources
e.g. a GnssSourceObservation.
Sources typically have lever arms, and may have mounting angles, which relate their position to the Vessel's common reference point.
Sensors
The Sensor component represents physical devices which observe data. The observation stream can be used to monitor these observations. Example sensors are depth, temperature - these can be configured using the Configuration Service.
DvlSensorRepresents a doppler velocity log (DVL) on the device.PressureSensorRepresents a pressure sensor on the device.TemperatureSensorRepresents a temperature sensor on the device.
Port Lists
The Port List component represents collections of data inputs/outputs.
Some port lists, e.g. ethernet port lists, can have entries added and removed.
Other port lists, e.g. serial port lists, represent physical ports on the device and are fixed length.
On a data port such as a SerialPort or an EthernetPort, it is possible to send and receive bytes using the CommsService.
EthernetPortListAllows adding, removing & configuring of TCP & UDP ports, these may be used as inputs to supported sources, and can be set as outputs in the output message module.ExternalControlPortListRepresents external control ports on the device, these may be used as inputs to supported sources.PowerPassPortListAllows management of power pass ports (e.g. enabling/disabling).SerialPortListAllows management of serial ports (e.g. setting baud rate), these may be used as inputs to supported sources, and can be set as outputs in the output message module.TriggerPortListAllows management of trigger ports.
Common Messages
Unlike the component messages, the common messages have no required suffixes. Common messages may only contain other common messages, whereas component messages may contain other component messages and common messages.
Common messages include LeverArms, MountingAngles, EthernetPort, SerialPort, and more.
Common messages also include the RequestEnvelope and ResponseEnvelope - to see how these are used,
see Using Non-gRPC Modes.
Additional Message Types
Reference Messages
Messages ending in the word "Reference" allow one message to point to another. Note that these references are read-only.
import sonardyne_api as son
with son.WrapperGrpc('0.0.0.0', 8103) as wrapper: # Device IP address & gRPC port:
result = wrapper.set_configuration(son.GnssSourceConfiguration(input_data_port=son.DataPortReference(set_uid=son.UniqueID(name="TCP-5000"))))
print(result)
DataPortReference.
the DataPortReference references a data port - an ethernet, serial, or external control port.
The DataPortReference can be set using set_uid, which allows us to refer to other configuration by
unique ID value or by name.
son.DataPortReference(set_uid=son.UniqueID(name="TCP-5000"))
son.DataPortReference(set_uid=son.UniqueID(value=3245395109))
son.DataPortReference(set_none=True)
set_none field may be used to clear the reference.
son.DataPortReference(set_any_ethernet_port=True)
son.DataPortReference(set_any_external_control_port=True)
son.DataPortReference(set_any_serial_port=True)
set_any fields, these allow data port references
to be set when no unique ID values are known.
Below is an example of a DataPortReference being set:
import sonardyne_api as son
with son.WrapperJsonTcp('0.0.0.0', 8111) as wrapper: # Device IP address & gRPC port:
print(wrapper.set_configuration(son.GnssSourceConfiguration(input_data_port=son.DataPortReference(set_uid=son.UniqueID(name="TCP-5000")))))
{
"@type": "type.googleapis.com/sonardyne.api.common.envelope.RequestEnvelope",
"uid": 1,
"requests": [
{
"@type": "type.googleapis.com/sonardyne.api.services.configuration_service.SetConfigurationRequest",
"configuration": {
"@type": "type.googleapis.com/sonardyne.api.sources.gnss_source.GnssSourceConfiguration",
"inputDataPort": {
"setUid": {
"name": "TCP-5000"
}
}
}
}
]
}
{
"@type": "type.googleapis.com/sonardyne.api.common.envelope.ResponseEnvelope",
"uid": 10,
"responses": [
{
"@type": "type.googleapis.com/sonardyne.api.services.configuration_service.SetConfigurationResponse",
"timestamp": {
"common_time_seconds": 1764954922.1296844,
"instrument_time_seconds": 225.084287999
},
"configuration": {
"@type": "type.googleapis.com/sonardyne.api.sources.gnss_source.GnssSourceConfiguration",
"uid": {
"value": "887217899",
"name": "GNSS Source"
},
"input_data_port": {
"readonly_uid": {
"value": "3245395109",
"name": "TCP-5000"
},
"readonly_ethernet_port_reference": {
"uid": {
"value": "3245395109",
"name": "TCP-5000"
},
"source_port": 5000,
"data_encoding": "DATA_ENCODING_NONE",
"tcp_server": {
"maximum_connections": 20
}
}
},
"lever_arms": {},
"fallback_horizontal_uncertainty_metres": 5,
"scale_uncertainty": 1,
"gnss_depth_mode": "GNSS_DEPTH_MODE_ELLIPSOIDAL"
},
"result": {
"success": "OUTCOME_SUCCESS"
}
}
]
}
The data port reference has "set" fields, and "readonly" fields. The readonly fields are populated when a data port reference is returned from the device.
Using Non-gRPC Modes
The API may be used without gRPC by sending proto messages as either JSON or Framed binary messages. Framed messages are serialised Protobuf messages wrapped in a Sonardyne Simple Binary Message and COBS encoded.
In non-gRPC modes, only message types ending in "Envelope" can be sent over the API. For example,
a RequestEnvelope can be sent as JSON and a corresponding ResponseEnvelope will be returned.
These envelopes can be matched by setting the UID on the RequestEnvelope.
A RequestEnvelope can contain any number of messages ending in "Request"
e.g. SetConfigurationRequest or SendCommandRequest,
and the returned ResponseEnvelope will match one to one with responses e.g. (SetConfigurationResponse or SendCommandResponse).
When streaming data in or out over non-gRPC modes, the ObservationEnvelope is used. When subscribing
to changing configurations, the ConfigurationEnvelopes is used. For more information on subscribing
to streams, see Subscribing to Streams.
Subscribing to Streams
Several services allow data streaming, these are:
ObservationStream(on theObservationService). Allows the monitoring of outputs from components e.g. streaming out readings from aPressureSensororGnssSource. Data can also be streamed into these components e.g. streamingGnssSourceObservationsinto aGnssSource.CommsStream(on theCommsService). Allows the monitoring of data being sent and received over serial and ethernet, also allows data to be sent out over these ports.ConfigurationStream(on theConfigurationService). Allows the monitoring changing configurations.
Messages ending in "SubscriptionRequest" (e.g. CommsSubscriptionRequest) allow the setting of
matching and rejection criteria based on message typenames and UniqueIDs.
For example, possible subscriptions include:
- All messages with a specified suffix e.g. "SensorObservation".
- All messages excluding a specified suffix e.g. "Observation" messages excluding "SourceObservation".
- All messages matching a specified unique ID name e.g. "GNSS Source.
- All messages matching a specified unique ID value e.g. 19572865462 (supposing this is the UID of a particular component).
Streams can be subscribed to by sending a "SubscriptionRequest" message. For example, an ObservationSubscriptionRequest
can be sent to the ObservationStream on the observation service to listen to pressure sensor readings.
The ConfigurationSubscriptionRequest may be used to monitor changing configurations.
The CommsSubscriptionRequest may be used to monitor incoming and outgoing data over a port (serial or ethernet).
The CommsEnvelope allows the sending of data out over a port, and must contain messages ending in "Comms" e.g.
DataPortComms.