Introduction

This workshop shows how to use the SimpleLink™ Wi-Fi® MQTT library, which enables you to connect as a MQTT Client to a cloud MQTT broker and/or create a local MQTT broker that can serve as a gateway for local MQTT clients.

This workshop will provide a brief overview of the MQTT protocol and then walk through some fundamental MQTT demos:

  1. MQTT Client Example
  2. MQTT Client-Server Example
  3. MQTT Client Example with secure connection

Prerequisites

Software

  • Code Composer Studio v9.1 or newer
    • SimpleLink Wi-Fi CC32xx Wireless MCUs support installed
    • Make sure that CCS is using the latest updates: HelpCheck for Updates
  • CC32xx SDK v3.20.00.06 or newer OR
  • SimpleLink SDK Wi-Fi Plugin v2.40.00.22 (if you are using a CC31xx BoosterPack)
  • UniFlash v5.0.0 or newer
  • Terminal emulator program such as TeraTerm or PuTTY
  • MQTT client application on an internet-connected smartphone/computer (e.g. MyMQTT for Android, ICPDAS MQTT for iOS)

Hardware

Instead of using a CC32xx LaunchPad, the following hardware can also be used:

Note

The MQTT Client-Server exercise in this lab requires two LaunchPads. The MQTT Client exercise can be completed with one LaunchPad.

MQTT Overview

MQTT Protocol

MQTT (Message Queue Telemetry Transport) protocol is a light-weight machine-to-machine connectivity protocol. It is based on a publish/subscribe messaging model and is designed to be used on the top of TCP/IP protocol. Key benefits of this protocol include small code footprint and a low network bandwidth requirement. Other features include faster response time, low power requirement, and ease of scalability. All of these advantages make it an ideal candidate for a communication protocol in embedded devices intended to implement IOT (Internet of Things) applications.

A Simple MQTT infrastructure contains a broker (like a central hub) connected to multiple clients, each of which has the capability of publishing on any topic (token). The broker has the responsibility of sending the message published on any topic to all the subscribers of that topic. A typical MQTT network has many more features and configuration parameters.

The MQTT library abstracts the underlying intricacies of a MQTT network and provides the user application with an intuitive and easy to use API to implement the MQTT protocol on the CC32xx device. Separate modules and APIs are used for the MQTT Server and the MQTT Client functionality.

The Client API includes the following:

  • Create (or delete) a client instance
  • Connect to an MQTT server (based on URL or IP Address)
  • Subscribe (or unsubscribe) to a topic
  • Publish a topic and a message
  • Run the client main task loop

The Server has a similar interface excluding the Connect command. The source for the MQTT library can be found under simplelink_cc32xx_sdk_x_xx_xx_xx\source\ti\net\mqtt

MQTT Client Demo

This application uses the MQTT Client API to communicate with an Eclipse M2M broker. Three LEDs on the Launchpad can be controlled from a remote MQTT client by publishing messages on appropriate topics. Similarly, a message can be published on pre-configured topics (defined in the code) by pressing a button on the host platform.

Task 1: Preparing the MQTT Client application

  1. In CCS, go to the menu Project → Import CCS Projects...
  2. Follow the appropriate step below to import the mqtt_client example depending on which device you are using.

    • Be sure you select your desired project "flavor" (CC3235S-LAUNCHXL, MSP432P401R, TI-RTOS, Free-RTOS, CCS, GCC, etc.).
    • This lab will be demonstrate the CC3220 TI-RTOS CCS example: mqtt_client_CC32xxSF_LAUNCHXL_tirtos_ccs

      Browse to the SimpleLink CC32xx SDK on your local hard drive and select the mqtt_client example: simplelink_cc32xx_sdk_x_xx_xx_xx\examples\rtos\CC3220SF_LAUNCHXL\demos\mqtt_client

      Browse to the SimpleLink SDK Wi-Fi Plugin on your local hard drive and select the mqtt_client example: simplelink_sdk_wifi_plugin_x_xx_xx_xx\examples\rtos\<supported host>\demos\mqtt_client

  3. Set the local access point parameters (SSID_NAME, SECURITY_TYPE and SECURITY_KEY) defined in network_if.h so they are configured according to your local access point.

  4. Take a look at your MQTT settings. They can be found in the macros at the beginning of mqtt_client_app.c. The important ones are:

    • SERVER_ADDRESS
    • PORT_NUMBER
    • Subscription topics:
      • SUBSCRIPTION_TOPIC0
      • SUBSCRIPTION_TOPIC1
      • etc.
    • ClientId (must be unique)
    • If ClientId is not specified, it is by default set to the local MAC Address in SetClientIdNamefromMacAddress()
    • Publishing topics:
      • publish_topic
      • publish_data

In this example, the client subscribes to 4 topics and publishes to 1 topic.

Task 2: Setting up the MQTT Client demo

  1. Download the correct certificates depending on your device.

    Open the UniFlash ImageCreator tool and add the entire "dummy" certificate chain as user files. You should also be sure you have flashed the latest servicepack. When you have all the files added correctly, your user file view in UniFlash ImageCreator will look as follows:

    Open the UniFlash ImageCreator tool and add the dummy-root-ca-cert as user files . You should also be sure you have flashed the latest servicepack. When you have the files added correctly, your user file view in UniFlash ImageCreator will look as follows:

  2. Flash and reset the LaunchPad to start the application, or start a CCS Debug session to load and run the application.

  3. Open a terminal emulation program such as TeraTerm and select the XDS110 Class Application/User UART port.

    UART Configuration
    Baud rate: 115200
    Data: 8 bit
    Parity: None
    Stop: 1 bit
    Flow control: None

  4. On a device connected to the internet, use your installed MQTT client (see lab prerequisites) to connect to the MQTT broker used by the CC32xx: m2m.eclipse.org

    • Verify that the port is 1883.
    • Leave all other settings as default, and Connect.

      Note

      Ensure that the Username and Password fields are left blank. By default, the MQTT client application does not set the Client Username and Client Password. However, this can be enabled by uncommenting the CLNT_USR_PWD macro in mqtt_client_app.c.

Task 3: Running the MQTT Client application

  1. Send a message from the Eclipse M2M client to the SimpleLink device by publishing the /cc3200/ToggleLEDCmdL<x> topic (the x should be between 1 and 3). You should see the corresponding LED toggle on the MCU device.

  2. Use /Broker/To/cc32xx topic to send a text message that will be printed on the console.

  3. Using the MQTT client app, subscribe to the topic published by the SimpleLink client (/cc32xx/ButtonPressEvtSw2).

  4. Send a message from the SimpleLink device to the Eclipse client by pressing the SW2 button on the Launchpad (or the corresponding button in your setup).

    Buttons on the LaunchPad

    Press the button listed below for your device.

    CC32xx Rev A LaunchPad: SW2

    CC3220S/SF Rev B LaunchPad: SW3

    MSP432P4 LaunchPad: S1

    MSP432E4 LaunchPad: SW1

    For more information on CC3220 LaunchPad revisions, refer to the CC3220 LaunchPad Development Kit Hardware User's Guide.

MQTT Client-Server Demo

In this example, the SimpleLink Wi-Fi device is running a MQTT server (“local broker”) which allows local MQTT clients to communicate with each other. Simultaneously, it is also running a client which is connected to a cloud broker. This operation mode is also called “bridge mode.” The interface between the on-board client and the server is such that the local clients can also communicate with the remote MQTT clients, which are connected to the same cloud broker as the on-board client.

MQTT allows remote control of an IOT device through a cloud-based broker. Every transaction through the external broker has a fee. The Client-Server demo demonstrates a solution for the local network that will eliminate the need for cloud broker access.

Within the local (home) network, the controlling device (typically a mobile phone) should connect to a local server rather than the cloud broker. The sample application demonstrates a working setup where multiple local MQTT clients can communicate with each other as well as talk to a remote client via an external broker.

For simplicity, the following abbreviations are used:

  • LC: MQTT Client (Local Client)
    • This can be the SimpleLink platform(s) running the MQTT Client application or a smartphone
  • LS: One SimpleLink platform running MQTT Server/Bridge (Local Server)
  • RC: Remote MQTT Client (mobile MQTT app connected to the Eclipse MQTT Broker)
  • BR: External MQTT Broker (Eclipse MQTT Server, http://m2m.eclipse.org)
  • AP: The access point with internet connection

LC1, LC2, and LS are all connected to the same AP. The server address configuration for LC(s) is the local address of LS.

Task 4: Setting up the MQTT Server/Bridge

In this task, we are setting up the local MQTT server (LS) on a CC32xx LaunchPad.

  1. Import the correct mqtt_client_server example for your device. For this lab, we will be demonstrating the mqtt_client_server_CC3220SF_LAUNCHXL_tirtos_ccs example (simplelink_cc32xx_sdk_x_xx_xx_xx/examples/rtos/CC3220SF_LAUNCHXL/demos/mqtt_client_server/tirtos/ccs).

  2. Take a look at your settings for the MQTT Server/Bridge. They can be found in the macros at the beginning of mqtt_server_app.c. The important ones are:

    • SERVER_ADDRESS
    • ClientId
    • publish_topic
    • SUBSCRIPTION_TOPIC0
    • ENROLL_TOPIC: These events received by the local MQTT server, will be distributed (published) to the cloud server
  3. In network_if.h, update the SSID_NAME, SECURITY_TYPE, and SECURITY_KEY to connect to your own Access Point (like a router).

  4. Recompile the MQTT Client-Server application and flash it to your LS (Local Server) device.

Task 5: Setting up the MQTT Clients

In this task, we are setting up the local MQTT clients. We will set up the second CC32xx LaunchPad as LC1 and use a mobile app for LC2.

For additional instructions on CCS debugger, see task 2 of the Wi-Fi Fundamentals lab.

  1. We need to find the server IP address in order to set up the local client. To find the server IP address, start by running the MQTT Client-Server application on the target device with CCS debugger. This is your LS (Local Server).

  2. Open a terminal emulation program such as TeraTerm and select the XDS110 Class Application/User UART port.

    UART Configuration
    Baud rate: 115200
    Data: 8 bit
    Parity: None
    Stop: 1 bit
    Flow control: None

  3. Once the terminal is connected, run the Client-Server application and record the IP address. Enter this address in the SERVER_IP_ADDRESS definition inside the mqtt_client_app.c of the mqtt_client application.

  4. Use the rest of settings from the MQTT Client example we completed earlier (task 1).

  5. Search for the Mqtt_ClientCtx structure in mqtt_client_app.c in the Variables section. Set the flags and address to the local broker address (shown below). We need the Local Clients to be linked to the Local Server by IP address instead of the example's default URL.

     MQTTClient_ConnParams Mqtt_ClientCtx =
     {
     //    MQTTCLIENT_NETCONN_URL,
     //    SERVER_ADDRESS,
     //    PORT_NUMBER, 0, 0, 0,
     //    NULL
          0,
          SERVER_IP_ADDRESS,
          PORT_NUMBER, 0, 0, 0,
          NULL
     };
    

    mqtt_client_app.c :: Mqtt_ClientCtx

  6. Check that the three LEDs are being configured in the board files (Board.h, CC3220SF_LAUNCHXL.h and CC3220SF_LAUNCHXL.c). If missing, add the following code:

     #define Board_GPIO_LED0              CC3220SF_LAUNCHXL_GPIO_LED_D7
     #define Board_GPIO_LED1              CC3220SF_LAUNCHXL_GPIO_LED_D6
     #define Board_GPIO_LED2              CC3220SF_LAUNCHXL_GPIO_LED_D5
    

    Board.h

     typedef enum CC3220SF_LAUNCHXL_GPIOName {
         CC3220SF_LAUNCHXL_GPIO_SW2 = 0,
         CC3220SF_LAUNCHXL_GPIO_SW3,
         CC3220SF_LAUNCHXL_GPIO_LED_D7,
         CC3220SF_LAUNCHXL_GPIO_LED_D6,
         CC3220SF_LAUNCHXL_GPIO_LED_D5,
    
         CC3220SF_LAUNCHXL_GPIOCOUNT
     } CC3220SF_LAUNCHXL_GPIOName;
    

    CC3220SF_LAUNCHXL.h

     GPIO_PinConfig gpioPinConfigs[] = {
         /* input pins with callbacks */
         /* CC3220SF_LAUNCHXL_GPIO_SW2 */
         GPIOCC32XX_GPIO_22 | GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING,
         /* CC3220SF_LAUNCHXL_GPIO_SW3 */
         GPIOCC32XX_GPIO_13 | GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING,
    
         /* output pins */
         /* CC3220SF_LAUNCHXL_GPIO_LED_D7 */
         GPIOCC32XX_GPIO_09 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
         /* CC3220SF_LAUNCHXL_GPIO_LED_D6 */
         GPIOCC32XX_GPIO_10 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
         /* CC3220SF_LAUNCHXL_GPIO_LED_D5 */
         GPIOCC32XX_GPIO_11 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
     };
    

    CC3220SF_LAUNCHXL.c

    If you are using a different device (CC3235x, MSP432P401R, etc.), adapt the code as needed.

  7. Recompile the mqtt_client application and program this to another LaunchPad. This is your LC1 (Local Client #1). LC1 should connect to LS.

  8. On your mobile app (LC2), connect to the same IP address you found with the MQTT server (task 5, step 3).

Task 6: Demo Local Communication (LC to LC)

This sequence demonstrates local communication, which is between two clients on a local network. LC1 -> LS -> LC2

In this demo, /cc32xx/ButtonPressEvtSw2 is the text for PUBLISH_TOPIC0. This message is triggered by pressing the SW2 on the CC32xx LaunchPad.

  1. Connect both local clients (LC1 and LC2) to the local server (LS).

  2. LC2 subscribes to PUBLISH_TOPIC0. (Use the text: /cc32xx/ButtonPressEvtSw2.)

  3. Press SW2 to publish PUBLISH_TOPIC0 from LC1.

    Buttons on the LaunchPad

    Press the button listed below for your device.

    CC32xx Rev A LaunchPad: SW2

    CC3220S/SF Rev B LaunchPad: SW3

    MSP432P4 LaunchPad: S1

    MSP432E4 LaunchPad: SW1

    For more information on CC3220 LaunchPad revisions, refer to the CC3220 LaunchPad Development Kit Hardware User's Guide.

Results

  • LC2 receives the event (message will be printed through the terminal).
  • Note that LS did not subscribe to the PUBLISH_TOPIC0, so LS shows nothing.
  • RC (Remote Client) and BR (external broker) show nothing.

Task 7: Demo Remote Control (RC to LC)

This sequence demonstrates communication between a remote client (through the cloud) and an IOT device. RC -> BR -> LS -> LC1

In this demo, /Broker/To/cc32xx will be the text for SUBSCRIPTION_TOPIC0. This message is triggered by entering text on RC.

Note

For rest of the lab, RC will be the same mobile app that we previously used as LC2. Instead of communicating over the local network, you can connect your mobile device to the internet via another AP or cellular network to demonstrate a remote client.

  1. LC1 subscribes to SUBSCRIPTION_TOPIC0. (Use the text: /Broker/To/cc32xx.)

  2. LS (as a client of the BR) also subscribes to the same topic. LS will forward any message it receives from BR to the local network.

  3. Publish the same text of SUBSCRIPTION_TOPIC0 (/Broker/To/cc32xx) from the Remote Client (RC).

Results

  • LS receives SUBSCRIPTION_TOPIC0 (see terminal), because topic is subscribed by LS.
  • LS will publish the message in the local network.
  • LC1 receives SUBSCRIPTION_TOPIC0 (see terminal) as a client on the local network.
  • Note LC2 shows nothing because it did not subscribe to SUBSCRIPTION_TOPIC0.

Task 8: Add a New Publish Function to MQTT Client

All the following modifications for this task are done within mqtt_client_CC3220SF_LAUNCHXL_tirtos_ccs/mqtt_client_app.c. We will be using this function later in the demos.

  1. Add the function below to mqtt_client_app.c. This publishes the status of the three LEDs.

     #include "stdio.h"
     #define PUBLISH_TOPIC1  "/cc32xx/To/Broker"
     const char *publish_topic1 = { PUBLISH_TOPIC1 };
    
     static void PublishLedStatusReport()
     {
         char pubMsg[20];
    
         /* retreive status of LEDs */
         sprintf(pubMsg, "L1=%d, L2=%d, L3=%d", GPIO_read(Board_GPIO_LED0), GPIO_read(Board_GPIO_LED1), GPIO_read(Board_GPIO_LED2));
         /* send publish message */
         MQTTClient_publish(gMqttClient, (char *)publish_topic1, strlen((char *)publish_topic1), pubMsg, 16, MQTT_QOS_2 | MQTT_PUBLISH_RETAIN);
    
         UART_PRINT("\n\r CC3220 Publishes the following message \n\r");
         UART_PRINT("Topic: %s\n\r", publish_topic1);
         UART_PRINT("Data: %s\n\r", pubMsg);
     }
    

    mqtt_client_app.c

  2. Add the PublishLedStatusReport() function call to the publish message case PUBLISH_PUSH_BUTTON_PRESSED in MqttClient() as shown below.

     PublishLedStatusReport();
    

    mqtt_client_app.c :: MqttClient()

  3. Recompile the mqtt_client application and program this to another CC32xx. This is still your LC1 (Local Client #1).

Task 9: Demo Remote Notification (LC to RC)

This sequence demonstrates an IOT device sending a notification to a remote client (through the local server and the cloud broker). LC1 -> LS -> BR -> RC

In this demo, /cc32xx/To/Broker will be the text for PUBLISH_TOPIC1 and ENROLLED_TOPIC.

  1. Subscribe RC to PUBLISH_TOPIC1. (Use the text: /cc32xx/To/Broker.)

  2. Enroll LS to topic ENROLLED_TOPIC which has the same string as PUBLISH_TOPIC1 (/cc32xx/To/Broker).

    • LS subscribes on an ENROLLED_TOPIC within the local network (as any other client). Whenever it will receive an enrolled message, LS will publish it to BR.
  3. Press SW2 to publish PUBLISH_TOPIC1 (/cc32xx/To/Broker) from LC1.

    Buttons on the LaunchPad

    Press the button listed below for your device.

    CC32xx Rev A LaunchPad: SW2

    CC3220S/SF Rev B LaunchPad: SW3

    MSP432P4 LaunchPad: S1

    MSP432E4 LaunchPad: SW1

    For more information on CC3220 LaunchPad revisions, refer to the CC3220 LaunchPad Development Kit Hardware User's Guide.

Results

  • LS receives PUBLISH_TOPIC1 (prints to terminal) and passes onto BR.
  • RC receives PUBLISH_TOPIC1 (prints to terminal).
  • LC2 shows nothing because it did not subscribe to PUBLISH_TOPIC1.

MQTT Secure Client Demo

These tasks will demonstrate the MQTT Client demo with a secure connection to the Eclipse broker. This will be done by using a TLS socket to communicate with the MQTT server. For more information on secure sockets, check out the Wi-Fi Secure Socket training.

Task 10: Enabling the Secured Client

  1. Find the SECURE_CLIENT define in the macros section of mqtt_client_app.c. Uncomment this to enable the secured client.

  2. Find the Mqtt_Client_secure_files array in mqtt_client_app.c, which by default has a size of 1 (as defined by CLIENT_NUM_SECURE_FILES). Change the string in this array from ca-cert.pem to a name of your choosing. In this example, we will name it to dstcert.cer.

  3. The final change needed to be made to mqtt_client_app.c is to update the MQTTClient_ConnParams struct. To connect sucessfully to the broker, the connection parameters need to be updated. Select the code below and replace the MQTTClient_ConnParams struct.

     MQTTClient_ConnParams Mqtt_ClientCtx = {
     MQTTCLIENT_NETCONN_URL | MQTTCLIENT_NETCONN_SEC |
     MQTTCLIENT_NETCONN_SKIP_CERTIFICATE_CATALOG_VERIFICATION |
     MQTTCLIENT_NETCONN_SKIP_DOMAIN_NAME_VERIFICATION,
     SERVER_ADDRESS,
     SECURED_PORT_NUMBER,
     SLNETSOCK_SEC_METHOD_SSLv3_TLSV1_2,
     SLNETSOCK_SEC_CIPHER_FULL_LIST,
     CLIENT_NUM_SECURE_FILES,
     Mqtt_Client_secure_files
     };
    

    mqtt_client_app.c

    What are the other MQTT connection parameters?

    These paramaters indicate that we want a secure connection, but we are skipping certificate catalog verification and domain name verification. For information on all of the MQTT library configurations, please see the Network Services API Reference Guide available in the SDK.

  4. To create a secure connection with the the Eclipse broker, we need to obtain the correct certificate. One way to do this is to obtain the certificate directly from the website. In this example, we will demonstrate this with Chrome as our browser.

    1. In your browser, go to https://iot.eclipse.org

    2. Next to the URL (in Chrome), click on the Lock symbol and then select on View Certificates to view the certificate for this website.

    3. In the Certificate window, click on the Certfication Path tab which will display the chain of certificates for this website. We are interested in the root certificate, which in this case is issued by DST ROOT CA X3. Double-click on this certificate.

    4. This will open up the Certificate tab for the root certificate. To download this certificate, click on DetailsCopy to File....

      Can't download the certificate?

      If the Copy to File button is grayed out for you, run your browser as an Administrator, and then try again.

    5. On the Certificate Export Wizard page, click Next, ensure that DER encoded binary X.509 is selected and click Next, and then save the certificate to your file system with the certificate name you picked earlier. In our example, it is dstcert.cer.

  5. Now that you have obtained the root certificate, use Uniflash ImageCreator to add it to the file system.

  6. Run tasks 2 and 3 from the MQTT Client Demo section and verify that you are able to successfully connect to the MQTT broker.

Want to test the security?

Do this task but flash the LaunchPad without the certificate we just added. It should fail to connect to the MQTT broker!

Technical support

For any questions, please search on the SimpleLink Wi-Fi E2E Forum

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.