nRF5 IoT SDK  v0.9.0
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
Publisher / Subscriber example

Overview

These example applications demonstrate how lwIP stack on nRF5x and the MQTT protocol can be used to talk to a Xively cloud service.

The example consists of two MQTT clients that realize the publish-subscribe pattern:

  • MQTT Publisher
  • MQTT Subscriber

The MQTT Publisher application can periodically update the state of a data channel (Thermometer), while the MQTT Subscriber can receive notifications about these updates.

To properly identify IoT devices, Xively uses Feed ID and API Key parameters. A Feed is the collection of channels (datastreams) defined for a device with additional metadata, such as location, whether the device is physical/virtual, fixed/mobile, indoor/outdoor, etc. An API Key determines the levels of permissions for access to Xively resources. Feed Id and API Key are generated automatically. However, you can change the API Key on the device's webpage.

These parameters and the channel name are hardcoded in the header section of main.c file of both applications. Parameters of your device can simply be put into quotation marks (without brackets).

#define APP_MQTT_XIVELY_CHANNEL "Thermometer" /**< Device's Channel name. */
#define APP_MQTT_XIVELY_FEED_ID "{PUT FEED ID HERE}" /**< Device's Feed ID. E.g. "1234567890" */
#define APP_MQTT_XIVELY_API_KEY "{PUT API KEY HERE}" /**< API key used for authentication. E.g. "abcdef123456" */
Note
To communicate with the cloud service, IPv6 global connectivity is required for the applications.

The IPv6 address of the Xively MQTT Broker is hardcoded in main.c.

For more information about the data format, protocols and API of Xively cloud, please refer to Xively REST API

The setup of the example applications is presented in Figure 1.


MQTT_Xively_Overall.svg
Figure 1: Setup of the cloud example applications for Xively.


Any recent data that has been published on MQTT publisher and has been received on MQTT subscriber is also transmitted through the serial device and terminal program (such as PUTTY) so that it can be used to monitor the COM port of each development kit through a terminal session.

The sequence of MQTT messages exchanged between the example applications and the MQTT broker is shown in Figure 2.

msc_02_xively_examples
Figure 2: Message sequence chart.

Xively MQTT Publisher

This application serves as a data source, sending periodic updates (at the interval of 10 seconds) with simulated temperature within the range 17.00 - 24.00 °C.

The Xively cloud accepts JSON data representation. For more information, see /v2/feeds/FEED_ID.json. The simulated temperature is sent using the following format:

{
"datastreams":
[
{
"id": "Thermometer",
"current_value" : "XX.00"
}
]
}

Pressing Button 1 triggers the MQTT connection establishment process and after its successful completion nRF5x kit starts publishing the timer. It is also possible to close the connection by pressing Button 2.

MQTT Xively publisher indicates the remainder of the temperature value with division by 4 on LED 3 and LED 4. So, for example, if the current value is 17, then LED3 is OFF and LED4 is ON indicating that the remainder is 1.

If the MQTT Publish Request is sent successfully, a new datapoint is registered on the MQTT cloud and it appears in the graph on the web interface (Figure 3).

11_xively_graph.png
Figure 3: Presenting data in value/time format.

Common module dependency and usage

This section summarizes the usage of nRF5x resources and common modules in the examples apart from the IoT 6lowpan and IPv6 stack library.

Module Inclusion/Usage Description
Timer 3 Three timers are used for IoT timer, buttons and for application purpose
Buttons 2 Buttons are used for initiating MQTT requests. See Button assignments section for details.
LEDs 4 LEDs are used to indicate the application states. See LED assignments section for details.
Adv Data Encoder Yes The device name used is 'MQTTXivelyPublisher', IPSP Service UUID is included in the UUID list.
Scheduler No Sceduler is not used for timer or stack events.
UART Trace Yes Tracing used to help mointor state of application.

Setup

The source code and project files of the example can be found in the following folder:
<InstallFolder>/examples/iot/cloud/mqtt/publisher

LED assignments

LED 1 LED 2 LED 3 LED 4
Blinking Off Off Off Device advertising as BLE peripheral.
On Blinking Off Off BLE link established, IPv6 interface down.
On Off Off Off IPv6 interface up.
Off On Off Off MQTT connection established.
Off On On/Off On/Off Recently sent temperature value (LED 3 LED 4 = temperature modulo 4).
For example, value of 17 = LED 3 OFF, LED 4 ON.
Value of 19 = LED 3 ON, LED 4 ON
On On On On Assertion failure in the application.

Button assignments

Button 1 Button 2
MQTT Xively Connection request.
Start periodic data updates.
MQTT Xively Disconnection request.
Stop periodic data updates.
Note
If commissioning is enabled, additional LED and Button assignments are made.

The example by default requests a secure connection on MQTT Secure port 8883. In order to disable security for MQTT clients, please follow the following setps.

  1. Change the MQTT broker port from 8883 to 1883.
  2. Edit the connection parameters for the mqtt_connect request as below. Change from:
    m_app_mqtt_id.transport_type = MQTT_TRANSPORT_SECURE;
    m_app_mqtt_id.p_security_settings = &m_tls_keys;
    uint32_t err_code = mqtt_connect(&m_app_mqtt_id);
    APP_ERROR_CHECK(err_code);
    To:
    m_app_mqtt_id.transport_type = MQTT_TRANSPORT_NON_SECURE;
    m_app_mqtt_id.p_security_settings = NULL;
    uint32_t err_code = mqtt_connect(&m_app_mqtt_id);
    APP_ERROR_CHECK(err_code);

Testing

See Connecting devices to the router for a list of relevant Linux commands.

  1. Compile and program the application. Observe that the device is advertising.
  2. Open a terminal program (for example PUTTY) to monitor the messages from the kit on the COM port.
  3. Prepare the Linux router device by initializing the 6LoWPAN module.
  4. Discover the advertising device by using the hcitool lescan command.
  5. Connect to the discovered device from the Linux console using the Bluetooth 6LoWPAN connect command.
  6. Check if the connected state is reflected by the LEDs (LED 2 is ON).
  7. Ensure that the kit has an IPv6 Internet connection.
  8. Push Button 1 on the kit and keep an eye on your terminal and LEDs. In addition, Wireshark with MQTT dissector can be used to track data exchange.
  9. Observe that LED 2 is ON, which means that the connection is established. In case the LED 2 is not turned on within 30 seconds, the procedure might have failed. This can be verified by observing a notification of MQTT_EVT_CONNECT with a failure (non-zero result code). Retry MQTT connection by pushing button 1. Pushing the button before the procedure is complete, either with success or failure, will result in application assertion.
  10. Observe that LED 3 and LED 4 change their state every 10 seconds.
  11. Check the Graph on the Xively web interface to see the new datapoints plotted.
  12. Push Button 2 on the kit.
  13. Observe that LED 2 is OFF, which means that the connection is closed.
  14. Disconnect from the device by using the Bluetooth 6LoWPAN disconnect command.
  15. Observe that LED 1 is blinking and that the device is advertising.

It is also possible to test Xively MQTT publisher without using another nRF5x kit with Xively MQTT Subscriber code. This part can be simulated with the following program.

Note
Remember to set a proper Feed Id and API Key.
# Installation of mosquitto clients, if needed.
sudo apt-get install mosquitto-clients
# Run MQTT subscriber
mosquitto_sub -h api.xively.com -t /v2/feeds/{FEED_ID}.json -u {API_KEY}

Xively MQTT Subscriber

This application acts as a MQTT subscriber that subscribes to the following topic: /v2/feeds/FEED_ID.json.

Pressing Button 1 triggers the MQTT connection establishment process and after its successful completion the nRF5x kit will send a subscribe message to the MQTT broker. Immediately after that the MQTT broker will send a MQTT Publish message with the actual value of the Thermometer channel. It is also possible to close the connection by pressing Button 2.

Xively MQTT Subscriber receives data from Xively MQTT Broker in JSON format. The application looks for the "current_value" string and converts the string temperature value to a decimal one. Finally, the remainder of the temperature value with division by 4 is presented on LED 3 and LED 4.

With a proper setup, Xively MQTT Subscriber should indicate the same status of LED 3 and LED 4 as Xively MQTT Publisher with a small delay.

Common module dependency and usage

This section summarizes the usage of nRF5x resources and common modules in the examples apart from the IoT 6lowpan and IPv6 stack library.

Module Inclusion/Usage Description
Timer 3 Three timers are used for IoT timer, buttons and for application purpose
Buttons 2 Buttons are used for initiating MQTT requests. See Button assignments section for details.
LEDs 4 LEDs are used to indicate the application states. See LED assignments section for details.
Adv Data Encoder Yes The device name used is 'MQTTXivelySubscriber', IPSP Service UUID is included in the UUID list.
Scheduler No Sceduler is not used for timer or stack events.
UART Trace Yes Tracing used to help mointor state of application.

Setup

The source code and project files of the example can be found in the following folder:
<InstallFolder>/examples/iot/cloud/mqtt/subscriber

LED assignments

LED 1 LED 2 LED 3 LED 4
Blinking Off Off Off Device advertising as BLE peripheral.
On Blinking Off Off BLE link established, IPv6 interface down.
On Off Off Off IPv6 interface up.
Off On Off Off MQTT connection established.
Off On On/Off On/Off Actual received temperature value (LED 3 LED 4 = temperature modulo 4).
For example, value of 17 = LED 3 OFF, LED 4 ON.
Value of 19 = LED 3 ON, LED 4 ON
On On On On Assertion failure in the application.

Button assignments

Button 1 Button 2
MQTT Xively Connection request.
Start periodic data updates.
MQTT Xively Disconnection request.
Stop periodic data updates.
Note
If commissioning is enabled, additional LED and Button assignments are made.

The example by default requests a secure connection on MQTT Secure port 8883. In order to disable security for MQTT clients, please follow the following setps.

  1. Change the MQTT broker port from 8883 to 1883.
  2. Edit the connection parameters for the mqtt_connect request as below. Change from:
    m_app_mqtt_id.transport_type = MQTT_TRANSPORT_SECURE;
    m_app_mqtt_id.p_security_settings = &m_tls_keys;
    uint32_t err_code = mqtt_connect(&m_app_mqtt_client);
    APP_ERROR_CHECK(err_code);
    To:
    m_app_mqtt_id.transport_type = MQTT_TRANSPORT_NON_SECURE;
    m_app_mqtt_id.p_security_settings = NULL;
    uint32_t err_code = mqtt_connect(&m_app_mqtt_client);
    APP_ERROR_CHECK(err_code);

Testing

See Connecting devices to the router for a list of relevant Linux commands.

Test steps:

  1. Compile and program the application. Observe that the device is advertising.
  2. Open a terminal program (for example PUTTY) to monitor the messages from the kit on the COM port.
  3. Open the serial port terminal to monitor messages from the kit.
  4. Prepare the Linux router device by initializing the 6LoWPAN module.
  5. Discover the advertising device by using the hcitool lescan command.
  6. Connect to the discovered device from the Linux console using the Bluetooth 6LoWPAN connect command.
  7. Check if the connected state is reflected by the LEDs (LED 2 is ON).
  8. Ensure that the kit has an IPv6 Internet connection.
  9. Push Button 1 on the kit and keep an eye on your terminal and LEDs. In addition, Wireshark with SSL/MQTT dissector can be used to track data exchange.
  10. Observe that LED 2 is ON, which means that the connection is established. In case the LED 2 is not turned on within 30 seconds, the procedure might have failed. This can be verified by observing a notification of MQTT_EVT_CONNECT with a failure (non-zero result code). Retry MQTT connection by pushing button 1. Pushing the button before the procedure is complete, either with success or failure, will result in application assertion.
  11. Observe that LED 3 and LED4 change their state on the current temperature update. This update can be triggered by Xively MQTT Publisher, python code, or directly on the Xively webpage.
  12. Push Button 2 on the kit.
  13. Observe that LED2 is OFF, which means that the connection is closed.
  14. Disconnect from the device by using the Bluetooth 6LoWPAN disconnect command.
  15. Observe that LED 1 is blinking and that the device is advertising.

It is also possible to test Xively MQTT Subscriber without using another nRF5x kit with Xively MQTT Publisher code. This part can be simulated with the following Python program.

Note
Remember to set a proper Feed Id and API Key.
Remember to change the current_value (from 17.00 to 24.00) to receive a new notification.
# Installation of mosquitto clients, if needed.
sudo apt-get install mosquitto-clients
# Run MQTT Publisher
mosquitto_pub -h api.xively.com -t /v2/feeds/{FEED_ID}.json -u {API_KEY} -m '{"datastreams":[{"id":"Thermometer","current_value":"17.00"}]}'

Restrictions

In the demonstration version of Xively cloud, some restrictions have been identified:

  1. After hundreds of seconds the MQTT connection in TCP level is dropped. Thus, an auto reconnection was implemented in the Xively example.
  2. Xively has usage limits that may cause a problem with connection or publishing/notification procedure, and so publishing interval of 10 seconds was chosen. For more information, see Usage limits
  3. By subscribing to the actual datastream (Thermometer, for example) instead of the whole feed (as it is on example), a subscriber may not receive the latest data in a notification.
  4. If multiple channels are created under the same feed id on Xively, subscriber parsing of published data fails.