Proposed Pull Request Change

title description author ms.author ms.date ms.topic ms.service ms.custom
Tutorial: Use MQTT to create an IoT device client Tutorial - Use the MQTT protocol directly to create an IoT device client without using the Azure IoT device SDKs ryanwinter baanders 03/11/2025 tutorial azure-iot devx-track-azurecli
📄 Document Links
GitHub View on GitHub Microsoft Learn View on Microsoft Learn
Raw New Markdown
Generating updated version of doc...
Rendered New Markdown
Generating updated version of doc...
+0 -0
+0 -0
--- title: "Tutorial: Use MQTT to create an IoT device client" description: Tutorial - Use the MQTT protocol directly to create an IoT device client without using the Azure IoT device SDKs author: ryanwinter ms.author: baanders ms.date: 03/11/2025 ms.topic: tutorial ms.service: azure-iot ms.custom: devx-track-azurecli #Customer intent: As a device builder, I want to see how I can use the MQTT protocol to create an IoT device client without using the Azure IoT Device SDKs. --- # Tutorial - Use MQTT to develop an IoT device client without using a device SDK You should use one of the Azure IoT Device SDKs to build your IoT device clients if at all possible. However, in scenarios such as using a memory constrained device, you might need to use an MQTT library to communicate with your IoT hub. The samples in this tutorial use the [Eclipse Mosquitto](http://mosquitto.org/) MQTT library. In this tutorial, you learn how to: * Build the C language device client sample applications. * Run a sample that uses the MQTT library to send telemetry. * Run a sample that uses the MQTT library to process a cloud-to-device message sent from your IoT hub. * Run a sample that uses the MQTT library to manage the device twin on the device. You can use either a Windows or Linux development machine to complete the steps in this tutorial. If you don't have an Azure subscription, create a [free account](https://azure.microsoft.com/pricing/purchase-options/azure-account?cid=msft_learn) before you begin. ## Prerequisites ### Development machine prerequisites # [Windows](#tab/windows) 1. Install [Visual Studio (Community, Professional, or Enterprise)](https://visualstudio.microsoft.com/downloads). Be sure to enable the **Desktop development with C++** workload. 1. Install [CMake](https://cmake.org/download/). Enable the **Add CMake to the system PATH for all users** option. 1. Install the **x64 version** of [Mosquitto](https://mosquitto.org/download/). # [Linux](#tab/linux) 1. Run the following command to install the build tools: ```bash sudo apt install cmake g++ ``` 1. Run the following command to install the Mosquitto client library: ```bash sudo apt install libmosquitto-dev ``` --- [!INCLUDE [azure-cli-prepare-your-environment-h3](~/reusable-content/azure-cli/azure-cli-prepare-your-environment-h3.md)] ## Set up your environment If you don't already have an IoT hub, run the following commands to create a free-tier IoT hub in a resource group called `mqtt-sample-rg`. The command uses the name `my-hub` as an example for the name of the IoT hub to create. Choose a unique name for your IoT hub to use in place of `my-hub`: ```azurecli-interactive az group create --name mqtt-sample-rg --location eastus az iot hub create --name my-hub --resource-group mqtt-sample-rg --sku F1 ``` Make a note of the name of your IoT hub, you need it later. Register a device in your IoT hub. The following command registers a device called `mqtt-dev-01` in an IoT hub called `my-hub`. Be sure to use the name of your IoT hub: ```azurecli-interactive az iot hub device-identity create --hub-name my-hub --device-id mqtt-dev-01 ``` Use the following command to create a SAS token that grants the device access to your IoT hub. Be sure to use the name of your IoT hub: ```dotnetcli az iot hub generate-sas-token --device-id mqtt-dev-01 --hub-name my-hub --du 7200 ``` Make a note of the SAS token the command outputs as you need it later. The SAS token looks like `SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761` > [!TIP] > By default, the SAS token is valid for 60 minutes. The `--du 7200` option in the previous command extends the token duration to two hours. If it expires before you're ready to use it, generate a new one. You can also create a token with a longer duration. To learn more, see [az iot hub generate-sas-token](/cli/azure/iot/hub#az-iot-hub-generate-sas-token). [!INCLUDE [iot-authentication-device-connection-string](../../includes/iot-authentication-device-connection-string.md)] ## Clone the sample repository Use the following command to clone the sample repository to a suitable location on your local machine: ```cmd git clone https://github.com/Azure-Samples/IoTMQTTSample.git ``` The repository also includes: * A Python sample that uses the `paho-mqtt` library. * Instructions for using the `mosquitto_pub` CLI to interact with your IoT hub. ## Build the C samples Before you build the sample, you need to add the IoT hub and device details. In the cloned IoTMQTTSample repository, open the _mosquitto/src/config.h_ file. Add your IoT hub name, device ID, and SAS token as follows. Be sure to use the name of your IoT hub: ```c // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #define IOTHUBNAME "my-hub" #define DEVICEID "mqtt-dev-01" #define SAS_TOKEN "SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761" #define CERTIFICATEFILE CERT_PATH "IoTHubRootCA.crt.pem" ``` > [!NOTE] > The *IoTHubRootCA.crt.pem* file includes the CA root certificates for the TLS connection. Save the changes to the _mosquitto/src/config.h_ file. To build the samples, run the following commands in your shell: ```bash cd mosquitto cmake -Bbuild cmake --build build ``` In Linux, the binaries are in the _./build_ folder underneath the _mosquitto_ folder. In Windows, the binaries are in the _.\build\Debug_ folder underneath the _mosquitto_ folder. ## Send telemetry The *mosquitto_telemetry* sample shows how to send a device-to-cloud telemetry message to your IoT hub by using the MQTT library. Before you run the sample application, run the following command to start the event monitor for your IoT hub. Be sure to use the name of your IoT hub: ```azurecli-interactive az iot hub monitor-events --hub-name my-hub ``` Run the _mosquitto_telemetry_ sample. For example, on Linux: ```bash ./build/mosquitto_telemetry ``` The `az iot hub monitor-events` generates the following output that shows the payload sent by the device: ```output Starting event monitor, use ctrl-c to stop... { "event": { "origin": "mqtt-dev-01", "module": "", "interface": "", "component": "", "payload": "Bonjour MQTT from Mosquitto" } } ``` You can now stop the event monitor. ### Review the code The following snippets are taken from the _mosquitto/src/mosquitto_telemetry.cpp_ file. The following statements define the connection information and the name of the MQTT topic you use to send the telemetry message: ```c #define HOST IOTHUBNAME ".azure-devices.net" #define PORT 8883 #define USERNAME HOST "/" DEVICEID "/?api-version=2020-09-30" #define TOPIC "devices/" DEVICEID "/messages/events/" ``` The `main` function sets the user name and password to authenticate with your IoT hub. The password is the SAS token you created for your device: ```c mosquitto_username_pw_set(mosq, USERNAME, SAS_TOKEN); ``` The sample uses the MQTT topic to send a telemetry message to your IoT hub: ```c int msgId = 42; char msg[] = "Bonjour MQTT from Mosquitto"; // once connected, we can publish a Telemetry message printf("Publishing....\r\n"); rc = mosquitto_publish(mosq, &msgId, TOPIC, sizeof(msg) - 1, msg, 1, true); if (rc != MOSQ_ERR_SUCCESS) { return mosquitto_error(rc); } printf("Publish returned OK\r\n"); ``` To learn more, see [Sending device-to-cloud messages](./iot-mqtt-connect-to-iot-hub.md#send-device-to-cloud-messages). ## Receive a cloud-to-device message The _mosquitto_subscribe_ sample shows how to subscribe to MQTT topics and receive a cloud-to-device message from your IoT hub by using the MQTT library. Run the _mosquitto_subscribe_ sample. For example, on Linux: ```bash ./build/mosquitto_subscribe ``` Run the following command to send a cloud-to-device message from your IoT hub. Be sure to use the name of your IoT hub: ```azurecli-interactive az iot device c2d-message send --hub-name my-hub --device-id mqtt-dev-01 --data "hello world" ``` The output from _mosquitto_subscribe_ looks like the following example: ```output Waiting for C2D messages... C2D message 'hello world' for topic 'devices/mqtt-dev-01/messages/devicebound/%24.mid=d411e727-...f98f&%24.to=%2Fdevices%2Fmqtt-dev-01%2Fmessages%2Fdevicebound&%24.ce=utf-8&iothub-ack=none' Got message for devices/mqtt-dev-01/messages/# topic ``` ### Review the code The following snippets are taken from the _mosquitto/src/mosquitto_subscribe.cpp_ file. The following statement defines the topic filter the device uses to receive cloud to device messages. The `#` is a multi-level wildcard: ```c #define DEVICEMESSAGE "devices/" DEVICEID "/messages/#" ``` The `main` function uses the `mosquitto_message_callback_set` function to set a callback to handle messages sent from your IoT hub and uses the `mosquitto_subscribe` function to subscribe to all messages. The following snippet shows the callback function: ```c void message_callback(struct mosquitto* mosq, void* obj, const struct mosquitto_message* message) { printf("C2D message '%.*s' for topic '%s'\r\n", message->payloadlen, (char*)message->payload, message->topic); bool match = 0; mosquitto_topic_matches_sub(DEVICEMESSAGE, message->topic, &match); if (match) { printf("Got message for " DEVICEMESSAGE " topic\r\n"); } } ``` To learn more, see [Use MQTT to receive cloud-to-device messages](./iot-mqtt-connect-to-iot-hub.md#receive-cloud-to-device-messages). ## Update a device twin The _mosquitto_device_twin_ sample shows how to set a reported property in a device twin and then read the property back. Run the _mosquitto_device_twin_ sample. For example, on Linux: ```bash ./build/mosquitto_device_twin ``` The output from _mosquitto_device_twin_ looks like the following example: ```output Setting device twin reported properties.... Device twin message '' for topic '$iothub/twin/res/204/?$rid=0&$version=2' Setting device twin properties SUCCEEDED. Getting device twin properties.... Device twin message '{"desired":{"$version":1},"reported":{"temperature":32,"$version":2}}' for topic '$iothub/twin/res/200/?$rid=1' Getting device twin properties SUCCEEDED. ``` ### Review the code The following snippets are taken from the _mosquitto/src/mosquitto_device_twin.cpp_ file. The following statements define the topics the device uses to subscribe to device twin updates, read the device twin, and update the device twin: ```c #define DEVICETWIN_SUBSCRIPTION "$iothub/twin/res/#" #define DEVICETWIN_MESSAGE_GET "$iothub/twin/GET/?$rid=%d" #define DEVICETWIN_MESSAGE_PATCH "$iothub/twin/PATCH/properties/reported/?$rid=%d" ``` The `main` function uses the `mosquitto_connect_callback_set` function to set a callback to handle messages sent from your IoT hub and uses the `mosquitto_subscribe` function to subscribe to the `$iothub/twin/res/#` topic. The following snippet shows the `connect_callback` function that uses `mosquitto_publish` to set a reported property in the device twin. The device publishes the message to the `$iothub/twin/PATCH/properties/reported/?$rid=%d` topic. The `%d` value is incremented each time the device publishes a message to the topic: ```c void connect_callback(struct mosquitto* mosq, void* obj, int result) { // ... other code ... printf("\r\nSetting device twin reported properties....\r\n"); char msg[] = "{\"temperature\": 32}"; char mqtt_publish_topic[64]; snprintf(mqtt_publish_topic, sizeof(mqtt_publish_topic), DEVICETWIN_MESSAGE_PATCH, device_twin_request_id++); int rc = mosquitto_publish(mosq, NULL, mqtt_publish_topic, sizeof(msg) - 1, msg, 1, true); if (rc != MOSQ_ERR_SUCCESS) // ... other code ... } ``` The device subscribes to the `$iothub/twin/res/#` topic and when it receives a message from your IoT hub, the `message_callback` function handles it. When you run the sample, the `message_callback` function gets called twice. The first time, the device receives a response from the IoT hub to the reported property update. The device then requests the device twin. The second time, the device receives the requested device twin. The following snippet shows the `message_callback` function: ```c void message_callback(struct mosquitto* mosq, void* obj, const struct mosquitto_message* message) { printf("Device twin message '%.*s' for topic '%s'\r\n", message->payloadlen, (char*)message->payload, message->topic); const char patchTwinTopic[] = "$iothub/twin/res/204/?$rid=0"; const char getTwinTopic[] = "$iothub/twin/res/200/?$rid=1"; if (strncmp(message->topic, patchTwinTopic, sizeof(patchTwinTopic) - 1) == 0) { // Process the reported property response and request the device twin printf("Setting device twin properties SUCCEEDED.\r\n\r\n"); printf("Getting device twin properties....\r\n"); char msg[] = "{}"; char mqtt_publish_topic[64]; snprintf(mqtt_publish_topic, sizeof(mqtt_publish_topic), DEVICETWIN_MESSAGE_GET, device_twin_request_id++); int rc = mosquitto_publish(mosq, NULL, mqtt_publish_topic, sizeof(msg) - 1, msg, 1, true); if (rc != MOSQ_ERR_SUCCESS) { printf("Error: %s\r\n", mosquitto_strerror(rc)); } } else if (strncmp(message->topic, getTwinTopic, sizeof(getTwinTopic) - 1) == 0) { // Process the device twin response and stop the client printf("Getting device twin properties SUCCEEDED.\r\n\r\n"); mosquitto_loop_stop(mosq, false); mosquitto_disconnect(mosq); // finished, exit program } } ``` To learn more, see [Use MQTT to update a device twin reported property](./iot-mqtt-connect-to-iot-hub.md#update-device-twins-reported-properties) and [Use MQTT to retrieve a device twin property](./iot-mqtt-connect-to-iot-hub.md#retrieve-device-twin-properties). ## Clean up resources [!INCLUDE [iot-pnp-clean-resources](../../includes/iot-pnp-clean-resources.md)] ## Next steps Now that you've learned how to use the Mosquitto MQTT library to communicate with IoT Hub, a suggested next step is to review the [MQTT Application samples](https://github.com/Azure-Samples/MqttApplicationSamples) on GitHub.
Success! Branch created successfully. Create Pull Request on GitHub
Error: