OK so now you know you need a broker, and you've got a few clients to connect up. You've loaded up your MQTT client software. Now what? How do you actually send/receive data?
Remember we mentioned that the whole point of protocols was to take the pile o' bits from the transport layer and organize them! With REST, the data is organized into URLs, but with MQTT we use topics.
Much like REST's GET/POST commands that reference a URL, MQTT clients publish and subscribe to a topic. And, like URLs, topics use / delimeters and ascii-text categorization.
We'll cover wildcards later, suffice to say that while REST strongly recommends, but does not require, true hierarchical URLs, because there's often meta-data in a REST call that can give more information, MQTT only has the topic name. So it's really important to have and consider MQTT topics a proper hierarchy.
Much like you would sort your files like
topics have a hierarchy.
We'll cover wildcards later, suffice to say that while REST strongly recommends, but does not require, true hierarchical URLs (because there's often meta-data in a REST call that can give more information) MQTT only has the topic name. So it's really important to have and consider MQTT topics a proper hierarchy.
Factory Temperature Network
Lets say you have a factory and you wanted to make temperature sensors placed on the HVAC units on each floor in your building publish their temperature, you could set up your topics like so:
So, when we setup the topics, they'll look like this:
The third floor main AC would be
- The tenth floor boiler would be
- The fourth floor heater would be
You don't have to organize the factory exactly like so, you have flexibility on how many layers of hierarchy you want, and what would be considered a super or sub category. But, you'll want to figure it out fast because its not easy to change once you've started pushing and storing data!
Most brokers require you to set up your topics ahead of time and will not let you publish or subscribe to non-existent topics (this is good for avoiding typos and corrupted data).
Others are flexible - whenever a publication comes in for a topic, that topic will be automatically created. This is good when you have a dynamic sensor network with new nodes joining without warning, so that you don't have to log into the server to tell it "hey we added another temperature sensor on the roof"
However, its much more likely that when a client subscribes to a topic, the brokers will send an error if that topic does not exist yet.
By default, MQTT brokers were not designed to store or log data (they can, of course, but it's not a requirement of protocol)
The broker's job is quite simple. Whenever a client publishes a message to the topic on the broker, the broker will immediately send the message to all the clients that have subscribed to that topic.
Using the topic model, you can do a lot with a little. For example, you can develop clients to only use specific topics to publish data to, and subscribe to a topic for configuration changes.
For example, say you have a remote cellular temperature sensor that publishes data to your broker under the sensors/outpost/temperature. Every temperature measurement requires power and data, so you don't want to transmit more than you need to. You could try to hard-code an algorithm for how often to measure (maybe more during the day than during night) or you could have a configuration client publish to the sensors/output/temperature_frequency topic. Then the sensor will be able to get updates at the next connection, and know to change the frequency of measurements. This kind of thing is possible with REST, but its not as elegant with polling as with a subscription-push.
One thing to note is that topics don’t have strict typing built in. HTTP for example, has data encoding on transfer in the headers. And if you remember in the REST JSON example, each element of the JSON collection had a type like a string, boolean or url - That's because its ascii-encoded.
With MQTT, to keep things light, we don't have any existing structure. There’s nothing stopping a client in your factory’s MQTT network from uploading a binary cat photo to the
temperature topic. This is unlike REST where you have more control over data checking. Now, you can add code to your MQTT broker that will scrub bad data out for you, but it’s not built in! So either be careful with your topics and do the data checking on the client pub/sub or perhaps have another client that subscribes to all topics and looks for bad data to clean up.
There is one clever trick that the broker can do with topics, that you cannot do with REST: wildcards! With wildcards, any client can subscribe to any part of that topic, rather than a fully qualified topic.
So, given our earlier factory example, maybe you want to subscribe to everything at at your location, or maybe only sensors on the 3rd floor, or maybe just a specific temperature sensor. Especially if you have new clients joining in, wildcards will take care of the groupings for you.
There are two wildcards available, # and +
+ wildcard is used to get a single level of hierarchy. Here’s an example wildcard topic:
This topic would let you monitor all of the temperature sensors on the 3rd floor.
You can get even more advanced with wildcard subscriptions with something like:
Note that there are two + wildcards here! This topic would get all the temperature data on all floors, that are publishing to a temperature topic. And you’d get updates any time one of those sensors were published.
# wildcard can be used as a match for all remaining levels of hierarchy.
For example if you wanted all to subscribe to everything going on all floors, you’d use:
Or maybe you want to listen in on all 10th floor sensors:
As you can see, thinking through your topic hierarchy is required if you want to take advantage of the + and # wildcards!