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