* AM2321的取温度间隔得大于2s,否则,i2c会不工作了 * SimpleTimer有个bug,会导致两次快速的读温度,现在读温度函数里加了保护 * Blynk有个bug,会导致无法把数据传到服务器 * 现在可以正常工作了
BlynkProtocol.h
00001 /** 00002 * @file BlynkProtocol.h 00003 * @author Volodymyr Shymanskyy 00004 * @license This project is released under the MIT License (MIT) 00005 * @copyright Copyright (c) 2015 Volodymyr Shymanskyy 00006 * @date Jan 2015 00007 * @brief Blynk protocol implementation 00008 * 00009 */ 00010 00011 #ifndef BlynkProtocol_h 00012 #define BlynkProtocol_h 00013 00014 #include <string.h> 00015 #include <stdlib.h> 00016 #include <Blynk/BlynkDebug.h> 00017 #include <Blynk/BlynkProtocolDefs.h> 00018 #include <Blynk/BlynkApi.h> 00019 #include <utility/BlynkUtility.h> 00020 00021 template <class Transp> 00022 class BlynkProtocol 00023 : public BlynkApi< BlynkProtocol<Transp> > 00024 { 00025 friend class BlynkApi< BlynkProtocol<Transp> >; 00026 public: 00027 enum BlynkState { 00028 CONNECTING, 00029 CONNECTED, 00030 DISCONNECTED, 00031 }; 00032 00033 BlynkProtocol(Transp& transp) 00034 : conn(transp) 00035 , authkey(NULL) 00036 , lastActivityIn(0) 00037 , lastActivityOut(0) 00038 , lastHeartbeat(0) 00039 #ifdef BLYNK_MSG_LIMIT 00040 , deltaCmd(0) 00041 #endif 00042 , currentMsgId(0) 00043 , state(CONNECTING) 00044 {} 00045 00046 bool connected () { 00047 LOG_ENTER; 00048 return state == CONNECTED; 00049 } 00050 00051 bool connect(uint32_t timeout = BLYNK_TIMEOUT_MS*3) { 00052 LOG_ENTER; 00053 conn.disconnect(); 00054 state = CONNECTING; 00055 millis_time_t started = this->getMillis(); 00056 while ((state != CONNECTED) && 00057 (this->getMillis() - started < timeout)) { 00058 run(); 00059 } 00060 return state == CONNECTED; 00061 } 00062 00063 void disconnect() { 00064 LOG_ENTER; 00065 conn.disconnect(); 00066 state = DISCONNECTED; 00067 BLYNK_LOG1(BLYNK_F("Disconnected")); 00068 } 00069 00070 bool run(bool avail = false); 00071 00072 // TODO: Fixme 00073 void startSession() { 00074 LOG_ENTER; 00075 conn.connect(); 00076 state = CONNECTING; 00077 #ifdef BLYNK_MSG_LIMIT 00078 deltaCmd = 1000; 00079 #endif 00080 currentMsgId = 0; 00081 lastHeartbeat = lastActivityIn = lastActivityOut = this->getMillis(); // TODO: - 5005UL 00082 } 00083 00084 void sendCmd(uint8_t cmd, uint16_t id = 0, const void* data = NULL, size_t length = 0, const void* data2 = NULL, size_t length2 = 0); 00085 00086 private: 00087 int readHeader(BlynkHeader& hdr); 00088 uint16_t getNextMsgId(); 00089 00090 protected: 00091 void begin(const char* auth) { 00092 BLYNK_LOG1(BLYNK_F("Blynk v" BLYNK_VERSION " on " BLYNK_INFO_DEVICE)); 00093 this->authkey = auth; 00094 } 00095 bool processInput(void); 00096 00097 Transp& conn; 00098 00099 private: 00100 const char* authkey; 00101 millis_time_t lastActivityIn; 00102 millis_time_t lastActivityOut; 00103 union { 00104 millis_time_t lastHeartbeat; 00105 millis_time_t lastLogin; 00106 }; 00107 #ifdef BLYNK_MSG_LIMIT 00108 millis_time_t deltaCmd; 00109 #endif 00110 uint16_t currentMsgId; 00111 protected: 00112 BlynkState state; 00113 }; 00114 00115 template <class Transp> 00116 bool BlynkProtocol<Transp>::run(bool avail) 00117 { 00118 //LOG_ENTER; 00119 #if !defined(BLYNK_NO_YIELD) 00120 asdf 00121 yield(); 00122 #endif 00123 00124 if (state == DISCONNECTED) { 00125 return false; 00126 } 00127 00128 const bool tconn = conn.connected(); 00129 00130 if (tconn) { 00131 if (avail || conn.available() > 0) { 00132 //BLYNK_LOG2(BLYNK_F("Available: "), conn.available()); 00133 //const unsigned long t = micros(); 00134 if (!processInput()) { 00135 conn.disconnect(); 00136 // TODO: Only when in direct mode? 00137 #ifdef BLYNK_USE_DIRECT_CONNECT 00138 state = CONNECTING; 00139 #endif 00140 //BlynkOnDisconnected(); 00141 return false; 00142 } 00143 //BLYNK_LOG2(BLYNK_F("Proc time: "), micros() - t); 00144 } 00145 } 00146 00147 const millis_time_t t = this->getMillis(); 00148 00149 if (state == CONNECTED) { 00150 if (!tconn) { 00151 state = CONNECTING; 00152 lastHeartbeat = t; 00153 //BlynkOnDisconnected(); 00154 return false; 00155 } 00156 00157 if (t - lastActivityIn > (1000UL * BLYNK_HEARTBEAT + BLYNK_TIMEOUT_MS*3)) { 00158 #ifdef BLYNK_DEBUG 00159 BLYNK_LOG6(BLYNK_F("Heartbeat timeout: "), t, BLYNK_F(", "), lastActivityIn, BLYNK_F(", "), lastHeartbeat); 00160 #else 00161 BLYNK_LOG1(BLYNK_F("Heartbeat timeout")); 00162 #endif 00163 conn.disconnect(); 00164 state = CONNECTING; 00165 //BlynkOnDisconnected(); 00166 return false; 00167 } else if ((t - lastActivityIn > 1000UL * BLYNK_HEARTBEAT || 00168 t - lastActivityOut > 1000UL * BLYNK_HEARTBEAT) && 00169 t - lastHeartbeat > BLYNK_TIMEOUT_MS) { 00170 // Send ping if we didn't either send or receive something 00171 // for BLYNK_HEARTBEAT seconds 00172 sendCmd(BLYNK_CMD_PING); 00173 lastHeartbeat = t; 00174 } 00175 #ifndef BLYNK_USE_DIRECT_CONNECT 00176 } else if (state == CONNECTING) { 00177 if (tconn && (t - lastLogin > BLYNK_TIMEOUT_MS)) { 00178 BLYNK_LOG1(BLYNK_F("Login timeout")); 00179 conn.disconnect(); 00180 state = CONNECTING; 00181 return false; 00182 } else if (!tconn && (t - lastLogin > 5000UL)) { 00183 conn.disconnect(); 00184 if (!conn.connect()) { 00185 lastLogin = t; 00186 return false; 00187 } 00188 00189 #ifdef BLYNK_MSG_LIMIT 00190 deltaCmd = 1000; 00191 #endif 00192 sendCmd(BLYNK_CMD_LOGIN, 1, authkey, strlen(authkey)); 00193 lastLogin = lastActivityOut; 00194 return true; 00195 } 00196 #else 00197 } else if (state == CONNECTING) { 00198 if (!tconn) 00199 conn.connect(); 00200 #endif 00201 } 00202 return true; 00203 } 00204 00205 template <class Transp> 00206 BLYNK_FORCE_INLINE 00207 bool BlynkProtocol<Transp>::processInput(void) 00208 { 00209 BlynkHeader hdr; 00210 const int ret = readHeader(hdr); 00211 00212 if (ret == 0) { 00213 return true; // Considered OK (no data on input) 00214 } 00215 00216 if (ret < 0 || hdr.msg_id == 0) { 00217 #ifdef BLYNK_DEBUG 00218 BLYNK_LOG2(BLYNK_F("Bad hdr len: "), ret); 00219 #endif 00220 return false; 00221 } 00222 00223 if (hdr.type == BLYNK_CMD_RESPONSE) { 00224 lastActivityIn = this->getMillis(); 00225 00226 #ifndef BLYNK_USE_DIRECT_CONNECT 00227 if (state == CONNECTING && (1 == hdr.msg_id)) { 00228 switch (hdr.length) { 00229 case BLYNK_SUCCESS: 00230 case BLYNK_ALREADY_LOGGED_IN: 00231 BLYNK_LOG3(BLYNK_F("Ready (ping: "), lastActivityIn-lastHeartbeat, BLYNK_F("ms).")); 00232 lastHeartbeat = lastActivityIn; 00233 state = CONNECTED; 00234 this->sendInfo(); 00235 #if !defined(BLYNK_NO_YIELD) 00236 yield(); 00237 #endif 00238 BlynkOnConnected(); 00239 return true; 00240 case BLYNK_INVALID_TOKEN: 00241 BLYNK_LOG1(BLYNK_F("Invalid auth token")); 00242 break; 00243 default: 00244 BLYNK_LOG2(BLYNK_F("Connect failed. code: "), hdr.length); 00245 } 00246 return false; 00247 } 00248 if (BLYNK_NOT_AUTHENTICATED == hdr.length) { 00249 return false; 00250 } 00251 #endif 00252 // TODO: return code may indicate App presence 00253 return true; 00254 } 00255 00256 if (hdr.length > BLYNK_MAX_READBYTES) { 00257 #ifdef BLYNK_DEBUG 00258 BLYNK_LOG2(BLYNK_F("Packet too big: "), hdr.length); 00259 #endif 00260 // TODO: Flush 00261 conn.connect(); 00262 return true; 00263 } 00264 00265 uint8_t inputBuffer[hdr.length+1]; // Add 1 to zero-terminate 00266 if (hdr.length != conn.read(inputBuffer, hdr.length)) { 00267 #ifdef DEBUG 00268 BLYNK_LOG1(BLYNK_F("Can't read body")); 00269 #endif 00270 return false; 00271 } 00272 inputBuffer[hdr.length] = '\0'; 00273 00274 BLYNK_DBG_DUMP(">", inputBuffer, hdr.length); 00275 00276 lastActivityIn = this->getMillis(); 00277 00278 switch (hdr.type) { 00279 case BLYNK_CMD_LOGIN: { 00280 #ifdef BLYNK_USE_DIRECT_CONNECT 00281 if (!strncmp(authkey, (char*)inputBuffer, 32)) { 00282 BLYNK_LOG1(BLYNK_F("Ready")); 00283 state = CONNECTED; 00284 sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_SUCCESS); 00285 this->sendInfo(); 00286 } else { 00287 BLYNK_LOG1(BLYNK_F("Invalid token")); 00288 sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_INVALID_TOKEN); 00289 } 00290 #else 00291 BLYNK_LOG1(BLYNK_F("Ready")); 00292 state = CONNECTED; 00293 sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_SUCCESS); 00294 this->sendInfo(); 00295 #endif 00296 } 00297 break; 00298 case BLYNK_CMD_PING: { 00299 sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_SUCCESS); 00300 } 00301 break; 00302 case BLYNK_CMD_HARDWARE: 00303 case BLYNK_CMD_BRIDGE: { 00304 currentMsgId = hdr.msg_id; 00305 this->processCmd(inputBuffer, hdr.length); 00306 currentMsgId = 0; 00307 } 00308 break; 00309 default: { 00310 #ifdef BLYNK_DEBUG 00311 BLYNK_LOG2(BLYNK_F("Invalid header type: "), hdr.type); 00312 #endif 00313 // TODO: Flush 00314 conn.connect(); 00315 } 00316 break; 00317 } 00318 00319 return true; 00320 } 00321 00322 template <class Transp> 00323 int BlynkProtocol<Transp>::readHeader(BlynkHeader& hdr) 00324 { 00325 size_t rlen = conn.read(&hdr, sizeof(hdr)); 00326 if (rlen == 0) { 00327 return 0; 00328 } 00329 00330 if (sizeof(hdr) != rlen) { 00331 return -1; 00332 } 00333 00334 BLYNK_DBG_DUMP(">", &hdr, sizeof(BlynkHeader)); 00335 00336 hdr.msg_id = ntohs(hdr.msg_id); 00337 hdr.length = ntohs(hdr.length); 00338 00339 return rlen; 00340 } 00341 00342 #ifndef BLYNK_SEND_THROTTLE 00343 #define BLYNK_SEND_THROTTLE 10 00344 #endif 00345 00346 #ifndef BLYNK_SEND_CHUNK 00347 #define BLYNK_SEND_CHUNK 1024 // Just a big number 00348 #endif 00349 00350 template <class Transp> 00351 void BlynkProtocol<Transp>::sendCmd(uint8_t cmd, uint16_t id, const void* data, size_t length, const void* data2, size_t length2) 00352 { 00353 //pc.printf("sendCmd: cmd=%d, id = %d, state=%d\r\n", cmd, id, state); 00354 if (0 == id) { 00355 id = getNextMsgId(); 00356 } 00357 //pc.printf("next Id:%d\r\n", id); 00358 #ifdef BLYNK_MICRODUINO 00359 if (!conn.connected()) { 00360 //pc.printf("not connected, so just return!\r\n"); 00361 return; 00362 } 00363 #else 00364 if (!conn.connected() || (cmd != BLYNK_CMD_RESPONSE && cmd != BLYNK_CMD_PING && cmd != BLYNK_CMD_LOGIN && state != CONNECTED) ) { 00365 //if (!conn.connected() || (cmd != BLYNK_CMD_RESPONSE && cmd != BLYNK_CMD_PING && cmd != BLYNK_CMD_LOGIN) ) { 00366 #ifdef BLYNK_DEBUG 00367 BLYNK_LOG2(BLYNK_F("Cmd skipped:"), cmd); 00368 #endif 00369 //pc.printf("Cmd skipped:", cmd); 00370 return; 00371 } 00372 asdf 00373 #endif 00374 const int full_length = (sizeof(BlynkHeader)) + 00375 (data ? length : 0) + 00376 (data2 ? length2 : 0); 00377 //pc.printf("full_length = %d\r\n", full_length); 00378 #if defined(BLYNK_SEND_ATOMIC) || defined(ESP8266) || defined(SPARK) || defined(PARTICLE) || defined(ENERGIA) 00379 // Those have more RAM and like single write at a time... 00380 00381 uint8_t buff[full_length]; 00382 00383 BlynkHeader* hdr = (BlynkHeader*)buff; 00384 hdr->type = cmd; 00385 hdr->msg_id = htons(id); 00386 hdr->length = htons(length+length2); 00387 00388 size_t pos = sizeof(BlynkHeader); 00389 if (data && length) { 00390 memcpy(buff + pos, data, length); 00391 pos += length; 00392 } 00393 if (data2 && length2) { 00394 memcpy(buff + pos, data2, length2); 00395 } 00396 00397 size_t wlen = 0; 00398 while (wlen < full_length) { 00399 const size_t chunk = BlynkMin(size_t(BLYNK_SEND_CHUNK), full_length - wlen); 00400 BLYNK_DBG_DUMP("<", buff + wlen, chunk); 00401 const size_t w = conn.write(buff + wlen, chunk); 00402 wait_ms(BLYNK_SEND_THROTTLE); 00403 if (w == 0) { 00404 #ifdef BLYNK_DEBUG 00405 BLYNK_LOG1(BLYNK_F("Cmd error")); 00406 #endif 00407 conn.disconnect(); 00408 state = CONNECTING; 00409 //BlynkOnDisconnected(); 00410 return; 00411 } 00412 wlen += w; 00413 } 00414 00415 #else 00416 BlynkHeader hdr; 00417 hdr.type = cmd; 00418 hdr.msg_id = htons(id); 00419 hdr.length = htons(length+length2); 00420 00421 BLYNK_DBG_DUMP("<", &hdr, sizeof(hdr)); 00422 size_t wlen = conn.write(&hdr, sizeof(hdr)); 00423 wait_ms(BLYNK_SEND_THROTTLE); 00424 00425 if (cmd != BLYNK_CMD_RESPONSE) { 00426 if (length) { 00427 BLYNK_DBG_DUMP("<", data, length); 00428 wlen += conn.write(data, length); 00429 wait_ms(BLYNK_SEND_THROTTLE); 00430 } 00431 if (length2) { 00432 BLYNK_DBG_DUMP("<", data2, length2); 00433 wlen += conn.write(data2, length2); 00434 wait_ms(BLYNK_SEND_THROTTLE); 00435 } 00436 } 00437 00438 #endif 00439 00440 if (wlen != full_length) { 00441 #ifdef BLYNK_DEBUG 00442 BLYNK_LOG4(BLYNK_F("Sent "), wlen, '/', full_length); 00443 #endif 00444 conn.disconnect(); 00445 state = CONNECTING; 00446 //BlynkOnDisconnected(); 00447 return; 00448 } 00449 00450 #if defined BLYNK_MSG_LIMIT && BLYNK_MSG_LIMIT > 0 00451 const millis_time_t ts = this->getMillis(); 00452 BlynkAverageSample<32>(deltaCmd, ts - lastActivityOut); 00453 lastActivityOut = ts; 00454 //BLYNK_LOG2(BLYNK_F("Delta: "), deltaCmd); 00455 if (deltaCmd < (1000/BLYNK_MSG_LIMIT)) { 00456 BLYNK_LOG_TROUBLE(BLYNK_F("flood-error")); 00457 conn.disconnect(); 00458 state = CONNECTING; 00459 //BlynkOnDisconnected(); 00460 } 00461 #else 00462 lastActivityOut = this->getMillis(); 00463 #endif 00464 00465 } 00466 00467 template <class Transp> 00468 uint16_t BlynkProtocol<Transp>::getNextMsgId() 00469 { 00470 static uint16_t last = 0; 00471 if (currentMsgId != 0) 00472 return currentMsgId; 00473 if (++last == 0) 00474 last = 1; 00475 return last; 00476 } 00477 00478 #endif 00479
Generated on Tue Jul 12 2022 13:01:27 by 1.7.2