Protocol specification
In short, keelson has opinions about:
- The format of the key used when publishing data to zenoh
- The format of the data published to zenoh
- The format of the key used when declaring a queryable (i.e. RPC endpoint) in zenoh
- The format of the requests and responses exchanged via a queryable (i.e. RPC endpoint) in zenoh
1. Common key-space design
In zenoh, both pub/sub and req/rep (queryables) messaging patterns all live in the same shared key "space". In keelson, the shared key-space has a common base hierarchy of three (3) levels:
{base_path}/@v{major_version}/{entity_id}/...
With:
base_pathbeing any base_path where to operate@v{major_version}is the major version of keelson used, the leading@makes this a verbatim chunk, allowing separation of different major versions.entity_idbeing a unique id representing an entity within the realm (Normally the platform name ei. landkrabban, masslab, logging_pc_one)...are specific key levels depending on the messaging pattern, these are further described below.
NOTE: Without exceptions, keys should adhere to
snake_casestyle.NOTE: Verbatim chunks allows some key spaces to be hermetically sealed from each other. Any chunk that starts with
@is treated as a verbatim chunk, and can only be matched by an identical chunk. In general, verbatim chunks are useful in ensuring that*and**accidentally match chunks that are not supposed to be matched. A common case is API versioning where@v1and@v2should not be mixed or at least explicitly selected.
Publish, Subscribe & RPC (Queryable)
RPC stands for remote procedure call and refers to the queryables in zenoh. So both connectors and processors can use both pubsub and rpc (queryables) depending on how the api is designed.
2. PUBSUB - Publish- Subscribe messaging
2.1 Specific key-space design
For pub/sub messaging, the lower levels of the key-space has the following levels:
.../pubsub/{subject}/{source_id}
With
pubsubbeing the hard-coded word "pubsub" letting users directly identify key expression categorysubjectbeing a well-known subject describing the information contained within the payloads published to this key. The concept of subjects is further described under Data format below.source_idbeing a unique id for the source producing the information described bysubject.source_idmay contain any number of addititional levels (i.e. forward slashes/) ei. camera/rbg/0
2.2 Message format specification
Each message published to zenoh must be a protobuf-encoded keelson Envelope. An Envelope contains exactly one (1) payload, we say that a payload is enclosed within an Envelope by the publisher and can later be uncovered from that Envelope by the subscriber.
Keelson support a set of well-known payloads, defined by the protobuf schemas available in messages. Each well-known payload is associated with an informative subject, the mapping between subjects and payloads is maintained in a look-up table in YAML format.
The main design principles behind this scheme are:
- Well-known payloads are defined by a schema that describes how to interpret the data.
- Each (well-known) payload is associated with one or more subjects that describes how to interpret the information.
- Each subject or procedure is part of the key when publishing data to zenoh, refer to the section about keys, this helps the sender and receiver to put the information into a context.
2.2.1 Naming convention for subjects category
There are three distinct kind of payloads that has to be covered by a naming convention for subjects:
- raw "arbitrary bytes", where we do not know the schema or do not want to express the schema as a protobuf type, these all fall under the special subject
rawusing the payload typeTimestampedBytes - primitive payloads, which have a specific meaning but where the protobuf type is generic, i.e
TimestampedFloator similar. In this case the subject needs to be very informative with regards to that value and we employ the following convention:<entity>_<property>_<unit>whereentity,propertyandunitare constrained to alphanumeric characters. For examplerudder_angle_deg. - complex payloads, which have a specific protobuf type that is not shared with any other subject. In this case, the subject name should be the snake_case version of the protobuf message name, for example
RawImage->raw_image.
In general, subjects.yaml contains the current well-known subjects and can be regarded as the style-guide to follow.
Units Summary in Subjects
| Unit Symbol | Full Unit Name | Example Subjects Using It |
|---|---|---|
| m | meter | location_fix_accuracy_horizontal_m, draught_mean_m, altitude_msl_m |
| deg | degree (angle) | heading_true_north_deg, roll_deg, target_bearing_relative_deg |
| degps | degrees per second | roll_rate_degps, yaw_rate_degps |
| knots | nautical miles per hour | speed_over_ground_knots, speed_through_water_knots |
| pct | percent | engine_throttle_pct, wheel_position_pct, battery_state_of_charge_pct |
| rpm | revolutions per minute | propeller_rate_rpm, engine_rate_rpm |
| celsius | degrees Celsius | engine_oil_temperature_celsius, air_temperature_celsius |
| psi | pounds per square inch | engine_oil_pressure_psi, engine_coolant_pressure_psi |
| lph | liters per hour | engine_fuel_rate_lph |
| l | liters | engine_fuel_consumed_l |
| volt | volts | battery_voltage_volt, battery_min_voltage_volt |
| amp | amperes | battery_current_amp |
| amph | ampere-hours | battery_capacity_amph |
| ah | ampere-hours | battery_current_consumed_ah |
| wh | watt-hours | battery_energy_consumed_wh |
| sec | seconds | battery_time_remaining_sec, device_uptime_duration |
| hpa | hectopascal | air_pressure_hpa |
| ppt | parts per thousand | water_salinity_ppt |
| mps | meters per second | true_wind_speed_mps, climb_rate_mps, surge_velocity_mps |
| mpss | meters per second squared | linear_acceleration_mpss, surge_acceleration_mpss |
| radps | radians per second | angular_velocity_radps |
| gauss | gauss (magnetic field strength) | magnetic_field_gauss |
| s | seconds | heave_period_s, target_tcpa_s |
| newton | newtons | force_newton |
| newton_meter | newton-meters | moment_newton_meter |
3. Query - Request-Reply messaging (Remote Procedure Calls)
3.1 Specific key-space design
For the request / reply messaging pattern, the lower level hierarchy in the key space consists of the following levels:
.../@rpc/{procedure}/source_id
With:
@rpcbeing the hardcoded word "@rpc" letting users directly identify key expression category. The@makes this a verbatim chunk and ensures it cant be mixed up with other chunks such aspubsub.procedurebeing a well-known procedure name as defined in a protobuf service.source_idbeing the platform unique name of the micro-service either an keelson connector or processor, may contain any number of additional levels (i.e. forward slashes/) ei. camera/mono/0 or lidar/0
3.2 Interface specification
Zenoh supports a generalized version of Remote Procedure Calls, namely queryables. This is leveraged for Request/Response messaging (RPC) in keelson with the following additional decrees:
- All RPC endpoints (queryables) should be defined by a protobuf service definition and thus accept Requests and return Responses in protobuf format.
- All RPC endpoints (queryables) should make use of the common
ErrorResponsereturn type and thereply_errfunctionality in zenoh to propagate errors from callee to caller.
4. Message definition specification
Most messages include a timestamp field, following the Google Protobuf Timestamp specification. The primary timestamp represents the system time of the logging computer. If synchronization with, or tracking of, other timekeeping devices or systems is logged with subject time.