GuidesAPI Reference
Guides

Protobuf definitions for MQTT messages

The payload of each MQTT message consists of exactly one protobuf message. You can copy the protobuf files from the code blocks below.

Configuration

/*
Copyright (C) 2023-2024 HERE Global B.V. and its affiliate(s).
All rights reserved.
This software and other materials contain proprietary information
controlled by HERE and are protected by applicable copyright legislation.
Any use and utilization of this software and other materials and
disclosure to any third parties is conditional upon having a separate
agreement with HERE for the access, use, utilization or disclosure of this
software. In the absence of such agreement, the use of the software is not
allowed.
*/

syntax = "proto3";

package here.hdgnss.positioning;

/*
Configuration message. Publishable to MQTT topics:
    - "v1/pub/app/<appId>/clients/<clientId>/configuration"
    - "v1/pub/project/<projectHrn>/clients/<clientId>/configuration"
The server will respond with a ServerResponse message containing either an Error or Information
with the status set to CONFIGURATION_SET.

Note: The responses will be published to an output topic matching the publish topic prefix (based
either on "user" or "project").

Note: The project HRN (<projectHrn>) must be URL encoded.

Note: The configuration will expire for idle clients. Therefore, it is recommended for the client to
publish the desired configuration as the first message every time it (re)connects to the service via
MQTT or when InformationStatus::CONFIGURATION_RESET has been included in the response. The positioning
session will reset if a configuration with a changed receiverType or beidouSignals is sent at any point.

Note: It is recommended to set (and check) the MQTTv5 correlationData property so that the client can
match the response to the published message.
*/
message Configuration {
    enum ReceiverType {
        // Use server default
        RECEIVER_TYPE_DEFAULT = 0;
        // Consumer-grade receiver (such as a phone)
        RECEIVER_TYPE_CONSUMER = 1;
        // Automotive-grade receiver
        RECEIVER_TYPE_AUTOMOTIVE = 2;
        // High-quality geodetic receiver
        RECEIVER_TYPE_GEODETIC = 3;
    }

    /*
    The service supports a maximum of three different frequencies/signals at a time. Choose the configuration
    that best matches the Beidou signals of the GNSS receiver (the chosen value is not expected to
    change during the positioning session). If the client does not publish a
    configuration, the server default setting will be used.
    */
    enum BeidouSignals {
        // Use server default
        BEIDOU_SIGNALS_DEFAULT = 0;
        // Use Beidou signals B1I, B1C, B2a
        BEIDOU_SIGNALS_SET_1 = 1;
        // Use Beidou signals B1I, B2I, B3I
        BEIDOU_SIGNALS_SET_2 = 2;
    }

    /*
    Set to true to force a positioning session reset when the configuration message is sent.
    If false, the reset will only happen if necessary for the requested configuration
    changes or if the positioning session has remained idle for a certain period.
    */
    bool forceSessionReset = 1;
    /*
    Client receiver type
    */
    ReceiverType receiverType = 2;
    /*
    Beidou signals to use
    */
    BeidouSignals beidouSignals = 3;
}

Measurements

/*
Copyright (C) 2023-2024 HERE Global B.V. and its affiliate(s).
All rights reserved.
This software and other materials contain proprietary information
controlled by HERE and are protected by applicable copyright legislation.
Any use and utilization of this software and other materials and
disclosure to any third parties is conditional upon having a separate
agreement with HERE for the access, use, utilization or disclosure of this
software. In the absence of such agreement, the use of the software is not
allowed.
*/

syntax = "proto3";

package here.hdgnss.positioning;

/*
Measurements container message. Publishable to MQTT topics:
    - "v1/pub/app/<appId>/clients/<clientId>/measurements"
    - "v1/pub/project/<projectHrn>/clients/<clientId>/measurements"
The server will respond with a ServerResponse message (assuming the client has subscribed to responses).

Note: The responses will be published to an output topic matching the publish topic prefix (based
either on "user" or "project").

Note: The project HRN (<projectHrn>) must be URL encoded.

Note: If the client needs to match the server responses to specific measurements, the
MQTTv5 correlationData property can be used for this.
*/
message Measurements {
    /*
    GNSS measurement container.
    */
    message GnssMeasurement {
        /*
        Android compatible GNSS measurements.
        Android API level 31 or later is recommended for clients.
        It is recommended to fill as many optional fields as possible
        as doing so improves the position quality. If a field in this protocol
        is mandatory but not available on Android, then the related observation
        should be skipped.
        */
        message GnssAndroidMeasurements {
            /*
            Container for HD GNSS satellite data
            */
            message SatelliteData {
                string codeType = 1;
                int32 constellationType = 2;
                int32 state = 3;
                int32 svId = 4;
                double cn0DbHz = 5;
                optional double basebandCn0DbHz = 6;
                float carrierFrequencyHz = 7;
                optional double snrInDb = 8;
                int32 multipathIndicator = 9;
                double timeOffsetNanos = 10;
                int64 receivedSvTimeNanos = 11;
                int64 receivedSvTimeUncertaintyNanos = 12;
                double pseudorangeRateMetersPerSecond = 13;
                double pseudorangeRateMetersPerSecondUncertainty = 14;
                int32 accumulatedDeltaRangeState = 15;
                double accumulatedDeltaRangeMeters = 16;
                double accumulatedDeltaRangeMetersUncertainty = 17;
                optional double satelliteInterSignalBiasNanos = 18;
                optional double satelliteInterSignalBiasUncertaintyNanos = 19;
                optional double fullInterSignalBiasNanos = 20;
                optional double fullInterSignalBiasUncertaintyNanos = 21;
            }

            int64 timeNanos = 1;
            int32 hwClockDiscontinuityCount = 2;
            optional double timeNanosUncertainty = 3;
            optional int32 leapSecond = 4;
            optional double biasNanos = 5;
            optional double biasNanosUncertainty = 6;
            optional int64 fullBiasNanos = 7;
            optional double driftNanosPerSecond = 8;
            optional double driftNanosPerSecondUncertainty = 9;
            optional double referenceCarrierFrequencyHzForIsb = 10;
            optional string referenceCodeTypeForIsb = 11;
            optional int32 referenceConstellationTypeForIsb = 12;
            optional bool isFullTracking = 13;

            repeated SatelliteData data = 14;
        }

        /*
        The Unix timestamp of the measurements in milliseconds
        */
        uint64 unixTimestampMs = 1;
        /*
        The client's system timestamp in milliseconds (continuous time, for example
        milliseconds since boot). It should be as close as possible to the moment when
        the measurements were made.
        Reserved for future use.
        */
        optional uint64 systemTimestampMs = 2;
        /*
        The GNSS measurements, which can be provided in one of the supported formats
        (but different formats should not be mixed by one client).
        */
        oneof gnssMeasurement {
            /*
            Android-compatible format
            */
            GnssAndroidMeasurements androidMeasurements = 3;
            /*
            Raw data for one RTCM3 frame (including preamble, frame header and CRC).
            Allows devices that receive RTCM3 data to provide the measurements directly
            with minimal internal processing. The frame must contain a supported RTCM
            measurements message; unsupported message types will be ignored.
            Supported RTCM message types are MSM4, MSM5, and MSM7:
                GPS:        1074, 1075, 1077
                Glonass:    1084, 1085, 1087
                Galileo:    1094, 1095, 1097
                Beidou:     1124, 1125, 1127
            Note that if the receiver has been configured to produce MSM messages for
            constellations other than these, they should all be sent to ensure that
            the message indicating the end of epoch ("MSM Multiple message bit") is not
            excluded.
            */
            bytes rtcmFrame = 4;
        }
    }

    /*
    GNSS measurements.
    When sending RTCM3 frames, it is required that the frames for the full epoch are included
    in the same message ("MSM Multiple message bit" is 0 for the last frame).
    Note that a client should provide only one chosen type of measurements from a single receiver;
    mixing different types or measurements from multiple receivers is not supported.
    */
    repeated GnssMeasurement gnssMeasurements = 1;
}

ServerResponse

/*
Copyright (C) 2023-2024 HERE Global B.V. and its affiliate(s).
All rights reserved.
This software and other materials contain proprietary information
controlled by HERE and are protected by applicable copyright legislation.
Any use and utilization of this software and other materials and
disclosure to any third parties is conditional upon having a separate
agreement with HERE for the access, use, utilization or disclosure of this
software. In the absence of such agreement, the use of the software is not
allowed.
*/

syntax = "proto3";

package here.hdgnss.positioning;

/*
Response from the server to the client. The binary payload received
from the server can be decoded as this type.
Subscribable from MQTT topic (depending on which option was used for
publishing the measurements/configuration):
    - "v1/sub/app/<appId>/clients/<clientId>/positions/protobuf"
    - "v1/sub/project/<projectHrn>/clients/<clientId>/positions/protobuf"

Note: The project HRN (<projectHrn>) must be URL encoded.
*/
message ServerResponse {
    /*
    Response element.
    */
    message Response {
        /*
        A valid position.
        */
        message Position {
            enum PositionTechnology {
                TECH_UNSPECIFIED = 0;
                TECH_PPP = 1; // Precise Point Positioning - utilizing carrier measurements and phaseranges
                TECH_SPP = 2; // Single Point Positioning - utilizing code measurements and pseudoranges
            }

            uint64 timestamp = 1;           // milliseconds (Unix time)
            double lat = 2;                 // latitude degrees (ITRF2014)
            double lng = 3;                 // longitude degrees (ITRF2014)
            float alt = 4;                  // altitude meters (ITRF2014)
            float horizontalUnc = 5;        // horizontal uncertainty meters, 68% confidence
            float verticalUnc = 6;          // altitude uncertainty meters, 68% confidence
            optional float speed = 7;       // m/s
            optional float speedUnc = 8;    // speed uncertainty m/s, 68% confidence
            optional float bearing = 9;     // degrees
            optional float bearingUnc = 10; // bearing uncertainty degrees, 68% confidence
            optional uint32 numSvs = 11;    // number of satellites used
            PositionTechnology positionTechnology = 12; // the technology used to determine the position
        }

        /*
        No position available with the provided measurements.
        */
        message NoPosition {
            enum Reason {
                // Unspecified reason
                UNSPECIFIED = 0;
                // Valid measurements have been received but no position could be calculated
                NO_POSITION = 1;
                // The provided measurements message did not contain usable data
                MEASUREMENTS_NOT_VALID = 2;
                // The provided measurements were too old
                MEASUREMENTS_TOO_OLD = 3;
            }
            Reason reason = 1;
        }

        /*
        Informative response.
        */
        message Information {
            enum InformationStatus {
                // Unspecified
                UNSPECIFIED = 0;
                // Indicates that the configuration was successfully set/updated
                CONFIGURATION_SET = 1;
                // Indicates that the client configuration has been reset to the server default.
                // If the client is using a non-default configuration, it should republish
                // the configuration message. If the client hasn't set the config (is using the
                // default), this can be ignored.
                CONFIGURATION_RESET = 2;
            }
            InformationStatus status = 1;
        }

        /*
        Error response.
        */
        message Error {
            enum ErrorStatus {
                // Unspecified error
                UNSPECIFIED = 0;
                // The provided configuration could not be used
                CONFIGURATION_FAILED = 1;
                // The provided data could not be decoded
                INVALID_DATA = 2;
                // The service is (temporarily) unavailable and the client's message was
                // not processed. The client may choose to buffer measurement data and continue as
                // usual with all buffered measurements. If this response is received
                // repeatedly, it's recommended to start waiting with an exponential back-off
                // delay before sending new measurements.
                SERVICE_UNAVAILABLE = 3;
                // The client is (no longer) authorized.
                // If a token was used for the original authorization, the client must
                // reconnect with a new token.
                UNAUTHORIZED = 4;
                // A server error prevented the data from being processed.
                // The client may choose to buffer measurement data and continue as
                // usual with all buffered measurements. If this response is received
                // repeatedly, it's recommended to start waiting with an exponential back-off
                // delay before sending new measurements.
                SERVER_ERROR = 5;
            }
            ErrorStatus status = 1;
            optional string errorMessage = 2;
        }

        oneof response {
            Position position = 1;
            NoPosition noPosition = 2;
            Information information = 3;
            Error error = 4;
        }
    }

    /*
    Response elements (at least one).
    */
    repeated Response responses = 1;
}