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@4:0c9bdee36e2a, 2014-12-26 (annotated)
- Committer:
- hillkim7
- Date:
- Fri Dec 26 07:54:23 2014 +0000
- Revision:
- 4:0c9bdee36e2a
- Parent:
- 3:64a7d39e423b
DHT11 module attached to update real temperature and humidity.
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 | |
hillkim7 | 4:0c9bdee36e2a | 35 | // It shows real temperature and humidity with DHT11. |
hillkim7 | 4:0c9bdee36e2a | 36 | #define DHT11_TEMPERATURE 0 |
hillkim7 | 4:0c9bdee36e2a | 37 | |
hillkim7 | 4:0c9bdee36e2a | 38 | #if DHT11_TEMPERATURE |
hillkim7 | 4:0c9bdee36e2a | 39 | #include "DHT11.h" |
hillkim7 | 4:0c9bdee36e2a | 40 | |
hillkim7 | 4:0c9bdee36e2a | 41 | DHT11 dht(D4); |
hillkim7 | 4:0c9bdee36e2a | 42 | |
hillkim7 | 4:0c9bdee36e2a | 43 | #endif |
hillkim7 | 4:0c9bdee36e2a | 44 | |
kaizen | 0:910036879da0 | 45 | #if (QUICKSTARTMODE) |
hillkim7 | 3:64a7d39e423b | 46 | // Configuration values needed to connect to IBM IoT Cloud |
hillkim7 | 3:64a7d39e423b | 47 | #define ORG "quickstart" // For a registered connection, replace with your org |
hillkim7 | 3:64a7d39e423b | 48 | #define ID "" // For a registered connection, replace with your id |
hillkim7 | 3:64a7d39e423b | 49 | #define AUTH_TOKEN "" // For a registered connection, replace with your auth-token |
hillkim7 | 3:64a7d39e423b | 50 | #define TYPE "iotsample-mbed-nucleo" |
kaizen | 0:910036879da0 | 51 | #else |
kaizen | 1:532d83b9f910 | 52 | #define ORG "uasfg" |
kaizen | 1:532d83b9f910 | 53 | #define ID "" |
kaizen | 1:532d83b9f910 | 54 | #define AUTH_TOKEN "mhhWy4Qg)C*w3jL@(O" |
kaizen | 1:532d83b9f910 | 55 | #define TYPE "W5500" |
kaizen | 0:910036879da0 | 56 | #endif |
kaizen | 0:910036879da0 | 57 | |
kaizen | 0:910036879da0 | 58 | #define MQTT_PORT 1883 |
kaizen | 0:910036879da0 | 59 | #define MQTT_TLS_PORT 8883 |
kaizen | 0:910036879da0 | 60 | #define IBM_IOT_PORT MQTT_PORT |
kaizen | 0:910036879da0 | 61 | |
kaizen | 0:910036879da0 | 62 | #define MQTT_MAX_PACKET_SIZE 250 |
kaizen | 0:910036879da0 | 63 | |
kaizen | 0:910036879da0 | 64 | |
kaizen | 1:532d83b9f910 | 65 | #define USING_HW_STACK_W5500 |
kaizen | 1:532d83b9f910 | 66 | |
kaizen | 0:910036879da0 | 67 | bool quickstartMode = (QUICKSTARTMODE) ? true : false; |
kaizen | 0:910036879da0 | 68 | char org[11] = ORG; |
kaizen | 0:910036879da0 | 69 | char type[30] = TYPE; |
kaizen | 0:910036879da0 | 70 | char id[30] = ID; // mac without colons |
kaizen | 0:910036879da0 | 71 | char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode |
kaizen | 0:910036879da0 | 72 | |
kaizen | 0:910036879da0 | 73 | bool connected = false; |
kaizen | 0:910036879da0 | 74 | |
kaizen | 0:910036879da0 | 75 | |
kaizen | 0:910036879da0 | 76 | char* getMac(EthernetInterface& eth, char* buf, int buflen) // Obtain MAC address |
kaizen | 0:910036879da0 | 77 | { |
kaizen | 1:532d83b9f910 | 78 | strncpy(buf, eth.getMACAddress(), buflen); |
kaizen | 0:910036879da0 | 79 | |
kaizen | 0:910036879da0 | 80 | char* pos; // Remove colons from mac address |
kaizen | 0:910036879da0 | 81 | while ((pos = strchr(buf, ':')) != NULL) |
kaizen | 0:910036879da0 | 82 | memmove(pos, pos + 1, strlen(pos) + 1); |
hillkim7 | 3:64a7d39e423b | 83 | |
hillkim7 | 3:64a7d39e423b | 84 | size_t len = strlen(buf); |
hillkim7 | 3:64a7d39e423b | 85 | while (len-- > 0) |
hillkim7 | 3:64a7d39e423b | 86 | if (buf[len] >= 'A' && buf[len] <= 'Z') |
hillkim7 | 3:64a7d39e423b | 87 | { |
hillkim7 | 3:64a7d39e423b | 88 | buf[len] = buf[len] + ('a' - 'A'); |
hillkim7 | 3:64a7d39e423b | 89 | } |
kaizen | 0:910036879da0 | 90 | return buf; |
kaizen | 0:910036879da0 | 91 | } |
kaizen | 0:910036879da0 | 92 | |
kaizen | 0:910036879da0 | 93 | |
kaizen | 0:910036879da0 | 94 | int connect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) |
kaizen | 0:910036879da0 | 95 | { |
kaizen | 0:910036879da0 | 96 | const char* iot_ibm = ".messaging.internetofthings.ibmcloud.com"; |
kaizen | 0:910036879da0 | 97 | |
kaizen | 0:910036879da0 | 98 | char hostname[strlen(org) + strlen(iot_ibm) + 1]; |
kaizen | 0:910036879da0 | 99 | sprintf(hostname, "%s%s", org, iot_ibm); |
hillkim7 | 3:64a7d39e423b | 100 | |
hillkim7 | 3:64a7d39e423b | 101 | //strcpy(hostname, "192.168.11.203"); |
hillkim7 | 3:64a7d39e423b | 102 | DEBUG("connect host='%s' port=%u\r\n", hostname, IBM_IOT_PORT); |
kaizen | 0:910036879da0 | 103 | int rc = ipstack->connect(hostname, IBM_IOT_PORT); |
kaizen | 1:532d83b9f910 | 104 | |
kaizen | 0:910036879da0 | 105 | if (rc != 0) |
kaizen | 0:910036879da0 | 106 | return rc; |
kaizen | 0:910036879da0 | 107 | |
kaizen | 0:910036879da0 | 108 | // Construct clientId - d:org:type:id |
kaizen | 0:910036879da0 | 109 | char clientId[strlen(org) + strlen(type) + strlen(id) + 5]; |
kaizen | 0:910036879da0 | 110 | sprintf(clientId, "d:%s:%s:%s", org, type, id); |
kaizen | 0:910036879da0 | 111 | DEBUG("clientid is %s\r\n", clientId); |
kaizen | 0:910036879da0 | 112 | |
kaizen | 0:910036879da0 | 113 | // MQTT Connect |
kaizen | 0:910036879da0 | 114 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; |
kaizen | 0:910036879da0 | 115 | data.MQTTVersion = 3; |
kaizen | 0:910036879da0 | 116 | data.clientID.cstring = clientId; |
kaizen | 0:910036879da0 | 117 | |
kaizen | 0:910036879da0 | 118 | if (!quickstartMode) |
kaizen | 0:910036879da0 | 119 | { |
kaizen | 0:910036879da0 | 120 | data.username.cstring = "use-token-auth"; |
kaizen | 0:910036879da0 | 121 | data.password.cstring = auth_token; |
kaizen | 0:910036879da0 | 122 | } |
kaizen | 0:910036879da0 | 123 | |
kaizen | 0:910036879da0 | 124 | if ((rc = client->connect(&data)) == 0) |
kaizen | 0:910036879da0 | 125 | { |
kaizen | 0:910036879da0 | 126 | connected = true; |
kaizen | 0:910036879da0 | 127 | } |
hillkim7 | 3:64a7d39e423b | 128 | else |
hillkim7 | 3:64a7d39e423b | 129 | { |
hillkim7 | 3:64a7d39e423b | 130 | WARN("MQTT client connect error: %d\r\n", rc); |
hillkim7 | 3:64a7d39e423b | 131 | } |
kaizen | 1:532d83b9f910 | 132 | |
kaizen | 0:910036879da0 | 133 | return rc; |
kaizen | 0:910036879da0 | 134 | } |
kaizen | 0:910036879da0 | 135 | |
kaizen | 0:910036879da0 | 136 | |
kaizen | 0:910036879da0 | 137 | int getConnTimeout(int attemptNumber) |
kaizen | 0:910036879da0 | 138 | { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute |
kaizen | 0:910036879da0 | 139 | // after 20 attempts, retry every 10 minutes |
kaizen | 0:910036879da0 | 140 | return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600; |
kaizen | 0:910036879da0 | 141 | } |
kaizen | 0:910036879da0 | 142 | |
kaizen | 0:910036879da0 | 143 | |
kaizen | 0:910036879da0 | 144 | void attemptConnect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) |
kaizen | 0:910036879da0 | 145 | { |
kaizen | 0:910036879da0 | 146 | int retryAttempt = 0; |
kaizen | 0:910036879da0 | 147 | connected = false; |
kaizen | 0:910036879da0 | 148 | |
kaizen | 0:910036879da0 | 149 | // make sure a cable is connected before starting to connect |
kaizen | 0:910036879da0 | 150 | while ( !ipstack->getEth().linkstatus() ) { |
kaizen | 0:910036879da0 | 151 | wait(1.0f); |
kaizen | 0:910036879da0 | 152 | WARN("Ethernet link not present. Check cable connection\r\n"); |
kaizen | 0:910036879da0 | 153 | } |
kaizen | 0:910036879da0 | 154 | |
kaizen | 0:910036879da0 | 155 | while (connect(client, ipstack) != 0) |
kaizen | 0:910036879da0 | 156 | { |
kaizen | 0:910036879da0 | 157 | int timeout = getConnTimeout(++retryAttempt); |
kaizen | 0:910036879da0 | 158 | WARN("Retry attempt number %d waiting %d\r\n", retryAttempt, timeout); |
kaizen | 0:910036879da0 | 159 | wait(timeout); |
kaizen | 0:910036879da0 | 160 | } |
kaizen | 0:910036879da0 | 161 | } |
kaizen | 0:910036879da0 | 162 | |
kaizen | 0:910036879da0 | 163 | int publish(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) |
kaizen | 0:910036879da0 | 164 | { |
kaizen | 0:910036879da0 | 165 | MQTT::Message message; |
kaizen | 0:910036879da0 | 166 | char* pubTopic = "iot-2/evt/status/fmt/json"; |
kaizen | 0:910036879da0 | 167 | |
kaizen | 0:910036879da0 | 168 | char buf[250]; |
hillkim7 | 4:0c9bdee36e2a | 169 | double temp, humi; |
hillkim7 | 4:0c9bdee36e2a | 170 | |
hillkim7 | 4:0c9bdee36e2a | 171 | #if DHT11_TEMPERATURE |
hillkim7 | 4:0c9bdee36e2a | 172 | int s = dht.readData(); |
hillkim7 | 4:0c9bdee36e2a | 173 | if (s != DHT11::OK) { |
hillkim7 | 4:0c9bdee36e2a | 174 | printf("DHT11 Error: %d\r\n", s); |
hillkim7 | 4:0c9bdee36e2a | 175 | temp = humi = 0; |
hillkim7 | 4:0c9bdee36e2a | 176 | } |
hillkim7 | 4:0c9bdee36e2a | 177 | else { |
hillkim7 | 4:0c9bdee36e2a | 178 | printf("T:%d, H:%d\r\n", dht.readTemperature(), dht.readHumidity()); |
hillkim7 | 4:0c9bdee36e2a | 179 | temp = dht.readTemperature(); |
hillkim7 | 4:0c9bdee36e2a | 180 | humi = dht.readHumidity(); |
hillkim7 | 4:0c9bdee36e2a | 181 | } |
hillkim7 | 4:0c9bdee36e2a | 182 | #else |
hillkim7 | 4:0c9bdee36e2a | 183 | // simulate environment data |
hillkim7 | 4:0c9bdee36e2a | 184 | temp = (120+(rand()%100)) / 10.0; |
hillkim7 | 4:0c9bdee36e2a | 185 | humi = (200+(rand()%150)) / 10.0; |
hillkim7 | 4:0c9bdee36e2a | 186 | #endif |
kaizen | 0:910036879da0 | 187 | sprintf(buf, |
hillkim7 | 4:0c9bdee36e2a | 188 | "{\"d\":{\"myName\":\"IoT mbed\",\"temperature\":%.1f,\"humidity\":%.1f}}", |
hillkim7 | 4:0c9bdee36e2a | 189 | temp, humi); |
kaizen | 0:910036879da0 | 190 | |
kaizen | 0:910036879da0 | 191 | message.qos = MQTT::QOS0; |
kaizen | 0:910036879da0 | 192 | message.retained = false; |
kaizen | 0:910036879da0 | 193 | message.dup = false; |
kaizen | 0:910036879da0 | 194 | message.payload = (void*)buf; |
kaizen | 0:910036879da0 | 195 | message.payloadlen = strlen(buf); |
kaizen | 0:910036879da0 | 196 | |
kaizen | 0:910036879da0 | 197 | LOG("Publishing %s\r\n", buf); |
kaizen | 0:910036879da0 | 198 | return client->publish(pubTopic, &message); |
kaizen | 0:910036879da0 | 199 | } |
kaizen | 0:910036879da0 | 200 | |
kaizen | 0:910036879da0 | 201 | |
kaizen | 0:910036879da0 | 202 | void messageArrived(MQTT::MessageData& md) |
kaizen | 0:910036879da0 | 203 | { |
kaizen | 0:910036879da0 | 204 | MQTT::Message &message = md.message; |
kaizen | 0:910036879da0 | 205 | char topic[md.topicName.lenstring.len + 1]; |
kaizen | 0:910036879da0 | 206 | |
kaizen | 0:910036879da0 | 207 | sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data); |
kaizen | 0:910036879da0 | 208 | |
kaizen | 0:910036879da0 | 209 | LOG("Message arrived on topic %s: %.*s\r\n", topic, message.payloadlen, message.payload); |
kaizen | 0:910036879da0 | 210 | |
kaizen | 0:910036879da0 | 211 | // Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/ |
kaizen | 0:910036879da0 | 212 | char* start = strstr(topic, "/cmd/") + 5; |
kaizen | 0:910036879da0 | 213 | int len = strstr(topic, "/fmt/") - start; |
kaizen | 0:910036879da0 | 214 | |
kaizen | 0:910036879da0 | 215 | if (memcmp(start, "blink", len) == 0) |
kaizen | 0:910036879da0 | 216 | { |
kaizen | 0:910036879da0 | 217 | char payload[message.payloadlen + 1]; |
kaizen | 0:910036879da0 | 218 | sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload); |
kaizen | 0:910036879da0 | 219 | |
kaizen | 0:910036879da0 | 220 | char* pos = strchr(payload, '}'); |
kaizen | 0:910036879da0 | 221 | if (pos != NULL) |
kaizen | 0:910036879da0 | 222 | { |
kaizen | 0:910036879da0 | 223 | *pos = '\0'; |
kaizen | 0:910036879da0 | 224 | if ((pos = strchr(payload, ':')) != NULL) |
kaizen | 0:910036879da0 | 225 | { |
kaizen | 0:910036879da0 | 226 | } |
kaizen | 0:910036879da0 | 227 | } |
kaizen | 0:910036879da0 | 228 | } |
kaizen | 0:910036879da0 | 229 | else |
kaizen | 0:910036879da0 | 230 | WARN("Unsupported command: %.*s\r\n", len, start); |
kaizen | 0:910036879da0 | 231 | } |
kaizen | 0:910036879da0 | 232 | |
kaizen | 0:910036879da0 | 233 | int main() |
kaizen | 0:910036879da0 | 234 | { |
hillkim7 | 3:64a7d39e423b | 235 | //#if defined(TARGET_KL25Z) |
kaizen | 2:87c816cd88e2 | 236 | Serial pc(USBTX, USBRX); |
kaizen | 2:87c816cd88e2 | 237 | pc.baud(115200); |
kaizen | 2:87c816cd88e2 | 238 | |
kaizen | 2:87c816cd88e2 | 239 | SPI spi(D11, D12, D13); // mosi, miso, sclk |
kaizen | 2:87c816cd88e2 | 240 | wait(1); |
hillkim7 | 3:64a7d39e423b | 241 | |
hillkim7 | 3:64a7d39e423b | 242 | #if defined(TARGET_STM32F401RE) |
hillkim7 | 3:64a7d39e423b | 243 | MQTTEthernet ipstack(&spi, D10, D5); |
hillkim7 | 3:64a7d39e423b | 244 | #else |
kaizen | 2:87c816cd88e2 | 245 | MQTTEthernet ipstack(&spi, D10, D9); //scs(D10), nRESET(PTA20) |
hillkim7 | 3:64a7d39e423b | 246 | #endif |
kaizen | 2:87c816cd88e2 | 247 | MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack); |
hillkim7 | 3:64a7d39e423b | 248 | //#endif |
kaizen | 0:910036879da0 | 249 | |
hillkim7 | 3:64a7d39e423b | 250 | LOG("ETH MAC: %s IP: %s GW: %s\r\n", |
hillkim7 | 3:64a7d39e423b | 251 | ipstack.getEth().getMACAddress(), |
hillkim7 | 3:64a7d39e423b | 252 | ipstack.getEth().getIPAddress(), |
hillkim7 | 3:64a7d39e423b | 253 | ipstack.getEth().getGateway()); |
kaizen | 1:532d83b9f910 | 254 | getMac(ipstack.getEth(), id, sizeof(id)); |
hillkim7 | 3:64a7d39e423b | 255 | LOG("attemptConnect\r\n"); |
kaizen | 0:910036879da0 | 256 | attemptConnect(&client, &ipstack); |
kaizen | 0:910036879da0 | 257 | |
kaizen | 0:910036879da0 | 258 | int count = 0; |
kaizen | 0:910036879da0 | 259 | while (true) |
kaizen | 0:910036879da0 | 260 | { |
kaizen | 0:910036879da0 | 261 | if (!ipstack.getEth().linkstatus()) { |
hillkim7 | 3:64a7d39e423b | 262 | WARN("Reset on link down\r\n"); |
hillkim7 | 3:64a7d39e423b | 263 | wait(1); |
kaizen | 0:910036879da0 | 264 | NVIC_SystemReset(); |
kaizen | 0:910036879da0 | 265 | // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed |
kaizen | 0:910036879da0 | 266 | // or maybe just add the proper members to do this disconnect and call attemptConnect(...) |
kaizen | 0:910036879da0 | 267 | } |
kaizen | 0:910036879da0 | 268 | |
hillkim7 | 4:0c9bdee36e2a | 269 | if (++count == 200) |
hillkim7 | 4:0c9bdee36e2a | 270 | { // Publish a message every two second |
kaizen | 0:910036879da0 | 271 | if (publish(&client, &ipstack) != 0) |
hillkim7 | 3:64a7d39e423b | 272 | { |
hillkim7 | 3:64a7d39e423b | 273 | WARN("publish error\r\n"); |
hillkim7 | 3:64a7d39e423b | 274 | //attemptConnect(&client, &ipstack); // if we have lost the connection |
hillkim7 | 3:64a7d39e423b | 275 | } |
kaizen | 0:910036879da0 | 276 | count = 0; |
kaizen | 0:910036879da0 | 277 | } |
kaizen | 0:910036879da0 | 278 | |
kaizen | 0:910036879da0 | 279 | client.yield(10); // allow the MQTT client to receive messages |
kaizen | 0:910036879da0 | 280 | } |
kaizen | 0:910036879da0 | 281 | } |
hillkim7 | 3:64a7d39e423b | 282 |