Skip to content

Getting started Part 1

Tomoaki edited this page Jun 4, 2015 · 5 revisions

About Client Application Framework

Let me briefly introduce the client application structure.
Structures are the same for Linux and Arduino applications.
Source codes Application.cpp and Application.ino are in ./AsyncMQTT-SN/AsyncClient/src directory.

First comes the declaration block, same as most applications.

#ifdef ARDUINO`
#include <MqttsnClientApp.h>
#include <MqttsnClient.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#else
#include "lib/MqttsnClientApp.h"
#include "lib/MqttsnClient.h"
#endif

#if defined(ARDUINO) && (defined(DEBUG_NW) || defined(DEBUG_MQTTSN) || defined(DEBUG))
#include <SoftwareSerial.h>
SoftwareSerial debug(8, 9);
#endif
    
using namespace std;
using namespace tomyAsyncClient;
extern MqttsnClient* theClient;      

Next block is to prepare configuration parameters related to UDP and Xbee, and to set up MQTT-SN.
For Client with Linux, IP addresses are obtained through DHCP server. In case of Arduino, MAC addresses and IP addresses must be explicitly set up.
Since SERCHGW, GWINFO, ADVERTISE messages will be broascasted, so we also need to specify Multicast IP address and Port No. Here we use the same values as with The Client and Gateway.
To set up MQTT-SN, I use KeepAlive to specify PINGREQ transmission interval in seconds.
If you want Will Messages, you can use WillTopic or WillMessage to specify character strings. Otherwise, use 0. “” null character cannot be used.
To set up for XBee, go to line 43 in MqttsnClentApp.h, and Comment Out ‘#define NETWORK_UDP’, this will lead you to the set-up.

/*============================================
 *
 *      MQTT-SN Client Application
 *
 *===========================================*/
 #ifdef NETWORK_XBEE
 XBEE_APP_CONFIG = {
    {
        "client01",     //ClientId
        38400,          //Baudrate
        0,              //Serial PortNo (for Arduino App)
        "/dev/ttyUSB0"  //Device (for linux App)
    },
    {
        300,            //KeepAlive
        true,           //Clean session
        false,          //EndDevice
        "xxxx/willTopic",    //WillTopic   or 0   DO NOT USE NULL STRING "" !
        "willMessage"   //WillMessage or 0   DO NOT USE NULL STRING "" !
    }
 };
#endif

#ifdef NETWORK_UDP
UDP_APP_CONFIG = {
    {
  	    "LinuxClient",      //ClientId
        {225,1,1,1},        // Multicast group IP
        1883,               // Multicast group Port
        {0,0,0,0},          // Local IP     (for Arduino App)
        12001,              // Local PortNo
        {0,0,0,0,0,0}       // MAC address  (for Arduino App)
    },
    {
        300,            //KeepAlive
        true,           //Clean session
        false,          //EndDevice
        "willTopic",    //WillTopic   or 0   DO NOT USE NULL STRING "" !
        "willMessage"   //WillMessage or 0   DO NOT USE NULL STRING "" !
    }
};
#endif

Next block is to define Topics that will be used in the application.
You should replace the XXXX accordingly. The Broker we will be using is test.mosquitto.org. Topics are shared by all users, so try not to overlap with others.

/*------------------------------------------------------
 *             Create Topic
 *------------------------------------------------------*/
const char* topic1 = "xxxx/onoff/arduino";
const char* topic2 = "xxxx/onoff/linux";    

Next block define tasks, which are activated periodically, as functions.
Function format is void func(void), multiple tasks are allowed.
PUBLISH(Topic*,Payload*,QoS) can be put within a task. Payload is the Class of binary data transmitted by PUBLISH messages. The format uses subset of MessagePack to compress data. Below shows how this is done:

/*------------------------------------------------------
 *             Tasks invoked by Timer
 *------------------------------------------------------*/

static bool onoffFlg = true;

void task1(void){
    printf("TASK1 invoked\n");
    Payload* pl = new Payload(10);  // This payload is deleted by PublishManager.
    onoffFlg = !onoffFlg;
    pl->set_bool(onoffFlg);
    PUBLISH(topic2,pl,2);
}

void task2(void){
    printf("TASK2 invoked\n");
}

Time intervals for the above tasks to be executed are set in seconds. Task1 has 2 seconds, task 2 has 20 seconds interval between executions.

/*---------------  List of task invoked by Timer ------------*/

TASK_LIST = {//TASK( const char* topic, executing duration in second),
             TASK(task1,15),
             TASK(task2,20),
             END_OF_TASK_LIST
            };

Define functions to be executed when the subscribed Topic is PUBLISHed. Use SUBSCRIBE_LIST to link Topics and Functions, specify QoS to PUBLISH.
Multiple functions are allowed. INDICATOR_ON(bool), SUBSCRIBE_LIST, SUB and END_OF_SUBSCRIBE_LIST are all Macro.

/*------------------------------------------------------
 *       Tasks invoked by PUBLISH command Packet
 *------------------------------------------------------*/

int on_publish(Payload* payload){
    printf("ON_PUBLISH invoked.  ");
    INDICATOR_ON(payload->get_bool(0));
    return 0;
}

/*------------ Link Callback to Topic -------------*/

SUBSCRIBE_LIST = {//SUB(topic, callback, QoS=0or1),
                  SUB(topic2, on_publish, 1),
                  END_OF_SUBSCRIBE_LIST
                 };

Next block define functions for interruption process and initialization. For our test, there is no need to do this.

/*------------------------------------------------------
 *            Tasks invoked by INT0 interruption
 *------------------------------------------------------*/
void interruptCallback(void){

}

Next block defines initial function of the application.

/*------------------------------------------------------
 *            setup() function
 *------------------------------------------------------*/
 void setup(void){

 }

That is all we need for Client Application. Library will take care of the rest.
Declare TASK_LIST and SUBSCRIBE_LIST, and we are done!

Clone this wiki locally