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
I post description regarding this source code here.
http://developer.mbed.org/users/hillkim7/notebook/ibmiotclientethernetexample_w5200/
main.cpp@3:64a7d39e423b, 2014-12-25 (annotated)
- Committer:
- hillkim7
- Date:
- Thu Dec 25 11:25:49 2014 +0000
- Revision:
- 3:64a7d39e423b
- Parent:
- 2:87c816cd88e2
- Child:
- 4:0c9bdee36e2a
MQTT client demo with Nucleo F401RE + Seeedstudio W5200 Ethernet Shield.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kaizen | 0:910036879da0 | 1 | #include "mbed.h" |
kaizen | 0:910036879da0 | 2 | #include "MQTTClient.h" |
kaizen | 0:910036879da0 | 3 | #include "MQTTEthernet.h" |
kaizen | 0:910036879da0 | 4 | |
hillkim7 | 3:64a7d39e423b | 5 | /* Dec 25, 2014 |
hillkim7 | 3:64a7d39e423b | 6 | This tutorial program is written to test IBM MQTT client functionality. |
hillkim7 | 3:64a7d39e423b | 7 | This program is based on sample from Wiznet team but they only provides sample for W5500 chip. |
hillkim7 | 3:64a7d39e423b | 8 | http://developer.mbed.org/teams/EthernetInterfaceW5500-makers/ |
hillkim7 | 3:64a7d39e423b | 9 | So I import that program and change it to run on W5200 chip. |
hillkim7 | 3:64a7d39e423b | 10 | |
hillkim7 | 3:64a7d39e423b | 11 | You don't need to subscribe IBM cloud service to test demo. |
hillkim7 | 3:64a7d39e423b | 12 | You can check it in QUICKSTARTMODE 1. |
hillkim7 | 3:64a7d39e423b | 13 | |
hillkim7 | 3:64a7d39e423b | 14 | Test Environment: |
hillkim7 | 3:64a7d39e423b | 15 | Nucleo F401RE + Seeedstudio W5200 Ethernet Shield. |
hillkim7 | 3:64a7d39e423b | 16 | |
hillkim7 | 3:64a7d39e423b | 17 | Before you run this sample it is strongly recommended to read quick overview page from IBM. |
hillkim7 | 3:64a7d39e423b | 18 | https://developer.ibm.com/iot/recipes/improvise-connect-quickstart/ |
hillkim7 | 3:64a7d39e423b | 19 | |
hillkim7 | 3:64a7d39e423b | 20 | Once you are success to compile and run this sample you can see demo result with your web browser |
hillkim7 | 3:64a7d39e423b | 21 | by typing MAC address in " https://quickstart.internetofthings.ibmcloud.com/". |
hillkim7 | 3:64a7d39e423b | 22 | Don't forget to change hard-coded MAC address in "W5200.cpp" file. |
hillkim7 | 3:64a7d39e423b | 23 | |
hillkim7 | 3:64a7d39e423b | 24 | |
hillkim7 | 3:64a7d39e423b | 25 | Keep in mind, MAC address in client ID field should be lowercase. |
hillkim7 | 3:64a7d39e423b | 26 | Original Wiznet code don't consider this and took my time. |
hillkim7 | 3:64a7d39e423b | 27 | char id[30] = ID; // <<---- MAC address in this variable |
hillkim7 | 3:64a7d39e423b | 28 | */ |
hillkim7 | 3:64a7d39e423b | 29 | |
kaizen | 0:910036879da0 | 30 | // Configuration values needed to connect to IBM IoT Cloud |
hillkim7 | 3:64a7d39e423b | 31 | // Defined "QUICKSTARTMODE 1" unless you subscribed IBM IoT service. |
hillkim7 | 3:64a7d39e423b | 32 | |
hillkim7 | 3:64a7d39e423b | 33 | #define QUICKSTARTMODE 1 |
hillkim7 | 3:64a7d39e423b | 34 | |
kaizen | 0:910036879da0 | 35 | #if (QUICKSTARTMODE) |
hillkim7 | 3:64a7d39e423b | 36 | // Configuration values needed to connect to IBM IoT Cloud |
hillkim7 | 3:64a7d39e423b | 37 | #define ORG "quickstart" // For a registered connection, replace with your org |
hillkim7 | 3:64a7d39e423b | 38 | #define ID "" // For a registered connection, replace with your id |
hillkim7 | 3:64a7d39e423b | 39 | #define AUTH_TOKEN "" // For a registered connection, replace with your auth-token |
hillkim7 | 3:64a7d39e423b | 40 | #define TYPE "iotsample-mbed-nucleo" |
kaizen | 0:910036879da0 | 41 | #else |
kaizen | 1:532d83b9f910 | 42 | #define ORG "uasfg" |
kaizen | 1:532d83b9f910 | 43 | #define ID "" |
kaizen | 1:532d83b9f910 | 44 | #define AUTH_TOKEN "mhhWy4Qg)C*w3jL@(O" |
kaizen | 1:532d83b9f910 | 45 | #define TYPE "W5500" |
kaizen | 0:910036879da0 | 46 | #endif |
kaizen | 0:910036879da0 | 47 | |
kaizen | 0:910036879da0 | 48 | #define MQTT_PORT 1883 |
kaizen | 0:910036879da0 | 49 | #define MQTT_TLS_PORT 8883 |
kaizen | 0:910036879da0 | 50 | #define IBM_IOT_PORT MQTT_PORT |
kaizen | 0:910036879da0 | 51 | |
kaizen | 0:910036879da0 | 52 | #define MQTT_MAX_PACKET_SIZE 250 |
kaizen | 0:910036879da0 | 53 | |
kaizen | 0:910036879da0 | 54 | |
kaizen | 1:532d83b9f910 | 55 | #define USING_HW_STACK_W5500 |
kaizen | 1:532d83b9f910 | 56 | |
kaizen | 0:910036879da0 | 57 | bool quickstartMode = (QUICKSTARTMODE) ? true : false; |
kaizen | 0:910036879da0 | 58 | char org[11] = ORG; |
kaizen | 0:910036879da0 | 59 | char type[30] = TYPE; |
kaizen | 0:910036879da0 | 60 | char id[30] = ID; // mac without colons |
kaizen | 0:910036879da0 | 61 | char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode |
kaizen | 0:910036879da0 | 62 | |
kaizen | 0:910036879da0 | 63 | bool connected = false; |
kaizen | 0:910036879da0 | 64 | |
kaizen | 0:910036879da0 | 65 | |
kaizen | 0:910036879da0 | 66 | char* getMac(EthernetInterface& eth, char* buf, int buflen) // Obtain MAC address |
kaizen | 0:910036879da0 | 67 | { |
kaizen | 1:532d83b9f910 | 68 | strncpy(buf, eth.getMACAddress(), buflen); |
kaizen | 0:910036879da0 | 69 | |
kaizen | 0:910036879da0 | 70 | char* pos; // Remove colons from mac address |
kaizen | 0:910036879da0 | 71 | while ((pos = strchr(buf, ':')) != NULL) |
kaizen | 0:910036879da0 | 72 | memmove(pos, pos + 1, strlen(pos) + 1); |
hillkim7 | 3:64a7d39e423b | 73 | |
hillkim7 | 3:64a7d39e423b | 74 | size_t len = strlen(buf); |
hillkim7 | 3:64a7d39e423b | 75 | while (len-- > 0) |
hillkim7 | 3:64a7d39e423b | 76 | if (buf[len] >= 'A' && buf[len] <= 'Z') |
hillkim7 | 3:64a7d39e423b | 77 | { |
hillkim7 | 3:64a7d39e423b | 78 | buf[len] = buf[len] + ('a' - 'A'); |
hillkim7 | 3:64a7d39e423b | 79 | } |
kaizen | 0:910036879da0 | 80 | return buf; |
kaizen | 0:910036879da0 | 81 | } |
kaizen | 0:910036879da0 | 82 | |
kaizen | 0:910036879da0 | 83 | |
kaizen | 0:910036879da0 | 84 | int connect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) |
kaizen | 0:910036879da0 | 85 | { |
kaizen | 0:910036879da0 | 86 | const char* iot_ibm = ".messaging.internetofthings.ibmcloud.com"; |
kaizen | 0:910036879da0 | 87 | |
kaizen | 0:910036879da0 | 88 | char hostname[strlen(org) + strlen(iot_ibm) + 1]; |
kaizen | 0:910036879da0 | 89 | sprintf(hostname, "%s%s", org, iot_ibm); |
hillkim7 | 3:64a7d39e423b | 90 | |
hillkim7 | 3:64a7d39e423b | 91 | //strcpy(hostname, "192.168.11.203"); |
hillkim7 | 3:64a7d39e423b | 92 | DEBUG("connect host='%s' port=%u\r\n", hostname, IBM_IOT_PORT); |
kaizen | 0:910036879da0 | 93 | int rc = ipstack->connect(hostname, IBM_IOT_PORT); |
kaizen | 1:532d83b9f910 | 94 | |
kaizen | 0:910036879da0 | 95 | if (rc != 0) |
kaizen | 0:910036879da0 | 96 | return rc; |
kaizen | 0:910036879da0 | 97 | |
kaizen | 0:910036879da0 | 98 | // Construct clientId - d:org:type:id |
kaizen | 0:910036879da0 | 99 | char clientId[strlen(org) + strlen(type) + strlen(id) + 5]; |
kaizen | 0:910036879da0 | 100 | sprintf(clientId, "d:%s:%s:%s", org, type, id); |
kaizen | 0:910036879da0 | 101 | DEBUG("clientid is %s\r\n", clientId); |
kaizen | 0:910036879da0 | 102 | |
kaizen | 0:910036879da0 | 103 | // MQTT Connect |
kaizen | 0:910036879da0 | 104 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; |
kaizen | 0:910036879da0 | 105 | data.MQTTVersion = 3; |
kaizen | 0:910036879da0 | 106 | data.clientID.cstring = clientId; |
kaizen | 0:910036879da0 | 107 | |
kaizen | 0:910036879da0 | 108 | if (!quickstartMode) |
kaizen | 0:910036879da0 | 109 | { |
kaizen | 0:910036879da0 | 110 | data.username.cstring = "use-token-auth"; |
kaizen | 0:910036879da0 | 111 | data.password.cstring = auth_token; |
kaizen | 0:910036879da0 | 112 | } |
kaizen | 0:910036879da0 | 113 | |
kaizen | 0:910036879da0 | 114 | if ((rc = client->connect(&data)) == 0) |
kaizen | 0:910036879da0 | 115 | { |
kaizen | 0:910036879da0 | 116 | connected = true; |
kaizen | 0:910036879da0 | 117 | } |
hillkim7 | 3:64a7d39e423b | 118 | else |
hillkim7 | 3:64a7d39e423b | 119 | { |
hillkim7 | 3:64a7d39e423b | 120 | WARN("MQTT client connect error: %d\r\n", rc); |
hillkim7 | 3:64a7d39e423b | 121 | } |
kaizen | 1:532d83b9f910 | 122 | |
kaizen | 0:910036879da0 | 123 | return rc; |
kaizen | 0:910036879da0 | 124 | } |
kaizen | 0:910036879da0 | 125 | |
kaizen | 0:910036879da0 | 126 | |
kaizen | 0:910036879da0 | 127 | int getConnTimeout(int attemptNumber) |
kaizen | 0:910036879da0 | 128 | { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute |
kaizen | 0:910036879da0 | 129 | // after 20 attempts, retry every 10 minutes |
kaizen | 0:910036879da0 | 130 | return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600; |
kaizen | 0:910036879da0 | 131 | } |
kaizen | 0:910036879da0 | 132 | |
kaizen | 0:910036879da0 | 133 | |
kaizen | 0:910036879da0 | 134 | void attemptConnect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) |
kaizen | 0:910036879da0 | 135 | { |
kaizen | 0:910036879da0 | 136 | int retryAttempt = 0; |
kaizen | 0:910036879da0 | 137 | connected = false; |
kaizen | 0:910036879da0 | 138 | |
kaizen | 0:910036879da0 | 139 | // make sure a cable is connected before starting to connect |
kaizen | 0:910036879da0 | 140 | while ( !ipstack->getEth().linkstatus() ) { |
kaizen | 0:910036879da0 | 141 | wait(1.0f); |
kaizen | 0:910036879da0 | 142 | WARN("Ethernet link not present. Check cable connection\r\n"); |
kaizen | 0:910036879da0 | 143 | } |
kaizen | 0:910036879da0 | 144 | |
kaizen | 0:910036879da0 | 145 | while (connect(client, ipstack) != 0) |
kaizen | 0:910036879da0 | 146 | { |
kaizen | 0:910036879da0 | 147 | int timeout = getConnTimeout(++retryAttempt); |
kaizen | 0:910036879da0 | 148 | WARN("Retry attempt number %d waiting %d\r\n", retryAttempt, timeout); |
kaizen | 0:910036879da0 | 149 | wait(timeout); |
kaizen | 0:910036879da0 | 150 | } |
kaizen | 0:910036879da0 | 151 | } |
kaizen | 0:910036879da0 | 152 | |
kaizen | 0:910036879da0 | 153 | int publish(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) |
kaizen | 0:910036879da0 | 154 | { |
kaizen | 0:910036879da0 | 155 | MQTT::Message message; |
kaizen | 0:910036879da0 | 156 | char* pubTopic = "iot-2/evt/status/fmt/json"; |
kaizen | 0:910036879da0 | 157 | |
kaizen | 0:910036879da0 | 158 | char buf[250]; |
kaizen | 0:910036879da0 | 159 | sprintf(buf, |
hillkim7 | 3:64a7d39e423b | 160 | "{\"d\":{\"myName\":\"IoT mbed\",\"test_value\":%d}}", |
hillkim7 | 3:64a7d39e423b | 161 | 12+(rand()%10)); |
kaizen | 0:910036879da0 | 162 | |
kaizen | 0:910036879da0 | 163 | message.qos = MQTT::QOS0; |
kaizen | 0:910036879da0 | 164 | message.retained = false; |
kaizen | 0:910036879da0 | 165 | message.dup = false; |
kaizen | 0:910036879da0 | 166 | message.payload = (void*)buf; |
kaizen | 0:910036879da0 | 167 | message.payloadlen = strlen(buf); |
kaizen | 0:910036879da0 | 168 | |
kaizen | 0:910036879da0 | 169 | LOG("Publishing %s\r\n", buf); |
kaizen | 0:910036879da0 | 170 | return client->publish(pubTopic, &message); |
kaizen | 0:910036879da0 | 171 | } |
kaizen | 0:910036879da0 | 172 | |
kaizen | 0:910036879da0 | 173 | |
kaizen | 0:910036879da0 | 174 | void messageArrived(MQTT::MessageData& md) |
kaizen | 0:910036879da0 | 175 | { |
kaizen | 0:910036879da0 | 176 | MQTT::Message &message = md.message; |
kaizen | 0:910036879da0 | 177 | char topic[md.topicName.lenstring.len + 1]; |
kaizen | 0:910036879da0 | 178 | |
kaizen | 0:910036879da0 | 179 | sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data); |
kaizen | 0:910036879da0 | 180 | |
kaizen | 0:910036879da0 | 181 | LOG("Message arrived on topic %s: %.*s\r\n", topic, message.payloadlen, message.payload); |
kaizen | 0:910036879da0 | 182 | |
kaizen | 0:910036879da0 | 183 | // Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/ |
kaizen | 0:910036879da0 | 184 | char* start = strstr(topic, "/cmd/") + 5; |
kaizen | 0:910036879da0 | 185 | int len = strstr(topic, "/fmt/") - start; |
kaizen | 0:910036879da0 | 186 | |
kaizen | 0:910036879da0 | 187 | if (memcmp(start, "blink", len) == 0) |
kaizen | 0:910036879da0 | 188 | { |
kaizen | 0:910036879da0 | 189 | char payload[message.payloadlen + 1]; |
kaizen | 0:910036879da0 | 190 | sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload); |
kaizen | 0:910036879da0 | 191 | |
kaizen | 0:910036879da0 | 192 | char* pos = strchr(payload, '}'); |
kaizen | 0:910036879da0 | 193 | if (pos != NULL) |
kaizen | 0:910036879da0 | 194 | { |
kaizen | 0:910036879da0 | 195 | *pos = '\0'; |
kaizen | 0:910036879da0 | 196 | if ((pos = strchr(payload, ':')) != NULL) |
kaizen | 0:910036879da0 | 197 | { |
kaizen | 0:910036879da0 | 198 | } |
kaizen | 0:910036879da0 | 199 | } |
kaizen | 0:910036879da0 | 200 | } |
kaizen | 0:910036879da0 | 201 | else |
kaizen | 0:910036879da0 | 202 | WARN("Unsupported command: %.*s\r\n", len, start); |
kaizen | 0:910036879da0 | 203 | } |
kaizen | 0:910036879da0 | 204 | |
kaizen | 0:910036879da0 | 205 | int main() |
kaizen | 0:910036879da0 | 206 | { |
hillkim7 | 3:64a7d39e423b | 207 | //#if defined(TARGET_KL25Z) |
kaizen | 2:87c816cd88e2 | 208 | Serial pc(USBTX, USBRX); |
kaizen | 2:87c816cd88e2 | 209 | pc.baud(115200); |
kaizen | 2:87c816cd88e2 | 210 | |
kaizen | 2:87c816cd88e2 | 211 | SPI spi(D11, D12, D13); // mosi, miso, sclk |
kaizen | 2:87c816cd88e2 | 212 | wait(1); |
hillkim7 | 3:64a7d39e423b | 213 | |
hillkim7 | 3:64a7d39e423b | 214 | #if defined(TARGET_STM32F401RE) |
hillkim7 | 3:64a7d39e423b | 215 | MQTTEthernet ipstack(&spi, D10, D5); |
hillkim7 | 3:64a7d39e423b | 216 | #else |
kaizen | 2:87c816cd88e2 | 217 | MQTTEthernet ipstack(&spi, D10, D9); //scs(D10), nRESET(PTA20) |
hillkim7 | 3:64a7d39e423b | 218 | #endif |
kaizen | 2:87c816cd88e2 | 219 | MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack); |
hillkim7 | 3:64a7d39e423b | 220 | //#endif |
kaizen | 0:910036879da0 | 221 | |
hillkim7 | 3:64a7d39e423b | 222 | LOG("ETH MAC: %s IP: %s GW: %s\r\n", |
hillkim7 | 3:64a7d39e423b | 223 | ipstack.getEth().getMACAddress(), |
hillkim7 | 3:64a7d39e423b | 224 | ipstack.getEth().getIPAddress(), |
hillkim7 | 3:64a7d39e423b | 225 | ipstack.getEth().getGateway()); |
kaizen | 1:532d83b9f910 | 226 | getMac(ipstack.getEth(), id, sizeof(id)); |
hillkim7 | 3:64a7d39e423b | 227 | LOG("attemptConnect\r\n"); |
kaizen | 0:910036879da0 | 228 | attemptConnect(&client, &ipstack); |
kaizen | 0:910036879da0 | 229 | |
kaizen | 0:910036879da0 | 230 | int count = 0; |
kaizen | 0:910036879da0 | 231 | while (true) |
kaizen | 0:910036879da0 | 232 | { |
kaizen | 0:910036879da0 | 233 | if (!ipstack.getEth().linkstatus()) { |
hillkim7 | 3:64a7d39e423b | 234 | WARN("Reset on link down\r\n"); |
hillkim7 | 3:64a7d39e423b | 235 | wait(1); |
kaizen | 0:910036879da0 | 236 | NVIC_SystemReset(); |
kaizen | 0:910036879da0 | 237 | // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed |
kaizen | 0:910036879da0 | 238 | // or maybe just add the proper members to do this disconnect and call attemptConnect(...) |
kaizen | 0:910036879da0 | 239 | } |
kaizen | 0:910036879da0 | 240 | |
kaizen | 0:910036879da0 | 241 | if (++count == 100) |
kaizen | 0:910036879da0 | 242 | { // Publish a message every second |
kaizen | 0:910036879da0 | 243 | if (publish(&client, &ipstack) != 0) |
hillkim7 | 3:64a7d39e423b | 244 | { |
hillkim7 | 3:64a7d39e423b | 245 | WARN("publish error\r\n"); |
hillkim7 | 3:64a7d39e423b | 246 | //attemptConnect(&client, &ipstack); // if we have lost the connection |
hillkim7 | 3:64a7d39e423b | 247 | } |
kaizen | 0:910036879da0 | 248 | count = 0; |
kaizen | 0:910036879da0 | 249 | } |
kaizen | 0:910036879da0 | 250 | |
kaizen | 0:910036879da0 | 251 | client.yield(10); // allow the MQTT client to receive messages |
kaizen | 0:910036879da0 | 252 | } |
kaizen | 0:910036879da0 | 253 | } |
hillkim7 | 3:64a7d39e423b | 254 |