Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: DHT WIZnetInterface mbed-src
ThingerMBedClient.h
00001 // The MIT License (MIT) 00002 // 00003 // Copyright (c) 2015 THINGER LTD 00004 // Author: alvarolb@gmail.com (Alvaro Luis Bustamante) 00005 // 00006 // Permission is hereby granted, free of charge, to any person obtaining a copy 00007 // of this software and associated documentation files (the "Software"), to deal 00008 // in the Software without restriction, including without limitation the rights 00009 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00010 // copies of the Software, and to permit persons to whom the Software is 00011 // furnished to do so, subject to the following conditions: 00012 // 00013 // The above copyright notice and this permission notice shall be included in 00014 // all copies or substantial portions of the Software. 00015 // 00016 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00017 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00018 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00019 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00020 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00021 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00022 // THE SOFTWARE. 00023 00024 #ifndef THINGER_MBED_CLIENT_H 00025 #define THINGER_MBED_CLIENT_H 00026 00027 #include "thinger/thinger.h" 00028 00029 //#define _DEBUG_ 00030 00031 using namespace protoson; 00032 00033 dynamic_memory_allocator alloc; 00034 //circular_memory_allocator<512> alloc; 00035 memory_allocator& protoson::pool = alloc; 00036 00037 #define THINGER_SERVER "iot.thinger.io" 00038 #define THINGER_PORT 25200 00039 #define RECONNECTION_TIMEOUT 5000 // milliseconds 00040 00041 //---For MBED---// 00042 00043 #ifndef Client 00044 #define Client TCPSocketConnectionArdu 00045 #endif 00046 00047 #ifndef millis 00048 #define millis() us_ticker_read()/1000 00049 #endif 00050 00051 #ifndef delay 00052 #define delay wait_ms 00053 #endif 00054 00055 00056 class ThingerClient : public thinger::thinger { 00057 00058 00059 public: 00060 ThingerClient(Client& client, const char* user, const char* device, const char* device_credential) : 00061 client_(client), username_(user), device_id_(device), device_password_(device_credential), 00062 temp_data_(NULL), out_size_(0) 00063 { 00064 00065 } 00066 00067 ~ThingerClient() 00068 { 00069 00070 } 00071 00072 protected: 00073 00074 virtual bool read(char* buffer, size_t size) 00075 { 00076 size_t total_read = 0; 00077 while(total_read<size){ 00078 int read = client_.readBytes((uint8_t*)buffer, size-total_read); 00079 if(read<0) return false; 00080 total_read += read; 00081 } 00082 return total_read == size; 00083 } 00084 00085 // TODO Allow removing this Nagle's algorithm implementation if the underlying device already implements it 00086 virtual bool write(const char* buffer, size_t size, bool flush=false){ 00087 if(size>0){ 00088 temp_data_ = (uint8_t*) realloc(temp_data_, out_size_ + size); 00089 memcpy(&temp_data_[out_size_], buffer, size); 00090 out_size_ += size; 00091 } 00092 if(flush && out_size_>0){ 00093 #ifdef _DEBUG_ 00094 printf("[THINGER] Writing bytes: %d", out_size_); 00095 #endif 00096 00097 size_t written = client_.write(temp_data_, out_size_); 00098 bool success = written == out_size_; 00099 free(temp_data_); 00100 temp_data_ = NULL; 00101 out_size_ = 0; 00102 00103 #ifdef _DEBUG_ 00104 printf(" [%s]\r\n",success ? "OK" : "FAIL"); 00105 #endif 00106 00107 //FIXME Without this small delay or activating the debug (which takes time), the CC3200 does not work well. Why? 00108 #ifdef __CC3200R1M1RGC__ 00109 delay(1); 00110 #endif 00111 return success; 00112 } 00113 return true; 00114 } 00115 00116 virtual void disconnected(){ 00117 thinger_state_listener(SOCKET_TIMEOUT); 00118 client_.stop(); 00119 thinger_state_listener(SOCKET_DISCONNECTED); 00120 } 00121 00122 virtual bool connect_network(){ 00123 return true; 00124 } 00125 00126 virtual bool network_connected(){ 00127 return true; 00128 } 00129 00130 enum THINGER_STATE{ 00131 NETWORK_CONNECTING, 00132 NETWORK_CONNECTED, 00133 NETWORK_CONNECT_ERROR, 00134 SOCKET_CONNECTING, 00135 SOCKET_CONNECTED, 00136 SOCKET_CONNECTION_ERROR, 00137 SOCKET_DISCONNECTED, 00138 SOCKET_TIMEOUT, 00139 THINGER_AUTHENTICATING, 00140 THINGER_AUTHENTICATED, 00141 THINGER_AUTH_FAILED 00142 }; 00143 00144 virtual void thinger_state_listener(THINGER_STATE state){ 00145 #ifdef _DEBUG_ 00146 switch(state){ 00147 case NETWORK_CONNECTING: 00148 printf("[NETWORK] Starting connection...\r\n"); 00149 break; 00150 case NETWORK_CONNECTED: 00151 printf("[NETWORK] Connected!\r\n"); 00152 break; 00153 case NETWORK_CONNECT_ERROR: 00154 printf("[NETWORK] Cannot connect!\r\n"); 00155 break; 00156 case SOCKET_CONNECTING: 00157 printf("[_SOCKET] Connecting to %s : %d ...", THINGER_SERVER,THINGER_PORT); 00158 break; 00159 case SOCKET_CONNECTED: 00160 printf("[_SOCKET] Connected!\r\n"); 00161 break; 00162 case SOCKET_CONNECTION_ERROR: 00163 printf("[_SOCKET] Error while connecting!\r\n"); 00164 break; 00165 case SOCKET_DISCONNECTED: 00166 printf("[_SOCKET] Is now closed!\r\n"); 00167 break; 00168 case SOCKET_TIMEOUT: 00169 printf("[_SOCKET] Timeout!\r\n"); 00170 break; 00171 case THINGER_AUTHENTICATING: 00172 printf("[THINGER] Authenticating. User: %s Device: %s\r\n",username_,device_id_); 00173 break; 00174 case THINGER_AUTHENTICATED: 00175 printf("[THINGER] Authenticated!\r\n"); 00176 break; 00177 case THINGER_AUTH_FAILED: 00178 printf("[THINGER] Auth Failed! Check username, device id, or device credentials.\r\n"); 00179 break; 00180 } 00181 #endif 00182 } 00183 00184 bool handle_connection() 00185 { 00186 bool network = network_connected(); 00187 00188 if(!network){ 00189 thinger_state_listener(NETWORK_CONNECTING); 00190 network = connect_network(); 00191 if(!network){ 00192 thinger_state_listener(NETWORK_CONNECT_ERROR); 00193 return false; 00194 } 00195 thinger_state_listener(NETWORK_CONNECTED); 00196 } 00197 00198 bool client = client_.connected(); 00199 if(!client){ 00200 client = connect_client(); 00201 if(!client){ 00202 return false; 00203 } 00204 } 00205 return network && client; 00206 } 00207 00208 bool connect_client(){ 00209 bool connected = false; 00210 client_.stop(); // cleanup previous socket 00211 thinger_state_listener(SOCKET_CONNECTING); 00212 if (client_.connect(THINGER_SERVER, THINGER_PORT) == 0) { 00213 delay(3000); 00214 thinger_state_listener(SOCKET_CONNECTED); 00215 thinger_state_listener(THINGER_AUTHENTICATING); 00216 connected = thinger::thinger::connect(username_, device_id_, device_password_); 00217 if(!connected){ 00218 thinger_state_listener(THINGER_AUTH_FAILED); 00219 client_.stop(); 00220 thinger_state_listener(SOCKET_DISCONNECTED); 00221 } 00222 else{ 00223 thinger_state_listener(THINGER_AUTHENTICATED); 00224 } 00225 } 00226 else{ 00227 thinger_state_listener(SOCKET_CONNECTION_ERROR); 00228 } 00229 return connected; 00230 } 00231 00232 public: 00233 00234 void handle(){ 00235 if(handle_connection()){ 00236 #ifdef _DEBUG_ 00237 if(client_.available()>0){ 00238 printf("[THINGER] Available bytes: %d", client_.available()); 00239 } 00240 #endif 00241 thinger::thinger::handle(millis(), client_.available()>0); 00242 }else{ 00243 delay(RECONNECTION_TIMEOUT); // get some delay for a connection retry 00244 } 00245 } 00246 00247 private: 00248 00249 Client& client_; 00250 const char* username_; 00251 const char* device_id_; 00252 const char* device_password_; 00253 uint8_t * temp_data_; 00254 size_t out_size_; 00255 }; 00256 00257 #endif
Generated on Wed Jul 13 2022 02:25:39 by
