Blynk library for embedded hardware. Works with Arduino, ESP8266, Raspberry Pi, Intel Edison/Galileo, LinkIt ONE, Particle Core/Photon, Energia, ARM mbed, etc. http://www.blynk.cc/

Dependents:   Blynk_RBL_BLE_Nano Blynk_MicroBit Blynk_Serial Blynk_RBL_BLE_Nano

Committer:
Volodymyr Shymanskyy
Date:
Wed Nov 29 14:05:41 2017 +0200
Revision:
18:c328c1a97f90
Parent:
15:975b60f7a8ff
Child:
19:bae78e167b11
Update version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vshymanskyy 0:58b20b438383 1 /**
vshymanskyy 0:58b20b438383 2 * @file BlynkProtocol.h
vshymanskyy 0:58b20b438383 3 * @author Volodymyr Shymanskyy
vshymanskyy 0:58b20b438383 4 * @license This project is released under the MIT License (MIT)
vshymanskyy 0:58b20b438383 5 * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
vshymanskyy 0:58b20b438383 6 * @date Jan 2015
vshymanskyy 0:58b20b438383 7 * @brief Blynk protocol implementation
vshymanskyy 0:58b20b438383 8 *
vshymanskyy 0:58b20b438383 9 */
vshymanskyy 0:58b20b438383 10
vshymanskyy 0:58b20b438383 11 #ifndef BlynkProtocol_h
vshymanskyy 0:58b20b438383 12 #define BlynkProtocol_h
vshymanskyy 0:58b20b438383 13
vshymanskyy 0:58b20b438383 14 #include <string.h>
vshymanskyy 0:58b20b438383 15 #include <stdlib.h>
vshymanskyy 0:58b20b438383 16 #include <Blynk/BlynkDebug.h>
vshymanskyy 0:58b20b438383 17 #include <Blynk/BlynkProtocolDefs.h>
vshymanskyy 0:58b20b438383 18 #include <Blynk/BlynkApi.h>
vshymanskyy 0:58b20b438383 19 #include <utility/BlynkUtility.h>
vshymanskyy 0:58b20b438383 20
vshymanskyy 0:58b20b438383 21 template <class Transp>
vshymanskyy 0:58b20b438383 22 class BlynkProtocol
vshymanskyy 0:58b20b438383 23 : public BlynkApi< BlynkProtocol<Transp> >
vshymanskyy 0:58b20b438383 24 {
vshymanskyy 0:58b20b438383 25 friend class BlynkApi< BlynkProtocol<Transp> >;
vshymanskyy 0:58b20b438383 26 public:
vshymanskyy 0:58b20b438383 27 enum BlynkState {
vshymanskyy 0:58b20b438383 28 CONNECTING,
vshymanskyy 0:58b20b438383 29 CONNECTED,
vshymanskyy 0:58b20b438383 30 DISCONNECTED,
vshymanskyy 0:58b20b438383 31 };
vshymanskyy 0:58b20b438383 32
vshymanskyy 0:58b20b438383 33 BlynkProtocol(Transp& transp)
vshymanskyy 0:58b20b438383 34 : conn(transp)
vshymanskyy 0:58b20b438383 35 , authkey(NULL)
Volodymyr Shymanskyy 9:7369ec77a3ea 36 , redir_serv(NULL)
vshymanskyy 0:58b20b438383 37 , lastActivityIn(0)
vshymanskyy 0:58b20b438383 38 , lastActivityOut(0)
vshymanskyy 0:58b20b438383 39 , lastHeartbeat(0)
vshymanskyy 0:58b20b438383 40 #ifdef BLYNK_MSG_LIMIT
vshymanskyy 0:58b20b438383 41 , deltaCmd(0)
vshymanskyy 0:58b20b438383 42 #endif
Volodymyr Shymanskyy 14:76d8fd871a4d 43 , msgIdOut(0)
Volodymyr Shymanskyy 14:76d8fd871a4d 44 , msgIdOutOverride(0)
Volodymyr Shymanskyy 18:c328c1a97f90 45 , nesting(0)
vshymanskyy 0:58b20b438383 46 , state(CONNECTING)
vshymanskyy 0:58b20b438383 47 {}
vshymanskyy 0:58b20b438383 48
vshymanskyy 0:58b20b438383 49 bool connected() { return state == CONNECTED; }
vshymanskyy 0:58b20b438383 50
vshymanskyy 0:58b20b438383 51 bool connect(uint32_t timeout = BLYNK_TIMEOUT_MS*3) {
Volodymyr Shymanskyy 9:7369ec77a3ea 52 conn.disconnect();
Volodymyr Shymanskyy 9:7369ec77a3ea 53 state = CONNECTING;
Volodymyr Shymanskyy 15:975b60f7a8ff 54 millis_time_t started = BlynkMillis();
Volodymyr Shymanskyy 9:7369ec77a3ea 55 while ((state != CONNECTED) &&
Volodymyr Shymanskyy 15:975b60f7a8ff 56 (BlynkMillis() - started < timeout))
Volodymyr Shymanskyy 9:7369ec77a3ea 57 {
Volodymyr Shymanskyy 9:7369ec77a3ea 58 run();
Volodymyr Shymanskyy 9:7369ec77a3ea 59 }
Volodymyr Shymanskyy 9:7369ec77a3ea 60 return state == CONNECTED;
vshymanskyy 0:58b20b438383 61 }
vshymanskyy 0:58b20b438383 62
vshymanskyy 0:58b20b438383 63 void disconnect() {
vshymanskyy 0:58b20b438383 64 conn.disconnect();
vshymanskyy 0:58b20b438383 65 state = DISCONNECTED;
vshymanskyy 0:58b20b438383 66 BLYNK_LOG1(BLYNK_F("Disconnected"));
vshymanskyy 0:58b20b438383 67 }
vshymanskyy 0:58b20b438383 68
vshymanskyy 0:58b20b438383 69 bool run(bool avail = false);
vshymanskyy 0:58b20b438383 70
Volodymyr Shymanskyy 3:31e4b850b126 71 // TODO: Fixme
vshymanskyy 0:58b20b438383 72 void startSession() {
Volodymyr Shymanskyy 3:31e4b850b126 73 conn.connect();
Volodymyr Shymanskyy 9:7369ec77a3ea 74 state = CONNECTING;
vshymanskyy 0:58b20b438383 75 #ifdef BLYNK_MSG_LIMIT
vshymanskyy 0:58b20b438383 76 deltaCmd = 1000;
vshymanskyy 0:58b20b438383 77 #endif
Volodymyr Shymanskyy 14:76d8fd871a4d 78 msgIdOut = 0;
Volodymyr Shymanskyy 15:975b60f7a8ff 79 lastHeartbeat = lastActivityIn = lastActivityOut = BlynkMillis(); // TODO: - 5005UL
vshymanskyy 0:58b20b438383 80 }
vshymanskyy 0:58b20b438383 81
vshymanskyy 0:58b20b438383 82 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);
vshymanskyy 0:58b20b438383 83
vshymanskyy 0:58b20b438383 84 private:
Volodymyr Shymanskyy 14:76d8fd871a4d 85
Volodymyr Shymanskyy 14:76d8fd871a4d 86 void internalReconnect() {
Volodymyr Shymanskyy 14:76d8fd871a4d 87 state = CONNECTING;
Volodymyr Shymanskyy 14:76d8fd871a4d 88 conn.disconnect();
Volodymyr Shymanskyy 14:76d8fd871a4d 89 BlynkOnDisconnected();
Volodymyr Shymanskyy 14:76d8fd871a4d 90 }
Volodymyr Shymanskyy 14:76d8fd871a4d 91
vshymanskyy 0:58b20b438383 92 int readHeader(BlynkHeader& hdr);
vshymanskyy 0:58b20b438383 93 uint16_t getNextMsgId();
vshymanskyy 0:58b20b438383 94
vshymanskyy 0:58b20b438383 95 protected:
vshymanskyy 0:58b20b438383 96 void begin(const char* auth) {
Volodymyr Shymanskyy 9:7369ec77a3ea 97 this->authkey = auth;
Volodymyr Shymanskyy 9:7369ec77a3ea 98
Volodymyr Shymanskyy 9:7369ec77a3ea 99 #if defined(BLYNK_NO_FANCY_LOGO)
vshymanskyy 0:58b20b438383 100 BLYNK_LOG1(BLYNK_F("Blynk v" BLYNK_VERSION " on " BLYNK_INFO_DEVICE));
Volodymyr Shymanskyy 9:7369ec77a3ea 101 #elif defined(BLYNK_FANCY_LOGO_3D)
Volodymyr Shymanskyy 9:7369ec77a3ea 102 BLYNK_LOG1(BLYNK_F("\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 103 " ____ ___ __\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 104 " /\\ _`\\ /\\_ \\ /\\ \\ _\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 105 " \\ \\ \\_\\ \\\\//\\ \\ __ __ ___ \\ \\ \\/ \\\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 106 " \\ \\ _ < \\ \\ \\ /\\ \\/\\ \\ /' _ `\\\\ \\ , <\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 107 " \\ \\ \\_\\ \\ \\_\\ \\_\\ \\ \\_\\ \\ /\\ \\/\\ \\\\ \\ \\\\`\\\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 108 " \\ \\____/ /\\____\\\\/`____ \\\\ \\_\\ \\_\\\\ \\_\\\\_\\\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 109 " \\/___/ \\/____/ `/___/\\ \\\\/_/\\/_/ \\/_//_/\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 110 " /\\___/\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 111 " \\/__/ " BLYNK_VERSION " on " BLYNK_INFO_DEVICE "\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 112 ));
Volodymyr Shymanskyy 9:7369ec77a3ea 113 #else
Volodymyr Shymanskyy 9:7369ec77a3ea 114 BLYNK_LOG1(BLYNK_F("\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 115 " ___ __ __\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 116 " / _ )/ /_ _____ / /__\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 117 " / _ / / // / _ \\/ '_/\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 118 " /____/_/\\_, /_//_/_/\\_\\\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 119 " /___/ v" BLYNK_VERSION " on " BLYNK_INFO_DEVICE "\n"
Volodymyr Shymanskyy 9:7369ec77a3ea 120 ));
Volodymyr Shymanskyy 9:7369ec77a3ea 121 #endif
vshymanskyy 0:58b20b438383 122 }
vshymanskyy 0:58b20b438383 123 bool processInput(void);
vshymanskyy 0:58b20b438383 124
vshymanskyy 0:58b20b438383 125 Transp& conn;
vshymanskyy 0:58b20b438383 126
vshymanskyy 0:58b20b438383 127 private:
vshymanskyy 0:58b20b438383 128 const char* authkey;
Volodymyr Shymanskyy 9:7369ec77a3ea 129 char* redir_serv;
vshymanskyy 0:58b20b438383 130 millis_time_t lastActivityIn;
vshymanskyy 0:58b20b438383 131 millis_time_t lastActivityOut;
vshymanskyy 0:58b20b438383 132 union {
Volodymyr Shymanskyy 9:7369ec77a3ea 133 millis_time_t lastHeartbeat;
Volodymyr Shymanskyy 9:7369ec77a3ea 134 millis_time_t lastLogin;
vshymanskyy 0:58b20b438383 135 };
vshymanskyy 0:58b20b438383 136 #ifdef BLYNK_MSG_LIMIT
vshymanskyy 0:58b20b438383 137 millis_time_t deltaCmd;
vshymanskyy 0:58b20b438383 138 #endif
Volodymyr Shymanskyy 14:76d8fd871a4d 139 uint16_t msgIdOut;
Volodymyr Shymanskyy 14:76d8fd871a4d 140 uint16_t msgIdOutOverride;
Volodymyr Shymanskyy 18:c328c1a97f90 141 uint8_t nesting;
Volodymyr Shymanskyy 3:31e4b850b126 142 protected:
vshymanskyy 0:58b20b438383 143 BlynkState state;
vshymanskyy 0:58b20b438383 144 };
vshymanskyy 0:58b20b438383 145
vshymanskyy 0:58b20b438383 146 template <class Transp>
vshymanskyy 0:58b20b438383 147 bool BlynkProtocol<Transp>::run(bool avail)
vshymanskyy 0:58b20b438383 148 {
Volodymyr Shymanskyy 9:7369ec77a3ea 149 BLYNK_RUN_YIELD();
vshymanskyy 0:58b20b438383 150
vshymanskyy 0:58b20b438383 151 if (state == DISCONNECTED) {
vshymanskyy 0:58b20b438383 152 return false;
vshymanskyy 0:58b20b438383 153 }
vshymanskyy 0:58b20b438383 154
Volodymyr Shymanskyy 18:c328c1a97f90 155 // Detect nesting
Volodymyr Shymanskyy 18:c328c1a97f90 156 BlynkHelperAutoInc guard(nesting);
Volodymyr Shymanskyy 18:c328c1a97f90 157 if (msgIdOutOverride || nesting > 2) {
Volodymyr Shymanskyy 18:c328c1a97f90 158 #ifdef BLYNK_DEBUG
Volodymyr Shymanskyy 18:c328c1a97f90 159 BLYNK_LOG1(BLYNK_F("Nested run() skipped"));
Volodymyr Shymanskyy 18:c328c1a97f90 160 #endif
Volodymyr Shymanskyy 18:c328c1a97f90 161 return true;
Volodymyr Shymanskyy 18:c328c1a97f90 162 }
Volodymyr Shymanskyy 18:c328c1a97f90 163
vshymanskyy 0:58b20b438383 164 const bool tconn = conn.connected();
vshymanskyy 0:58b20b438383 165
vshymanskyy 0:58b20b438383 166 if (tconn) {
Volodymyr Shymanskyy 18:c328c1a97f90 167 while (avail || conn.available() > 0) {
vshymanskyy 0:58b20b438383 168 //BLYNK_LOG2(BLYNK_F("Available: "), conn.available());
vshymanskyy 0:58b20b438383 169 //const unsigned long t = micros();
vshymanskyy 0:58b20b438383 170 if (!processInput()) {
vshymanskyy 0:58b20b438383 171 conn.disconnect();
vshymanskyy 0:58b20b438383 172 // TODO: Only when in direct mode?
vshymanskyy 0:58b20b438383 173 #ifdef BLYNK_USE_DIRECT_CONNECT
vshymanskyy 0:58b20b438383 174 state = CONNECTING;
vshymanskyy 0:58b20b438383 175 #endif
Volodymyr Shymanskyy 14:76d8fd871a4d 176 BlynkOnDisconnected();
vshymanskyy 0:58b20b438383 177 return false;
vshymanskyy 0:58b20b438383 178 }
Volodymyr Shymanskyy 18:c328c1a97f90 179 avail = false;
vshymanskyy 0:58b20b438383 180 //BLYNK_LOG2(BLYNK_F("Proc time: "), micros() - t);
vshymanskyy 0:58b20b438383 181 }
vshymanskyy 0:58b20b438383 182 }
vshymanskyy 0:58b20b438383 183
Volodymyr Shymanskyy 15:975b60f7a8ff 184 const millis_time_t t = BlynkMillis();
vshymanskyy 0:58b20b438383 185
vshymanskyy 0:58b20b438383 186 if (state == CONNECTED) {
vshymanskyy 0:58b20b438383 187 if (!tconn) {
vshymanskyy 0:58b20b438383 188 lastHeartbeat = t;
Volodymyr Shymanskyy 14:76d8fd871a4d 189 internalReconnect();
vshymanskyy 0:58b20b438383 190 return false;
vshymanskyy 0:58b20b438383 191 }
vshymanskyy 0:58b20b438383 192
vshymanskyy 0:58b20b438383 193 if (t - lastActivityIn > (1000UL * BLYNK_HEARTBEAT + BLYNK_TIMEOUT_MS*3)) {
vshymanskyy 0:58b20b438383 194 #ifdef BLYNK_DEBUG
vshymanskyy 0:58b20b438383 195 BLYNK_LOG6(BLYNK_F("Heartbeat timeout: "), t, BLYNK_F(", "), lastActivityIn, BLYNK_F(", "), lastHeartbeat);
vshymanskyy 0:58b20b438383 196 #else
vshymanskyy 0:58b20b438383 197 BLYNK_LOG1(BLYNK_F("Heartbeat timeout"));
vshymanskyy 0:58b20b438383 198 #endif
Volodymyr Shymanskyy 14:76d8fd871a4d 199 internalReconnect();
vshymanskyy 0:58b20b438383 200 return false;
vshymanskyy 0:58b20b438383 201 } else if ((t - lastActivityIn > 1000UL * BLYNK_HEARTBEAT ||
vshymanskyy 0:58b20b438383 202 t - lastActivityOut > 1000UL * BLYNK_HEARTBEAT) &&
vshymanskyy 0:58b20b438383 203 t - lastHeartbeat > BLYNK_TIMEOUT_MS)
vshymanskyy 0:58b20b438383 204 {
vshymanskyy 0:58b20b438383 205 // Send ping if we didn't either send or receive something
vshymanskyy 0:58b20b438383 206 // for BLYNK_HEARTBEAT seconds
vshymanskyy 0:58b20b438383 207 sendCmd(BLYNK_CMD_PING);
vshymanskyy 0:58b20b438383 208 lastHeartbeat = t;
vshymanskyy 0:58b20b438383 209 }
vshymanskyy 0:58b20b438383 210 } else if (state == CONNECTING) {
Volodymyr Shymanskyy 9:7369ec77a3ea 211 #ifdef BLYNK_USE_DIRECT_CONNECT
Volodymyr Shymanskyy 9:7369ec77a3ea 212 if (!tconn)
Volodymyr Shymanskyy 9:7369ec77a3ea 213 conn.connect();
Volodymyr Shymanskyy 9:7369ec77a3ea 214 #else
vshymanskyy 0:58b20b438383 215 if (tconn && (t - lastLogin > BLYNK_TIMEOUT_MS)) {
vshymanskyy 0:58b20b438383 216 BLYNK_LOG1(BLYNK_F("Login timeout"));
vshymanskyy 0:58b20b438383 217 conn.disconnect();
vshymanskyy 0:58b20b438383 218 state = CONNECTING;
vshymanskyy 0:58b20b438383 219 return false;
vshymanskyy 0:58b20b438383 220 } else if (!tconn && (t - lastLogin > 5000UL)) {
vshymanskyy 0:58b20b438383 221 conn.disconnect();
vshymanskyy 0:58b20b438383 222 if (!conn.connect()) {
vshymanskyy 0:58b20b438383 223 lastLogin = t;
vshymanskyy 0:58b20b438383 224 return false;
vshymanskyy 0:58b20b438383 225 }
vshymanskyy 0:58b20b438383 226
vshymanskyy 0:58b20b438383 227 #ifdef BLYNK_MSG_LIMIT
vshymanskyy 0:58b20b438383 228 deltaCmd = 1000;
vshymanskyy 0:58b20b438383 229 #endif
Volodymyr Shymanskyy 14:76d8fd871a4d 230 msgIdOut = 1;
vshymanskyy 0:58b20b438383 231 sendCmd(BLYNK_CMD_LOGIN, 1, authkey, strlen(authkey));
vshymanskyy 0:58b20b438383 232 lastLogin = lastActivityOut;
vshymanskyy 0:58b20b438383 233 return true;
vshymanskyy 0:58b20b438383 234 }
vshymanskyy 0:58b20b438383 235 #endif
vshymanskyy 0:58b20b438383 236 }
vshymanskyy 0:58b20b438383 237 return true;
vshymanskyy 0:58b20b438383 238 }
vshymanskyy 0:58b20b438383 239
vshymanskyy 0:58b20b438383 240 template <class Transp>
vshymanskyy 0:58b20b438383 241 BLYNK_FORCE_INLINE
vshymanskyy 0:58b20b438383 242 bool BlynkProtocol<Transp>::processInput(void)
vshymanskyy 0:58b20b438383 243 {
vshymanskyy 0:58b20b438383 244 BlynkHeader hdr;
vshymanskyy 0:58b20b438383 245 const int ret = readHeader(hdr);
vshymanskyy 0:58b20b438383 246
vshymanskyy 0:58b20b438383 247 if (ret == 0) {
vshymanskyy 0:58b20b438383 248 return true; // Considered OK (no data on input)
vshymanskyy 0:58b20b438383 249 }
vshymanskyy 0:58b20b438383 250
vshymanskyy 0:58b20b438383 251 if (ret < 0 || hdr.msg_id == 0) {
vshymanskyy 0:58b20b438383 252 #ifdef BLYNK_DEBUG
Volodymyr Shymanskyy 3:31e4b850b126 253 BLYNK_LOG2(BLYNK_F("Bad hdr len: "), ret);
vshymanskyy 0:58b20b438383 254 #endif
vshymanskyy 0:58b20b438383 255 return false;
vshymanskyy 0:58b20b438383 256 }
vshymanskyy 0:58b20b438383 257
vshymanskyy 0:58b20b438383 258 if (hdr.type == BLYNK_CMD_RESPONSE) {
Volodymyr Shymanskyy 15:975b60f7a8ff 259 lastActivityIn = BlynkMillis();
vshymanskyy 0:58b20b438383 260
vshymanskyy 0:58b20b438383 261 #ifndef BLYNK_USE_DIRECT_CONNECT
vshymanskyy 0:58b20b438383 262 if (state == CONNECTING && (1 == hdr.msg_id)) {
vshymanskyy 0:58b20b438383 263 switch (hdr.length) {
vshymanskyy 0:58b20b438383 264 case BLYNK_SUCCESS:
Volodymyr Shymanskyy 9:7369ec77a3ea 265 case BLYNK_ALREADY_REGISTERED:
vshymanskyy 0:58b20b438383 266 BLYNK_LOG3(BLYNK_F("Ready (ping: "), lastActivityIn-lastHeartbeat, BLYNK_F("ms)."));
vshymanskyy 0:58b20b438383 267 lastHeartbeat = lastActivityIn;
vshymanskyy 0:58b20b438383 268 state = CONNECTED;
Volodymyr Shymanskyy 18:c328c1a97f90 269 #ifdef BLYNK_DEBUG
Volodymyr Shymanskyy 18:c328c1a97f90 270 if (size_t ram = BlynkFreeRam()) {
Volodymyr Shymanskyy 18:c328c1a97f90 271 BLYNK_LOG2(BLYNK_F("Free RAM: "), ram);
Volodymyr Shymanskyy 18:c328c1a97f90 272 }
Volodymyr Shymanskyy 18:c328c1a97f90 273 #endif
vshymanskyy 0:58b20b438383 274 this->sendInfo();
Volodymyr Shymanskyy 9:7369ec77a3ea 275 BLYNK_RUN_YIELD();
vshymanskyy 0:58b20b438383 276 BlynkOnConnected();
vshymanskyy 0:58b20b438383 277 return true;
vshymanskyy 0:58b20b438383 278 case BLYNK_INVALID_TOKEN:
vshymanskyy 0:58b20b438383 279 BLYNK_LOG1(BLYNK_F("Invalid auth token"));
vshymanskyy 0:58b20b438383 280 break;
vshymanskyy 0:58b20b438383 281 default:
vshymanskyy 0:58b20b438383 282 BLYNK_LOG2(BLYNK_F("Connect failed. code: "), hdr.length);
vshymanskyy 0:58b20b438383 283 }
vshymanskyy 0:58b20b438383 284 return false;
vshymanskyy 0:58b20b438383 285 }
vshymanskyy 0:58b20b438383 286 if (BLYNK_NOT_AUTHENTICATED == hdr.length) {
vshymanskyy 0:58b20b438383 287 return false;
vshymanskyy 0:58b20b438383 288 }
vshymanskyy 0:58b20b438383 289 #endif
vshymanskyy 0:58b20b438383 290 // TODO: return code may indicate App presence
vshymanskyy 0:58b20b438383 291 return true;
vshymanskyy 0:58b20b438383 292 }
vshymanskyy 0:58b20b438383 293
vshymanskyy 0:58b20b438383 294 if (hdr.length > BLYNK_MAX_READBYTES) {
vshymanskyy 0:58b20b438383 295 BLYNK_LOG2(BLYNK_F("Packet too big: "), hdr.length);
Volodymyr Shymanskyy 3:31e4b850b126 296 // TODO: Flush
Volodymyr Shymanskyy 15:975b60f7a8ff 297 internalReconnect();
Volodymyr Shymanskyy 3:31e4b850b126 298 return true;
vshymanskyy 0:58b20b438383 299 }
vshymanskyy 0:58b20b438383 300
vshymanskyy 0:58b20b438383 301 uint8_t inputBuffer[hdr.length+1]; // Add 1 to zero-terminate
vshymanskyy 0:58b20b438383 302 if (hdr.length != conn.read(inputBuffer, hdr.length)) {
vshymanskyy 0:58b20b438383 303 #ifdef DEBUG
vshymanskyy 0:58b20b438383 304 BLYNK_LOG1(BLYNK_F("Can't read body"));
vshymanskyy 0:58b20b438383 305 #endif
vshymanskyy 0:58b20b438383 306 return false;
vshymanskyy 0:58b20b438383 307 }
vshymanskyy 0:58b20b438383 308 inputBuffer[hdr.length] = '\0';
vshymanskyy 0:58b20b438383 309
vshymanskyy 0:58b20b438383 310 BLYNK_DBG_DUMP(">", inputBuffer, hdr.length);
vshymanskyy 0:58b20b438383 311
Volodymyr Shymanskyy 15:975b60f7a8ff 312 lastActivityIn = BlynkMillis();
vshymanskyy 0:58b20b438383 313
vshymanskyy 0:58b20b438383 314 switch (hdr.type)
vshymanskyy 0:58b20b438383 315 {
Volodymyr Shymanskyy 3:31e4b850b126 316 case BLYNK_CMD_LOGIN: {
vshymanskyy 0:58b20b438383 317 #ifdef BLYNK_USE_DIRECT_CONNECT
Volodymyr Shymanskyy 13:ed6276c0afb7 318 if (strncmp(authkey, (char*)inputBuffer, 32)) {
Volodymyr Shymanskyy 13:ed6276c0afb7 319 BLYNK_LOG1(BLYNK_F("Invalid token"));
Volodymyr Shymanskyy 13:ed6276c0afb7 320 sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_INVALID_TOKEN);
Volodymyr Shymanskyy 13:ed6276c0afb7 321 break;
Volodymyr Shymanskyy 13:ed6276c0afb7 322 }
Volodymyr Shymanskyy 13:ed6276c0afb7 323 #endif
Volodymyr Shymanskyy 13:ed6276c0afb7 324 if (state == CONNECTING) {
Volodymyr Shymanskyy 3:31e4b850b126 325 BLYNK_LOG1(BLYNK_F("Ready"));
vshymanskyy 0:58b20b438383 326 state = CONNECTED;
Volodymyr Shymanskyy 18:c328c1a97f90 327 #ifdef BLYNK_DEBUG
Volodymyr Shymanskyy 18:c328c1a97f90 328 if (size_t ram = BlynkFreeRam()) {
Volodymyr Shymanskyy 18:c328c1a97f90 329 BLYNK_LOG2(BLYNK_F("Free RAM: "), ram);
Volodymyr Shymanskyy 18:c328c1a97f90 330 }
Volodymyr Shymanskyy 18:c328c1a97f90 331 #endif
vshymanskyy 0:58b20b438383 332 this->sendInfo();
Volodymyr Shymanskyy 18:c328c1a97f90 333 BLYNK_RUN_YIELD();
Volodymyr Shymanskyy 3:31e4b850b126 334 BlynkOnConnected();
vshymanskyy 0:58b20b438383 335 }
Volodymyr Shymanskyy 9:7369ec77a3ea 336 sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_SUCCESS);
vshymanskyy 0:58b20b438383 337 } break;
vshymanskyy 0:58b20b438383 338 case BLYNK_CMD_PING: {
vshymanskyy 0:58b20b438383 339 sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_SUCCESS);
vshymanskyy 0:58b20b438383 340 } break;
Volodymyr Shymanskyy 9:7369ec77a3ea 341 case BLYNK_CMD_REDIRECT: {
Volodymyr Shymanskyy 9:7369ec77a3ea 342 if (!redir_serv) {
Volodymyr Shymanskyy 9:7369ec77a3ea 343 redir_serv = (char*)malloc(32);
Volodymyr Shymanskyy 9:7369ec77a3ea 344 }
Volodymyr Shymanskyy 9:7369ec77a3ea 345 BlynkParam param(inputBuffer, hdr.length);
Volodymyr Shymanskyy 9:7369ec77a3ea 346 uint16_t redir_port = BLYNK_DEFAULT_PORT; // TODO: Fixit
Volodymyr Shymanskyy 9:7369ec77a3ea 347
Volodymyr Shymanskyy 9:7369ec77a3ea 348 BlynkParam::iterator it = param.begin();
Volodymyr Shymanskyy 9:7369ec77a3ea 349 if (it >= param.end())
Volodymyr Shymanskyy 9:7369ec77a3ea 350 return false;
Volodymyr Shymanskyy 9:7369ec77a3ea 351 strncpy(redir_serv, it.asStr(), 32);
Volodymyr Shymanskyy 9:7369ec77a3ea 352 if (++it < param.end())
Volodymyr Shymanskyy 9:7369ec77a3ea 353 redir_port = it.asLong();
Volodymyr Shymanskyy 9:7369ec77a3ea 354 BLYNK_LOG4(BLYNK_F("Redirecting to "), redir_serv, ':', redir_port);
Volodymyr Shymanskyy 9:7369ec77a3ea 355 conn.disconnect();
Volodymyr Shymanskyy 9:7369ec77a3ea 356 conn.begin(redir_serv, redir_port);
Volodymyr Shymanskyy 9:7369ec77a3ea 357 lastLogin = lastActivityIn - 5000L; // Reconnect immediately
Volodymyr Shymanskyy 9:7369ec77a3ea 358 state = CONNECTING;
Volodymyr Shymanskyy 9:7369ec77a3ea 359 } break;
vshymanskyy 0:58b20b438383 360 case BLYNK_CMD_HARDWARE:
vshymanskyy 0:58b20b438383 361 case BLYNK_CMD_BRIDGE: {
Volodymyr Shymanskyy 14:76d8fd871a4d 362 msgIdOutOverride = hdr.msg_id;
vshymanskyy 0:58b20b438383 363 this->processCmd(inputBuffer, hdr.length);
Volodymyr Shymanskyy 14:76d8fd871a4d 364 msgIdOutOverride = 0;
vshymanskyy 0:58b20b438383 365 } break;
Volodymyr Shymanskyy 10:c241e4227173 366 case BLYNK_CMD_INTERNAL: {
Volodymyr Shymanskyy 10:c241e4227173 367 BlynkReq req = { 0 };
Volodymyr Shymanskyy 10:c241e4227173 368 BlynkParam param(inputBuffer, hdr.length);
Volodymyr Shymanskyy 10:c241e4227173 369 BlynkParam::iterator it = param.begin();
Volodymyr Shymanskyy 10:c241e4227173 370 if (it >= param.end())
Volodymyr Shymanskyy 10:c241e4227173 371 return true;
Volodymyr Shymanskyy 10:c241e4227173 372
Volodymyr Shymanskyy 10:c241e4227173 373 uint32_t cmd32;
Volodymyr Shymanskyy 10:c241e4227173 374 memcpy(&cmd32, it.asStr(), sizeof(cmd32));
Volodymyr Shymanskyy 10:c241e4227173 375
Volodymyr Shymanskyy 14:76d8fd871a4d 376 ++it;
Volodymyr Shymanskyy 14:76d8fd871a4d 377 char* start = (char*)(it).asStr();
Volodymyr Shymanskyy 14:76d8fd871a4d 378 unsigned length = hdr.length - (start - (char*)inputBuffer);
Volodymyr Shymanskyy 14:76d8fd871a4d 379 BlynkParam param2(start, length);
Volodymyr Shymanskyy 10:c241e4227173 380
Volodymyr Shymanskyy 10:c241e4227173 381 switch (cmd32) {
Volodymyr Shymanskyy 10:c241e4227173 382 case BLYNK_INT_RTC: BlynkWidgetWriteInternalPinRTC(req, param2); break;
Volodymyr Shymanskyy 10:c241e4227173 383 case BLYNK_INT_OTA: BlynkWidgetWriteInternalPinOTA(req, param2); break;
Volodymyr Shymanskyy 10:c241e4227173 384 case BLYNK_INT_ACON: BlynkWidgetWriteInternalPinACON(req, param2); break;
Volodymyr Shymanskyy 10:c241e4227173 385 case BLYNK_INT_ADIS: BlynkWidgetWriteInternalPinADIS(req, param2); break;
Volodymyr Shymanskyy 14:76d8fd871a4d 386 #ifdef DEBUG
Volodymyr Shymanskyy 14:76d8fd871a4d 387 default: BLYNK_LOG2(BLYNK_F("Invalid internal cmd:"), param.asStr());
Volodymyr Shymanskyy 14:76d8fd871a4d 388 #endif
Volodymyr Shymanskyy 10:c241e4227173 389 }
Volodymyr Shymanskyy 9:7369ec77a3ea 390 } break;
Volodymyr Shymanskyy 9:7369ec77a3ea 391 case BLYNK_CMD_DEBUG_PRINT: {
Volodymyr Shymanskyy 9:7369ec77a3ea 392 if (hdr.length) {
Volodymyr Shymanskyy 9:7369ec77a3ea 393 BLYNK_LOG2(BLYNK_F("Server: "), (char*)inputBuffer);
Volodymyr Shymanskyy 9:7369ec77a3ea 394 }
Volodymyr Shymanskyy 9:7369ec77a3ea 395 } break;
vshymanskyy 0:58b20b438383 396 default: {
vshymanskyy 0:58b20b438383 397 #ifdef BLYNK_DEBUG
vshymanskyy 0:58b20b438383 398 BLYNK_LOG2(BLYNK_F("Invalid header type: "), hdr.type);
vshymanskyy 0:58b20b438383 399 #endif
Volodymyr Shymanskyy 3:31e4b850b126 400 // TODO: Flush
Volodymyr Shymanskyy 15:975b60f7a8ff 401 internalReconnect();
vshymanskyy 0:58b20b438383 402 } break;
vshymanskyy 0:58b20b438383 403 }
vshymanskyy 0:58b20b438383 404
vshymanskyy 0:58b20b438383 405 return true;
vshymanskyy 0:58b20b438383 406 }
vshymanskyy 0:58b20b438383 407
vshymanskyy 0:58b20b438383 408 template <class Transp>
vshymanskyy 0:58b20b438383 409 int BlynkProtocol<Transp>::readHeader(BlynkHeader& hdr)
vshymanskyy 0:58b20b438383 410 {
vshymanskyy 0:58b20b438383 411 size_t rlen = conn.read(&hdr, sizeof(hdr));
vshymanskyy 0:58b20b438383 412 if (rlen == 0) {
vshymanskyy 0:58b20b438383 413 return 0;
vshymanskyy 0:58b20b438383 414 }
vshymanskyy 0:58b20b438383 415
vshymanskyy 0:58b20b438383 416 if (sizeof(hdr) != rlen) {
vshymanskyy 0:58b20b438383 417 return -1;
vshymanskyy 0:58b20b438383 418 }
Volodymyr Shymanskyy 3:31e4b850b126 419
Volodymyr Shymanskyy 3:31e4b850b126 420 BLYNK_DBG_DUMP(">", &hdr, sizeof(BlynkHeader));
Volodymyr Shymanskyy 3:31e4b850b126 421
vshymanskyy 0:58b20b438383 422 hdr.msg_id = ntohs(hdr.msg_id);
vshymanskyy 0:58b20b438383 423 hdr.length = ntohs(hdr.length);
vshymanskyy 0:58b20b438383 424
vshymanskyy 0:58b20b438383 425 return rlen;
vshymanskyy 0:58b20b438383 426 }
vshymanskyy 0:58b20b438383 427
vshymanskyy 0:58b20b438383 428 #ifndef BLYNK_SEND_THROTTLE
vshymanskyy 0:58b20b438383 429 #define BLYNK_SEND_THROTTLE 0
vshymanskyy 0:58b20b438383 430 #endif
vshymanskyy 0:58b20b438383 431
vshymanskyy 0:58b20b438383 432 #ifndef BLYNK_SEND_CHUNK
vshymanskyy 0:58b20b438383 433 #define BLYNK_SEND_CHUNK 1024 // Just a big number
vshymanskyy 0:58b20b438383 434 #endif
vshymanskyy 0:58b20b438383 435
vshymanskyy 0:58b20b438383 436 template <class Transp>
vshymanskyy 0:58b20b438383 437 void BlynkProtocol<Transp>::sendCmd(uint8_t cmd, uint16_t id, const void* data, size_t length, const void* data2, size_t length2)
vshymanskyy 0:58b20b438383 438 {
vshymanskyy 0:58b20b438383 439 if (!conn.connected() || (cmd != BLYNK_CMD_RESPONSE && cmd != BLYNK_CMD_PING && cmd != BLYNK_CMD_LOGIN && state != CONNECTED) ) {
vshymanskyy 0:58b20b438383 440 #ifdef BLYNK_DEBUG
vshymanskyy 0:58b20b438383 441 BLYNK_LOG2(BLYNK_F("Cmd skipped:"), cmd);
vshymanskyy 0:58b20b438383 442 #endif
vshymanskyy 0:58b20b438383 443 return;
vshymanskyy 0:58b20b438383 444 }
vshymanskyy 0:58b20b438383 445
Volodymyr Shymanskyy 18:c328c1a97f90 446 if (0 == id) {
Volodymyr Shymanskyy 18:c328c1a97f90 447 id = getNextMsgId();
Volodymyr Shymanskyy 18:c328c1a97f90 448 }
Volodymyr Shymanskyy 18:c328c1a97f90 449
Volodymyr Shymanskyy 18:c328c1a97f90 450 #if defined(BLYNK_MSG_LIMIT) && BLYNK_MSG_LIMIT > 0
Volodymyr Shymanskyy 18:c328c1a97f90 451 if (cmd >= BLYNK_CMD_TWEET && cmd <= BLYNK_CMD_HARDWARE) {
Volodymyr Shymanskyy 18:c328c1a97f90 452 const millis_time_t allowed_time = BlynkMax(lastActivityOut, lastActivityIn) + 1000/BLYNK_MSG_LIMIT;
Volodymyr Shymanskyy 18:c328c1a97f90 453 long wait_time = allowed_time - BlynkMillis();
Volodymyr Shymanskyy 18:c328c1a97f90 454 if (wait_time >= 0) {
Volodymyr Shymanskyy 18:c328c1a97f90 455 #ifdef BLYNK_DEBUG
Volodymyr Shymanskyy 18:c328c1a97f90 456 BLYNK_LOG2(BLYNK_F("Waiting:"), wait_time);
Volodymyr Shymanskyy 18:c328c1a97f90 457 #endif
Volodymyr Shymanskyy 18:c328c1a97f90 458 while (wait_time >= 0) {
Volodymyr Shymanskyy 18:c328c1a97f90 459 run();
Volodymyr Shymanskyy 18:c328c1a97f90 460 wait_time = allowed_time - BlynkMillis();
Volodymyr Shymanskyy 18:c328c1a97f90 461 }
Volodymyr Shymanskyy 18:c328c1a97f90 462 }
Volodymyr Shymanskyy 18:c328c1a97f90 463 }
Volodymyr Shymanskyy 18:c328c1a97f90 464 #endif
Volodymyr Shymanskyy 18:c328c1a97f90 465
Volodymyr Shymanskyy 7:8879692d4e6c 466 const size_t full_length = (sizeof(BlynkHeader)) +
Volodymyr Shymanskyy 7:8879692d4e6c 467 (data ? length : 0) +
Volodymyr Shymanskyy 7:8879692d4e6c 468 (data2 ? length2 : 0);
vshymanskyy 0:58b20b438383 469
vshymanskyy 0:58b20b438383 470 #if defined(BLYNK_SEND_ATOMIC) || defined(ESP8266) || defined(SPARK) || defined(PARTICLE) || defined(ENERGIA)
vshymanskyy 0:58b20b438383 471 // Those have more RAM and like single write at a time...
vshymanskyy 0:58b20b438383 472
vshymanskyy 0:58b20b438383 473 uint8_t buff[full_length];
vshymanskyy 0:58b20b438383 474
vshymanskyy 0:58b20b438383 475 BlynkHeader* hdr = (BlynkHeader*)buff;
vshymanskyy 0:58b20b438383 476 hdr->type = cmd;
vshymanskyy 0:58b20b438383 477 hdr->msg_id = htons(id);
vshymanskyy 0:58b20b438383 478 hdr->length = htons(length+length2);
vshymanskyy 0:58b20b438383 479
vshymanskyy 0:58b20b438383 480 size_t pos = sizeof(BlynkHeader);
vshymanskyy 0:58b20b438383 481 if (data && length) {
vshymanskyy 0:58b20b438383 482 memcpy(buff + pos, data, length);
vshymanskyy 0:58b20b438383 483 pos += length;
vshymanskyy 0:58b20b438383 484 }
vshymanskyy 0:58b20b438383 485 if (data2 && length2) {
vshymanskyy 0:58b20b438383 486 memcpy(buff + pos, data2, length2);
vshymanskyy 0:58b20b438383 487 }
vshymanskyy 0:58b20b438383 488
vshymanskyy 0:58b20b438383 489 size_t wlen = 0;
vshymanskyy 0:58b20b438383 490 while (wlen < full_length) {
vshymanskyy 0:58b20b438383 491 const size_t chunk = BlynkMin(size_t(BLYNK_SEND_CHUNK), full_length - wlen);
Volodymyr Shymanskyy 9:7369ec77a3ea 492 BLYNK_DBG_DUMP("<", buff + wlen, chunk);
vshymanskyy 0:58b20b438383 493 const size_t w = conn.write(buff + wlen, chunk);
Volodymyr Shymanskyy 15:975b60f7a8ff 494 BlynkDelay(BLYNK_SEND_THROTTLE);
Volodymyr Shymanskyy 9:7369ec77a3ea 495 if (w == 0) {
vshymanskyy 0:58b20b438383 496 #ifdef BLYNK_DEBUG
vshymanskyy 0:58b20b438383 497 BLYNK_LOG1(BLYNK_F("Cmd error"));
vshymanskyy 0:58b20b438383 498 #endif
vshymanskyy 0:58b20b438383 499 conn.disconnect();
vshymanskyy 0:58b20b438383 500 state = CONNECTING;
Volodymyr Shymanskyy 15:975b60f7a8ff 501 BlynkOnDisconnected();
vshymanskyy 0:58b20b438383 502 return;
Volodymyr Shymanskyy 9:7369ec77a3ea 503 }
vshymanskyy 0:58b20b438383 504 wlen += w;
vshymanskyy 0:58b20b438383 505 }
vshymanskyy 0:58b20b438383 506
vshymanskyy 0:58b20b438383 507 #else
vshymanskyy 0:58b20b438383 508
vshymanskyy 0:58b20b438383 509 BlynkHeader hdr;
vshymanskyy 0:58b20b438383 510 hdr.type = cmd;
vshymanskyy 0:58b20b438383 511 hdr.msg_id = htons(id);
vshymanskyy 0:58b20b438383 512 hdr.length = htons(length+length2);
vshymanskyy 0:58b20b438383 513
Volodymyr Shymanskyy 9:7369ec77a3ea 514 BLYNK_DBG_DUMP("<", &hdr, sizeof(hdr));
vshymanskyy 0:58b20b438383 515 size_t wlen = conn.write(&hdr, sizeof(hdr));
Volodymyr Shymanskyy 15:975b60f7a8ff 516 BlynkDelay(BLYNK_SEND_THROTTLE);
vshymanskyy 0:58b20b438383 517
vshymanskyy 0:58b20b438383 518 if (cmd != BLYNK_CMD_RESPONSE) {
vshymanskyy 0:58b20b438383 519 if (length) {
vshymanskyy 0:58b20b438383 520 BLYNK_DBG_DUMP("<", data, length);
vshymanskyy 0:58b20b438383 521 wlen += conn.write(data, length);
Volodymyr Shymanskyy 15:975b60f7a8ff 522 BlynkDelay(BLYNK_SEND_THROTTLE);
vshymanskyy 0:58b20b438383 523 }
vshymanskyy 0:58b20b438383 524 if (length2) {
vshymanskyy 0:58b20b438383 525 BLYNK_DBG_DUMP("<", data2, length2);
vshymanskyy 0:58b20b438383 526 wlen += conn.write(data2, length2);
Volodymyr Shymanskyy 15:975b60f7a8ff 527 BlynkDelay(BLYNK_SEND_THROTTLE);
vshymanskyy 0:58b20b438383 528 }
vshymanskyy 0:58b20b438383 529 }
vshymanskyy 0:58b20b438383 530
vshymanskyy 0:58b20b438383 531 #endif
vshymanskyy 0:58b20b438383 532
vshymanskyy 0:58b20b438383 533 if (wlen != full_length) {
vshymanskyy 0:58b20b438383 534 #ifdef BLYNK_DEBUG
vshymanskyy 0:58b20b438383 535 BLYNK_LOG4(BLYNK_F("Sent "), wlen, '/', full_length);
vshymanskyy 0:58b20b438383 536 #endif
Volodymyr Shymanskyy 14:76d8fd871a4d 537 internalReconnect();
vshymanskyy 0:58b20b438383 538 return;
vshymanskyy 0:58b20b438383 539 }
vshymanskyy 0:58b20b438383 540
Volodymyr Shymanskyy 18:c328c1a97f90 541 lastActivityOut = BlynkMillis();
vshymanskyy 0:58b20b438383 542
vshymanskyy 0:58b20b438383 543 }
vshymanskyy 0:58b20b438383 544
vshymanskyy 0:58b20b438383 545 template <class Transp>
vshymanskyy 0:58b20b438383 546 uint16_t BlynkProtocol<Transp>::getNextMsgId()
vshymanskyy 0:58b20b438383 547 {
Volodymyr Shymanskyy 14:76d8fd871a4d 548 if (msgIdOutOverride != 0)
Volodymyr Shymanskyy 14:76d8fd871a4d 549 return msgIdOutOverride;
Volodymyr Shymanskyy 14:76d8fd871a4d 550 if (++msgIdOut == 0)
Volodymyr Shymanskyy 14:76d8fd871a4d 551 msgIdOut = 1;
Volodymyr Shymanskyy 14:76d8fd871a4d 552 return msgIdOut;
vshymanskyy 0:58b20b438383 553 }
vshymanskyy 0:58b20b438383 554
vshymanskyy 0:58b20b438383 555 #endif