Mosquitto to Azure IoT Hub

While I was playing around with my local MQTT broker that I use for my home automation (openhab2, by the way), I though about using Azure IoT Hub as MQTT broker. Here is how far I got…

What is MQTT?

MQTT is short for Message Queuing Telemetry Transport, an open message protocol for machine to machine communication. The server is called „broker“ and clients can send messages to the broker (called „publish“) or receive messages from the broker (called „subscribe“). No big magic. MQTT organizes messages in „topics“, much like a filesystem. For example my smartphone sends (ah, sorry: publishes) messages to my broker under a topic named: mobile/ralf/s8. And „mosquitto“ is another way to say M-Q-T-T

What is Azure IoT Hub?

Here is what the Azure Documentation says about Azure IoT Hub:

IoT Hub is a managed service, hosted in the cloud, that acts as a central message hub for bi-directional communication between your IoT application and the devices it manages. You can use Azure IoT Hub to build IoT solutions with reliable and secure communications between millions of IoT devices and a cloud-hosted solution backend. You can connect virtually any device to IoT Hub.

How to send MQTT messages to Azure IoT Hub?

There are many ways to do this, and there are many libraries available, discussed and explained in many articles. Most of the time I use a set of commandline tools under Linux to send messages to my MQTT broker, so I was interested how to do this with mosquitto_pub.

No matter how you connect, there are a few things you need for nearly all of them, so let’s collect them. This sounds easy, but we may need different tools for it. If you are familiar with CLI or Visual Studio Code (VSCode), congratulations. If you are PowerShell or Portal user, not bad, but you need CLI or VSCode for at least one step, the generation of the SAS token. You can generate a SAS token with the device explorer tool, the CLI extension command (az iot hub generate-sas-token, or the Azure IoT Tools for Visual Studio Code.

To cover multiple environments, I’ll create the IoT Hub in the Portal and use VSCode for the SAS token generation. Feel free to use your familiar tool instead. SO before we start, let’s install the extension for VSCode:

Install Visual Studio Extension

The extension we need is the „Azure IoT Hub Toolkit“. Simply install it and find the „Azure IoT Hub Devices“. Notice the three dots next to it.

VSCode2

From here you could do all of the next steps, but to get familiar with the portal IoT Hub part, we will create the IoT Hub and the device via portal.

Azure IoT Hub

To send messages to Azure IoT Hub, it’s a good idea to have one running. If you don’t have an IoT Hub, simply create one. Give it a name and choose the Free Tier F1 for the testing and compare the available tiers later by reading the documentation. Wait until the IoT Hub is deployed, and open the „Overview“.

First thing we need is the hostname. You find it on the overview page of the resource, it’s something like ralfiot2.azure-devices.net.

Second thing we need is a connection string. We only need this to tell VSCode how to connect to the hub, not for the MQTT messaging. Connection strings are listed under the „Shared Access Policies“ menue. Select „iothubowner“ policy and look at the right pane for „Connection String – primary key„. Copy it.

Device

You can create a device directly in the portal, or use a tool like VSCode. Let’s do it in VSCode.

Click on the three dots next to the Azure IoT extension and select „Set IoT Hub Connection String“. Paste the connection string you copied in the last step, and you should have a successful connection to your hub.

VSCode

Note: You could have used VSCode already for the creation of the hub. That would require you to sign in to Azure, either when asked, or by using the VSCode extension „Azure Account“. In the second case you don’t need the connection string (of course), you simply connect with your Azure account.

Now go on and create the device. How? Simply click on the three dots in VSCode again and select „Create Device“. Give it a name, like „surface“, and there we go. You should see the device under „Azure Iot Hub Devices“ in VS Code and also in the portal under IoT Devices. Check it out.

Generate a SAS token

The device needs to authenticate at the IoT Hub. There is a very detailed article on Azure Documentation about this, for our example we will use a SAS token generated by VSCode. Right-click on the device in VSCode and select „Generate SAS token for device“.

VSCode1

Part of the SAS token is a duration, enter the hours the SAS token should be valid. After that, you can copy and paste the SAS token from the output window. It looks something like this:

SharedAccessSignature sr=ralfiot2.azure-devices.net%2Fdevices%2Fsurface&sig=fQ....bY%3D&se=1552382275

We need the complete line, including the „SharedAccessSignature“ at the beginning! This will be used as our password. Keep in mind that this SAS token grants access to the device (not the hub) for everybody who has access to the token until the token expires. Unless you know what you do, use a small duration period while testing.

Get the Certificate

Did I already mention that we need to encrypt all our traffic to Azure IoT Hub? No? Well, you should do this anyways, and when you want to send MQTT messages it is the only way since no unencrypted communication is allowed here. The device needs to verofy the certificate of the Hub, and we can do this by checking the root certificate. But where to get it from? I copied it from the IoT SDK, published here on GitHub. There are 3 CA Root certificates, and depending on where your IoT Hub is running you need a different one. For me working in Azure global the Baltimore CA worked fine, if you are working in Azure Germany, you need the D-Trust root certificate. Copy everything between (and including) the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- into a separate file (let’s call it ca.pem) and get rid of the quotes at the start and end of the line, and also delete the CRLF at the end. It should look like this:

-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
(...)
R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
-----END CERTIFICATE-----

If you want to verify the format, enter:

openssl x509 -in ca.pem -text

Putting it all together

Let’s see if we have everything. mosquitto_pub needs those parameters:

  • -h Hostname. That’s what we got first, the FQDN of the IoT Hub
  • -u Username. That’s a combination of the hostname, the devicename and the API version: ralfiot2.azure-devices.net/surface/?api-version=2018-06-30
  • -P Password. we got this already, it’s the string beginning with „SharedAccessSignature“ (and make sure that you use a capital „P“)
  • -t Topic. The topic is (as mentioned at the beginning of this article) the place where the MQTT broker will store the message. For us, this is a combination of „devices/“, devicename and „messages/events“, so in total: devices/surface/messages/events.
  • –cafile CAfile. We just created this file (and hopefully picked the right certificate and did the format correct). Also take care of the double-dash.
  • -p Port. For secure MQTT use port 8883.
  • -i ID. This is how your device shows up in the mqtt message. Optional.
  • -V version. Use mqtt311. Although this seems optional at first, it doesn’t work without it!
  • -d to enable some debug messages, also optional
  • -m message. Actually that’s why we did all this, to send a device-to-cloud message

Here is an example of how it might look (I broke it into several lines and of course changed the password):

mosquitto_pub
-h ralfiot2.azure-devices.net
-u "ralfiot2.azure-devices.net/surface/?api-version=2018-06-30"
-P "SharedAccessSignature sr=ralfiot2.azure-devices.net%2Fdevices%2Fsurface&sig=fQnotforyouCbY%3D&se=1552382275"
-t "devices/surface/messages/events/"
--cafile ca.pem
-p 8883
-i surface
-V mqttv311
-d
-m '{"id":"123"}'

Client surface sending CONNECT
Client surface received CONNACK
Client surface sending PUBLISH (d0, q0, r0, m1, 'devices/surface/messages/events/', ... (12 bytes))
Client surface sending DISCONNECT

Yes! We did it! Puuh! We successfully used <code>mosquitto_pub</code> to send MQTT messages to Azure IoT Hub. As already mentioned, when you play around with Device-to-Cloud messages, no matter what libraries you use, things like SAS token, username, hostname and so on will appear, and now you know how to get the information.

I’ll write a follow-up on how to access the data that you send to Azure IoT Hub. Stay tuned…

Hinterlasse einen Kommentar