MQTT demo program for Nucleo F401RE and Seeedstudio W5200 Ethernet Shield which is based on Wiznet IBMIoTClientEthernetExample_W5500.

Dependencies:   MQTT W5200Interface mbed DHT11

Fork of IBMIoTClientEthernetExample_W5500 by W5500-Ethernet-Interface Makers

I post description regarding this source code here.

http://developer.mbed.org/users/hillkim7/notebook/ibmiotclientethernetexample_w5200/

main.cpp

Committer:
kaizen
Date:
2014-09-29
Revision:
1:532d83b9f910
Parent:
0:910036879da0
Child:
2:87c816cd88e2

File content as of revision 1:532d83b9f910:

#include "mbed.h"
#include "MQTTClient.h"
#include "MQTTEthernet.h"

// Configuration values needed to connect to IBM IoT Cloud
#define QUICKSTARTMODE 0
#if (QUICKSTARTMODE)
#define ORG "uasfg"
#define ID ""
#define AUTH_TOKEN "mhhWy4Qg)C*w3jL@(O"
#define TYPE "W5500"
#else
#define ORG "uasfg"
#define ID ""
#define AUTH_TOKEN "mhhWy4Qg)C*w3jL@(O"
#define TYPE "W5500"
#endif

#define MQTT_PORT 1883
#define MQTT_TLS_PORT 8883
#define IBM_IOT_PORT MQTT_PORT

#define MQTT_MAX_PACKET_SIZE 250


#define USING_HW_STACK_W5500

bool quickstartMode = (QUICKSTARTMODE) ? true : false;
char org[11] = ORG;  
char type[30] = TYPE;
char id[30] = ID;                 // mac without colons
char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode

bool connected = false;


char* getMac(EthernetInterface& eth, char* buf, int buflen)    // Obtain MAC address
{   
    strncpy(buf, eth.getMACAddress(), buflen);

    char* pos;                                                 // Remove colons from mac address
    while ((pos = strchr(buf, ':')) != NULL)
        memmove(pos, pos + 1, strlen(pos) + 1);
    return buf;
}


int connect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack)
{
    const char* iot_ibm = ".messaging.internetofthings.ibmcloud.com";

    char hostname[strlen(org) + strlen(iot_ibm) + 1];
    sprintf(hostname, "%s%s", org, iot_ibm);
    int rc = ipstack->connect(hostname, IBM_IOT_PORT);

    if (rc != 0)
        return rc;

    // Construct clientId - d:org:type:id
    char clientId[strlen(org) + strlen(type) + strlen(id) + 5];
    sprintf(clientId, "d:%s:%s:%s", org, type, id);
    DEBUG("clientid is %s\r\n", clientId);

    // MQTT Connect
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.MQTTVersion = 3;
    data.clientID.cstring = clientId;

    if (!quickstartMode)
    {
        data.username.cstring = "use-token-auth";
        data.password.cstring = auth_token;
    }

    if ((rc = client->connect(&data)) == 0)
    {
        connected = true;
    }

    return rc;
}


int getConnTimeout(int attemptNumber)
{  // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
   // after 20 attempts, retry every 10 minutes
    return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
}


void attemptConnect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack)
{
    int retryAttempt = 0;
    connected = false;

    // make sure a cable is connected before starting to connect
    while ( !ipstack->getEth().linkstatus() ) {
        wait(1.0f);
        WARN("Ethernet link not present. Check cable connection\r\n");
    }

    while (connect(client, ipstack) != 0)
    {
        int timeout = getConnTimeout(++retryAttempt);
        WARN("Retry attempt number %d waiting %d\r\n", retryAttempt, timeout);
        wait(timeout);
    }
}

int publish(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack)
{
    MQTT::Message message;
    char* pubTopic = "iot-2/evt/status/fmt/json";

    char buf[250];
    sprintf(buf,
     "{\"d\":{\"myName\":\"IoT mbed\",\"cputemp\":%0.4f,\"testvalue\":%s}}",
            12.4,"W5500");

    message.qos = MQTT::QOS0;
    message.retained = false;
    message.dup = false;
    message.payload = (void*)buf;
    message.payloadlen = strlen(buf);

    LOG("Publishing %s\r\n", buf);
    return client->publish(pubTopic, &message);
}


void messageArrived(MQTT::MessageData& md)
{
    MQTT::Message &message = md.message;
    char topic[md.topicName.lenstring.len + 1];

    sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data);

    LOG("Message arrived on topic %s: %.*s\r\n",  topic, message.payloadlen, message.payload);

    // Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/
    char* start = strstr(topic, "/cmd/") + 5;
    int len = strstr(topic, "/fmt/") - start;

    if (memcmp(start, "blink", len) == 0)
    {
        char payload[message.payloadlen + 1];
        sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload);

        char* pos = strchr(payload, '}');
        if (pos != NULL)
        {
            *pos = '\0';
            if ((pos = strchr(payload, ':')) != NULL)
            {
            }
        }
    }
    else
        WARN("Unsupported command: %.*s\r\n", len, start);
}

int main()
{    
#if defined(TARGET_KL25Z)
        SPI spi(D11, D12, D13); // mosi, miso, sclk
        wait(1);
    
        MQTTEthernet ipstack(&spi, D10, D9); //scs(D10), nRESET(PTA20)
        MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);
#endif    

    getMac(ipstack.getEth(), id, sizeof(id));
    attemptConnect(&client, &ipstack);

    int count = 0;
    while (true)
    {
        if (!ipstack.getEth().linkstatus()) {
            NVIC_SystemReset();
            // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
            //  or maybe just add the proper members to do this disconnect and call attemptConnect(...)
        }

        if (++count == 100)
        {               // Publish a message every second
            if (publish(&client, &ipstack) != 0)
                attemptConnect(&client, &ipstack);   // if we have lost the connection
            count = 0;
        }

        client.yield(10);  // allow the MQTT client to receive messages
    }
}