Jack Hansdampf / mbed-mqtt-GSOE1

Dependents:   ESP8266MQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers IBMIoTUDPExample.cpp Source File

IBMIoTUDPExample.cpp

00001 /*******************************************************************************
00002  * Copyright (c) 2014 IBM Corp.
00003  *
00004  * All rights reserved. This program and the accompanying materials
00005  * are made available under the terms of the Eclipse Public License v1.0
00006  * and Eclipse Distribution License v1.0 which accompany this distribution.
00007  *
00008  * The Eclipse Public License is available at
00009  *    http://www.eclipse.org/legal/epl-v10.html
00010  * and the Eclipse Distribution License is available at
00011  *   http://www.eclipse.org/org/documents/edl-v10.php.
00012  *
00013  * Contributors:
00014  *    Ian Craggs - refactoring to remove STL and other changes
00015  *******************************************************************************/
00016 
00017 #define WARN printf
00018 
00019 #include "MQTTClient.h"
00020 
00021 #define DEFAULT_STACK_SIZE -1
00022 
00023 #include "linux.cpp"
00024 
00025 #include <stdlib.h>
00026 
00027 // Configuration values needed to connect to IBM IoT Cloud
00028 #define ORG "quickstart"             // For a registered connection, replace with your org
00029 #define ID "8002f7f1ad23"                        // For a registered connection, replace with your id
00030 #define AUTH_TOKEN ""                // For a registered connection, replace with your auth-token
00031 #define TYPE "mytype"       // For a registered connection, replace with your type
00032 
00033 #define MQTT_PORT 1883
00034 #define MQTT_TLS_PORT 8883
00035 #define IBM_IOT_PORT MQTT_PORT
00036 
00037 #define MQTT_MAX_PACKET_SIZE 250
00038 
00039 bool quickstartMode = true;
00040 char org[11] = ORG;  
00041 char type[30] = TYPE;
00042 char id[30] = ID;                 // mac without colons
00043 char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode
00044 
00045 bool connected = false;
00046 const char* joystickPos = "CENTRE";
00047 int blink_interval = 0;
00048 
00049 
00050 
00051 int connect(MQTT::Client<IPStack, Countdown, MQTT_MAX_PACKET_SIZE>* client, IPStack* ipstack)
00052 {   
00053     const char* iot_ibm = ".messaging.internetofthings.ibmcloud.com";
00054     
00055     char hostname[strlen(org) + strlen(iot_ibm) + 1];
00056     sprintf(hostname, "%s%s", org, iot_ibm);
00057     DEBUG("connecting to %s\n", hostname);
00058     int rc = ipstack->connect(hostname, IBM_IOT_PORT);
00059     if (rc != 0)
00060         return rc;
00061      
00062     // Construct clientId - d:org:type:id
00063     char clientId[strlen(org) + strlen(type) + strlen(id) + 5];
00064     sprintf(clientId, "d:%s:%s:%s", org, type, id);
00065     DEBUG("clientid is %s\n", clientId);
00066     
00067     // MQTT Connect
00068     MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
00069     data.MQTTVersion = 4;
00070     data.clientID.cstring = clientId;
00071     
00072     if (!quickstartMode) 
00073     {        
00074         data.username.cstring = "use-token-auth";
00075         data.password.cstring = auth_token;
00076     }
00077     
00078     if ((rc = client->connect(data)) == 0) 
00079         connected = true;
00080     return rc;
00081 }
00082 
00083 
00084 int getConnTimeout(int attemptNumber)
00085 {  // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
00086    // after 20 attempts, retry every 10 minutes
00087     return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
00088 }
00089 
00090 
00091 void attemptConnect(MQTT::Client<IPStack, Countdown, MQTT_MAX_PACKET_SIZE>* client, IPStack* ipstack)
00092 {
00093     int retryAttempt = 0;
00094     connected = false;
00095         
00096     while (connect(client, ipstack) != 0) 
00097     {    
00098         int timeout = getConnTimeout(++retryAttempt);
00099         WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
00100         
00101         // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
00102         //  or maybe just add the proper members to do this disconnect and call attemptConnect(...)
00103         
00104         sleep(timeout);
00105     }
00106 }
00107 
00108 
00109 int publish(MQTT::Client<IPStack, Countdown, MQTT_MAX_PACKET_SIZE>* client, IPStack* ipstack)
00110 {
00111     MQTT::Message message;
00112     char* pubTopic = "iot-2/evt/status/fmt/json";
00113     static const char* joypos[] = {"LEFT", "RIGHT", "CENTRE", "UP", "DOWN"};
00114             
00115     char buf[250];
00116     sprintf(buf,
00117      "{\"d\":{\"myName\":\"IoT mbed\",\"accelX\":%0.4f,\"accelY\":%0.4f,\"accelZ\":%0.4f,\"temp\":%0.4f,\"joystick\":\"%s\",\"potentiometer1\":%0.4f,\"potentiometer2\":%0.4f}}",
00118             (rand() % 10) * 2.0, (rand() % 10) * 2.0, (rand() % 10) * 2.0, (rand() % 10) + 18.0, joypos[rand() % 5], (rand() % 10) * 30.0, (rand() % 10) * 30.0); 
00119             //MMA.x(), MMA.y(), MMA.z(), sensor.temp(), joystickPos, ain1.read(), ain2.read());
00120     message.qos = MQTT::QOS0;
00121     message.retained = false;
00122     message.dup = false;
00123     message.payload = (void*)buf;
00124     message.payloadlen = strlen(buf);
00125     
00126     LOG("Publishing %s\n", buf);
00127     return client->publish(pubTopic, message);
00128 }
00129 
00130 
00131 void messageArrived(MQTT::MessageData& md)
00132 {
00133     MQTT::Message &message = md.message;
00134     char topic[md.topicName.lenstring.len + 1];
00135     
00136     sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data);
00137     
00138     LOG("Message arrived on topic %s: %.*s\n",  topic, message.payloadlen, message.payload);
00139           
00140     // Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/
00141     char* start = strstr(topic, "/cmd/") + 5;
00142     int len = strstr(topic, "/fmt/") - start;
00143     
00144     if (memcmp(start, "blink", len) == 0)
00145     {
00146         char payload[message.payloadlen + 1];
00147         sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload);
00148     
00149         char* pos = strchr(payload, '}');
00150         if (pos != NULL)
00151         {
00152             *pos = '\0';
00153             if ((pos = strchr(payload, ':')) != NULL)
00154             {
00155                 int blink_rate = atoi(pos + 1);       
00156                 blink_interval = (blink_rate <= 0) ? 0 : (blink_rate > 50 ? 1 : 50/blink_rate);
00157             }
00158         }
00159     }
00160     else
00161         WARN("Unsupported command: %.*s\n", len, start);
00162 }
00163 
00164 
00165 int main()
00166 {    
00167     quickstartMode = (strcmp(org, "quickstart") == 0);
00168     
00169     IPStack ipstack = IPStack();
00170     MQTT::Client<IPStack, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);
00171     
00172     attemptConnect(&client, &ipstack);
00173     
00174     if (!quickstartMode) 
00175     {
00176         int rc = 0;
00177         if ((rc = client.subscribe("iot-2/cmd/+/fmt/json", MQTT::QOS1, messageArrived)) != 0)
00178             WARN("rc from MQTT subscribe is %d\n", rc); 
00179     }
00180    
00181     int count = 0;
00182     while (true)
00183     {
00184         if (++count == 100)
00185         {               // Publish a message every second
00186             if (publish(&client, &ipstack) != 0) 
00187                 attemptConnect(&client, &ipstack);   // if we have lost the connection
00188             count = 0;
00189         }
00190         client.yield(10);  // allow the MQTT client to receive messages
00191     }
00192 }
00193