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:
hillkim7
Date:
2014-12-26
Revision:
4:0c9bdee36e2a
Parent:
3:64a7d39e423b

File content as of revision 4:0c9bdee36e2a:

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

/* Dec 25, 2014
This tutorial program is written to test IBM MQTT client functionality.
This program is based on sample from Wiznet team but they only provides sample for W5500 chip.
http://developer.mbed.org/teams/EthernetInterfaceW5500-makers/
So I import that program and change it to run on W5200 chip.

You don't need to subscribe IBM cloud service to test demo.
You can check it in QUICKSTARTMODE 1.

Test Environment:
Nucleo F401RE + Seeedstudio W5200 Ethernet Shield.

Before you run this sample it is strongly recommended to read quick overview page from IBM.
https://developer.ibm.com/iot/recipes/improvise-connect-quickstart/

Once you are success to compile and run this sample you can see demo result with your web browser
by typing MAC address in " https://quickstart.internetofthings.ibmcloud.com/".
Don't forget to change hard-coded MAC address in "W5200.cpp" file.


Keep in mind, MAC address in client ID field should be lowercase.
Original Wiznet code don't consider this and took my time.
char id[30] = ID; // <<---- MAC address in this variable
*/

// Configuration values needed to connect to IBM IoT Cloud
// Defined "QUICKSTARTMODE 1" unless you subscribed IBM IoT service.

#define QUICKSTARTMODE 1

// It shows real temperature and humidity with DHT11.
#define DHT11_TEMPERATURE 0

#if DHT11_TEMPERATURE
#include "DHT11.h"

DHT11 dht(D4);

#endif

#if (QUICKSTARTMODE)
// Configuration values needed to connect to IBM IoT Cloud
#define ORG "quickstart"             // For a registered connection, replace with your org
#define ID ""                        // For a registered connection, replace with your id
#define AUTH_TOKEN ""                // For a registered connection, replace with your auth-token
#define TYPE "iotsample-mbed-nucleo"
#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);

	size_t len = strlen(buf);
	while (len-- > 0)
		if (buf[len] >= 'A' && buf[len] <= 'Z')
		{
			buf[len] = buf[len] + ('a' - 'A');
		}
    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);

	//strcpy(hostname, "192.168.11.203");
    DEBUG("connect host='%s' port=%u\r\n", hostname, IBM_IOT_PORT);
    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;
    }
	else
	{		
        WARN("MQTT client connect error: %d\r\n", rc);
	}

    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];
    double temp, humi;

#if DHT11_TEMPERATURE
	int s = dht.readData();
	if (s != DHT11::OK) {
	     printf("DHT11 Error: %d\r\n", s);
	     temp = humi = 0;
	}
	else {
		printf("T:%d, H:%d\r\n", dht.readTemperature(), dht.readHumidity());
		temp = dht.readTemperature();
		humi = dht.readHumidity();
	}
#else
	// simulate environment data
	temp = (120+(rand()%100)) / 10.0;
	humi = (200+(rand()%150)) / 10.0;
#endif
    sprintf(buf,
     "{\"d\":{\"myName\":\"IoT mbed\",\"temperature\":%.1f,\"humidity\":%.1f}}",
            temp, humi);

    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)
    Serial pc(USBTX, USBRX);
    pc.baud(115200);

    SPI spi(D11, D12, D13); // mosi, miso, sclk
    wait(1);

#if defined(TARGET_STM32F401RE)
    MQTTEthernet ipstack(&spi, D10, D5);
#else
    MQTTEthernet ipstack(&spi, D10, D9); //scs(D10), nRESET(PTA20)
#endif
    MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);
//#endif    

	LOG("ETH MAC: %s IP: %s GW: %s\r\n",
		ipstack.getEth().getMACAddress(),
		ipstack.getEth().getIPAddress(),
		ipstack.getEth().getGateway());
    getMac(ipstack.getEth(), id, sizeof(id));
	LOG("attemptConnect\r\n");
    attemptConnect(&client, &ipstack);

    int count = 0;
    while (true)
    {
        if (!ipstack.getEth().linkstatus()) {
			WARN("Reset on link down\r\n");
			wait(1);
            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 == 200)
        {               // Publish a message every two second
            if (publish(&client, &ipstack) != 0)
            {
				WARN("publish error\r\n");
                //attemptConnect(&client, &ipstack);   // if we have lost the connection
            }
            count = 0;
        }

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