Skip to content

MQTTSN client implementation

Łukasz Dmitrowski edited this page Aug 22, 2014 · 2 revisions

MQTT-SN protocol client implementation

This project was made during Google Summer of Code 2014 - 'MQTT-SN implementation for Wiselib'


Introduction

MQTT is machine-to-machine connectivity protocol. Is is designed to use publisher/subscriber message pattern and is very lightweight. Clients are connected to a MQTT broker and can work as publishers and subscribers. Publishers registers topics on a broker and then send messages for these certain topics, without a knowledge about any receivers. Subscribers express interest in one or more topics and receive only messages sent for topics which they are subscribed for.

MQTT specification

MQTT-SN is a variation of MQTT designed especially for sensor networks. It an open communication standard between devices that communicate with each other without human interaction. It is suitable for constrained environments which consist of low-power devices with limited processing capabilities. As MQTT-SN is slightly different from MQTT it is needed to use MQTT-SN gateway between clients and a broker.

MQTT-SN specification

Code structure

Code of MQTT-SN client is located in wiselib.testing/algorithms/protocols/mqttsn

messages - contains implementation of messages:

  • ADVERTISE
  • CONACK
  • CONNECT
  • DISCONNECT
  • GWINFO
  • PINGREQ
  • PINGRESP
  • PUBACK
  • PUBLISH
  • REGACK
  • REGISTER
  • SEARCHGW
  • SUBACK
  • SUBSCRIBE
  • UNSUBACK
  • UNSUBSCRIBE
  • WILLMSG
  • WILLMSGREQ
  • WILLTOPIC
  • WILLTOPICREQ

mqttsn_flex_static_string - simple string non template parameter class designed to create fixed size string objects without using dynamic allocation

mqttsn_messages.h - contains includes to all messages

mqttsn_topics.h - class which represents a container for registered/subscribed topics

mqttsn.h - class which represents an instance of a MQTT-SN client

Implementation

First thing to do when writing MQTT-SN client application is to create an instance and initialize it. This is a template of application:

#include "external_interface/external_interface.h"
#include "algorithms/protocols/mqttsn/mqttsn.h"

typedef wiselib::OSMODEL Os;
typedef wiselib::MqttSn<Os, Os::Radio> MqttSnClient;

class MqttsnExampleApplication
{
public:
    typedef MqttsnExampleApplication self_type;

    void init( Os::AppMainParameter& value )
    {
        radio_ = &wiselib::FacetProvider<Os, Os::Radio>::get_facet( value );
        timer_ = &wiselib::FacetProvider<Os, Os::Timer>::get_facet( value );
        debug_ = &wiselib::FacetProvider<Os, Os::Debug>::get_facet( value );
        rand_ = &wiselib::FacetProvider<Os, Os::Rand>::get_facet( value );

        debug_->debug( "Hello World from MqttSn Client!\n" );
        timer_->set_timer<MqttsnExampleApplication,  
                      &MqttsnExampleApplication::start>( 1000, this, 0 );
    }

    void start( void* )
    {
        // INITIALIZATION
        mqttsn_client.init( *radio_, *debug_, *timer_, *rand_ );
    }

    / --------------------------------------------------------------------

    private:
        Os::Radio::self_pointer_t radio_;
        Os::Timer::self_pointer_t timer_;
        Os::Debug::self_pointer_t debug_;
        Os::Rand::self_pointer_t rand_;
        MqttSnClient mqttsn_client;
};

// --------------------------------------------------------------------------
wiselib::WiselibApplication<Os, MqttsnExampleApplication> example_app;
// --------------------------------------------------------------------------

void application_main( Os::AppMainParameter& value )
{
    example_app.init( value );
}    

Before client is initialized we can set a type of connection procedure with will flag

  • Setting will connect - sets a will flag in CONNECT message and then provided will topic and will message will be sent as reponse for WILLTOPICREQ and WILLMSGREQ

    mqttsn_client.set_will_connect("ExampleTopic", "Not connected");

After client is initialized we can use MQTT specific operations like:

  • Topic registration - to publish a data for registered topic

    mqttsn_client.send_register("TopicToRegister");

  • Topic subscription - to receive data published for subscribed topic

    mqttsn_client.send_subscribe("TopicToSubscribe");

  • Topic unsubscription - to stop receiving data published for previously subscribed topic

    mqttsn_client.send_unsubscribe("TopicToUnsubscribe");

  • Publishing data - nodes which are subscribed for a topic which we publish for will receive a data

    block_data_t message[] = {'H','e','l','l','o','\0'}; mqttsn_client.send_publish("RegisteredTopicName", message, sizeof(message));

  • Will topic update - to update a topic previously provided by set_will_connect(...) function

    mqttsn_client.send_will_topic_update("WillTopicUpd");

  • Will message update - to update a message previously provided by set_will_connect(...) function

    mqttsn_client.send_will_msg_update("WillMessageUpd");

  • Delete will data - to delete will data previously provided by set_will_connect(...) function

    mqttsn_client.send_delete_will();

  • Disconnect - disconnects with currently connected gateway

    mqttsn_client.send_disconnect();

Registering callbacks for PUBLISH messages

It is possible to register a function which will process a data provided by PUBLISH function.

  • Global callback registration - registers a callback which will be used with every received PUBLISH message

    void myRecvPublish( const char* topic_name, block_data_t *data ) { ... }

    mqttsn_client.reg_recv_publish<self_type, &self_type::myRecvPublish>( this );

  • Specific topics callback registration - register a callback which will be used only for received PUBLISH messages connected with specified topic, this callback has higher priority than a global one

    void myRecvPublish( const char* topic_name, block_data_t *data )
    {
    ...
    }

    void myRecvPublish2( const char* topic_name, block_data_t *data )
    {
    ...
    }

    mqttsn_client.reg_recv_publish_topic<self_type, &self_type::myRecvPublish>(this, "Topic1");
    mqttsn_client.reg_recv_publish_topic<self_type, &self_type::myRecvPublish2>(this, "Topic2");


Check Example MQTT-SN network with use of Raspberry Pi and Arduino


Łukasz Dmitrowski