MQTT adapter

The MQTT protocol adapter exposes an MQTT topic hierarchy for publishing messages and events to Bosch IoT Hub’s Telemetry and Event endpoints.

The adapter does not behave like a general purpose MQTT broker. Therefore the following applies to the adapter:

  • Supports MQTT 3.1.1 only.
  • Does not maintain session state for clients. Therefore setting the clean session flag on the client side does not have an impact on the adapter. The adapter will set the session present to 0 in the CONNACK packet in any case.
  • Ignores any Will contained in the CONNECT packet.
  • Only supports the topic names mentioned in the sections below. Custom topics are not supported.
  • Does not support retaining messages. But if the retain flag is present in a message, then a x-opt-retain message annotation is added to the AMQP 1.0 message sent to the business application. The application can then decide to react upon the presence of this annotation.

Establishing the connection

The MQTT adapter requires clients to authenticate during connection establishment. The adapter supports both username/password based authentication as well as client certificate based authentication. In order to do so, clients need to provide a username and a password in the MQTT CONNECT packet or a client certificate. The username must have the format auth-id@tenant-id.

The server certificate of Bosch IoT Hub is issued by Let’s Encrypt. Some devices directly trust the Let’s Encrypt root certificate, in such case downloading the server certificate is not necessary. If that is not the case, you need to import the Let’s Encrypt certificate of Bosch IoT Hub in your trust store to establish a TLS connection to the MQTT adapter.

For the examples below mosquitto_pub is used. mosquitto_pub needs the server certificate to establish a TLS connection to Bosch IoT Hub. The certificate can be downloaded as follows:

curl -o iothub.crt https://docs.bosch-iot-suite.com/hub/iothub.crt

Inactivity timeout

The client should provide a Keep Alive value of less than 60s in the MQTT CONNECT packet to ensure that connection issues can be detected. Connected devices which are neither sending nor receiving data will be disconnected after one and a half times the Keep Alive time period, or after 60s, whichever comes first. To keep the connection open a device must send MQTT PINGREQ packages if needed to indicate to the server that the device is still active.

Note that if a device is subscribed to receive commands and the MQTT connection fails, a subsequent successful new connection and command subscription by the client may still result in commands not getting delivered until the Keep Alive time period has elapsed and the server detects the connection failure. This should be taken into consideration when choosing the Keep Alive value.

Communication patterns

Publishing telemetry data

The MQTT adapter supports publishing of telemetry data by means of MQTT PUBLISH packets using QoS 0 or QoS 1. The devices can optionally indicate the content type of the payload by setting the content-type property explicitly in the property-bag. The details regarding configuring the property-bag for telemetry messages can be found in Hono Documentation.

Publishing events

The MQTT adapter supports publishing of events by means of MQTT PUBLISH packets using QoS 1 only. The adapter will send an MQTT PUBACK packet to the client once the event has been settled with the accepted outcome by the AMQP 1.0 Messaging Network. The devices can optionally indicate a time-to-live duration for event messages and the content type of the payload by setting the hono-ttl and content-type properties explicitly in the property-bag. The details on configuring the property-bag for event messages can be found in Hono Documentation.

Command & control

The MQTT adapter supports receiving commands by means of MQTT SUBSCRIBE. Devices can subscribe to commands with QoS 0 or QoS 1. The responses to commands can being published using either QoS 0 or QoS 1.

All above mentioned communication patterns can be used by devices connecting directly to the MQTT protocol adapter or by gateways connecting to the MQTT protocol adapter and acting on behalf of the actual devices. See Gateway mode for a more detailed description.

Devices connected directly to MQTT adapter

Publishing telemetry data

  • Topic: telemetry
  • Authentication: required with credentials of device
  • Payload:
    • (required) Arbitrary payload

Example:

Upload a JSON string for device:

mosquitto_pub -h mqtt.bosch-iot-hub.com -p 8883 -u {auth-id}@{tenant-id} -P {password} -t telemetry -m '{"temp": 5}' --cafile iothub.crt

Publishing events

  • Topic: event
  • Authentication: required with credentials of device
  • Payload:
    • (required) Arbitrary payload

Example:

Upload a JSON string for device:

mosquitto_pub -h mqtt.bosch-iot-hub.com -p 8883 -u {auth-id}@{tenant-id} -P {password} -t event -m '{"alarm": 1}' -q 1 --cafile iothub.crt

Receiving commands

  • Topic Filter: command///req/#

  • The actual topic is structured as follows:

    • for one-way commands: command///req//{command-subject}
    • for request/response commands command///req/{req-id}/{command-subject}

    Parameters:

    command-subject: The command subject (e.g. the name of the command to execute)

  • QoS: Devices can subscribe with QoS 1 or QoS 0.

  • Authentication: required with credentials of device.

  • The payload of the message contains the command payload.

Subscribe to command topic:

mosquitto_sub -d -h mqtt.bosch-iot-hub.com -p 8883 -u {auth-id}@{tenant-id} -P {secret} -k 30 --cafile iothub.crt -t command///req/#
Note
Previous versions of Bosch IoT Hub used topic filter command/+/+/req/# for subscribing to commands. This old topic is still supported but deprecated.

Sending a response to a command

  • Topic: command///res/{req-id}/{status-code}
    • req-id: the unique identifier of the command execution request
    • status-code: a HTTP status code indicating the outcome of executing the command.
  • Authentication: required with credentials of device
  • Payload:
    • (required) Arbitrary command payload

Send back command response:

mosquitto_pub -d -h mqtt.bosch-iot-hub.com -p 8883 -u {auth-id}@{tenant-id} -P {secret} --cafile iothub.crt -t command///res/{req-id}/200 -m '{"greetingDurationInSec": 23}'

Gateways connected to MQTT adapter

Publishing telemetry data

  • Topic: telemetry/{tenant-id}/{device-id}
  • Authentication: required with credentials of gateway
  • Payload:
    • (required) Arbitrary payload
Note
In Gateway Mode {device-id} is the ID of the actual device while credentials are the credentials of the gateway.

Example:

Upload a JSON string for device through gateway:

mosquitto_pub -h mqtt.bosch-iot-hub.com -p 8883 -u {auth-id}@{tenant-id} -P {password} -t telemetry/{tenant-id}/{device-id} -m '{"temp": 5}' --cafile iothub.crt

Publishing events

  • Topic: event/{tenant-id}/{device-id}
  • Authentication: required with credentials of gateway
  • Payload:
    • (required) Arbitrary payload
Note
In Gateway Mode {device-id} is the ID of the actual device while credentials are the credentials of the gateway.

Example:

Upload a JSON string for device through gateway:

mosquitto_pub -h mqtt.bosch-iot-hub.com -p 8883 -u {auth-id}@{tenant-id} -P {password} -t event/{tenant-id}/{device-id} -m '{"alarm": 5}' -q 1 --cafile iothub.crt

Receiving commands

The gateway may receive commands for all devices in whose behalf it acts using topic filter command//+/req/# or for a specific device using topic filter command//${device-id}/req//{command-subject}.

  • Topic Filter to subscribe to commands for all devices in whose behalf a gateway acts: command//+/req/#

  • The actual topic is structured as follows:

    • for one-way commands for all devices: command//+/req//{command-subject}
    • for request/response commands for all devices: command//+/req/{req-id}/{command-subject}
  • Topic Filter to subscribe only to commands for a specific device, an authenticated gateway uses the topic filter command//${device-id}/req/#

  • The actual topic is structured as follows:

    • for one-way commands for a specific device: command//${device-id}/req//{command-subject}
    • for request/response commands for a specific device: command//${device-id}/req/{req-id}/{command-subject}
  • QoS: Devices can subscribe with QoS 1 or QoS 0.

  • Authentication: required with credentials of gateway.

  • The payload of the message contains the command payload.

​Subscribe to command topic:

​A subscription to commands for all devices that a gateway acts on behalf of looks like this:

mosquitto_sub -d -h mqtt.bosch-iot-hub.com -p 8883 -u {auth-id}@{tenant-id} -P {secret} -k 30 --cafile iothub.crt -t command//+/req/#

​A subscription to commands for a specific device can be done like this:

mosquitto_sub -d -h mqtt.bosch-iot-hub.com -p 8883 -u {auth-id}@{tenant-id} -P {secret} -k 30 --cafile iothub.crt -t command//{device-id}/req/#   

Sending a response to a command

An authenticated gateway sends a device’s response to a command it has received on behalf of the device

  • Topic: command//${device-id}/res/${req-id}/${status-code}
    • req-id: the unique identifier of the command execution request
    • status-code: a HTTP status code indicating the outcome of executing the command.
  • Authentication: required with credentials of gateway
  • Payload:
    • (required) Arbitrary command payload

Send back command response:

mosquitto_pub -d -h mqtt.bosch-iot-hub.com -p 8883 -u {auth-id}@{tenant-id} -P {secret} --cafile iothub.crt -t command//{device-id}/res/{req-id}/200 -m '{"greetingDurationInSec": 23}'

Error Reporting via Error Topic

The default behaviour when an error occurs while publishing telemetry, event or command response messages is for the MQTT adapter in IoT Hub to ignore the error and send no PUBACK back for the message that caused the error.

An alternative way of dealing with errors involves keeping the connection intact and letting the MQTT adapter publish a corresponding error message on a specific error topic to the device. To enable that behaviour, the device sends an MQTT SUBSCRIBE packet with a topic filter as described below on the same MQTT connection that is also used for publishing the telemetry, event or command response messages. Devices can subscribe with QoS 0 only. The adapter indicates the outcome of the subscription request by sending back a corresponding SUBACK packet. The SUBACK packet will contain Success - QoS 0 (0x00) for a valid error topic filter and will contain the Failure (0x80) value for an invalid or unsupported filter. In order to again activate the default error handling behaviour, the device can send an MQTT UNSUBSCRIBE packet to the adapter, including the same topic filter that has been used to subscribe.

The following sections define the topic filters to use for subscribing to error messages, and the resulting error message topic. Instead of the error topic path segment, the shorthand version e is also supported.

The following variables are used:

  • ${endpoint-type}: The endpoint type of the device message that caused the error. Its value is either telemetry, event or the respective shorthand version. In case of a command response device message command-response or c-s is used.
  • ${correlation-id}: The identifier that may be used to correlate the error message with the device message that caused the error. The identifier is either the value of a correlation-id property bag value contained in the device message topic, or the identifier is the packet-id of the device message if it was sent with QoS 1. Otherwise, a value of -1 is used.
  • ${error-status}: The HTTP status code of the error that was caused by the device message.
Note
Since the subscription on the error topic needs to be done on the same MQTT connection that is also used for publishing the telemetry, event or command response messages, the Mosquitto MQTT Command Line Client cannot be used. The MQTT CLI tool with its shell mode is an alternative that supports using one MQTT connection for both subscribing and publishing.

Receiving Error Messages

An authenticated device MUST use the following topic filter for subscribing to error messages:

error/[${tenant-id}]/[${device-id}]/#

Both the tenant and the device ID are optional. If specified, they MUST match the authenticated device’s tenant and/or device ID. Note that the authentication identifier used in the device’s credentials is not necessarily the same as the device ID.

The protocol adapter will publish error messages for the device to the following topic name

error/[${tenant-id}]/[${device-id}]/${endpoint-type}/${correlation-id}/${error-status}

The tenant-id and/or device-id will be included in the topic name if the tenant and/or device ID had been included in the topic filter used for subscribing to error messages.

Example

An example using the MQTT CLI that will produce an error output provided there is no downstream consumer for the device messages.

mqtt shell
con -V 3 -h [MQTT_ADAPTER_IP] -u [DEVICE]@[TENANT] -pw [PWD]
sub -t error///# --qos 0 --outputToConsole
pub -t telemetry -m '{"temp": 5}' --qos 1

Using an explicit correlation id:

pub -t telemetry/?correlation-id=123 -m '{"temp": 5}' --qos 1

Receiving Error Messages via a Gateway

A gateway MUST use one of the following topic filters for subscribing to error messages:

Topic Filter Description
error//+/#
error/${tenant-id}/+/#
Subscribe to error messages for all devices that the gateway is authorized to act on behalf of.
error//${device-id}/#
error/${tenant-id}/${device-id}/#
Subscribe to error messages for a specific device that the gateway is authorized to act on behalf of.

The protocol adapter will publish error messages for the device to the following topic name

error/[${tenant-id}]/[${device-id}]/${endpoint-type}/${correlation-id}/${error-status}

The tenant-id and/or device-id will be included in the topic name if the tenant and/or device ID had been included in the topic filter used for subscribing to error messages.

Error Message Payload

The MQTT adapter publishes error messages with a UTF-8 encoded JSON payload containing the following fields:

Name Mandatory JSON Type Description
code yes number The HTTP error status code. See the table below for possible values.
message yes string The error detail message.
timestamp yes string The date and time the error message was published by the MQTT adapter. The value is an ISO 8601 compliant combined date and time representation in extended format.
correlation-id yes string The identifier that may be used to correlate the error message with the device message that caused the error. The identifier is either the value of a correlation-id property bag value contained in the device message topic, or the identifier is the packet-id of the device message if it was sent with QoS 1. Otherwise a value of -1 is used.

The error message’s code field may contain the following HTTP status codes:

Code Description
400 Bad Request, the request cannot be processed. A possible reason for this is an invalid PUBLISH topic.
403 Forbidden, the device’s registration status cannot be asserted.
404 Not Found, the device is disabled or does not exist.
413 Request Entity Too Large, the request body exceeds the maximum supported size.
429 Too Many Requests, the tenant’s message limit for the current period is exceeded.
503 Service Unavailable, the request cannot be processed. Possible reasons for this include:
  • There is no consumer of telemetry data for the given tenant connected to IoT Hub, or the consumer has not indicated that it may receive further messages (not giving credits).
  • If the QoS level header is set to 1 (at least once semantics), the reason may be:
    • The consumer has indicated that it didn’t process the telemetry data.
    • The consumer failed to indicate in time whether it has processed the telemetry data.

Example payload:

{
  "code": 400,
  "message": "malformed topic name",
  "timestamp": "2020-12-24T19:00:00+0100",
  "correlation-id": "5"
}

Error Handling

When a device publishes a telemetry, event or command response message and there is an error processing the message, the handling of the error depends on whether there is an error topic subscription for the device and whether a on-error property bag parameter was set on the topic used for sending the message.

If no error subscription is in place and no on-error parameter was set, the default error handling behaviour is to ignore the message that caused the error and no PUBACK will get sent. If the device has a subscription on the error topic (on the same MQTT connection the device uses for sending messages), the default behaviour is to keep the MQTT connection open unless a terminal error happens. The errors that are classified as terminal are listed below.

  • The adapter is disabled for the tenant that the client belongs to.
  • The authenticated device or gateway is disabled or not registered.
  • The tenant is disabled or does not exist.
Note
When a terminal error occurs, the connection will always be closed irrespective of any on-error parameter or error subscription.

The following table lists the different behaviours based on the value of the on-error property bag parameter and the existence of an error subscription:

on-error topic parameter Error subscription exists Description
default or value not set no The error will be ignored and no PUBACK for the message that caused the error will get sent (like with the skip-ack option).
disconnect no The connection to the device will get closed.
ignore no The error will be ignored and a PUBACK for the message that caused the error will get sent.
skip-ack no The error will be ignored and no PUBACK for the message that caused the error will get sent.
default or value not set yes After having sent an error message on the error topic, the error will be ignored and a PUBACK for the message that caused the error will get sent (like with the ignore option).
disconnect yes After having sent an error message on the error topic, the connection to the device will get closed.
ignore yes After having sent an error message on the error topic, the error will be ignored and a PUBACK for the message that caused the error will get sent.
skip-ack yes After having sent an error message on the error topic, the error will be ignored and no PUBACK for the message that caused the error will get sent.

Example

A device wanting to have errors be always ignored can for example publish telemetry messages on this topic:

telemetry/?on-error=ignore

Troubleshooting

Issue Solution
Device subscription for receiving commands was not acknowledged by the adapter. Verify that you are using QoS level 1 as QoS level 2 is not supported. Please note that some client programs might use QoS level 2 by default. If this is the case with your client software, please explicitly set QoS level to 1.
Corporate information Data protection notice Legal information Support Free plans