Saturday, March 25, 2017

MQTT - Topics and Wildcards

Topics are what MQTT uses to organize what can be a considerable amount of incoming data. Publishers must publish to a topic, and subscribers must subscribe to a topic. As we saw in the last tutorial, there is no need for a client to create a topic before subscribing to it or publishing to it.

As we'll see, there are four specific characters of importance to MQTT topics:

  • / - topic level separator
  • + - single level wildcard
  • # - multi-level wildcard
  • $ - reserved for system usage.

Topics can contain wildcards, the "+" and "#" characters. It is not possible to publish to a topic containing a wildcard, it is only possible to subscribe to such a topic.

This tutorial covers the following, ahem, topics:

  1. Topic Levels
  2. Single Level Wildcards
  3. Multi-Level Wildcards
  4. SYS Topics
  5. Best Practices


Topic Levels
Topics are case-sensitive, so the following two topics are distinct:

  • home/living-room/temperature
  • home/living-room/Temperature
meaning that a message published to home/living-room/temperature will not be sent to a client subscribed to home/living-room/Temperature.

An easy way of testing this is to open four Terminal windows and issue the following commands:

Window #1: mosquitto -v
Window #2: mosquitto_sub -d -h localhost -t home/living-room/temperature
Window #3: mosquitto_sub -d -h localhost -t home/living-room/Temperature
Window #4: mosquitto_pub -d -h localhost -t home/living-room/temperature -m "Living room temperature"
The message sent in the fourth window will only be displayed in the second window.

MQTT topic levels can be the empty string. For this reason, the following are all valid topics:

  • /b/c/d
  • a//c/d
  • a/b/c/
In each, there are four levels. For example, in the topic /b/c/d, the empty string before the "/" is a topic level.

Because empty-string topic levels are acceptable, the following two topics are distinct:

  • home/living-room/temperature
  • /home/living-room/temperature


Single Level Wildcards

A single level wildcard (+) matches exactly one level. So, the following are all matched by "home/+/temperature":

  • home/living-room/temperature
  • home/kitchen/temperature
  • home/bedroom/temperature
  • home//temperature
whereas the following are not matched by "home/+/temperature":
  • home/living-room/temperature/degrees-fahrenheit
  • /home/living-room/temperature
  • home/first-floor/living-room/temperature

Also, "home/living-room/+" matches the following:

  • home/living-room/temperature
  • home/living-room/humidity
  • home/living-room/barometric-pressure
  • home/living-room/

Topics that contain more than one single level wildcards are OK. For example, "home/+/+" matches:

  • home/living-room/
  • home/living-room/humidity
  • home//

Finally, single level wildcard can be used at the start, and "+/first-floor/temperature" matches:

  • home/first-floor/temperature
  • building/first-floor/temperature


Multi-Level Wildcards
Unlike a single level wildcard, a multi-level wildcard (#) matches multiple levels. They can only be used at the end of a topic.

For example, "home/living-room/#" matches the following:

  • home/living-room/temperature
  • home/living-room/temperature/degrees-fahrenheit
but it does not match:
  • home/kitchen/temperature
  • home/first-floor/living-room/temperature

These two types of wildcards can be mixed. For example, "home/+/#" matches:

  • home/first-floor/temperature
  • home/first-floor/temperature/degrees-fahrenheit
  • home/first-floor//degrees-fahrenheit
  • home/first-floor//
  • home/first-floor///
  • home/first-floor///temperature

To reiterate, it is not possible to publish to a topic containing a wildcard, it is only possible to subscribe to such a topic.


SYS Topics
Topics that start with "$" are called "SYS topics". These are used by the broker to report various pieces of information about the broker, such as the number of messages sent, the uptime, etc. It is only possible to subscribe to such a topic. Also, messages sent to SYS topics are not captured when subscribed to '#'.

Here are some examples:

  • $SYS/broker/uptime
  • $SYS/broker/messages/sent - this includes PINGRESP as well as messages sent on other SYS-topics.

There is no standard describing what SYS topics must be supported by a broker, but a list of commonly supported SYS topics can be found at https://github.com/mqtt/mqtt.github.io/wiki/SYS-Topics

To subscribe to SYS topics, the topic must be surrounded by quotes. For example:
mosquitto_sub -d -v -h localhost -t '$SYS/broker/uptime'


Best Practices

  • The topic is included in each message, so it is best to keep topics as short as possible. This means that the name of each topic should be short, and the number of levels should be kept small.
  • Avoid empty-string topics
  • Using wildcards to subscribe to topics that are "high volume" will put undo load on that client.
  • Avoid starting topics with "/"
  • Keep the topics focused, so that only one type of value should be published to a topic. So, having three separate topics:
    • home/living-room/temperature
    • home/living-room/humidity
    • home/living-room/barometric-pressure
    with appropriate values published to each is preferable to using a single topic like
    • home/living-room
    and publishing temperatures, humidity levels, and air pressures to that one topic
  • Design topic hierarchy with extensibility in mind. For example, it is more likely that you would add an additional sensor to your living room than it is to add a new room to your house! So, it makes more sense to use a hierarchy like this:
    • home/living-room/temperature
    than it does to do this:
    • home/temperature/living-room
  • Include a client ID in the topic when it makes sense to do so.

No comments:

Post a Comment