IBMIoTClientEthernetExample for WIZwiki-W7500 platform

Dependencies:   MQTT WIZnetInterface mbed-src

main.cpp

Committer:
hkjung
Date:
2015-09-17
Revision:
4:167fd0256a06
Parent:
2:b1dcfd885d7f

File content as of revision 4:167fd0256a06:

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

Serial pc(USBTX, USBRX);

// Update this to the next number *before* a commit
#define __APP_SW_REVISION__ "1"

// Configuration values needed to connect to IBM IoT Cloud
#define QUICKSTARTMODE      1
#if (QUICKSTARTMODE)
    #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 DEFAULT_TYPE_NAME      // For a registered connection, replace with your type
#else
    #define ORG         ""              // 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        "WIZwiki-W7500" // For a registered connection, replace with your type
#endif

#if defined(TARGET_WIZwiki_W7500)
//#warning "Compiling for mbed WIZwiki-W7500"
#include "WIZwiki-W7500.h"
#endif

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

#define MQTT_MAX_PACKET_SIZE 250

#if defined(TARGET_WIZwiki_W7500)
// RGB LED control
void off();
void red();
void green();
void blue();
#endif

bool quickstartMode = QUICKSTARTMODE;
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;
int blink_interval = 0;

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);
    
    //const char* iot_ibm = "23.246.232.210";
    //char hostname[strlen(iot_ibm) + 1];
    //sprintf(hostname, "%s", iot_ibm);
        
    DEBUG("hostname is %s\r\n", hostname);
    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;
#if defined(TARGET_WIZwiki_W7500)       
        green();
#endif  
        printf("Connected\r\n");
        wait(2);
    }
    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 (!linkStatus()) {
        wait(1.0f);
        WARN("Ethernet link not present. Check cable connection\n");
    }
    */

    while (connect(client, ipstack) != 0) {
#if defined(TARGET_WIZwiki_W7500)
        red();
#endif
        int timeout = getConnTimeout(++retryAttempt);
        WARN("Retry attempt number %d waiting %d\r\n", retryAttempt, timeout);        

        // 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(...)

        // this works - reset the system when the retry count gets to a threshold
        if (retryAttempt == 5)
            NVIC_SystemReset();
        else
            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\",\"potentiometer\":%0.3f}}", ain0.read());
    //sprintf(buf, "{\"d\":{\"myName\":\"IoT mbed\",\"potentiometer\":%0.4f}}", ain0.read());
            
    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);
}

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;
}

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) {
                int blink_rate = atoi(pos + 1);
                blink_interval = (blink_rate <= 0) ? 0 : (blink_rate > 50 ? 1 : 50/blink_rate);
            }
        }
    } else
        WARN("Unsupported command: %.*s\r\n", len, start);        
}

int main (void)
{
    pc.baud(115200);   
    
#if defined(TARGET_WIZwiki_W7500)
    // Board init indicator : Init success    
    red();
    wait(0.2);
    blue();
    wait(0.2);
    green();
    wait(0.2);
    off();
    wait(0.2);
    // end of board init indicator
#endif

    quickstartMode = (strcmp(org, "quickstart") == 0);    
    printf("Connecting...\r\n");

#if defined(TARGET_WIZwiki_W7500)
    blue();
#endif

    MQTTEthernet ipstack;
    MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);

    if (quickstartMode) {
        getMac(ipstack.getEth(), id, sizeof(id));        
        //printf("getMac: %s\r\n", id);        
    }
    
    attemptConnect(&client, &ipstack);
    
    if (!quickstartMode) 
    {
        int rc = 0;
        if ((rc = client.subscribe("iot-2/cmd/+/fmt/json", MQTT::QOS1, messageArrived)) != 0)
            WARN("rc from MQTT subscribe is %d\r\n", rc);             
    }
    
    blink_interval = 0;
    int count = 0;
    
    while(true) 
    {
        if (++count == 100)        
        {               // Publish a message every second        
            
            //printf("A0: %0.4f\r\n", ain0.read());
        
            if (publish(&client, &ipstack) != 0) 
                attemptConnect(&client, &ipstack);   // if we have lost the connection
            count = 0;
        }
        
        
        // Control the LED Blink interval: By Bluemix Node-RED        
        if (blink_interval == 0)            
            off();
        else if (count % blink_interval == 0)            
            b = !b;
        
        client.yield(10);  // allow the MQTT client to receive messages    
    }   
}

#if defined(TARGET_WIZwiki_W7500)
// RGB LED control -> DigitalOut
void off()
{    
    r = g = b = 1;
}

void red()
{    
    r = 0; g = 1; b = 1;
}

void green()
{    
    r = 1; g = 0; b = 1;
}

void blue()
{    
    r = 1; g = 1; b = 0;
}
#endif