Thinger IO Cloude Service Test Example with WIZwiki-W7500
Dependencies: DHT WIZnetInterface mbed-src
Smart WIZwiki_W7500 IoT platform with the Open source IoT Cloud server thinger.io
Overview
This project is based on mbed WIZwiki-W7500 platform launced by WIZnet. WIZwiki-W7500 can connect to the smart IoT cloud server called thinger.io.
Demos
For more detail
ThingerIO/ThingerMBedClient.h@5:c4c405bc6e6d, 2015-09-24 (annotated)
- Committer:
- MidnightCow
- Date:
- Thu Sep 24 01:02:46 2015 +0000
- Revision:
- 5:c4c405bc6e6d
- Parent:
- 1:fa957f28633b
Code refined.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MidnightCow | 1:fa957f28633b | 1 | // The MIT License (MIT) |
MidnightCow | 1:fa957f28633b | 2 | // |
MidnightCow | 1:fa957f28633b | 3 | // Copyright (c) 2015 THINGER LTD |
MidnightCow | 1:fa957f28633b | 4 | // Author: alvarolb@gmail.com (Alvaro Luis Bustamante) |
MidnightCow | 1:fa957f28633b | 5 | // |
MidnightCow | 1:fa957f28633b | 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy |
MidnightCow | 1:fa957f28633b | 7 | // of this software and associated documentation files (the "Software"), to deal |
MidnightCow | 1:fa957f28633b | 8 | // in the Software without restriction, including without limitation the rights |
MidnightCow | 1:fa957f28633b | 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
MidnightCow | 1:fa957f28633b | 10 | // copies of the Software, and to permit persons to whom the Software is |
MidnightCow | 1:fa957f28633b | 11 | // furnished to do so, subject to the following conditions: |
MidnightCow | 1:fa957f28633b | 12 | // |
MidnightCow | 1:fa957f28633b | 13 | // The above copyright notice and this permission notice shall be included in |
MidnightCow | 1:fa957f28633b | 14 | // all copies or substantial portions of the Software. |
MidnightCow | 1:fa957f28633b | 15 | // |
MidnightCow | 1:fa957f28633b | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
MidnightCow | 1:fa957f28633b | 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
MidnightCow | 1:fa957f28633b | 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
MidnightCow | 1:fa957f28633b | 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
MidnightCow | 1:fa957f28633b | 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
MidnightCow | 1:fa957f28633b | 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
MidnightCow | 1:fa957f28633b | 22 | // THE SOFTWARE. |
MidnightCow | 1:fa957f28633b | 23 | |
MidnightCow | 1:fa957f28633b | 24 | #ifndef THINGER_MBED_CLIENT_H |
MidnightCow | 1:fa957f28633b | 25 | #define THINGER_MBED_CLIENT_H |
MidnightCow | 1:fa957f28633b | 26 | |
MidnightCow | 1:fa957f28633b | 27 | #include "thinger/thinger.h" |
MidnightCow | 1:fa957f28633b | 28 | |
MidnightCow | 1:fa957f28633b | 29 | //#define _DEBUG_ |
MidnightCow | 1:fa957f28633b | 30 | |
MidnightCow | 1:fa957f28633b | 31 | using namespace protoson; |
MidnightCow | 1:fa957f28633b | 32 | |
MidnightCow | 1:fa957f28633b | 33 | dynamic_memory_allocator alloc; |
MidnightCow | 1:fa957f28633b | 34 | //circular_memory_allocator<512> alloc; |
MidnightCow | 1:fa957f28633b | 35 | memory_allocator& protoson::pool = alloc; |
MidnightCow | 1:fa957f28633b | 36 | |
MidnightCow | 1:fa957f28633b | 37 | #define THINGER_SERVER "iot.thinger.io" |
MidnightCow | 1:fa957f28633b | 38 | #define THINGER_PORT 25200 |
MidnightCow | 1:fa957f28633b | 39 | #define RECONNECTION_TIMEOUT 5000 // milliseconds |
MidnightCow | 1:fa957f28633b | 40 | |
MidnightCow | 1:fa957f28633b | 41 | //---For MBED---// |
MidnightCow | 1:fa957f28633b | 42 | |
MidnightCow | 1:fa957f28633b | 43 | #ifndef Client |
MidnightCow | 1:fa957f28633b | 44 | #define Client TCPSocketConnectionArdu |
MidnightCow | 1:fa957f28633b | 45 | #endif |
MidnightCow | 1:fa957f28633b | 46 | |
MidnightCow | 1:fa957f28633b | 47 | #ifndef millis |
MidnightCow | 1:fa957f28633b | 48 | #define millis() us_ticker_read()/1000 |
MidnightCow | 1:fa957f28633b | 49 | #endif |
MidnightCow | 1:fa957f28633b | 50 | |
MidnightCow | 1:fa957f28633b | 51 | #ifndef delay |
MidnightCow | 1:fa957f28633b | 52 | #define delay wait_ms |
MidnightCow | 1:fa957f28633b | 53 | #endif |
MidnightCow | 1:fa957f28633b | 54 | |
MidnightCow | 1:fa957f28633b | 55 | |
MidnightCow | 1:fa957f28633b | 56 | class ThingerClient : public thinger::thinger { |
MidnightCow | 1:fa957f28633b | 57 | |
MidnightCow | 1:fa957f28633b | 58 | |
MidnightCow | 1:fa957f28633b | 59 | public: |
MidnightCow | 1:fa957f28633b | 60 | ThingerClient(Client& client, const char* user, const char* device, const char* device_credential) : |
MidnightCow | 1:fa957f28633b | 61 | client_(client), username_(user), device_id_(device), device_password_(device_credential), |
MidnightCow | 1:fa957f28633b | 62 | temp_data_(NULL), out_size_(0) |
MidnightCow | 1:fa957f28633b | 63 | { |
MidnightCow | 1:fa957f28633b | 64 | |
MidnightCow | 1:fa957f28633b | 65 | } |
MidnightCow | 1:fa957f28633b | 66 | |
MidnightCow | 1:fa957f28633b | 67 | ~ThingerClient() |
MidnightCow | 1:fa957f28633b | 68 | { |
MidnightCow | 1:fa957f28633b | 69 | |
MidnightCow | 1:fa957f28633b | 70 | } |
MidnightCow | 1:fa957f28633b | 71 | |
MidnightCow | 1:fa957f28633b | 72 | protected: |
MidnightCow | 1:fa957f28633b | 73 | |
MidnightCow | 1:fa957f28633b | 74 | virtual bool read(char* buffer, size_t size) |
MidnightCow | 1:fa957f28633b | 75 | { |
MidnightCow | 1:fa957f28633b | 76 | size_t total_read = 0; |
MidnightCow | 1:fa957f28633b | 77 | while(total_read<size){ |
MidnightCow | 1:fa957f28633b | 78 | int read = client_.readBytes((uint8_t*)buffer, size-total_read); |
MidnightCow | 1:fa957f28633b | 79 | if(read<0) return false; |
MidnightCow | 1:fa957f28633b | 80 | total_read += read; |
MidnightCow | 1:fa957f28633b | 81 | } |
MidnightCow | 1:fa957f28633b | 82 | return total_read == size; |
MidnightCow | 1:fa957f28633b | 83 | } |
MidnightCow | 1:fa957f28633b | 84 | |
MidnightCow | 1:fa957f28633b | 85 | // TODO Allow removing this Nagle's algorithm implementation if the underlying device already implements it |
MidnightCow | 1:fa957f28633b | 86 | virtual bool write(const char* buffer, size_t size, bool flush=false){ |
MidnightCow | 1:fa957f28633b | 87 | if(size>0){ |
MidnightCow | 1:fa957f28633b | 88 | temp_data_ = (uint8_t*) realloc(temp_data_, out_size_ + size); |
MidnightCow | 1:fa957f28633b | 89 | memcpy(&temp_data_[out_size_], buffer, size); |
MidnightCow | 1:fa957f28633b | 90 | out_size_ += size; |
MidnightCow | 1:fa957f28633b | 91 | } |
MidnightCow | 1:fa957f28633b | 92 | if(flush && out_size_>0){ |
MidnightCow | 1:fa957f28633b | 93 | #ifdef _DEBUG_ |
MidnightCow | 1:fa957f28633b | 94 | printf("[THINGER] Writing bytes: %d", out_size_); |
MidnightCow | 1:fa957f28633b | 95 | #endif |
MidnightCow | 1:fa957f28633b | 96 | |
MidnightCow | 1:fa957f28633b | 97 | size_t written = client_.write(temp_data_, out_size_); |
MidnightCow | 1:fa957f28633b | 98 | bool success = written == out_size_; |
MidnightCow | 1:fa957f28633b | 99 | free(temp_data_); |
MidnightCow | 1:fa957f28633b | 100 | temp_data_ = NULL; |
MidnightCow | 1:fa957f28633b | 101 | out_size_ = 0; |
MidnightCow | 1:fa957f28633b | 102 | |
MidnightCow | 1:fa957f28633b | 103 | #ifdef _DEBUG_ |
MidnightCow | 1:fa957f28633b | 104 | printf(" [%s]\r\n",success ? "OK" : "FAIL"); |
MidnightCow | 1:fa957f28633b | 105 | #endif |
MidnightCow | 1:fa957f28633b | 106 | |
MidnightCow | 1:fa957f28633b | 107 | //FIXME Without this small delay or activating the debug (which takes time), the CC3200 does not work well. Why? |
MidnightCow | 1:fa957f28633b | 108 | #ifdef __CC3200R1M1RGC__ |
MidnightCow | 1:fa957f28633b | 109 | delay(1); |
MidnightCow | 1:fa957f28633b | 110 | #endif |
MidnightCow | 1:fa957f28633b | 111 | return success; |
MidnightCow | 1:fa957f28633b | 112 | } |
MidnightCow | 1:fa957f28633b | 113 | return true; |
MidnightCow | 1:fa957f28633b | 114 | } |
MidnightCow | 1:fa957f28633b | 115 | |
MidnightCow | 1:fa957f28633b | 116 | virtual void disconnected(){ |
MidnightCow | 1:fa957f28633b | 117 | thinger_state_listener(SOCKET_TIMEOUT); |
MidnightCow | 1:fa957f28633b | 118 | client_.stop(); |
MidnightCow | 1:fa957f28633b | 119 | thinger_state_listener(SOCKET_DISCONNECTED); |
MidnightCow | 1:fa957f28633b | 120 | } |
MidnightCow | 1:fa957f28633b | 121 | |
MidnightCow | 1:fa957f28633b | 122 | virtual bool connect_network(){ |
MidnightCow | 1:fa957f28633b | 123 | return true; |
MidnightCow | 1:fa957f28633b | 124 | } |
MidnightCow | 1:fa957f28633b | 125 | |
MidnightCow | 1:fa957f28633b | 126 | virtual bool network_connected(){ |
MidnightCow | 1:fa957f28633b | 127 | return true; |
MidnightCow | 1:fa957f28633b | 128 | } |
MidnightCow | 1:fa957f28633b | 129 | |
MidnightCow | 1:fa957f28633b | 130 | enum THINGER_STATE{ |
MidnightCow | 1:fa957f28633b | 131 | NETWORK_CONNECTING, |
MidnightCow | 1:fa957f28633b | 132 | NETWORK_CONNECTED, |
MidnightCow | 1:fa957f28633b | 133 | NETWORK_CONNECT_ERROR, |
MidnightCow | 1:fa957f28633b | 134 | SOCKET_CONNECTING, |
MidnightCow | 1:fa957f28633b | 135 | SOCKET_CONNECTED, |
MidnightCow | 1:fa957f28633b | 136 | SOCKET_CONNECTION_ERROR, |
MidnightCow | 1:fa957f28633b | 137 | SOCKET_DISCONNECTED, |
MidnightCow | 1:fa957f28633b | 138 | SOCKET_TIMEOUT, |
MidnightCow | 1:fa957f28633b | 139 | THINGER_AUTHENTICATING, |
MidnightCow | 1:fa957f28633b | 140 | THINGER_AUTHENTICATED, |
MidnightCow | 1:fa957f28633b | 141 | THINGER_AUTH_FAILED |
MidnightCow | 1:fa957f28633b | 142 | }; |
MidnightCow | 1:fa957f28633b | 143 | |
MidnightCow | 1:fa957f28633b | 144 | virtual void thinger_state_listener(THINGER_STATE state){ |
MidnightCow | 1:fa957f28633b | 145 | #ifdef _DEBUG_ |
MidnightCow | 1:fa957f28633b | 146 | switch(state){ |
MidnightCow | 1:fa957f28633b | 147 | case NETWORK_CONNECTING: |
MidnightCow | 1:fa957f28633b | 148 | printf("[NETWORK] Starting connection...\r\n"); |
MidnightCow | 1:fa957f28633b | 149 | break; |
MidnightCow | 1:fa957f28633b | 150 | case NETWORK_CONNECTED: |
MidnightCow | 1:fa957f28633b | 151 | printf("[NETWORK] Connected!\r\n"); |
MidnightCow | 1:fa957f28633b | 152 | break; |
MidnightCow | 1:fa957f28633b | 153 | case NETWORK_CONNECT_ERROR: |
MidnightCow | 1:fa957f28633b | 154 | printf("[NETWORK] Cannot connect!\r\n"); |
MidnightCow | 1:fa957f28633b | 155 | break; |
MidnightCow | 1:fa957f28633b | 156 | case SOCKET_CONNECTING: |
MidnightCow | 1:fa957f28633b | 157 | printf("[_SOCKET] Connecting to %s : %d ...", THINGER_SERVER,THINGER_PORT); |
MidnightCow | 1:fa957f28633b | 158 | break; |
MidnightCow | 1:fa957f28633b | 159 | case SOCKET_CONNECTED: |
MidnightCow | 1:fa957f28633b | 160 | printf("[_SOCKET] Connected!\r\n"); |
MidnightCow | 1:fa957f28633b | 161 | break; |
MidnightCow | 1:fa957f28633b | 162 | case SOCKET_CONNECTION_ERROR: |
MidnightCow | 1:fa957f28633b | 163 | printf("[_SOCKET] Error while connecting!\r\n"); |
MidnightCow | 1:fa957f28633b | 164 | break; |
MidnightCow | 1:fa957f28633b | 165 | case SOCKET_DISCONNECTED: |
MidnightCow | 1:fa957f28633b | 166 | printf("[_SOCKET] Is now closed!\r\n"); |
MidnightCow | 1:fa957f28633b | 167 | break; |
MidnightCow | 1:fa957f28633b | 168 | case SOCKET_TIMEOUT: |
MidnightCow | 1:fa957f28633b | 169 | printf("[_SOCKET] Timeout!\r\n"); |
MidnightCow | 1:fa957f28633b | 170 | break; |
MidnightCow | 1:fa957f28633b | 171 | case THINGER_AUTHENTICATING: |
MidnightCow | 1:fa957f28633b | 172 | printf("[THINGER] Authenticating. User: %s Device: %s\r\n",username_,device_id_); |
MidnightCow | 1:fa957f28633b | 173 | break; |
MidnightCow | 1:fa957f28633b | 174 | case THINGER_AUTHENTICATED: |
MidnightCow | 1:fa957f28633b | 175 | printf("[THINGER] Authenticated!\r\n"); |
MidnightCow | 1:fa957f28633b | 176 | break; |
MidnightCow | 1:fa957f28633b | 177 | case THINGER_AUTH_FAILED: |
MidnightCow | 1:fa957f28633b | 178 | printf("[THINGER] Auth Failed! Check username, device id, or device credentials.\r\n"); |
MidnightCow | 1:fa957f28633b | 179 | break; |
MidnightCow | 1:fa957f28633b | 180 | } |
MidnightCow | 1:fa957f28633b | 181 | #endif |
MidnightCow | 1:fa957f28633b | 182 | } |
MidnightCow | 1:fa957f28633b | 183 | |
MidnightCow | 1:fa957f28633b | 184 | bool handle_connection() |
MidnightCow | 1:fa957f28633b | 185 | { |
MidnightCow | 1:fa957f28633b | 186 | bool network = network_connected(); |
MidnightCow | 1:fa957f28633b | 187 | |
MidnightCow | 1:fa957f28633b | 188 | if(!network){ |
MidnightCow | 1:fa957f28633b | 189 | thinger_state_listener(NETWORK_CONNECTING); |
MidnightCow | 1:fa957f28633b | 190 | network = connect_network(); |
MidnightCow | 1:fa957f28633b | 191 | if(!network){ |
MidnightCow | 1:fa957f28633b | 192 | thinger_state_listener(NETWORK_CONNECT_ERROR); |
MidnightCow | 1:fa957f28633b | 193 | return false; |
MidnightCow | 1:fa957f28633b | 194 | } |
MidnightCow | 1:fa957f28633b | 195 | thinger_state_listener(NETWORK_CONNECTED); |
MidnightCow | 1:fa957f28633b | 196 | } |
MidnightCow | 1:fa957f28633b | 197 | |
MidnightCow | 1:fa957f28633b | 198 | bool client = client_.connected(); |
MidnightCow | 1:fa957f28633b | 199 | if(!client){ |
MidnightCow | 1:fa957f28633b | 200 | client = connect_client(); |
MidnightCow | 1:fa957f28633b | 201 | if(!client){ |
MidnightCow | 1:fa957f28633b | 202 | return false; |
MidnightCow | 1:fa957f28633b | 203 | } |
MidnightCow | 1:fa957f28633b | 204 | } |
MidnightCow | 1:fa957f28633b | 205 | return network && client; |
MidnightCow | 1:fa957f28633b | 206 | } |
MidnightCow | 1:fa957f28633b | 207 | |
MidnightCow | 1:fa957f28633b | 208 | bool connect_client(){ |
MidnightCow | 1:fa957f28633b | 209 | bool connected = false; |
MidnightCow | 1:fa957f28633b | 210 | client_.stop(); // cleanup previous socket |
MidnightCow | 1:fa957f28633b | 211 | thinger_state_listener(SOCKET_CONNECTING); |
MidnightCow | 1:fa957f28633b | 212 | if (client_.connect(THINGER_SERVER, THINGER_PORT) == 0) { |
MidnightCow | 1:fa957f28633b | 213 | delay(3000); |
MidnightCow | 1:fa957f28633b | 214 | thinger_state_listener(SOCKET_CONNECTED); |
MidnightCow | 1:fa957f28633b | 215 | thinger_state_listener(THINGER_AUTHENTICATING); |
MidnightCow | 1:fa957f28633b | 216 | connected = thinger::thinger::connect(username_, device_id_, device_password_); |
MidnightCow | 1:fa957f28633b | 217 | if(!connected){ |
MidnightCow | 1:fa957f28633b | 218 | thinger_state_listener(THINGER_AUTH_FAILED); |
MidnightCow | 1:fa957f28633b | 219 | client_.stop(); |
MidnightCow | 1:fa957f28633b | 220 | thinger_state_listener(SOCKET_DISCONNECTED); |
MidnightCow | 1:fa957f28633b | 221 | } |
MidnightCow | 1:fa957f28633b | 222 | else{ |
MidnightCow | 1:fa957f28633b | 223 | thinger_state_listener(THINGER_AUTHENTICATED); |
MidnightCow | 1:fa957f28633b | 224 | } |
MidnightCow | 1:fa957f28633b | 225 | } |
MidnightCow | 1:fa957f28633b | 226 | else{ |
MidnightCow | 1:fa957f28633b | 227 | thinger_state_listener(SOCKET_CONNECTION_ERROR); |
MidnightCow | 1:fa957f28633b | 228 | } |
MidnightCow | 1:fa957f28633b | 229 | return connected; |
MidnightCow | 1:fa957f28633b | 230 | } |
MidnightCow | 1:fa957f28633b | 231 | |
MidnightCow | 1:fa957f28633b | 232 | public: |
MidnightCow | 1:fa957f28633b | 233 | |
MidnightCow | 1:fa957f28633b | 234 | void handle(){ |
MidnightCow | 1:fa957f28633b | 235 | if(handle_connection()){ |
MidnightCow | 1:fa957f28633b | 236 | #ifdef _DEBUG_ |
MidnightCow | 1:fa957f28633b | 237 | if(client_.available()>0){ |
MidnightCow | 1:fa957f28633b | 238 | printf("[THINGER] Available bytes: %d", client_.available()); |
MidnightCow | 1:fa957f28633b | 239 | } |
MidnightCow | 1:fa957f28633b | 240 | #endif |
MidnightCow | 1:fa957f28633b | 241 | thinger::thinger::handle(millis(), client_.available()>0); |
MidnightCow | 1:fa957f28633b | 242 | }else{ |
MidnightCow | 1:fa957f28633b | 243 | delay(RECONNECTION_TIMEOUT); // get some delay for a connection retry |
MidnightCow | 1:fa957f28633b | 244 | } |
MidnightCow | 1:fa957f28633b | 245 | } |
MidnightCow | 1:fa957f28633b | 246 | |
MidnightCow | 1:fa957f28633b | 247 | private: |
MidnightCow | 1:fa957f28633b | 248 | |
MidnightCow | 1:fa957f28633b | 249 | Client& client_; |
MidnightCow | 1:fa957f28633b | 250 | const char* username_; |
MidnightCow | 1:fa957f28633b | 251 | const char* device_id_; |
MidnightCow | 1:fa957f28633b | 252 | const char* device_password_; |
MidnightCow | 1:fa957f28633b | 253 | uint8_t * temp_data_; |
MidnightCow | 1:fa957f28633b | 254 | size_t out_size_; |
MidnightCow | 1:fa957f28633b | 255 | }; |
MidnightCow | 1:fa957f28633b | 256 | |
MidnightCow | 1:fa957f28633b | 257 | #endif |