├── .gitignore ├── ELClient ├── ELClient.cpp ├── ELClient.h ├── ELClientCmd.cpp ├── ELClientCmd.h ├── ELClientMqtt.cpp ├── ELClientMqtt.h ├── ELClientResponse.cpp ├── ELClientResponse.h ├── ELClientRest.cpp ├── ELClientRest.h ├── ELClientSocket.cpp ├── ELClientSocket.h ├── ELClientWebServer.cpp ├── ELClientWebServer.h ├── FP.cpp ├── FP.h ├── examples │ ├── arduino.mk │ ├── avrflash │ ├── demo │ │ ├── .dep │ │ │ ├── demo.ino.dep │ │ │ └── temperature.ino.dep │ │ ├── Makefile │ │ ├── README.md │ │ ├── demo.hex │ │ └── demo.ino │ ├── mqtt │ │ ├── Makefile │ │ ├── README.md │ │ ├── mqtt.hex │ │ └── mqtt.ino │ ├── rest │ │ ├── Makefile │ │ ├── README.md │ │ ├── rest.hex │ │ └── rest.ino │ ├── tcp_client │ │ └── tcp_client.ino │ ├── tcp_client_resp │ │ └── tcp_client_resp.ino │ ├── tcp_server │ │ └── tcp_server.ino │ ├── test-reset │ │ ├── Makefile │ │ ├── README.md │ │ ├── test.hex │ │ └── test.ino │ ├── thingspeak │ │ ├── README.md │ │ └── thingspeak.ino │ ├── udp │ │ └── udp.ino │ ├── webserver_controls │ │ ├── LED.html │ │ ├── LedPage.ino │ │ ├── Pages.h │ │ ├── User.html │ │ ├── UserPage.ino │ │ ├── Voltage.html │ │ ├── VoltagePage.ino │ │ └── webserver_controls.ino │ └── webserver_led │ │ ├── Makefile │ │ ├── SimpleLED.html │ │ ├── webserver_led.hex │ │ └── webserver_led.ino └── library.json ├── LICENSE.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | .dep 3 | .lib 4 | docs 5 | -------------------------------------------------------------------------------- /ELClient/ELClient.cpp: -------------------------------------------------------------------------------- 1 | /*! \file ELClient.cpp 2 | \brief Constructor and functions for ELClient 3 | \author B. Runnels 4 | \author T. von Eicken 5 | \date 2016 6 | */ 7 | // Copyright (c) 2016 by B. Runnels and T. von Eicken 8 | 9 | #include "ELClient.h" 10 | 11 | #define SLIP_END 0300 /**< Indicates end of packet */ 12 | #define SLIP_ESC 0333 /**< Indicates byte stuffing */ 13 | #define SLIP_ESC_END 0334 /**< ESC ESC_END means END data byte */ 14 | #define SLIP_ESC_ESC 0335 /**< ESC ESC_ESC means ESC data byte */ 15 | 16 | //===== Input 17 | 18 | /*! protoCompletedCb(void *res) 19 | @brief Process a received SLIP message 20 | @details Callback to process a SLIP message and check CRCs 21 | If a user callback function was defined in the message, ELClientResponse is called to handle the callback. 22 | @note 23 | This function is usually not needed for applications. The communication to the ESP8266 is handled by the cmd, rest, mqtt, tcp and udp library parts. 24 | @return ELClientPacket 25 | Pointer to ELClientPacket structure generated or NULL if it the message is from a callback or if an error occured 26 | @par Example 27 | @code 28 | no example code yet 29 | @endcode 30 | */ 31 | ELClientPacket* ELClient::protoCompletedCb(void) { 32 | // the packet starts with a ELClientPacket 33 | ELClientPacket* packet = (ELClientPacket*)_proto.buf; 34 | if (_debugEn) { 35 | _debug->print("ELC: got "); 36 | _debug->print(_proto.dataLen); 37 | _debug->print(" @"); 38 | _debug->print((uint32_t)_proto.buf, 16); 39 | _debug->print(": "); 40 | _debug->print(packet->cmd, 16); 41 | _debug->print(" "); 42 | _debug->print(packet->value, 16); 43 | _debug->print(" "); 44 | _debug->print(packet->argc, 16); 45 | for (uint16_t i=8; i<_proto.dataLen; i++) { 46 | _debug->print(" "); 47 | _debug->print(*(uint8_t*)(_proto.buf+i), 16); 48 | } 49 | _debug->println(); 50 | } 51 | 52 | // verify CRC 53 | uint16_t crc = crc16Data(_proto.buf, _proto.dataLen-2, 0); 54 | uint16_t resp_crc = *(uint16_t*)(_proto.buf+_proto.dataLen-2); 55 | if (crc != resp_crc) { 56 | DBG("ELC: Invalid CRC"); 57 | return NULL; 58 | } 59 | 60 | // dispatch based on command 61 | switch (packet->cmd) { 62 | case CMD_RESP_V: // response with a value: return the packet 63 | // value response 64 | if (_debugEn) { 65 | _debug->print("RESP_V: "); 66 | _debug->println(packet->value); 67 | } 68 | return packet; 69 | case CMD_RESP_CB: // response callback: perform the callback! 70 | FP *fp; 71 | // callback reponse 72 | if (_debugEn) { 73 | _debug->print("RESP_CB: "); 74 | _debug->print(packet->value); 75 | _debug->print(" "); 76 | _debug->println(packet->argc); 77 | } 78 | fp = (FP*)packet->value; 79 | if (fp->attached()) { 80 | ELClientResponse resp(packet); 81 | (*fp)(&resp); 82 | } 83 | return NULL; 84 | case CMD_SYNC: // esp-link is not in sync, it may have reset, signal up the stack 85 | _debug->println("NEED_SYNC!"); 86 | if (resetCb != NULL) (*resetCb)(); 87 | return NULL; 88 | default: 89 | // command (NOT IMPLEMENTED) 90 | if (_debugEn) _debug->println("CMD??"); 91 | return NULL; 92 | } 93 | } 94 | 95 | /*! Process() 96 | @brief Handle serial input. 97 | @details Read all characters available on the serial input and process any messages that arrive, 98 | but stop if a non-callback response comes in 99 | @return ELClientPacket 100 | Pointer to ELClientResponse structure with the received response 101 | @par Example 102 | @code 103 | void loop() 104 | { 105 | ELClientPacket *packet; 106 | // process any callbacks coming from esp_link 107 | packet = esp.Process(); 108 | if (packet != 0) 109 | { 110 | // process the received package // 111 | } 112 | } 113 | @endcode 114 | */ 115 | ELClientPacket *ELClient::Process() { 116 | int value; 117 | while (_serial->available()) { 118 | value = _serial->read(); 119 | if (value == SLIP_ESC) { 120 | _proto.isEsc = 1; 121 | } else if (value == SLIP_END) { 122 | ELClientPacket *packet = _proto.dataLen >= 8 ? protoCompletedCb() : 0; 123 | _proto.dataLen = 0; 124 | _proto.isEsc = 0; 125 | if (packet != NULL) return packet; 126 | } else { 127 | if (_proto.isEsc) { 128 | if (value == SLIP_ESC_END) value = SLIP_END; 129 | if (value == SLIP_ESC_ESC) value = SLIP_ESC; 130 | _proto.isEsc = 0; 131 | } 132 | if (_proto.dataLen < _proto.bufSize) { 133 | _proto.buf[_proto.dataLen++] = value; 134 | } 135 | } 136 | } 137 | return NULL; 138 | } 139 | 140 | //===== Output 141 | 142 | /*! write(uint8_t data) 143 | @brief Send a byte 144 | @details Write a byte to the output stream and perform SLIP escaping 145 | @note 146 | This function is usually not needed for applications. The communication to the ESP8266 is handled by the cmd, rest, mqtt, tcp and udp library parts. 147 | @param data 148 | Byte to be sent 149 | @par Example 150 | @code 151 | no example code yet 152 | @endcode 153 | */ 154 | void ELClient::write(uint8_t data) { 155 | switch (data) { 156 | case SLIP_END: 157 | _serial->write(SLIP_ESC); 158 | _serial->write(SLIP_ESC_END); 159 | break; 160 | case SLIP_ESC: 161 | _serial->write(SLIP_ESC); 162 | _serial->write(SLIP_ESC_ESC); 163 | break; 164 | default: 165 | _serial->write(data); 166 | } 167 | } 168 | 169 | /*! write(void* data, uint16_t len) 170 | @brief Send several byte 171 | @details Write some bytes to the output stream, no SLIP escaping is performed 172 | @note 173 | This function is usually not needed for applications. The communication to the ESP8266 is handled by the cmd, rest, mqtt, tcp and udp library parts. 174 | @param data 175 | Pointer to data buffer to be sent 176 | @param len 177 | Size of data buffer 178 | @par Example 179 | @code 180 | no example code yet 181 | @endcode 182 | */ 183 | void ELClient::write(void* data, uint16_t len) { 184 | uint8_t *d = (uint8_t*)data; 185 | while (len--) 186 | write(*d++); 187 | } 188 | 189 | /*! Request(uint16_t cmd, uint32_t value, uint16_t argc) 190 | @brief Start a request 191 | @details Start preparing a request by sending the command, number of arguments 192 | and the first argument (which can be a callback pointer) 193 | @note 194 | This function is usually not needed for applications. The communication to the ESP8266 is handled by the cmd, rest, mqtt, tcp and udp library parts. 195 | @param cmd 196 | Command for the ESP, see enum CmdName for available commands 197 | @param value 198 | First argument or pointer to a callback function 199 | @param argc 200 | Number of arguments in this request 201 | @par Example 202 | @code 203 | _elc->Request(CMD_MQTT_LWT, 0, 4); 204 | _elc->Request(topic, strlen(topic)); 205 | _elc->Request(message, strlen(message)); 206 | _elc->Request(&qos, 1); 207 | _elc->Request(&retain, 1); 208 | _elc->Request(); 209 | @endcode 210 | */ 211 | void ELClient::Request(uint16_t cmd, uint32_t value, uint16_t argc) { 212 | crc = 0; 213 | _serial->write(SLIP_END); 214 | write(&cmd, 2); 215 | crc = crc16Data((unsigned const char*)&cmd, 2, crc); 216 | 217 | write(&argc, 2); 218 | crc = crc16Data((unsigned const char*)&argc, 2, crc); 219 | 220 | write(&value, 4); 221 | crc = crc16Data((unsigned const char*)&value, 4, crc); 222 | } 223 | 224 | /*! Request(uint16_t cmd, uint32_t value, uint16_t argc) 225 | @brief Append an argument to the request 226 | @details Send additional arguments as appendment to the ESP 227 | @note 228 | This function is usually not needed for applications. The communication to the ESP8266 is handled by the cmd, rest, mqtt, tcp and udp library parts. 229 | @param data 230 | Pointer to the buffer with the argument 231 | @param len 232 | Size of the argument buffer 233 | @par Example 234 | @code 235 | _elc->Request(CMD_MQTT_LWT, 0, 4); 236 | _elc->Request(topic, strlen(topic)); 237 | _elc->Request(message, strlen(message)); 238 | _elc->Request(&qos, 1); 239 | _elc->Request(&retain, 1); 240 | _elc->Request(); 241 | @endcode 242 | */ 243 | void ELClient::Request(const void* data, uint16_t len) { 244 | uint8_t *d = (uint8_t*)data; 245 | 246 | // write the length 247 | write(&len, 2); 248 | crc = crc16Data((unsigned const char*)&len, 2, crc); 249 | 250 | // output the data 251 | for (uint16_t l=len; l>0; l--) { 252 | write(*d); 253 | crc = crc16Add(*d, crc); 254 | d++; 255 | } 256 | 257 | // output padding 258 | uint16_t pad = (4-(len&3))&3; 259 | uint8_t temp = 0; 260 | while (pad--) { 261 | write(temp); 262 | crc = crc16Add(temp, crc); 263 | } 264 | } 265 | 266 | /*! Request(const __FlashStringHelper* data, uint16_t len) 267 | @brief Append an argument to the request 268 | @details Send additional arguments located in flash as appendment to the ESP 269 | @note 270 | This function is usually not needed for applications. The communication to the ESP8266 is handled by the cmd, rest, mqtt, tcp and udp library parts. 271 | @param data 272 | Pointer to the buffer with the argument 273 | @param len 274 | Size of the argument buffer 275 | @par Example 276 | @code 277 | _elc->Request(CMD_MQTT_LWT, 0, 4); 278 | _elc->Request(topic, strlen(topic)); 279 | _elc->Request(message, strlen(message)); 280 | _elc->Request(&qos, 1); 281 | _elc->Request(&retain, 1); 282 | _elc->Request(); 283 | @endcode 284 | */ 285 | void ELClient::Request(const __FlashStringHelper* data, uint16_t len) { 286 | // write the length 287 | write(&len, 2); 288 | crc = crc16Data((unsigned const char*)&len, 2, crc); 289 | 290 | // output the data 291 | PGM_P p = reinterpret_cast(data); 292 | for (uint16_t l=len; l>0; l--) { 293 | uint8_t c = pgm_read_byte(p++); 294 | write(c); 295 | crc = crc16Add(c, crc); 296 | } 297 | 298 | // output padding 299 | uint16_t pad = (4-(len&3))&3; 300 | uint8_t temp = 0; 301 | while (pad--) { 302 | write(temp); 303 | crc = crc16Add(temp, crc); 304 | } 305 | } 306 | 307 | /*! Request(void) 308 | @brief Finish the request 309 | @details Send final CRC and SLIP_END to the ESP to finish the request 310 | @note 311 | This function is usually not needed for applications. The communication to the ESP8266 is handled by the cmd, rest, mqtt, tcp and udp library parts. 312 | @par Example 313 | @code 314 | _elc->Request(CMD_MQTT_LWT, 0, 4); 315 | _elc->Request(topic, strlen(topic)); 316 | _elc->Request(message, strlen(message)); 317 | _elc->Request(&qos, 1); 318 | _elc->Request(&retain, 1); 319 | _elc->Request(); 320 | @endcode 321 | */ 322 | void ELClient::Request(void) { 323 | write((uint8_t*)&crc, 2); 324 | _serial->write(SLIP_END); 325 | } 326 | 327 | //===== Initialization 328 | 329 | /*! init() 330 | @brief Initialize ELClient protocol 331 | @details Prepare buffer for protocol 332 | @note 333 | This function is usually not needed for applications. The communication to the ESP8266 is handled by the cmd, rest, mqtt, tcp and udp library parts. 334 | @par Example 335 | @code 336 | no example code yet 337 | @endcode 338 | */ 339 | void ELClient::init() { 340 | _proto.buf = _protoBuf; 341 | _proto.bufSize = sizeof(_protoBuf); 342 | _proto.dataLen = 0; 343 | _proto.isEsc = 0; 344 | } 345 | 346 | /*! ELClient(Stream* serial) 347 | @brief Initialize ELClient 348 | @details Store serial stream to be used for the communication 349 | @param serial 350 | Serial stream for communication with ESP 351 | @par Example for hardware serial ports 352 | @code 353 | //########################################################### 354 | // For boards using the hardware serial port! 355 | //########################################################### 356 | // Initialize a connection to esp-link using the normal hardware serial port for SLIP messages. 357 | ELClient esp(&Serial); 358 | @endcode 359 | @par Example for ARDUINO UNO WIFI board with I2C to serial chip connected to the ESP8266 360 | @code 361 | //########################################################### 362 | // For ARDUINO UNO WIFI board with I2C to serial chip connected to the ESP8266! 363 | //########################################################### 364 | // Serial port to ESP8266 365 | #include 366 | SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA); 367 | // Initialize a connection to esp-link using the I2Cuart chip of the Arduino Uno WiFi board for SLIP messages. 368 | ELClient esp(&i2cuart); 369 | @endcode 370 | */ 371 | ELClient::ELClient(Stream* serial) : 372 | _serial(serial) { 373 | _debugEn = false; 374 | init(); 375 | } 376 | 377 | /*! ELClient(Stream* serial, Stream* debug) 378 | @brief Initialize ELClient and enable debug output 379 | @details Store serial streams to be used for the communication 380 | @param serial 381 | Serial stream for communication with ESP 382 | @param debug 383 | Serial stream for debug output 384 | @par Example for hardware serial ports 385 | @code 386 | //########################################################### 387 | // For boards using the hardware serial port! 388 | //########################################################### 389 | // Initialize a connection to esp-link using the normal hardware serial port both for SLIP and for debug messages. 390 | ELClient esp(&Serial, &Serial); 391 | @endcode 392 | @par Example for ARDUINO UNO WIFI board with I2C to serial chip connected to the ESP8266 393 | @code 394 | //########################################################### 395 | // For ARDUINO UNO WIFI board with I2C to serial chip connected to the ESP8266! 396 | //########################################################### 397 | // Serial port to ESP8266 398 | #include 399 | SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA); 400 | // Initialize a connection to esp-link using the I2Cuart chip of the Arduino Uno WiFi board for SLIP messages. 401 | ELClient esp(&i2cuart, &Serial); 402 | @endcode 403 | */ 404 | ELClient::ELClient(Stream* serial, Stream* debug) : 405 | _debug(debug), _serial(serial) { 406 | _debugEn = true; 407 | init(); 408 | } 409 | 410 | /*! ELClient::DBG(const char* info) 411 | @brief Send debug message over serial debug stream 412 | @param info 413 | Debug message 414 | @par Example 415 | @code 416 | no example code yet 417 | @endcode 418 | */ 419 | void ELClient::DBG(const char* info) { 420 | if (_debugEn) _debug->println(info); 421 | } 422 | 423 | //===== Responses 424 | 425 | /*! WaitReturn(uint32_t timeout) 426 | @brief Wait for a response from ESP for a given timeout 427 | @param timeout 428 | Time in milliseconds to wait for a response, defaults to ESP_TIMEOUT 429 | @return ELClientPacket 430 | Received packet or null if timeout occured 431 | @par Example 432 | @code 433 | // Wait for WiFi to be connected. 434 | esp.GetWifiStatus(); 435 | ELClientPacket *packet; 436 | Serial.print("Waiting for WiFi "); 437 | if ((packet=esp.WaitReturn()) != NULL) { 438 | Serial.print("."); 439 | Serial.println(packet->value); 440 | } 441 | Serial.println(""); 442 | @endcode 443 | */ 444 | ELClientPacket *ELClient::WaitReturn(uint32_t timeout) { 445 | uint32_t wait = millis(); 446 | while (millis() - wait < timeout) { 447 | ELClientPacket *packet = Process(); 448 | if (packet != NULL) return packet; 449 | } 450 | return NULL; 451 | } 452 | 453 | //===== CRC helper functions 454 | 455 | /*! crc16Add(unsigned char b, uint16_t acc) 456 | @brief Create CRC for a byte add it to an existing CRC checksum and return the result 457 | @param b 458 | Byte which CRC will be added 459 | @param acc 460 | Existing CRC checksum 461 | @return uint16_t 462 | New CRC checksum 463 | @par Example 464 | @code 465 | no example code yet 466 | @endcode 467 | */ 468 | uint16_t ELClient::crc16Add(unsigned char b, uint16_t acc) 469 | { 470 | acc ^= b; 471 | acc = (acc >> 8) | (acc << 8); 472 | acc ^= (acc & 0xff00) << 4; 473 | acc ^= (acc >> 8) >> 4; 474 | acc ^= (acc & 0xff00) >> 5; 475 | return acc; 476 | } 477 | 478 | /*! crc16Data(const unsigned char *data, uint16_t len, uint16_t acc) 479 | @brief Create/add CRC for a data buffer 480 | @param data 481 | The data buffer which will be CRCed 482 | @param len 483 | Size of the data buffer 484 | @param acc 485 | Existing CRC checksum 486 | @return uint16_t 487 | New CRC checksum 488 | @par Example 489 | @code 490 | no example code yet 491 | @endcode 492 | */ 493 | uint16_t ELClient::crc16Data(const unsigned char *data, uint16_t len, uint16_t acc) 494 | { 495 | for (uint16_t i=0; iboolean 507 | True if synchronization succeeds or False if it fails 508 | @par Example 509 | @code 510 | // Sync-up with esp-link, this is required at the start of any sketch and initializes the callbacks to the wifi status change callback. The callback gets called with the initial status right after Sync() below completes. 511 | esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired) 512 | bool ok; 513 | do 514 | { 515 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 516 | if (!ok) Serial.println("EL-Client sync failed!"); 517 | } while(!ok); 518 | Serial.println("EL-Client synced!"); 519 | @endcode 520 | */ 521 | boolean ELClient::Sync(uint32_t timeout) { 522 | // send a SLIP END char to make sure we get a clean start 523 | _serial->write(SLIP_END); 524 | // send sync request 525 | Request(CMD_SYNC, (uint32_t)&wifiCb, 0); 526 | Request(); 527 | // we don't want to get a stale response that we need to sync 'cause that has the effect of 528 | // calling us again recursively.... 529 | void (*rr)() = resetCb; 530 | resetCb = NULL; 531 | // empty the response queue hoping to find the wifiCb address 532 | ELClientPacket *packet; 533 | while ((packet = WaitReturn(timeout)) != NULL) { 534 | if (packet->value == (uint32_t)&wifiCb) { 535 | if (_debugEn) _debug->println("SYNC!"); 536 | resetCb = rr; 537 | return true; 538 | } 539 | if (_debugEn) { 540 | _debug->print("BAD: "); 541 | _debug->println(packet->value); 542 | } 543 | } 544 | // doesn't look like we got a real response 545 | resetCb = rr; 546 | return false; 547 | } 548 | 549 | /*! GetWifiStatus(void) 550 | @brief Request WiFi status from the ESP 551 | @par Example 552 | @code 553 | // Wait for WiFi to be connected. 554 | esp.GetWifiStatus(); 555 | ELClientPacket *packet; 556 | Serial.print("Waiting for WiFi "); 557 | if ((packet=esp.WaitReturn()) != NULL) { 558 | Serial.print("."); 559 | Serial.println(packet->value); 560 | } 561 | Serial.println(""); 562 | @endcode 563 | */ 564 | void ELClient::GetWifiStatus(void) { 565 | Request(CMD_WIFI_STATUS, 0, 0); 566 | Request(); 567 | } 568 | -------------------------------------------------------------------------------- /ELClient/ELClient.h: -------------------------------------------------------------------------------- 1 | /*! \file ELClient.h 2 | \brief Definitions for ELClient 3 | */ 4 | 5 | #ifndef _EL_CLIENT_H_ 6 | #define _EL_CLIENT_H_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include "ELClientResponse.h" 12 | #include "FP.h" 13 | 14 | #define ESP_TIMEOUT 2000 /**< Default timeout for TCP requests when waiting for a response */ 15 | 16 | // Enumeration of commands supported by esp-link, this needs to match the definition in 17 | // esp-link! 18 | typedef enum { 19 | CMD_NULL = 0, /**< null, mainly to prevent 0 from doing something bad */ 20 | CMD_SYNC, /**< Synchronize, starts the protocol */ 21 | CMD_RESP_V, /**< Response with a value */ 22 | CMD_RESP_CB, /**< Response with a callback */ 23 | CMD_WIFI_STATUS, /**< Get the wifi status */ 24 | CMD_CB_ADD, /**< Add a custom callback */ 25 | CMD_CB_EVENTS, /**< ??? */ 26 | CMD_GET_TIME, /**< Get current time in seconds since the unix epoch */ 27 | //CMD_GET_INFO, 28 | 29 | CMD_MQTT_SETUP = 10, /**< Register callback functions */ 30 | CMD_MQTT_PUBLISH, /**< Publish MQTT topic */ 31 | CMD_MQTT_SUBSCRIBE, /**< Subscribe to MQTT topic */ 32 | CMD_MQTT_LWT, /**< Define MQTT last will */ 33 | 34 | CMD_REST_SETUP = 20, /**< Setup REST connection */ 35 | CMD_REST_REQUEST, /**< Make request to REST server */ 36 | CMD_REST_SETHEADER, /**< Define HTML header */ 37 | 38 | CMD_WEB_SETUP = 30, /**< web-server setup */ 39 | CMD_WEB_DATA, /**< used for publishing web-server data */ 40 | 41 | CMD_SOCKET_SETUP = 40, /**< Setup socket connection */ 42 | CMD_SOCKET_SEND, /**< Send socket packet */ 43 | } CmdName; /**< Enumeration of commands supported by esp-link, this needs to match the definition in esp-link! */ 44 | 45 | enum WIFI_STATUS { 46 | STATION_IDLE = 0, /**< Idle status */ 47 | STATION_CONNECTING, /**< Trying to connect */ 48 | STATION_WRONG_PASSWORD, /**< Connection error, wrong password */ 49 | STATION_NO_AP_FOUND, /**< Connection error, AP not found */ 50 | STATION_CONNECT_FAIL, /**< Connection error, connection failed */ 51 | STATION_GOT_IP /**< Connected, received IP */ 52 | }; /**< Enumeration of possible WiFi status */ 53 | 54 | typedef struct { 55 | uint8_t* buf; 56 | uint16_t bufSize; 57 | uint16_t dataLen; 58 | uint8_t isEsc; 59 | } ELClientProtocol; /**< Protocol structure */ 60 | 61 | // The ELClient class implements the basic protocol to communicate with esp-link using SLIP. 62 | // The SLIP protocol just provides framing, i.e., it delineates the start and end of packets. 63 | // The format of each packet is dictated by ELClient and consists of a 2-byte command, a 2-byte 64 | // count of arguments, a 4-byte callback addr, then the arguments, and finally 1 2-byte CRC. 65 | // 66 | // ELClient handles communication set-up and reset. It has to take a number of scenarios into 67 | // account, including simultaneous power-on reset of arduino and esp-link, spontaneous reset of 68 | // esp-link, and reset of arduino. Returning to a consistent state in all these cases is handled by 69 | // the Sync function and null commands. 70 | // 71 | // When ELClient starts it needs to send a Sync to esp-link. This clears all state and callbacks on 72 | // the esp-link side and then ELClient can install callbacks, etc. In order to catch the cases where 73 | // esp-link resets ELClient ensures that it sends periodic commands to esp-link and checks whether 74 | // esp-link responds with a "not synced" error, which indicates that it reset. If such an error 75 | // occurs ELClient starts with a fresh Sync. Unfortunately this has to be propagated up the 76 | // communication layers because the client may have to re-subscribe to MQTT messages or to certain 77 | // callbacks. 78 | class ELClient { 79 | public: 80 | // Create an esp-link client based on a stream and with a specified debug output stream. 81 | ELClient(Stream* serial, Stream* debug); 82 | // Create an esp-link client based on a stream with no debug output 83 | ELClient(Stream* serial); 84 | 85 | Stream* _debug; /**< Data stream for debug use */ 86 | 87 | //== Requests 88 | // Start a request. cmd is the command to execute, value is either the address of a function 89 | // to call with a response or a first argument to the command if there is no CB. 90 | // Argc is the number of additional arguments 91 | void Request(uint16_t cmd, uint32_t value, uint16_t argc); 92 | // Add a an argument consisting of a data block to a request 93 | void Request(const void* data, uint16_t len); 94 | // Add a an argument consisting of a data block in flash to a request 95 | void Request(const __FlashStringHelper* data, uint16_t len); 96 | // Finish a request 97 | void Request(void); 98 | 99 | //== Responses 100 | // Process the input stream, call this in loop() to dispatch call-back based responses. 101 | // Callbacks on FP are invoked with an ElClientResponse pointer as argument. 102 | // Returns the ELClientPacket if a non-callback response was received, typically this is 103 | // used to create an ELClientResponse. Returns NULL if no response needs to be processed. 104 | ELClientPacket *Process(void); 105 | // Busy wait for a response with a timeout in milliseconds, returns an ELClientPacket 106 | // if a response was recv'd and NULL otherwise. The ELClientPacket is typically used to 107 | // create an ELClientResponse. 108 | ELClientPacket *WaitReturn(uint32_t timeout=ESP_TIMEOUT); 109 | 110 | //== Commands built-into ELClient 111 | // Initialize and synchronize communication with esp-link with a timeout in milliseconds, 112 | // and remove all existing callbacks. Registers the wifiCb and returns true on success 113 | boolean Sync(uint32_t timeout=ESP_TIMEOUT); 114 | // Request the wifi status 115 | void GetWifiStatus(void); 116 | 117 | // Callback for wifi status changes. This callback must be attached before calling Sync 118 | FP wifiCb; /**< Pointer to callback function */ 119 | // Callback to indicate protocol reset, typically due to esp-link resetting. The callback 120 | // should call Sync and perform any other callback registration afresh. 121 | void (*resetCb)(); /**< Pointer to callback function */ 122 | 123 | //private: 124 | Stream* _serial; /**< Serial stream for communication with ESP */ 125 | boolean _debugEn; /**< Flag for debug - True = enabled, False = disabled */ 126 | uint16_t crc; /**< CRC checksum */ 127 | ELClientProtocol _proto; /**< Protocol structure */ 128 | uint8_t _protoBuf[128]; /**< Protocol buffer */ 129 | 130 | void init(); 131 | void DBG(const char* info); 132 | ELClientPacket *protoCompletedCb(void); 133 | void write(uint8_t data); 134 | void write(void* data, uint16_t len); 135 | uint16_t crc16Add(unsigned char b, uint16_t acc); 136 | uint16_t crc16Data(const unsigned char *data, uint16_t len, uint16_t acc); 137 | }; 138 | #endif // _EL_CLIENT_H_ 139 | -------------------------------------------------------------------------------- /ELClient/ELClientCmd.cpp: -------------------------------------------------------------------------------- 1 | /*! \file ELClientCmd.cpp 2 | \brief Constructor and functions for ELClientCmd 3 | \author B. Runnels 4 | \author T. von Eicken 5 | \date 2016 6 | */ 7 | // Copyright (c) 2016 by B. Runnels and T. von Eicken 8 | 9 | #include "ELClientCmd.h" 10 | 11 | /*! ELClientCmd(ELClient* elc) 12 | @brief Constructor for ELClientCmd 13 | */ 14 | ELClientCmd::ELClientCmd(ELClient* elc) :_elc(elc) {} 15 | 16 | /*! GetTime() 17 | @brief Get time from ESP 18 | @details Time from the ESP is unformated value of seconds 19 | @warning If the ESP cannot connect to the NTP server or the connection NTP server is not setup, 20 | then this time is the number of seconds since the last reboot of the ESP 21 | @return uint32_t 22 | current time as number of seconds 23 | - since Thu Jan 1 00:00:58 UTC 1970 if ESP has time from NTP 24 | - since last reboot of ESP if no NTP time is available 25 | @par Example 26 | @code 27 | uint32_t t = cmd.GetTime(); 28 | Serial.print("Time: "); Serial.println(t); 29 | @endcode 30 | */ 31 | uint32_t ELClientCmd::GetTime() { 32 | _elc->Request(CMD_GET_TIME, 0, 0); 33 | _elc->Request(); 34 | 35 | ELClientPacket *pkt = _elc->WaitReturn(); 36 | return pkt ? pkt->value : 0; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /ELClient/ELClientCmd.h: -------------------------------------------------------------------------------- 1 | /*! \file ELClientCmd.h 2 | \brief Definitions for ELClientCmd 3 | \note Miscellaneous commands 4 | */ 5 | // Miscellaneous commands 6 | 7 | #ifndef _EL_CLIENT_CMD_H_ 8 | #define _EL_CLIENT_CMD_H_ 9 | 10 | #include 11 | #include "ELClient.h" 12 | #include "FP.h" 13 | 14 | class ELClientCmd { 15 | public: 16 | // Constructor 17 | ELClientCmd(ELClient* elc); 18 | // Get the current time in seconds since the epoch, 0 if the time is unknown 19 | uint32_t GetTime(); 20 | 21 | private: 22 | ELClient* _elc; /**< ELClient instance */ 23 | }; 24 | #endif 25 | -------------------------------------------------------------------------------- /ELClient/ELClientMqtt.cpp: -------------------------------------------------------------------------------- 1 | /*! \file ELClientMqtt.cpp 2 | \brief Constructor and functions for ELClientMqtt 3 | \author B. Runnels 4 | \author T. von Eicken 5 | \date 2016 6 | */ 7 | // Copyright (c) 2016 by B. Runnels and T. von Eicken 8 | 9 | #include 10 | #include "ELClientMqtt.h" 11 | 12 | // constructor 13 | /*! ELClientMqtt(ELClient* elc) 14 | @brief Constructor for ELClientMqtt 15 | @par Example 16 | @code 17 | ELClientMqtt(ELClient* elc); 18 | @endcode 19 | */ 20 | ELClientMqtt::ELClientMqtt(ELClient* elc) :_elc(elc) {} 21 | 22 | /*! setup(void) 23 | @brief Setup mqtt 24 | @details Send callback functions for MQTT events to the ESP 25 | @par Example 26 | @code 27 | mqtt.connectedCb.attach(mqttConnected); 28 | mqtt.disconnectedCb.attach(mqttDisconnected); 29 | mqtt.publishedCb.attach(mqttPublished); 30 | mqtt.dataCb.attach(mqttData); 31 | mqtt.setup(); 32 | @endcode 33 | */ 34 | void ELClientMqtt::setup(void) { 35 | Serial.print(F("ConnectedCB is 0x")); Serial.println((uint32_t)&connectedCb, 16); 36 | _elc->Request(CMD_MQTT_SETUP, 0, 4); 37 | uint32_t cb = (uint32_t)&connectedCb; 38 | _elc->Request(&cb, 4); 39 | cb = (uint32_t)&disconnectedCb; 40 | _elc->Request(&cb, 4); 41 | cb = (uint32_t)&publishedCb; 42 | _elc->Request(&cb, 4); 43 | cb = (uint32_t)&dataCb; 44 | _elc->Request(&cb, 4); 45 | _elc->Request(); 46 | } 47 | 48 | // LWT 49 | 50 | /*! lwt(const char* topic, const char* message, uint8_t qos, uint8_t retain) 51 | @brief Set MQTT last will. 52 | @details Sends the "last will" to the ESP. 53 | @param topic 54 | Last will topic name 55 | @param message 56 | Last will message 57 | @param qos 58 | (optional) Requested qos level, default 0 59 | @param retain 60 | (optional) Requested retain level, default 0 61 | @warning At the moment only qos level 0 is implemented and supported! 62 | @par Example 63 | @code 64 | Serial.println("ARDUINO: setup mqtt lwt"); 65 | mqtt.lwt("/lwt", "offline", 0, 0); //or mqtt.lwt("/lwt", "offline"); 66 | @endcode 67 | */ 68 | void ELClientMqtt::lwt(const char* topic, const char* message, uint8_t qos, uint8_t retain) { 69 | _elc->Request(CMD_MQTT_LWT, 0, 4); 70 | _elc->Request(topic, strlen(topic)); 71 | _elc->Request(message, strlen(message)); 72 | _elc->Request(&qos, 1); 73 | _elc->Request(&retain, 1); 74 | _elc->Request(); 75 | } 76 | 77 | /*! lwt(const __FlashStringHelper* topic, const __FlashStringHelper* message, uint8_t qos, uint8_t retain) 78 | @brief Set MQTT last will. 79 | @details Sends the "last will" to the ESP with the topic and message stored in program memory 80 | @param topic 81 | Last will topic name 82 | @param message 83 | Last will message 84 | @param qos 85 | (optional) Requested qos level, default 0 86 | @param retain 87 | (optional) Requested retain level, default 0 88 | @warning At the moment only qos level 0 is implemented and supported! 89 | @par Example 90 | @code 91 | no example code yet 92 | @endcode 93 | */ 94 | void ELClientMqtt::lwt(const __FlashStringHelper* topic, const __FlashStringHelper* message, 95 | uint8_t qos, uint8_t retain) 96 | { 97 | _elc->Request(CMD_MQTT_LWT, 0, 4); 98 | _elc->Request(topic, strlen_P((const char*)topic)); 99 | _elc->Request(message, strlen_P((const char*)message)); 100 | _elc->Request(&qos, 1); 101 | _elc->Request(&retain, 1); 102 | _elc->Request(); 103 | } 104 | 105 | // SUBSCRIBE 106 | 107 | /*! subscribe(const char* topic, uint8_t qos) 108 | @brief Subscribe to MQTT topic 109 | @details Sends the MQTT subscription request to the ESP 110 | @param topic 111 | Topic name 112 | @param qos 113 | (optional) Requested qos level, default 0 114 | @warning At the moment only qos level 0 is implemented and supported! 115 | @par Example 116 | @code 117 | mqtt.subscribe("/esp-link/1"); 118 | mqtt.subscribe("/hello/world/#"); 119 | @endcode 120 | */ 121 | void ELClientMqtt::subscribe(const char* topic, uint8_t qos) { 122 | _elc->Request(CMD_MQTT_SUBSCRIBE, 0, 2); 123 | _elc->Request(topic, strlen(topic)); 124 | _elc->Request(&qos, 1); 125 | _elc->Request(); 126 | } 127 | 128 | /*! subscribe(const __FlashStringHelper* topic, uint8_t qos) 129 | @brief Subscribe to MQTT topic 130 | @details Sends the MQTT subscription request to the ESP with the topic and message stored in program memory 131 | @param topic 132 | Topic name 133 | @param qos 134 | (optional) Requested qos level, default 0 135 | @warning At the moment only qos level 0 is implemented and supported! 136 | @par Example 137 | @code 138 | no example code yet 139 | @endcode 140 | */ 141 | void ELClientMqtt::subscribe(const __FlashStringHelper* topic, uint8_t qos) { 142 | _elc->Request(CMD_MQTT_SUBSCRIBE, 0, 2); 143 | _elc->Request(topic, strlen_P((const char*)topic)); 144 | _elc->Request(&qos, 1); 145 | _elc->Request(); 146 | } 147 | 148 | // PUBLISH 149 | 150 | /*! publish(const char* topic, const uint8_t* data, const uint16_t len, uint8_t qos, uint8_t retain) 151 | @brief Subscribe to MQTT topic 152 | @details Sends the MQTT subscription request to the ESP 153 | @param topic 154 | Topic name 155 | @param data 156 | Pointer to data buffer 157 | @param len 158 | Size of data buffer 159 | @param qos 160 | (optional) Requested qos level, default 0 161 | @param retain 162 | (optional) Requested retain level, default 0 163 | @warning At the moment only qos level 0 is implemented and supported! 164 | @par Example 165 | @code 166 | char buf[12]; 167 | itoa(count++, buf, 10); 168 | mqtt.publish("/esp-link/1", buf); 169 | itoa(count+99, buf, 10); 170 | mqtt.publish("/hello/world/arduino", buf, 12); 171 | @endcode 172 | */ 173 | void ELClientMqtt::publish(const char* topic, const uint8_t* data, const uint16_t len, 174 | uint8_t qos, uint8_t retain) 175 | { 176 | _elc->Request(CMD_MQTT_PUBLISH, 0, 5); 177 | _elc->Request(topic, strlen(topic)); 178 | _elc->Request(data, len); 179 | _elc->Request(&len, 2); 180 | _elc->Request(&qos, 1); 181 | _elc->Request(&retain, 1); 182 | _elc->Request(); 183 | } 184 | 185 | /*! publish(const char* topic, const char* data, uint8_t qos, uint8_t retain) 186 | @brief Subscribe to MQTT topic 187 | @details Sends the MQTT subscription request to the ESP. Data must be null-terminated 188 | @param topic 189 | Topic name 190 | @param data 191 | Pointer to data buffer 192 | @param qos 193 | (optional) Requested qos level, default 0 194 | @param retain 195 | (optional) Requested retain level, default 0 196 | @warning At the moment only qos level 0 is implemented and supported! 197 | @par Example 198 | @code 199 | char buf[12]; 200 | itoa(count++, buf, 10); 201 | mqtt.publish("/esp-link/1", buf); 202 | itoa(count+99, buf, 10); 203 | mqtt.publish("/hello/world/arduino", buf); 204 | @endcode 205 | */ 206 | void ELClientMqtt::publish(const char* topic, const char* data, uint8_t qos, uint8_t retain) 207 | { 208 | publish(topic, (uint8_t*)data, strlen(data), qos, retain); 209 | } 210 | 211 | /*! publish(const __FlashStringHelper* topic, const __FlashStringHelper* data, const uint16_t len, uint8_t qos, uint8_t retain) 212 | @brief Subscribe to MQTT topic 213 | @details Sends the MQTT subscription request to the ESP with the topic and data stored in program memory 214 | @param topic 215 | Topic name 216 | @param data 217 | Pointer to data buffer 218 | @param len 219 | Size of data buffer 220 | @param qos 221 | (optional) Requested qos level, default 0 222 | @param retain 223 | (optional) Requested retain level, default 0 224 | @warning At the moment only qos level 0 is implemented and supported! 225 | @par Example 226 | @code 227 | no example code yet 228 | @endcode 229 | */ 230 | void ELClientMqtt::publish(const __FlashStringHelper* topic, const __FlashStringHelper* data, 231 | const uint16_t len, uint8_t qos, uint8_t retain) 232 | { 233 | _elc->Request(CMD_MQTT_PUBLISH, 0, 5); 234 | _elc->Request(topic, strlen_P((const char*)topic)); 235 | _elc->Request(data, len); 236 | _elc->Request(&len, 2); 237 | _elc->Request(&qos, 1); 238 | _elc->Request(&retain, 1); 239 | _elc->Request(); 240 | } 241 | 242 | /*! ELClientMqtt::publish(const char* topic, const __FlashStringHelper* data, const uint16_t len, uint8_t qos, uint8_t retain) 243 | @brief Subscribe to MQTT topic 244 | @details Sends the MQTT subscription request to the ESP with the data stored in program memory 245 | @param topic 246 | Topic name 247 | @param data 248 | Pointer to data buffer 249 | @param len 250 | Size of data buffer 251 | @param qos 252 | (optional) Requested qos level, default 0 253 | @param retain 254 | (optional) Requested retain level, default 0 255 | @warning At the moment only qos level 0 is implemented and supported! 256 | @par Example 257 | @code 258 | no example code yet 259 | @endcode 260 | */ 261 | void ELClientMqtt::publish(const char* topic, const __FlashStringHelper* data, 262 | const uint16_t len, uint8_t qos, uint8_t retain) 263 | { 264 | _elc->Request(CMD_MQTT_PUBLISH, 0, 5); 265 | _elc->Request(topic, strlen(topic)); 266 | _elc->Request(data, len); 267 | _elc->Request(&len, 2); 268 | _elc->Request(&qos, 1); 269 | _elc->Request(&retain, 1); 270 | _elc->Request(); 271 | } 272 | 273 | /*! publish(const __FlashStringHelper* topic, const uint8_t* data, const uint16_t len, uint8_t qos, uint8_t retain) 274 | @brief Subscribe to MQTT topic 275 | @details Sends the MQTT subscription request to the ESP with the topic stored in program memory 276 | @param topic 277 | Topic name 278 | @param data 279 | Pointer to data buffer 280 | @param len 281 | Size of data buffer 282 | @param qos 283 | (optional) Requested qos level, default 0 284 | @param retain 285 | (optional) Requested retain level, default 0 286 | @warning At the moment only qos level 0 is implemented and supported! 287 | @par Example 288 | @code 289 | no example code yet 290 | @endcode 291 | */ 292 | void ELClientMqtt::publish(const __FlashStringHelper* topic, const uint8_t* data, 293 | const uint16_t len, uint8_t qos, uint8_t retain) 294 | { 295 | _elc->Request(CMD_MQTT_PUBLISH, 0, 5); 296 | _elc->Request(topic, strlen_P((const char*)topic)); 297 | _elc->Request(data, len); 298 | _elc->Request(&len, 2); 299 | _elc->Request(&qos, 1); 300 | _elc->Request(&retain, 1); 301 | _elc->Request(); 302 | } 303 | -------------------------------------------------------------------------------- /ELClient/ELClientMqtt.h: -------------------------------------------------------------------------------- 1 | /*! \file ELClientMqtt.h 2 | \brief Definitions for ELClientMqtt 3 | \author B. Runnels 4 | \author T. von Eicken 5 | \date 2016 6 | */ 7 | // Copyright (c) 2016 by B. Runnels and T. von Eicken 8 | 9 | #ifndef _EL_CLIENT_MQTT_H_ 10 | #define _EL_CLIENT_MQTT_H_ 11 | 12 | #include 13 | #include "FP.h" 14 | #include "ELClient.h" 15 | 16 | // Class to send and receive MQTT messages. This class should be used with a singleton object 17 | // because the esp-link implementation currently only supports a single MQTT server, so there is 18 | // no value in instantiating multiple ELClientMqtt objects (although it's possible). 19 | // All the server settings are made in esp-link and esp-link takes care to automatically 20 | // reconnect and retry if the connection is lost. This means that on the arduino side the only 21 | // code that is necessary is to send and receive messsages. 22 | class ELClientMqtt { 23 | public: 24 | // Initialize with an ELClient object 25 | ELClientMqtt(ELClient* elc); 26 | 27 | // setup transmits the set of callbacks to esp-link. It assumes that the desired callbacks 28 | // have previously been attached using something like mqtt->connectedCb.attach(myCallbackFun). 29 | // After setup is called either the connectedCb or the disconnectedCb is invoked to provide 30 | // information about the initial connection status. 31 | void setup(void); 32 | 33 | // callbacks that can be attached prior to calling setup 34 | FP connectedCb; /**< callback with no args when MQTT is connected */ 35 | FP disconnectedCb; /**< callback with no args when MQTT is disconnected */ 36 | FP publishedCb; /**< not yet implemented */ 37 | FP dataCb; /**< callback when a message is received, called with two arguments: the topic and the message (max ~110 bytes for both) */ 38 | 39 | // subscribe to a topic, the default qos is 0. When messages are recevied for the topic the 40 | // data callback is invoked. 41 | void subscribe(const char* topic, uint8_t qos=0); 42 | void subscribe(const __FlashStringHelper* topic, uint8_t qos=0); 43 | 44 | // publish a message to a topic 45 | void publish(const char* topic, const uint8_t* data, 46 | const uint16_t len, uint8_t qos=0, uint8_t retain=0); 47 | void publish(const char* topic, const char* data, 48 | uint8_t qos=0, uint8_t retain=0); 49 | void publish(const __FlashStringHelper* topic, const __FlashStringHelper* data, 50 | const uint16_t len, uint8_t qos=0, uint8_t retain=0); 51 | void publish(const char* topic, const __FlashStringHelper* data, 52 | const uint16_t len, uint8_t qos=0, uint8_t retain=0); 53 | void publish(const __FlashStringHelper* topic, const uint8_t* data, 54 | const uint16_t len, uint8_t qos=0, uint8_t retain=0); 55 | 56 | // set a last-will topic & message 57 | void lwt(const char* topic, const char* message, uint8_t qos=0, uint8_t retain=0); 58 | void lwt(const __FlashStringHelper* topic, const __FlashStringHelper* message, 59 | uint8_t qos=0, uint8_t retain=0); 60 | 61 | private: 62 | ELClient* _elc; /**< ELClient instance */ 63 | }; 64 | 65 | #endif // _EL_CLIENT_MQTT_H_ 66 | -------------------------------------------------------------------------------- /ELClient/ELClientResponse.cpp: -------------------------------------------------------------------------------- 1 | /*! \file ELClientResponse.cpp 2 | \brief Constructor and functions for ELClientResponse 3 | */ 4 | #include "ELClientResponse.h" 5 | 6 | /*! ELClientResponse(ELClientPacket* packet) 7 | @brief Constructor for ELClientResponse with ELClientPacket packet 8 | @param packet 9 | Pointer to packet for response 10 | @par Example 11 | @code 12 | no example code yet 13 | @endcode 14 | */ 15 | ELClientResponse::ELClientResponse(ELClientPacket* packet) { 16 | _cmd = packet; 17 | _arg_ptr = _cmd->args; 18 | _arg_num = 0; 19 | } 20 | 21 | /*! ELClientResponse(void* packet) 22 | @brief Constructor for ELClientResponse with void packet 23 | @param packet 24 | Pointer to packet for response 25 | @par Example 26 | @code 27 | no example code yet 28 | @endcode 29 | */ 30 | ELClientResponse::ELClientResponse(void* packet) { 31 | _cmd = (ELClientPacket *)packet; 32 | _arg_ptr = _cmd->args; 33 | _arg_num = 0; 34 | } 35 | 36 | /*! popArgPtr(void **data) 37 | @brief Extract pointer to an argument from the response packet 38 | @param data 39 | Pointer to buffer for the argument pointer 40 | @return int16_t 41 | Size of argument 42 | @par Example 43 | @code 44 | no example code yet 45 | @endcode 46 | */ 47 | int16_t ELClientResponse::popArgPtr(void **data) { 48 | if (_arg_num >= _cmd->argc) return -1; 49 | 50 | uint16_t len = *(uint16_t*)_arg_ptr; 51 | uint16_t pad = (4-((len+2)&3))&3; // pad to next multiple of 4, including length 52 | _arg_ptr += 2; 53 | _arg_num++; 54 | 55 | *data = _arg_ptr; 56 | _arg_ptr += len + pad; 57 | return len; 58 | } 59 | 60 | /*! popArg(void* d, uint16_t maxLen) 61 | @brief Extract an argument from the response packet 62 | @param d 63 | Pointer to buffer for the argument 64 | @param maxLen 65 | Size of the buffer for the argument 66 | @return int16_t 67 | Size of argument 68 | @par Example 69 | @code 70 | no example code yet 71 | @endcode 72 | */ 73 | int16_t ELClientResponse::popArg(void* d, uint16_t maxLen) { 74 | if (_arg_num >= _cmd->argc) return -1; 75 | 76 | uint16_t len = *(uint16_t*)_arg_ptr; 77 | uint16_t pad = (4-((len+2)&3))&3; // pad to next multiple of 4, including length 78 | _arg_ptr += 2; 79 | _arg_num++; 80 | 81 | uint8_t *data = (uint8_t *)d; 82 | uint16_t l = len > maxLen ? maxLen : len; 83 | uint8_t *p = _arg_ptr; 84 | while (l--) 85 | *data++ = *p++; 86 | 87 | _arg_ptr += len + pad; 88 | return len; 89 | } 90 | 91 | /*! popChar(char* buffer) 92 | @brief Extract a character from the response packet 93 | @param buffer 94 | Pointer to buffer for the character 95 | @par Example 96 | @code 97 | no example code yet 98 | @endcode 99 | */ 100 | void ELClientResponse::popChar(char* buffer) { 101 | uint16_t len = *(uint16_t*)_arg_ptr; 102 | uint16_t pad = (4-((len+2)&3))&3; // pad to next multiple of 4, including length 103 | _arg_ptr += 2; 104 | _arg_num++; 105 | 106 | uint8_t i; 107 | for (i = 0; i < len; i++) { 108 | buffer[i] = (char)*_arg_ptr++; 109 | } 110 | buffer[i] = '\0'; 111 | 112 | _arg_ptr += pad; 113 | } 114 | 115 | /*! popString() 116 | @brief Extract a string from the response packet 117 | @return String 118 | String extracted from the response packet 119 | @par Example 120 | @code 121 | no example code yet 122 | @endcode 123 | */ 124 | String ELClientResponse::popString() { 125 | String ret; 126 | uint16_t len = *(uint16_t*)_arg_ptr; 127 | uint16_t pad = (4-((len+2)&3))&3; // pad to next multiple of 4, including length 128 | _arg_ptr += 2; 129 | _arg_num++; 130 | 131 | while (len--) 132 | ret += (char)*_arg_ptr++; 133 | 134 | _arg_ptr += pad; 135 | return ret; 136 | } 137 | 138 | /*! popString(String* data) 139 | @brief Extract the pointer to a string from the response packet 140 | @param data 141 | Pointer to be set to the string in the response packet 142 | @par Example 143 | @code 144 | no example code yet 145 | @endcode 146 | */ 147 | void ELClientResponse::popString(String* data) { 148 | uint16_t len = *(uint16_t*)_arg_ptr; 149 | uint16_t pad = (4-((len+2)&3))&3; // pad to next multiple of 4, including length 150 | _arg_ptr += 2; 151 | _arg_num++; 152 | 153 | while (len--) 154 | data->concat((char)*_arg_ptr++); 155 | 156 | _arg_ptr += pad; 157 | } 158 | -------------------------------------------------------------------------------- /ELClient/ELClientResponse.h: -------------------------------------------------------------------------------- 1 | /*! \file ELClientResponse.h 2 | \brief Definitions for ELClientResponse 3 | */ 4 | #ifndef _EL_CLIENT_RESPONSE_H_ 5 | #define _EL_CLIENT_RESPONSE_H_ 6 | 7 | #if _MSC_VER 8 | #define PACKED 9 | #else 10 | #define PACKED __attribute__ ((__packed__)) 11 | #endif 12 | 13 | #include 14 | 15 | #define VARIABLE_ARG_NUM 255 16 | 17 | typedef struct PACKED { 18 | uint16_t cmd; /**< Command to execute */ 19 | uint16_t argc; /**< Number of arguments */ 20 | uint32_t value; /**< Callback to invoke, NULL if none; or response value */ 21 | uint8_t args[0]; /**< Arguments */ 22 | } ELClientPacket; /**< Packet structure */ 23 | 24 | // ELClientResponse is a parser for responses. The constructor initializes the parser based on 25 | // a packet and the various pop functions consume one response argument at a time. 26 | class ELClientResponse { 27 | public: 28 | // Create a response from a packet, this is done internally in ELClient 29 | ELClientResponse(ELClientPacket* packet); 30 | ELClientResponse(void *packet); 31 | 32 | // Accessors to the response fields 33 | uint16_t argc() { return _cmd->argc; } /**< Get number of arguments */ 34 | uint16_t cmd() { return _cmd->cmd; } /**< Get command */ 35 | uint32_t value() { return _cmd->value; } /**< Get returned value */ 36 | 37 | // Return the length of the next argument 38 | uint16_t argLen() { return *(uint16_t*)_arg_ptr; } /**< Get length of argument */ 39 | // Pop one argument from the response, returns the actual length. Returns -1 if there is 40 | // no arg left. 41 | int16_t popArg(void* data, uint16_t maxLen); 42 | // Pop one argument as a poiner from the response, returns the actual length. 43 | int16_t popArgPtr(void **data); 44 | // Pop one argument into a string buffer and append a null character. The buffer needs to 45 | // be large enough (argLen()+1) 46 | void popChar(char* buffer); 47 | // Pop one argument into a String buffer 48 | String popString(); 49 | // Pop one argument into a String buffer 50 | void popString(String* data); 51 | 52 | private: 53 | uint16_t _arg_num; /**< Argument number */ 54 | uint8_t* _arg_ptr; /**< Pointer to argument */ 55 | ELClientPacket* _cmd; /**< Pointer to packet */ 56 | }; 57 | 58 | #endif // _EL_CLIENT_RESPONSE_H_ 59 | -------------------------------------------------------------------------------- /ELClient/ELClientRest.cpp: -------------------------------------------------------------------------------- 1 | /*! \file ELClientRest.cpp 2 | \brief Constructor and functions for ELClientRest 3 | \author B. Runnels 4 | \author T. von Eicken 5 | \date 2016 6 | */ 7 | // Copyright (c) 2016 by B. Runnels and T. von Eicken 8 | 9 | #include "ELClientRest.h" 10 | 11 | typedef enum { 12 | HEADER_GENERIC = 0, /**< Header is generic */ 13 | HEADER_CONTENT_TYPE, /**< Header is content type */ 14 | HEADER_USER_AGENT /**< Header is user agent */ 15 | } HEADER_TYPE; /**< Enum of header types */ 16 | 17 | /*! ELClientRest(ELClient *e) 18 | @brief Constructor for ELClientRest 19 | @param e 20 | Pointer to ELClient structure 21 | @par Example 22 | @code 23 | ELClientRest(ELClient *e); 24 | @endcode 25 | */ 26 | ELClientRest::ELClientRest(ELClient *e) 27 | { 28 | _elc = e; 29 | remote_instance = -1; 30 | } 31 | 32 | /*! restCallback(void *res) 33 | @brief Function called by esp-link when data is sent, received or an error occured. 34 | @details The function is called by esp-link when data is sent or received from the remote server. 35 | @note Internal library function 36 | @param res 37 | Pointer to ELClientResponse structure 38 | @warning The content of the response structure is overwritten when the next package arrives! 39 | */ 40 | void ELClientRest::restCallback(void *res) 41 | { 42 | if (!res) return; 43 | 44 | ELClientResponse *resp = (ELClientResponse *)res; 45 | 46 | resp->popArg(&_status, sizeof(_status)); 47 | if (_elc->_debugEn) { 48 | _elc->_debug->print("REST code "); 49 | _elc->_debug->println(_status); 50 | } 51 | 52 | _len = resp->popArgPtr(&_data); 53 | } 54 | 55 | /*! begin(const char* host, uint16_t port, boolean security) 56 | @brief Initialize communication to a REST server 57 | @details Initialize communication to a remote server, 58 | this communicates with esp-link but does not open a connection to the remote server. 59 | @param host 60 | Host to be connected. Can be a URL or an IP address in the format of xxx.xxx.xxx.xxx . 61 | @param port 62 | Port to be used to send/receive packets. Port MUST NOT be 80, 23 or 2323, as these ports are already used by EL-CLIENT on the ESP8266 63 | @param security 64 | Flag if secure connection should be established 65 | @warning Port MUST NOT be 80, 23 or 2323, as these ports are already used by EL-CLIENT on the ESP8266. 66 | Max 4 connections are supported! 67 | @par Example 68 | @code 69 | int err = rest.begin("www.timeapi.org"); 70 | if (err != 0) 71 | { 72 | Serial.print("REST begin failed: "); 73 | Serial.println(err); 74 | while(1) ; 75 | } 76 | @endcode 77 | */ 78 | int ELClientRest::begin(const char* host, uint16_t port, boolean security) 79 | { 80 | uint8_t sec = !!security; 81 | restCb.attach(this, &ELClientRest::restCallback); 82 | 83 | _elc->Request(CMD_REST_SETUP, (uint32_t)&restCb, 3); 84 | _elc->Request(host, strlen(host)); 85 | _elc->Request(&port, 2); 86 | _elc->Request(&sec, 1); 87 | _elc->Request(); 88 | 89 | ELClientPacket *pkt = _elc->WaitReturn(); 90 | if (pkt && (int32_t)pkt->value >= 0) { 91 | remote_instance = pkt->value; 92 | return 0; 93 | } 94 | return (int)pkt->value; 95 | } 96 | 97 | /*! request(const char* path, const char* method, const char* data, int len) 98 | @brief Send request to REST server. 99 | @param path 100 | Path that extends the URL of the REST request (command or data for the REST server) 101 | @param method 102 | REST method, allowed values are "GET", "POST", "PUT" or "DELETE" 103 | @param data 104 | Pointer to data buffer 105 | @param len 106 | Size of data buffer 107 | @par Example 108 | @code 109 | no example code yet 110 | @endcode 111 | */ 112 | void ELClientRest::request(const char* path, const char* method, const char* data, int len) 113 | { 114 | _status = 0; 115 | if (remote_instance < 0) return; 116 | if (data != 0 && len > 0) _elc->Request(CMD_REST_REQUEST, remote_instance, 3); 117 | else _elc->Request(CMD_REST_REQUEST, remote_instance, 2); 118 | _elc->Request(method, strlen(method)); 119 | _elc->Request(path, strlen(path)); 120 | if (data != NULL && len > 0) { 121 | _elc->Request(data, len); 122 | } 123 | 124 | _elc->Request(); 125 | } 126 | 127 | /*! request(const char* path, const char* method, const char* data) 128 | @brief Send request to REST server. 129 | @details The data must be null-terminated. 130 | @param path 131 | Path that extends the URL of the REST request (command or data for the REST server) 132 | @param method 133 | REST method, allowed values are "GET", "POST", "PUT" or "DELETE" 134 | @param data 135 | Pointer to data buffer 136 | @par Example 137 | @code 138 | no example code yet 139 | @endcode 140 | */ 141 | void ELClientRest::request(const char* path, const char* method, const char* data) 142 | { 143 | request(path, method, data, strlen(data)); 144 | } 145 | 146 | /*! get(const char* path, const char* data) 147 | @brief Send GET request to REST server 148 | @warning The received data might not be null-terminated. 149 | @param path 150 | Path that extends the URL of the REST request (command or data for the REST server) 151 | @param data 152 | Pointer to data buffer 153 | @par Example 154 | @code 155 | // Request /utc/now from the previously set-up server 156 | rest.get("/utc/now"); 157 | @endcode 158 | */ 159 | void ELClientRest::get(const char* path, const char* data) { request(path, "GET", data); } 160 | 161 | /*! post(const char* path, const char* data) 162 | @brief Send POST request to REST server 163 | @warning The received data must be null-terminated. 164 | @param path 165 | Path that extends the URL of the REST request (command or data for the REST server) 166 | @param data 167 | Pointer to data buffer 168 | @par Example 169 | @code 170 | // Generate a fake value starting from 100 going up to 300 171 | solarValue = solarValue + 0.5; 172 | if (solarValue == 300) 173 | { 174 | solarValue = 100; 175 | } 176 | String solarValString = String(solarValue); 177 | const char *solarValChar = solarValString.c_str(); 178 | // Reserve a buffer for sending the data 179 | char path_data[BUFLEN]; 180 | // Copy the path and API key into the buffer 181 | sprintf(path_data, "%s", "/update?api_key="); 182 | sprintf(path_data + strlen(path_data), "%s", api_key); 183 | // Copy the field number and value into the buffer 184 | // If you have more than one field to update, 185 | // repeat and change field1 to field2, field3, ... 186 | sprintf(path_data + strlen(path_data), "%s", "&field1="); 187 | sprintf(path_data + strlen(path_data), "%s", solarValChar); 188 | // Send PUT request to thingspeak.com 189 | rest.post(path_data,""); 190 | @endcode 191 | */ 192 | void ELClientRest::post(const char* path, const char* data) { request(path, "POST", data); } 193 | 194 | /*! put(const char* path, const char* data) 195 | @brief Send PUT request to REST server 196 | @warning The received data must be null-terminated. 197 | @param path 198 | Path that extends the URL of the REST request (command or data for the REST server) 199 | @param data 200 | Pointer to data buffer 201 | @par Example 202 | @code 203 | no example code yet 204 | @endcode 205 | */ 206 | void ELClientRest::put(const char* path, const char* data) { request(path, "PUT", data); } 207 | 208 | /*! del(const char* path) 209 | @brief Send DELETE request to REST server 210 | @param path 211 | Path that extends the URL of the REST request (command or data for the REST server) 212 | @par Example 213 | @code 214 | no example code yet 215 | @endcode 216 | */ 217 | void ELClientRest::del(const char* path) { request(path, "DELETE", 0); } 218 | 219 | /*! setHeader(const char* value) 220 | @brief Set generic header content 221 | @details If no generic header is set, it defaults to an empty string 222 | @param value 223 | Header content 224 | @par Example 225 | @code 226 | no example code yet 227 | @endcode 228 | */ 229 | void ELClientRest::setHeader(const char* value) 230 | { 231 | uint8_t header_index = HEADER_GENERIC; 232 | _elc->Request(CMD_REST_SETHEADER, remote_instance, 2); 233 | _elc->Request(&header_index, 1); 234 | _elc->Request(value, strlen(value)); 235 | _elc->Request(); 236 | } 237 | 238 | /*! setContentType(const char* value) 239 | @brief Set content type of header 240 | @details If no content type is set, it defaults to "x-www-form-urlencoded" 241 | @param value 242 | Content type 243 | @par Example 244 | @code 245 | no example code yet 246 | @endcode 247 | */ 248 | void ELClientRest::setContentType(const char* value) 249 | { 250 | uint8_t header_index = HEADER_CONTENT_TYPE; 251 | _elc->Request(CMD_REST_SETHEADER, remote_instance, 2); 252 | _elc->Request(&header_index, 1); 253 | _elc->Request(value, strlen(value)); 254 | _elc->Request(); 255 | } 256 | 257 | /*! setUserAgent(const char* value) 258 | @brief Set user agent of header 259 | @details If no user agent is set, it defaults to "esp-link" 260 | @param value 261 | User agent 262 | @par Example 263 | @code 264 | no example code yet 265 | @endcode 266 | */ 267 | void ELClientRest::setUserAgent(const char* value) 268 | { 269 | uint8_t header_index = HEADER_USER_AGENT; 270 | _elc->Request(CMD_REST_SETHEADER, remote_instance, 2); 271 | _elc->Request(&header_index, 1); 272 | _elc->Request(value, strlen(value)); 273 | _elc->Request(); 274 | } 275 | 276 | /*! getResponse(char* data, uint16_t maxLen) 277 | @brief Retrieve response. 278 | @details Checks if a response from the remote server was received, 279 | returns the HTTP status code or 0 if no response (may need to wait longer) 280 | @param data 281 | Pointer to buffer for received packet 282 | @param maxLen 283 | Size of buffer for received packet. If the received packet is larger than the buffer, the received packet will be truncated. 284 | @return uint16_t 285 | Size of received packet or number of sent bytes or 0 if no response 286 | @par Example 287 | @code 288 | #define BUFLEN 266 289 | void loop() 290 | { 291 | // process any callbacks coming from esp_link 292 | esp.Process(); 293 | void loop() 294 | { 295 | // process any callbacks coming from esp_link 296 | esp.Process(); 297 | // if we're connected make an HTTP request 298 | if(wifiConnected) 299 | { 300 | // Request /utc/now from the previously set-up server 301 | rest.get("/utc/now"); 302 | char response[BUFLEN]; 303 | memset(response, 0, BUFLEN); 304 | uint16_t code = rest.waitResponse(response, BUFLEN); 305 | if(code == HTTP_STATUS_OK) 306 | { 307 | Serial.println("ARDUINO: GET successful:"); 308 | Serial.println(response); 309 | } 310 | else 311 | { 312 | Serial.print("ARDUINO: GET failed: "); 313 | Serial.println(code); 314 | } 315 | delay(1000); 316 | } 317 | } 318 | } 319 | @endcode 320 | */ 321 | uint16_t ELClientRest::getResponse(char* data, uint16_t maxLen) 322 | { 323 | if (_status == 0) return 0; 324 | memcpy(data, _data, _len>maxLen?maxLen:_len); 325 | int16_t s = _status; 326 | _status = 0; 327 | return s; 328 | } 329 | 330 | /*! waitResponse(char* data, uint16_t maxLen, uint32_t timeout) 331 | @brief Wait for the response 332 | @details Wait for the response from the remote server for time_out, 333 | returns the HTTP status code, 0 if no response (may need to wait longer) 334 | @warning Blocks the Arduino code for 5 seconds! not recommended to use. 335 | Received packet is NOT null-terminated 336 | @param data 337 | Pointer to buffer for received packet 338 | @param maxLen 339 | Size of buffer for received packet. If the received packet is larger than the buffer, the received packet will be truncated. 340 | @param timeout 341 | (optional) Timout in milli seconds to wait for a response, defaults to 5000ms 342 | @return uint16_t 343 | Size of received packet or number of sent bytes or 0 if no response 344 | @par Example 345 | @code 346 | #define BUFLEN 266 347 | void loop() 348 | { 349 | // process any callbacks coming from esp_link 350 | esp.Process(); 351 | // if we're connected make an HTTP request 352 | if(wifiConnected) 353 | { 354 | // Request /utc/now from the previously set-up server 355 | rest.get("/utc/now"); 356 | char response[BUFLEN]; 357 | memset(response, 0, BUFLEN); 358 | uint16_t code = rest.waitResponse(response, BUFLEN); 359 | if(code == HTTP_STATUS_OK) 360 | { 361 | Serial.println("ARDUINO: GET successful:"); 362 | Serial.println(response); 363 | } 364 | else 365 | { 366 | Serial.print("ARDUINO: GET failed: "); 367 | Serial.println(code); 368 | } 369 | delay(1000); 370 | } 371 | } 372 | @endcode 373 | */ 374 | uint16_t ELClientRest::waitResponse(char* data, uint16_t maxLen, uint32_t timeout) 375 | { 376 | uint32_t wait = millis(); 377 | while (_status == 0 && (millis() - wait < timeout)) { 378 | _elc->Process(); 379 | } 380 | return getResponse(data, maxLen); 381 | } 382 | -------------------------------------------------------------------------------- /ELClient/ELClientRest.h: -------------------------------------------------------------------------------- 1 | /*! \file ELClientRest.h 2 | \brief Definitions for ELClientRes 3 | \author B. Runnels 4 | \author T. von Eicken 5 | \date 2016 6 | */ 7 | // Copyright (c) 2016 by B. Runnels and T. von Eicken 8 | 9 | #ifndef _EL_CLIENT_REST_H_ 10 | #define _EL_CLIENT_REST_H_ 11 | 12 | #include 13 | #include "FP.h" 14 | #include "ELClient.h" 15 | 16 | // Default timeout for REST requests when waiting for a response 17 | #define DEFAULT_REST_TIMEOUT 5000 /**< Default timeout for REST requests when waiting for a response */ 18 | 19 | typedef enum { 20 | HTTP_STATUS_OK = 200 /**< HTTP status OK response. */ 21 | } HTTP_STATUS; 22 | 23 | // The ELClientRest class makes simple REST requests to a remote server. Each instance 24 | // is used to communicate with one server and multiple instances can be created to make 25 | // requests to multiple servers. 26 | // The ELClientRest class does not support concurrent requests to the same server because 27 | // only a single response can be recevied at a time and the responses of the two requests 28 | // may arrive out of order. 29 | // A major limitation of the REST class is that it does not store the response body. The 30 | // response status is saved in the class instance, so after a request completes and before 31 | // the next request is made a call to getResponse will return the status. However, only a pointer 32 | // to the response body is saved, which means that if any other message arrives and is 33 | // processed then the response body is overwritten by it. What this means is that if you 34 | // need the response body you best use waitResponse or ensure that any call to ELClient::process 35 | // is followed by a call to getResponse. Ideally someone improves this class to take a callback 36 | // into the user's sketch? 37 | // Another limitation is that the response body is 100 chars long at most, this is due to the 38 | // limitation of the SLIP protocol buffer available. 39 | class ELClientRest { 40 | public: 41 | ELClientRest(ELClient *e); 42 | 43 | // Initialize communication to a remote server, this communicates with esp-link but does not 44 | // open a connection to the remote server. Host may be a hostname or an IP address, 45 | // security causes HTTPS to be used (not yet supported). Returns 0 if the set-up is 46 | // successful, returns a negative error code if it failed. 47 | int begin(const char* host, uint16_t port=80, boolean security=false); 48 | 49 | // Make a request to the remote server. The data must be null-terminated 50 | void request(const char* path, const char* method, const char* data=NULL); 51 | 52 | // Make a request to the remote server. 53 | void request(const char* path, const char* method, const char* data, int len); 54 | 55 | // Make a GET request to the remote server with NULL-terminated data 56 | void get(const char* path, const char* data=NULL); 57 | 58 | // Make a POST request to the remote server with NULL-terminated data 59 | void post(const char* path, const char* data); 60 | 61 | // Make a PUT request to the remote server with NULL-terminated data 62 | void put(const char* path, const char* data); 63 | 64 | // Make a DELETE request to the remote server 65 | void del(const char* path); 66 | 67 | // Retrieve the response from the remote server, returns the HTTP status code, 0 if no 68 | // response (may need to wait longer) 69 | uint16_t getResponse(char* data, uint16_t maxLen); 70 | 71 | // Wait for the response from the remote server, returns the HTTP status code, 0 if no 72 | // response (timeout occurred). This is not recommended except for quick demos, use 73 | // getResponse periodically instead. 74 | uint16_t waitResponse(char* data, uint16_t maxLen, uint32_t timeout=DEFAULT_REST_TIMEOUT); 75 | 76 | // Set the user-agent for all subsequent requests 77 | void setUserAgent(const char* value); 78 | 79 | // Set the Content-Type Header for all subsequent requests 80 | void setContentType(const char* value); 81 | 82 | // Set a custom header for all subsequent requests 83 | void setHeader(const char* value); 84 | 85 | private: 86 | int32_t remote_instance; /**< Connection number, value can be 0 to 3 */ 87 | ELClient *_elc; /**< ELClient instance */ 88 | void restCallback(void* resp); 89 | FP restCb; /**< Pointer to external callback function */ 90 | 91 | int16_t _status; /**< Connection status */ 92 | uint16_t _len; /**< Number of sent/received bytes */ 93 | void *_data; /**< Buffer for received data */ 94 | 95 | 96 | }; 97 | #endif // _EL_CLIENT_REST_H_ 98 | -------------------------------------------------------------------------------- /ELClient/ELClientSocket.cpp: -------------------------------------------------------------------------------- 1 | /*! \file ELClientSocket.cpp 2 | \brief Constructor and functions for ELClientSocket 3 | \author BeeGee 4 | \version 1.0 5 | \date 2016 6 | \copyright GNU Public License. 7 | \warning Needs ESP-LINK V2.4 8 | */ 9 | 10 | #include "ELClientSocket.h" 11 | 12 | /*! ELClientSocket(ELClient *e) 13 | @brief Class to send/receive data 14 | @details The ELClientSocket class sends data over a Socket to a remote server or acts as a TCP socket server. 15 | Each instance is used to communicate with one server and multiple instances can be created to send to multiple servers. 16 | The ELClientSocket class does not support concurrent requests to the same server because only a single response can be recevied at a time and the responses of the two requests may arrive out of order. 17 | @param e 18 | Pointer to ELClient. Check ELClient API documentation. 19 | @par Example 20 | @code 21 | ELClientSocket socket(&esp); 22 | @endcode 23 | */ 24 | ELClientSocket::ELClientSocket(ELClient *e) 25 | { 26 | _elc = e; 27 | remote_instance = -1; 28 | } 29 | 30 | /*! socketCallback(void *res) 31 | @brief Callback function when data is sent, received or an error occured. 32 | @details The function is called when data is sent or received from the remote server. 33 | If a user callback function (userCb) was defined it is called and the response is sent as an argument. 34 | @note Internal library function 35 | @param res 36 | Pointer to ELClientResponse structure 37 | @warning The content of the response structure is overwritten when the next package arrives! 38 | */ 39 | void ELClientSocket::socketCallback(void *res) 40 | { 41 | if (!res) return; 42 | 43 | ELClientResponse *resp = (ELClientResponse *)res; 44 | 45 | #ifdef DEBUG_EN 46 | int argNum = resp->argc(); 47 | Serial.println("Number of arguments: "+String(argNum)); 48 | uint16_t _cmd = resp->cmd(); 49 | Serial.println("Command: "+String(_cmd)); 50 | uint16_t _value = resp->value(); 51 | Serial.println("Value: "+String(_value)); 52 | #endif 53 | 54 | resp->popArg(&_resp_type, 1); 55 | resp->popArg(&_client_num, 1); 56 | resp->popArg(&_len, 2); 57 | #ifdef DEBUG_EN 58 | Serial.print("Type: "); 59 | Serial.print(_resp_type); 60 | Serial.print(" client: "); 61 | Serial.print(_client_num); 62 | Serial.print(" size: "+String(_len)); 63 | #endif 64 | if (_resp_type == 1) 65 | { 66 | #ifdef DEBUG_EN 67 | int argLen = resp->argLen(); 68 | Serial.print(" data length: "+String(argLen)); 69 | #endif 70 | resp->popArgPtr((void**)&_data); 71 | #ifdef DEBUG_EN 72 | _data[_len] = '\0'; 73 | Serial.print(" data: "+String(_data)); 74 | #endif 75 | } 76 | #ifdef DEBUG_EN 77 | Serial.println(""); 78 | #endif 79 | _status = 1; 80 | if (_hasUserCb) 81 | { 82 | _userCb(_resp_type, _client_num, _len, _data); 83 | } 84 | } 85 | 86 | /*! begin(const char* host, uint16_t port, uint8_t sock_mode, void (*userCb)(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data)) 87 | @brief Initialize communication to a remote server 88 | @details Initialize communication to a remote server, 89 | this communicates with esp-link but does not open a connection to the remote server. 90 | @param host 91 | Host to be connected. Can be a URL or an IP address in the format of xxx.xxx.xxx.xxx . 92 | @param port 93 | Port to be used to send/receive packets. Port MUST NOT be 80, 23 or 2323, as these ports are already used by EL-CLIENT on the ESP8266 94 | @param sock_mode 95 | Set socket mode to SOCKET_TCP_CLIENT, SOCKET_TCP_CLIENT_LISTEN, SOCKET_TCP_SERVER or SOCKET_UDP 96 | @param (*userCb)(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data) 97 | (optional) Pointer to callback function that is called if data after data has been sent, received or if an error occured 98 | @warning Port MUST NOT be 80, 23 or 2323, as these ports are already used by EL-CLIENT on the ESP8266. 99 | Max 4 connections are supported! 100 | @par Example1 101 | @code 102 | // Setup a simple client to send data and disconnect after data was sent 103 | socketConnNum = socket.begin(socketServer, socketPort, SOCKET_TCP_CLIENT, socketCb); 104 | @endcode 105 | @par Example2 106 | @code 107 | // Setup a client to send data and wait for response from remote server 108 | socketConnNum = socket.begin(socketServer, socketPort, SOCKET_TCP_CLIENT_LISTEN, socketCb); 109 | @endcode 110 | @par Example3 111 | @code 112 | // Setup a TCP server and wait for a client to connect 113 | socketConnNum = socket.begin(socketServer, socketPort, SOCKET_TCP_SERVER, socketCb); 114 | @endcode 115 | @par Example3 116 | @code 117 | // Setup a TCP server and wait for a client to connect 118 | socketConnNum = socket.begin(socketServer, socketPort, SOCKET_UDP, socketCb); 119 | @endcode 120 | */ 121 | int ELClientSocket::begin(const char* host, uint16_t port, uint8_t sock_mode, void (*userCb)(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data)) 122 | { 123 | if (userCb != 0) 124 | { 125 | _userCb = userCb; 126 | _hasUserCb = true; 127 | } 128 | 129 | socketCb.attach(this, &ELClientSocket::socketCallback); 130 | 131 | _elc->Request(CMD_SOCKET_SETUP, (uint32_t)&socketCb, 3); 132 | _elc->Request(host, strlen(host)); 133 | _elc->Request(&port, 2); 134 | _elc->Request(&sock_mode, 1); 135 | _elc->Request(); 136 | 137 | ELClientPacket *pkt = _elc->WaitReturn(); 138 | 139 | if (pkt && (int32_t)pkt->value >= 0) 140 | { 141 | remote_instance = pkt->value; 142 | // return 0; 143 | } 144 | return (int)pkt->value; 145 | } 146 | 147 | /*! send(const char* data, int len) 148 | @brief Send data to the remote server. 149 | @param data 150 | Pointer to SOCKET packet 151 | @param len 152 | Length of SOCKET packet 153 | @par Example 154 | @code 155 | Serial.println("Sending JSON array to SOCKET server"); 156 | char socketPacket = "{"device":"spm","s":622.02,"c":-165.86}" 157 | socket.send(socketPacket, 39); 158 | @endcode 159 | */ 160 | void ELClientSocket::send(const char* data, int len) 161 | { 162 | _status = 0; 163 | if (remote_instance < 0) return; 164 | _elc->Request(CMD_SOCKET_SEND, remote_instance, 2); 165 | _elc->Request(data, strlen(data)); 166 | if (data != NULL && len > 0) 167 | { 168 | _elc->Request(data, len); 169 | } 170 | 171 | _elc->Request(); 172 | } 173 | 174 | /*! send(const char* data) 175 | @brief Send null-terminated data to the remote server. 176 | @param data 177 | Pointer to SOCKET packet, must be null-terminated 178 | @par Example 179 | @code 180 | Serial.println("Sending text message to SOCKET server"); 181 | socket.send("Message from your Arduino Uno WiFi over TCP socket"); 182 | @endcode 183 | */ 184 | void ELClientSocket::send(const char* data) 185 | { 186 | send(data, strlen(data)); 187 | } 188 | 189 | /*! getResponse(uint8_t *resp_type, uint8_t *client_num, char* data, uint16_t maxLen) 190 | @brief Retrieve response. 191 | @details Check if a response from the remote server was received, 192 | returns the number of send or received bytes, 193 | 0 if no response (may need to wait longer) 194 | @param resp_type 195 | Pointer to response type. Is USERCB_SENT if packet was sent or USERCB_RECV if a packet was received. 196 | @param client_num 197 | Pointer to connection number. Can be used to distinguish between different socket clients. 198 | @param data 199 | Pointer to buffer for received packet 200 | @param maxLen 201 | Size of buffer for received packet. If the received packet is larger than the buffer, the received packet will be truncated. 202 | @return uint16_t 203 | Size of received packet or number of sent bytes or 0 if no response 204 | @par Example 205 | @code 206 | #define BUFLEN 266 207 | void loop() 208 | { 209 | // process any callbacks coming from esp_link 210 | esp.Process(); 211 | // Check if we received a packet or if the last send request has finished 212 | char response[BUFLEN]; 213 | memset(response, 0, BUFLEN); 214 | uint8_t resp_type; 215 | uint8_t client_num; 216 | uint16_t len = socket.getResponse(&resp_type, &client_num, response, BUFLEN); 217 | if (len != 0) 218 | { 219 | if (resp_type == USERCB_SENT) 220 | { 221 | Serial.println("Sent "+String(len)+" bytes"); 222 | } 223 | else 224 | { 225 | Serial.print("Received packet: "); 226 | for (int i=0; imaxLen?maxLen:_len); 240 | *resp_type = _resp_type; 241 | *client_num = _client_num; 242 | _status = 0; 243 | return _len; 244 | } 245 | 246 | /*! waitResponse(uint8_t *resp_type, uint8_t *client_num, char* data, uint16_t maxLen, uint32_t timeout) 247 | @brief Wait for the response 248 | @details Checks if a response from the remote server has arrived for timeout seconds, 249 | returns the number of send or received bytes, 250 | 0 if no response (may need to wait longer) 251 | @warning Blocks the Arduino code for 5 seconds! not recommended to use. Use callback function instead! 252 | Received packet is NOT null-terminated 253 | @param resp_type 254 | Pointer to response type. Is USERCB_SENT if packet was sent or USERCB_RECV if a packet was received. 255 | @param client_num 256 | Pointer to connection number. Can be used to distinguish between different socket clients. 257 | @param data 258 | Pointer to buffer for received packet 259 | @param maxLen 260 | Size of buffer for received packet. If the received packet is larger than the buffer, the received packet will be truncated. 261 | @param timeout 262 | (optional) Timout in milli seconds to wait for a response, defaults to 5000ms 263 | @return uint16_t 264 | Size of received packet or number of sent bytes or 0 if no response 265 | @par Example 266 | @code 267 | #define BUFLEN 266 268 | bool haveRemoteResponse = true; 269 | void loop() 270 | { 271 | // process any callbacks coming from esp_link 272 | esp.Process(); 273 | if (haveRemoteResponse) // If last packet was sent, send a new one 274 | { 275 | Serial.println("Sending JSON array to TCP server"); 276 | char socketPacket = "{"device":"spm","s":622.02,"c":-165.86}" 277 | socket.send(socketPacket, 39); 278 | haveRemoteResponse = false; 279 | } 280 | // Check if we received a packet or if the last send request has finished 281 | char response[BUFLEN]; 282 | memset(response, 0, BUFLEN); 283 | uint8_t resp_type; 284 | uint8_t client_num; 285 | uint16_t len = socket.waitResponse(&resp_type, &client_num, response, BUFLEN); 286 | if (len != 0) 287 | { 288 | if (resp_type == USERCB_SENT) 289 | { 290 | Serial.println("Sent "+String(len)+" bytes"); 291 | } 292 | else 293 | { 294 | Serial.print("Received packet: "); 295 | for (int i=0; iProcess(); 313 | } else { 314 | return -3; 315 | } 316 | } 317 | return getResponse(resp_type, client_num, data, maxLen); 318 | } 319 | -------------------------------------------------------------------------------- /ELClient/ELClientSocket.h: -------------------------------------------------------------------------------- 1 | /*! \file ELClientSocket.h 2 | \brief Definitions for ELClientSocket 3 | \author BeeGee 4 | \version 1.0 5 | \date 2016 6 | \copyright GNU Public License. 7 | \warning Needs ESP-LINK V2.4 8 | */ 9 | 10 | #ifndef _EL_CLIENT_SOCKET_H_ 11 | #define _EL_CLIENT_SOCKET_H_ 12 | 13 | #include 14 | #include "FP.h" 15 | #include "ELClient.h" 16 | 17 | #define DEFAULT_SOCKET_TIMEOUT 5000 /**< Default timeout for SOCKET requests when waiting for a response */ 18 | 19 | #define USERCB_SENT 0 /**< Type of callback from ELClient. SOCKET packet has been sent */ 20 | #define USERCB_RECV 1 /**< Type of callback from ELClient. SOCKET packet has been received */ 21 | #define USERCB_RECO 2 /**< Type of callback from ELClient. SOCKET connection error */ 22 | #define USERCB_CONN 3 /**< Type of callback from ELClient. SOCKET socket connected or disconnected */ 23 | 24 | // Socket mode definitions 25 | #define SOCKET_TCP_CLIENT 0 /**< TCP socket client for sending only, doesn't wait for response from server */ 26 | #define SOCKET_TCP_CLIENT_LISTEN 1 /**< TCP socket client, waits for response from server after sending */ 27 | #define SOCKET_TCP_SERVER 2 /**< TCP socket server */ 28 | #define SOCKET_UDP 3 /**< UDP socket for sending and receiving UDP packets */ 29 | 30 | // Enable/disable debug output. If defined enables the debug output on Serial port 31 | //#define DEBUG_EN /**< Enable/disable debug output */ 32 | 33 | // The ELClientSocket class sends data over a simple Socket connection to a remote server. Each instance 34 | // is used to communicate with one server and multiple instances can be created to send 35 | // to multiple servers. 36 | // The ELClientSocket class does not support concurrent requests to the same server because 37 | // only a single response can be recevied at a time and the responses of the two requests 38 | // may arrive out of order. 39 | // A major limitation of the Socket class is that it does not wait for the response data. 40 | class ELClientSocket { 41 | public: 42 | ELClientSocket(ELClient *e); 43 | 44 | // Initialize communication to a remote server, this communicates with esp-link but does not 45 | // open a connection to the remote server. Host may be a hostname or an IP address. 46 | // Port needs to be defined different from usual HTTP/HTTPS/FTP/SSH ports 47 | // sock_mode defines whether the socket act as a client (with or without receiver) or as a server 48 | // Returns 0 if the set-up is 49 | // successful, returns a negative error code if it failed. 50 | // Optional a pointer to a callback function be added. The callback function will be called after data is sent out, 51 | // after data was received or when an error occured. See example code port how to use it. 52 | int begin(const char* host, uint16_t port, uint8_t sock_mode, void (*userCb)(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data)=0); 53 | 54 | // Send data to the remote server. The data must be null-terminated 55 | void send(const char* data); 56 | 57 | // Send data to the remote server. 58 | void send(const char* data, int len); 59 | 60 | // Retrieve the response from the remote server, returns the number of send or received bytes, 0 if no 61 | // response (may need to wait longer) 62 | // !!! UDP doesn't check if the data was received or if the receiver IP/socket is available !!! You need to implement your own 63 | // error control! 64 | uint16_t getResponse(uint8_t *resp_type, uint8_t *client_num, char* data, uint16_t maxLen); 65 | 66 | // Wait for the response from the remote server, returns the length of received data or 0 if no 67 | // response (timeout occurred) 68 | // Blocks the Arduino code for 5 seconds! not recommended to use. See code examples how to use the callback function instead 69 | uint16_t waitResponse(uint8_t *resp_type, uint8_t *client_num, char* data, uint16_t maxLen, uint32_t timeout=DEFAULT_SOCKET_TIMEOUT); 70 | 71 | int32_t remote_instance; /**< Connection number, value can be 0 to 3 */ 72 | 73 | private: 74 | ELClient *_elc; /**< ELClient instance */ 75 | void socketCallback(void* resp); 76 | FP socketCb; /**< Pointer to external callback function */ 77 | 78 | /*! void (* _userCallback)(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data) 79 | @brief Callback function when data is sent or received 80 | @details This function is called by ELClient library when a packet was sent, a packet was received or an error occured 81 | The function is user specific and therefor included in the program code, not in the library 82 | This function does not block the Arduino code execution 83 | @param resp_type 84 | Response type. Is USERCB_SENT if packet was sent, USERCB_RECV if a packet was received, USERCB_RECO if a connection error occured or USERCB_CONN on a connect or disconnect event 85 | @param client_num 86 | Connection number. Can be used to distinguish between different UDP clients. 87 | @param len 88 | Size of received packet or number of sent bytes. 89 | @param data 90 | Buffer with the received packet. 91 | @note 92 | The function is user specific and therefor included in the program code, not in the library 93 | @par Example 94 | @code 95 | void socketCb(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data) 96 | { 97 | Serial.println("socketCb connection #"+String(client_num)); 98 | if (resp_type == USERCB_SENT) 99 | { 100 | Serial.println("\tSent " + String(len) + " bytes over client#" + String(client_num)); 101 | } 102 | else if (resp_type == USERCB_RECV) 103 | { 104 | char recvData[len+1]; // Prepare buffer for the received data 105 | memcpy(recvData, data, len); // Copy received data into the buffer 106 | recvData[len] = '\0'; // Terminate the buffer with 0 for proper printout! 107 | Serial.println("\tReceived " + String(len) + " bytes over the server on connection #" + String(client_num)); 108 | Serial.println("\tReceived: " + String(recvData)); 109 | char respData[len+11]; // Prepare buffer for the response data 110 | char *respHdr = "Received: "; 111 | memcpy (respData, respHdr, 10); 112 | memcpy(&respData[10], recvData, len); // Copy received data into the buffer 113 | respData[len+10] = '\0'; 114 | Serial.println("\tSend response: " + String(respData)); 115 | socket.send(respData); 116 | } 117 | else if (resp_type == USERCB_RECO) 118 | { 119 | Serial.println("Connection problem: "+String(len)); 120 | } 121 | else if (resp_type == USERCB_CONN) 122 | { 123 | if (len == 0) 124 | { 125 | Serial.println("\tDisconnected"); 126 | } 127 | else 128 | { 129 | Serial.println("\tConnected"); 130 | } 131 | } 132 | else 133 | { 134 | Serial.println("Received invalid response type"); 135 | } 136 | } 137 | @endcode 138 | */ 139 | typedef void (* _userCallback)(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data); 140 | _userCallback _userCb; /**< Pointer to internal callback function */ 141 | 142 | bool _hasUserCb = false; /**< Flag for user callback, true if user callback has been set */ 143 | int16_t _status; /**< Connection status */ 144 | uint16_t _len; /**< Number of sent/received bytes */ 145 | char *_data; /**< Buffer for received data */ 146 | uint8_t _resp_type; /**< Response type: 0 = send, 1 = receive; 2 = reset connection, 3 = connection */ 147 | uint8_t _client_num; /**< Connection number, value can be 0 to 3 */ 148 | }; 149 | #endif // _EL_CLIENT_SOCKET_H_ 150 | -------------------------------------------------------------------------------- /ELClient/ELClientWebServer.h: -------------------------------------------------------------------------------- 1 | /*! \file ELClientWebServer.h 2 | \brief Definitions for ELClientWebServer 3 | \author Cs. Karai 4 | \author T. von Eicken 5 | \date 2016 6 | */ 7 | // Copyright (c) 2016 by Cs. Karai and T. von Eicken 8 | 9 | #ifndef _EL_CLIENT_WEB_SERVER_H_ 10 | #define _EL_CLIENT_WEB_SERVER_H_ 11 | 12 | #include 13 | #include "ELClient.h" 14 | #include "FP.h" 15 | 16 | /** Web Server URL handler structure. */ 17 | typedef struct URL_HANDLER 18 | { 19 | 20 | String URL; ///< the URL to handle 21 | 22 | /*! loadCb() 23 | @brief Callback for HTML page loading 24 | @details This callback is called when browser loads a custom page for the first time. 25 | The callback should populate all the fields that are required for displaying the page. 26 | @param url 27 | The URL of the page to load. 28 | @par Example 29 | @code 30 | void loadCb(char * url) 31 | { 32 | webServer.setArgString(F("field1"), F("value")); 33 | webServer.setArgInt(F("field2"), 123); 34 | webServer.setArgFloat(F("field3"), 12.3); 35 | } 36 | @endcode 37 | */ 38 | FP loadCb; 39 | 40 | /*! refreshCb() 41 | @brief Callback for HTML page refresh 42 | @details This callback is called when browser refreshes a page. The callback should populate 43 | all the fields that are required for displaying changes on the page. 44 | @param url 45 | The URL of the page to load. 46 | @par Example 47 | @code 48 | void refreshCb(char * url) 49 | { 50 | webServer.setArgString(F("field1"), F("changed_value")); 51 | webServer.setArgInt(F("field2"), 543); 52 | webServer.setArgFloat(F("field3"), 54.3); 53 | } 54 | @endcode 55 | */ 56 | FP refreshCb; 57 | 58 | /*! buttonCb() 59 | @brief callback for setting a field from a HTML form 60 | @details This callback is called when a HTML form is submitted. The callback should save 61 | field changes. After processing the callback, a page refresh will also be initiated to 62 | reflect the changes. 63 | 64 | The size of the receive buffer on ELClient is 128 bytes which can be small for receiving 65 | a large form. When the data exceeds 128 bytes, Esp-Link segments the query into smaller 66 | parts. If the callback is slow, it's possible that the UART buffer overruns while receiving 67 | the next packet causing data loss. The callback has 5ms to process the request if data comes 68 | at 115200 baud. 69 | 70 | If debugging is enabled, data loss is very likely to happen because of packet logging. 71 | @warning Write this routine to be as fast as possible and turn off debugging for receiving 72 | large forms. 73 | 74 | @param field_id 75 | The ID of the field 76 | @par Example 77 | @code 78 | int32_t value; 79 | 80 | // this code should be fast 81 | void setFieldCb(char * field_id) 82 | { 83 | String id = field_id; 84 | 85 | if( id == F("my_field") ) 86 | { 87 | value = webServer.getArgInt(); 88 | } 89 | } 90 | @endcode 91 | */ 92 | FP setFieldCb; 93 | 94 | /*! buttonCb() 95 | @brief callback for a HTML button press 96 | @details This callback is called when user presses a HTML button. After processing this 97 | callback, a page refresh will also be called to reflect the changes. 98 | @param button_id 99 | The ID of the button 100 | @par Example 101 | @code 102 | void buttonCb(char * button_id) 103 | { 104 | String id = button_id; 105 | 106 | if( id == F("my_button") ) 107 | { 108 | Serial.println("My button was pressed"); 109 | } 110 | } 111 | @endcode 112 | */ 113 | FP buttonCb; 114 | struct URL_HANDLER * next; ///< next handler 115 | } URLHandler; 116 | 117 | // This class implements functions for the web-server 118 | class ELClientWebServer { 119 | public: 120 | // Initialize with an ELClient object 121 | ELClientWebServer(ELClient* elc); 122 | 123 | // initializes the web-server 124 | void setup(); 125 | 126 | // creates a URL handler 127 | URLHandler * createURLHandler(const char * URL); 128 | // creates a URL handler from flash 129 | URLHandler * createURLHandler(const __FlashStringHelper * URL); 130 | // creates a URL handler from String 131 | URLHandler * createURLHandler(const String &s); 132 | 133 | // destroys a URL handler 134 | void destroyURLHandler(URLHandler * handler); 135 | 136 | // sets int value of a HTML field 137 | void setArgInt(const char * name, int32_t value); 138 | // sets int value of a HTML field 139 | void setArgInt(const __FlashStringHelper * name, int32_t value); 140 | // sets JSON value of a HTML field 141 | void setArgJson(const char * name, const char * value); 142 | // sets JSON value of a HTML field 143 | void setArgJson(const __FlashStringHelper * name, const char * value); 144 | // sets JSON value of a HTML field 145 | void setArgJson(const __FlashStringHelper * name, const __FlashStringHelper * value); 146 | // sets string value of a HTML field 147 | void setArgString(const char * name, const char * value); 148 | // sets string value of a HTML field 149 | void setArgString(const __FlashStringHelper * name, const char * value); 150 | // sets string value of a HTML field 151 | void setArgString(const __FlashStringHelper * name, const __FlashStringHelper * value); 152 | // sets boolean value of a HTML field 153 | void setArgBoolean(const char * name, uint8_t value); 154 | // sets boolean value of a HTML field 155 | void setArgBoolean(const __FlashStringHelper * name, uint8_t value); 156 | // sets null value of a HTML field 157 | void setArgNull(const char * name); 158 | // sets null value of a HTML field 159 | void setArgNull(const __FlashStringHelper * name); 160 | // sets float value of a HTML field 161 | void setArgFloat(const char * name, float f); 162 | // sets float value of a HTML field 163 | void setArgFloat(const __FlashStringHelper * name, float f); 164 | 165 | 166 | // setFieldCb: gets the value of the field as integer 167 | int32_t getArgInt(); 168 | // setFieldCb: gets the value of the field as string 169 | char * getArgString(); 170 | // setFieldCb: gets the value of the field as boolean 171 | uint8_t getArgBoolean(); 172 | // setFieldCb: gets the value of the field as float 173 | float getArgFloat(); 174 | 175 | 176 | /*! ELClientWebServer::getInstance() 177 | @brief Returns the singleton web-server instance. 178 | @details Web-Server is a singleton object. This object can be read by calling ELClientWebServer::getInstance(). 179 | @returns 180 | The singleton web-server instance. 181 | @par Example code 182 | @code 183 | ELClientWebServer *webServer = ELClientWebServer::getInstance(); 184 | @endcode 185 | */ 186 | static ELClientWebServer * getInstance() { return instance; } 187 | 188 | private: 189 | ELClient* _elc; 190 | 191 | static void webServerPacketHandler(void * packet); 192 | void processResponse(ELClientResponse *packet); // internal 193 | static ELClientWebServer * instance; 194 | 195 | uint8_t remote_ip[4]; 196 | uint16_t remote_port; 197 | 198 | struct URL_HANDLER * handlers; 199 | char * arg_ptr; 200 | FP webServerCb; 201 | }; 202 | 203 | #endif // _EL_CLIENT_WEB_SERVER_H_ 204 | -------------------------------------------------------------------------------- /ELClient/FP.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file FP.h 3 | * @brief Core Utility - Templated Function Pointer Class 4 | * @author sam grove 5 | * @version 1.0 6 | * @see 7 | * 8 | * Copyright (c) 2013 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | */ 22 | 23 | #ifndef FP_H 24 | #define FP_H 25 | 26 | /** Example using the FP Class with global functions 27 | * @code 28 | * #include "mbed.h" 29 | * #include "FP.h" 30 | * 31 | * FPfp; 32 | * DigitalOut myled(LED1); 33 | * 34 | * void handler(bool value) 35 | * { 36 | * myled = value; 37 | * return; 38 | * } 39 | * 40 | * int main() 41 | * { 42 | * fp.attach(&handler); 43 | * 44 | * while(1) 45 | * { 46 | * fp(1); 47 | * wait(0.2); 48 | * fp(0); 49 | * wait(0.2); 50 | * } 51 | * } 52 | * @endcode 53 | */ 54 | 55 | /** Example using the FP Class with different class member functions 56 | * @code 57 | * #include "mbed.h" 58 | * #include "FP.h" 59 | * 60 | * FPfp; 61 | * DigitalOut myled(LED4); 62 | * 63 | * class Wrapper 64 | * { 65 | * public: 66 | * Wrapper(){} 67 | * 68 | * void handler(bool value) 69 | * { 70 | * myled = value; 71 | * return; 72 | * } 73 | * }; 74 | * 75 | * int main() 76 | * { 77 | * Wrapper wrapped; 78 | * fp.attach(&wrapped, &Wrapper::handler); 79 | * 80 | * while(1) 81 | * { 82 | * fp(1); 83 | * wait(0.2); 84 | * fp(0); 85 | * wait(0.2); 86 | * } 87 | * } 88 | * @endcode 89 | */ 90 | 91 | /** Example using the FP Class with member FP and member function 92 | * @code 93 | * #include "mbed.h" 94 | * #include "FP.h" 95 | * 96 | * DigitalOut myled(LED2); 97 | * 98 | * class Wrapper 99 | * { 100 | * public: 101 | * Wrapper() 102 | * { 103 | * fp.attach(this, &Wrapper::handler); 104 | * } 105 | * 106 | * void handler(bool value) 107 | * { 108 | * myled = value; 109 | * return; 110 | * } 111 | * 112 | * FPfp; 113 | * }; 114 | * 115 | * int main() 116 | * { 117 | * Wrapper wrapped; 118 | * 119 | * while(1) 120 | * { 121 | * wrapped.fp(1); 122 | * wait(0.2); 123 | * wrapped.fp(0); 124 | * wait(0.2); 125 | * } 126 | * } 127 | * @endcode 128 | */ 129 | 130 | /** 131 | * @class FP 132 | * @brief API abstraction for a Function Pointers 133 | */ 134 | template 135 | class FP 136 | { 137 | public: 138 | /** Create the FP object 139 | */ 140 | FP(); 141 | 142 | /** Add a callback function to the class 143 | * @param item - Address of the initialized class 144 | * @param method - Address of the member function (dont forget the scope that the function is defined in) 145 | */ 146 | template 147 | void attach(T *item, retT (T::*method)(argT)) 148 | { 149 | obj_callback = (FPtrDummy *)(item); 150 | method_callback = (retT (FPtrDummy::*)(argT))(method); 151 | return; 152 | } 153 | 154 | /** Add a callback function to the class 155 | * @param function - The address of a globally defined function 156 | */ 157 | void attach(retT (*function)(argT)); 158 | 159 | /** Invoke the function attached to the class 160 | * @param arg - An argument that is passed into the function handler that is called 161 | * @return The return from the function hanlder called by this class 162 | */ 163 | retT operator()(argT arg) const; 164 | 165 | bool attached(); 166 | 167 | void detach(); 168 | 169 | private: 170 | 171 | // empty type used for casting 172 | class FPtrDummy; 173 | 174 | FPtrDummy *obj_callback; 175 | 176 | /** 177 | * @union Funciton 178 | * @brief Member or global callback function 179 | */ 180 | union 181 | { 182 | retT (*c_callback)(argT); /*!< Footprint for a global function */ 183 | retT (FPtrDummy::*method_callback)(argT); /*!< Footprint for a member function */ 184 | }; 185 | }; 186 | 187 | #endif 188 | 189 | -------------------------------------------------------------------------------- /ELClient/examples/avrflash: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # Flash an AVR with optiboot using the esp-link built-in programmer 4 | # Basically we first reset the AVR and get in sync, and then send the hex file 5 | # 6 | # ---------------------------------------------------------------------------- 7 | # "THE BEER-WARE LICENSE" (Revision 42): 8 | # Thorsten von Eicken wrote this file. As long as you retain 9 | # this notice you can do whatever you want with this stuff. If we meet some day, 10 | # and you think this stuff is worth it, you can buy me a beer in return. 11 | # ---------------------------------------------------------------------------- 12 | 13 | show_help() { 14 | cat </dev/null; then 26 | echo "ERROR: Cannot find curl: it is required for this script." >&2 27 | exit 1 28 | fi 29 | 30 | start=`date +%s` 31 | 32 | # ===== Parse arguments 33 | 34 | verbose= 35 | 36 | while getopts "hvx:" opt; do 37 | case "$opt" in 38 | h) show_help; exit 0 ;; 39 | v) verbose=1 ;; 40 | x) foo="$OPTARG" ;; 41 | '?') show_help >&2; exit 1 ;; 42 | esac 43 | done 44 | 45 | # Shift off the options and optional --. 46 | shift "$((OPTIND-1))" 47 | 48 | # Get the fixed arguments 49 | if [[ $# != 2 ]]; then 50 | show_help >&2 51 | exit 1 52 | fi 53 | hostname=$1 54 | hex=$2 55 | 56 | re='[-A-Za-z0-9.]+' 57 | if [[ ! "$hostname" =~ $re ]]; then 58 | echo "ERROR: hostname ${hostname} is not a valid hostname or ip address" >&2 59 | exit 1 60 | fi 61 | 62 | if [[ ! -r "$hex" ]]; then 63 | echo "ERROR: cannot read hex file ($hex)" >&2 64 | exit 1 65 | fi 66 | 67 | # ===== Get AVR in sync 68 | 69 | [[ -n "$verbose" ]] && echo "Resetting AVR with http://$hostname/pgm/sync" >&2 70 | v=; [[ -n "$verbose" ]] && v=-v 71 | sync=`curl -m 10 $v -s -w '%{http_code}' -XPOST "http://$hostname/pgm/sync"` 72 | if [[ $? != 0 || "$sync" != 204 ]]; then 73 | echo "Error resetting AVR" >&2 74 | exit 1 75 | fi 76 | 77 | while true; do 78 | sync=`curl -m 10 $v -s "http://$hostname/pgm/sync"` 79 | if [[ $? != 0 ]]; then 80 | echo "Error checking sync" >&2 81 | exit 1 82 | fi 83 | case "$sync" in 84 | SYNC*) 85 | echo "AVR in $sync" >&2 86 | break;; 87 | "NOT READY"*) 88 | [[ -n "$verbose" ]] && echo " Waiting for sync..." >&2 89 | ;; 90 | *) 91 | echo "Error checking sync: $sync" >&2 92 | exit 1 93 | ;; 94 | esac 95 | sleep 0.1 96 | done 97 | 98 | # ===== Send HEX file 99 | 100 | [[ -n "$verbose" ]] && echo "Sending HEX file for programming" >&2 101 | sync=`curl -m 10 $v -s -g -d "@$hex" "http://$hostname/pgm/upload"` 102 | echo $sync 103 | if [[ $? != 0 || ! "$sync" =~ ^Success ]]; then 104 | echo "Error programming AVR" >&2 105 | exit 1 106 | fi 107 | 108 | sec=$(( `date +%s` - $start )) 109 | echo "Success, took $sec seconds" >&2 110 | exit 0 111 | -------------------------------------------------------------------------------- /ELClient/examples/demo/.dep/demo.ino.dep: -------------------------------------------------------------------------------- 1 | demo.o: demo.ino \ 2 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Arduino.h \ 3 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/binary.h \ 4 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/WCharacter.h \ 5 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/WString.h \ 6 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/HardwareSerial.h \ 7 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Stream.h \ 8 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Print.h \ 9 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Printable.h \ 10 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/new.h \ 11 | /home/arduino/arduino-1.0.5/hardware/arduino//variants/standard/pins_arduino.h \ 12 | ../../../espduino/espduino.h \ 13 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/HardwareSerial.h \ 14 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Arduino.h \ 15 | ../../../espduino/FP.h ../../../espduino/crc16.h \ 16 | ../../../espduino/ringbuf.h ../../../espduino/rest.h 17 | 18 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Arduino.h: 19 | 20 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/binary.h: 21 | 22 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/WCharacter.h: 23 | 24 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/WString.h: 25 | 26 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/HardwareSerial.h: 27 | 28 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Stream.h: 29 | 30 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Print.h: 31 | 32 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Printable.h: 33 | 34 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/new.h: 35 | 36 | /home/arduino/arduino-1.0.5/hardware/arduino//variants/standard/pins_arduino.h: 37 | 38 | ../../../espduino/espduino.h: 39 | 40 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/HardwareSerial.h: 41 | 42 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Arduino.h: 43 | 44 | ../../../espduino/FP.h: 45 | 46 | ../../../espduino/crc16.h: 47 | 48 | ../../../espduino/ringbuf.h: 49 | 50 | ../../../espduino/rest.h: 51 | -------------------------------------------------------------------------------- /ELClient/examples/demo/.dep/temperature.ino.dep: -------------------------------------------------------------------------------- 1 | temperature.o: temperature.ino \ 2 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Arduino.h \ 3 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/binary.h \ 4 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/WCharacter.h \ 5 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/WString.h \ 6 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/HardwareSerial.h \ 7 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Stream.h \ 8 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Print.h \ 9 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Printable.h \ 10 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/new.h \ 11 | /home/arduino/arduino-1.0.5/hardware/arduino//variants/standard/pins_arduino.h \ 12 | ../../../espduino/espduino.h \ 13 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/HardwareSerial.h \ 14 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Arduino.h \ 15 | ../../../espduino/FP.h ../../../espduino/crc16.h \ 16 | ../../../espduino/ringbuf.h ../../../espduino/rest.h 17 | 18 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Arduino.h: 19 | 20 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/binary.h: 21 | 22 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/WCharacter.h: 23 | 24 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/WString.h: 25 | 26 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/HardwareSerial.h: 27 | 28 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Stream.h: 29 | 30 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Print.h: 31 | 32 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Printable.h: 33 | 34 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/new.h: 35 | 36 | /home/arduino/arduino-1.0.5/hardware/arduino//variants/standard/pins_arduino.h: 37 | 38 | ../../../espduino/espduino.h: 39 | 40 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/HardwareSerial.h: 41 | 42 | /home/arduino/arduino-1.0.5/hardware/arduino//cores/arduino/Arduino.h: 43 | 44 | ../../../espduino/FP.h: 45 | 46 | ../../../espduino/crc16.h: 47 | 48 | ../../../espduino/ringbuf.h: 49 | 50 | ../../../espduino/rest.h: 51 | -------------------------------------------------------------------------------- /ELClient/examples/demo/Makefile: -------------------------------------------------------------------------------- 1 | LIBRARYPATH = $(ARDUINODIR)/libraries ../../.. 2 | LIBRARIES = espduino 3 | CPPFLAGS = 4 | SERIALDEV = net:esp-link:23 5 | include ../arduino.mk 6 | 7 | run: upload size 8 | nc esp-link 23 9 | -------------------------------------------------------------------------------- /ELClient/examples/demo/README.md: -------------------------------------------------------------------------------- 1 | Simple demo 2 | =========== 3 | 4 | **WARNING: this example has not been updated for EL-Client!** 5 | 6 | -------------------------------------------------------------------------------- /ELClient/examples/demo/demo.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Demo sketch that makes a rest request to api.thingspeak.com with the RTT of the previous 3 | * request. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | ESP esp(&Serial, 4); 10 | 11 | REST rest(&esp); 12 | 13 | boolean wifiConnected = false; 14 | 15 | void wifiCb(void* response) 16 | { 17 | uint32_t status; 18 | RESPONSE res(response); 19 | 20 | if(res.getArgc() == 1) { 21 | res.popArgs((uint8_t*)&status, 4); 22 | if(status == STATION_GOT_IP) { 23 | Serial.println("WIFI CONNECTED"); 24 | 25 | wifiConnected = true; 26 | } else { 27 | wifiConnected = false; 28 | } 29 | } 30 | } 31 | 32 | void setup() { 33 | Serial.begin(115200); 34 | delay(10); 35 | Serial.println("ARDUINO: starting"); 36 | esp.enable(); 37 | delay(10); 38 | esp.reset(); 39 | delay(10); 40 | while(!esp.ready()) { 41 | Serial.println("ARDUINO: ESP not ready..."); 42 | delay(1000); 43 | } 44 | 45 | Serial.println("ARDUINO: setup rest client"); 46 | if(!rest.begin("api.thingspeak.com")) { 47 | Serial.println("ARDUINO: failed to setup rest client"); 48 | while(1); 49 | } 50 | 51 | /*setup wifi*/ 52 | Serial.println("ARDUINO: setup wifi"); 53 | esp.wifiCb.attach(&wifiCb); 54 | 55 | esp.wifiConnect("",""); 56 | Serial.println("ARDUINO: system started"); 57 | } 58 | 59 | void printChar(char c) { 60 | if (c < ' ' || c >= '~') { 61 | Serial.print("\\x"); 62 | uint8_t c1 = (uint8_t)c >> 4; 63 | Serial.print((char)(c1 >= 10 ? 'A'+c1-10 : '0' + c1)); 64 | uint8_t c2 = (uint8_t)c & 0xf; 65 | Serial.print((char)(c2 >= 10 ? 'A'+c2-10 : '0' + c2)); 66 | } else { 67 | Serial.print(c); 68 | } 69 | } 70 | 71 | uint32_t timer = 0; 72 | 73 | void loop() { 74 | char response[266]; 75 | esp.process(); 76 | if(wifiConnected) { 77 | char buff[64]; 78 | uint32_t t0 = millis(); 79 | sprintf(buff, "/update?api_key=MAY03AKJDMPP4Y4I&field1=%ld", timer); 80 | Serial.print("ARDUINO: send get "); 81 | Serial.println(buff); 82 | rest.get((const char*)buff); 83 | 84 | uint16_t err = rest.getResponse(response, 266); 85 | if(err == HTTP_STATUS_OK){ 86 | Serial.println("ARDUINO: GET successful"); 87 | Serial.print("ARDUINO: got <<"); 88 | int len = strlen(response); 89 | for (int i=0; i>"); 91 | } else if (err == 0) { 92 | Serial.println("ARDUINO: GET timed out"); 93 | } else { 94 | Serial.print("ARDUINO: GET failed: "); 95 | Serial.println(err); 96 | } 97 | timer = millis() - t0; 98 | Serial.print("ARDUINO: took "); 99 | Serial.print(timer); 100 | Serial.println("ms"); 101 | delay(3000); 102 | } 103 | delay(100); 104 | } 105 | -------------------------------------------------------------------------------- /ELClient/examples/mqtt/Makefile: -------------------------------------------------------------------------------- 1 | HOST ?= esp-link 2 | LIBRARYPATH = $(ARDUINODIR)/libraries ../../.. 3 | LIBRARIES = ELClient 4 | CPPFLAGS = 5 | SERIALDEV = net:$(HOST):2323 6 | include ../arduino.mk 7 | 8 | flash: all 9 | ../avrflash $(HOST) mqtt.hex 10 | nc $(HOST) 23 11 | 12 | run: upload size 13 | nc $(HOST) 23 14 | -------------------------------------------------------------------------------- /ELClient/examples/mqtt/README.md: -------------------------------------------------------------------------------- 1 | MQTT example 2 | ============ 3 | 4 | This is a simple example of a sketch that subscribes to an mqtt topic and then publishes messages 5 | to that topic, which it subsequently receives and prints. 6 | 7 | **Important** For this sketch to work you must turn off the UART debug log in esp-link (on 8 | the Debug Log page). The reason is that otherwise esp-link prints too much to its uart and then 9 | misses incoming characters. 10 | -------------------------------------------------------------------------------- /ELClient/examples/mqtt/mqtt.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple example to demo the esp-link MQTT client 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | // Initialize a connection to esp-link using the normal hardware serial port both for 10 | // SLIP and for debug messages. 11 | ELClient esp(&Serial, &Serial); 12 | 13 | // Initialize CMD client (for GetTime) 14 | ELClientCmd cmd(&esp); 15 | 16 | // Initialize the MQTT client 17 | ELClientMqtt mqtt(&esp); 18 | 19 | // Callback made from esp-link to notify of wifi status changes 20 | // Here we just print something out for grins 21 | void wifiCb(void* response) { 22 | ELClientResponse *res = (ELClientResponse*)response; 23 | if (res->argc() == 1) { 24 | uint8_t status; 25 | res->popArg(&status, 1); 26 | 27 | if(status == STATION_GOT_IP) { 28 | Serial.println("WIFI CONNECTED"); 29 | } else { 30 | Serial.print("WIFI NOT READY: "); 31 | Serial.println(status); 32 | } 33 | } 34 | } 35 | 36 | bool connected; 37 | 38 | // Callback when MQTT is connected 39 | void mqttConnected(void* response) { 40 | Serial.println("MQTT connected!"); 41 | mqtt.subscribe("/esp-link/1"); 42 | mqtt.subscribe("/hello/world/#"); 43 | //mqtt.subscribe("/esp-link/2", 1); 44 | //mqtt.publish("/esp-link/0", "test1"); 45 | connected = true; 46 | } 47 | 48 | // Callback when MQTT is disconnected 49 | void mqttDisconnected(void* response) { 50 | Serial.println("MQTT disconnected"); 51 | connected = false; 52 | } 53 | 54 | // Callback when an MQTT message arrives for one of our subscriptions 55 | void mqttData(void* response) { 56 | ELClientResponse *res = (ELClientResponse *)response; 57 | 58 | Serial.print("Received: topic="); 59 | String topic = res->popString(); 60 | Serial.println(topic); 61 | 62 | Serial.print("data="); 63 | String data = res->popString(); 64 | Serial.println(data); 65 | } 66 | 67 | void mqttPublished(void* response) { 68 | Serial.println("MQTT published"); 69 | } 70 | 71 | void setup() { 72 | Serial.begin(115200); 73 | Serial.println("EL-Client starting!"); 74 | 75 | // Sync-up with esp-link, this is required at the start of any sketch and initializes the 76 | // callbacks to the wifi status change callback. The callback gets called with the initial 77 | // status right after Sync() below completes. 78 | esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired) 79 | bool ok; 80 | do { 81 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 82 | if (!ok) Serial.println("EL-Client sync failed!"); 83 | } while(!ok); 84 | Serial.println("EL-Client synced!"); 85 | 86 | // Set-up callbacks for events and initialize with es-link. 87 | mqtt.connectedCb.attach(mqttConnected); 88 | mqtt.disconnectedCb.attach(mqttDisconnected); 89 | mqtt.publishedCb.attach(mqttPublished); 90 | mqtt.dataCb.attach(mqttData); 91 | mqtt.setup(); 92 | 93 | //Serial.println("ARDUINO: setup mqtt lwt"); 94 | //mqtt.lwt("/lwt", "offline", 0, 0); //or mqtt.lwt("/lwt", "offline"); 95 | 96 | Serial.println("EL-MQTT ready"); 97 | } 98 | 99 | static int count; 100 | static uint32_t last; 101 | 102 | void loop() { 103 | esp.Process(); 104 | 105 | if (connected && (millis()-last) > 4000) { 106 | Serial.println("publishing"); 107 | char buf[12]; 108 | 109 | itoa(count++, buf, 10); 110 | mqtt.publish("/esp-link/1", buf); 111 | 112 | itoa(count+99, buf, 10); 113 | mqtt.publish("/hello/world/arduino", buf); 114 | 115 | uint32_t t = cmd.GetTime(); 116 | Serial.print("Time: "); Serial.println(t); 117 | 118 | last = millis(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /ELClient/examples/rest/Makefile: -------------------------------------------------------------------------------- 1 | HOST ?= esp-link 2 | LIBRARYPATH = $(ARDUINODIR)/libraries ../../.. 3 | LIBRARIES = ELClient 4 | CPPFLAGS = 5 | SERIALDEV = net:$(HOST):2323 6 | include ../arduino.mk 7 | 8 | flash: all 9 | ../avrflash $(HOST) rest.hex 10 | nc $(HOST) 23 11 | 12 | run: upload size 13 | nc $(HOST) 23 14 | -------------------------------------------------------------------------------- /ELClient/examples/rest/README.md: -------------------------------------------------------------------------------- 1 | REST example 2 | ============ 3 | 4 | Simple REST example that configures a REST client to talk to www.timeapi.org and then 5 | makes a request every second to get the current time and print it. 6 | 7 | This example prints a whole lot more than one would normally given the typical space constraints... 8 | 9 | -------------------------------------------------------------------------------- /ELClient/examples/rest/rest.hex: -------------------------------------------------------------------------------- 1 | :100000000C9436000C945E000C945E000C945E0020 2 | :100010000C945E000C945E000C945E000C945E00E8 3 | :100020000C945E000C945E000C945E000C945E00D8 4 | :100030000C945E000C945E000C945E000C945E00C8 5 | :100040000C947A010C945E000C9456020C94880275 6 | :100050000C945E000C945E000C945E000C945E00A8 7 | :100060000C945E000C945E006D01B80211241FBE5A 8 | :10007000CFEFD8E0DEBFCDBF12E0A0E0B1E0E8E313 9 | :10008000F8E102C005900D92AE35B107D9F723E033 10 | :10009000AEE5B2E001C01D92AB3AB207E1F710E065 11 | :1000A000CCE6D0E004C02297FE010E940D0CC836B9 12 | :1000B000D107C9F70E9441040C941A0C0C9400005B 13 | :1000C000CF93DF931F92CDB7DEB7DC011496ED918D 14 | :1000D000FC911597228133812130310519F541E0DA 15 | :1000E00050E0BE016F5F7F4F0E94C3098981853058 16 | :1000F00051F466E071E08EE093E00E949B0481E0A1 17 | :1001000080935E020FC065E171E08EE093E00E9493 18 | :100110008E044AE050E069818EE093E00E947C0505 19 | :1001200010925E020F90DF91CF910895CF93DF93ED 20 | :1001300026E040E052EC61E070E08EE093E00E9447 21 | :10014000DE0366E271E08EE093E00E949B0460E6CD 22 | :1001500070E083E792E00E94AF0B40ED57E060E073 23 | :1001600070E081E792E00E941A09811107C06AE3FA 24 | :1001700071E08EE093E00E949B04EFCF61E971E0B3 25 | :100180008EE093E00E949B0481E792E00E94750953 26 | :1001900040ED57E060E070E081E792E00E940908DE 27 | :1001A000EC01009781F061E571E08EE093E00E9440 28 | :1001B0008E044C815D816E817F812AE030E08EE08B 29 | :1001C00093E00E94AF0520E040E550E06FE571E06C 30 | :1001D0008FE592E00E94490AEC01009771F06FE60A 31 | :1001E00071E08EE093E00E948E044AE050E0BE0190 32 | :1001F0008EE093E00E945005FFCF63E871E08EE04F 33 | :1002000093E0DF91CF910C949B04EF92FF920F93B8 34 | :100210001F93CF93DF93CDB7DEB7CA50D1400FB64F 35 | :10022000F894DEBF0FBECDBF81E792E00E94B00719 36 | :1002300080915E02882309F442C040E050E063EA06 37 | :1002400071E08FE592E00E94440B9E012F5F3F4FCB 38 | :1002500079018AE091E0F9019C011192215030402E 39 | :10026000E1F708E813E120E030E04AE051E0B701AF 40 | :100270008FE592E00E94670B8C01883C910561F448 41 | :100280006CEA71E08EE093E00E949B04B7018EE07F 42 | :1002900093E00E949B040DC065EC71E08EE093E05A 43 | :1002A0000E948E044AE050E0B8018EE093E00E9484 44 | :1002B000990568EE73E080E090E00E94F301C65F6C 45 | :1002C000DE4F0FB6F894DEBF0FBECDBFDF91CF91EA 46 | :1002D0001F910F91FF90EF9008954EE053E0BA0107 47 | :1002E00081E792E00E94270661E772E08FE592E0E5 48 | :1002F0000C94320A1F920F920FB60F9211242F9373 49 | :100300003F938F939F93AF93BF93809106039091F8 50 | :100310000703A0910803B09109033091050323E07E 51 | :10032000230F2D3720F40196A11DB11D05C026E82D 52 | :10033000230F0296A11DB11D209305038093060390 53 | :1003400090930703A0930803B093090380910A03D5 54 | :1003500090910B03A0910C03B0910D030196A11D88 55 | :10036000B11D80930A0390930B03A0930C03B093E9 56 | :100370000D03BF91AF919F918F913F912F910F905E 57 | :100380000FBE0F901F9018952FB7F8946091060339 58 | :100390007091070380910803909109032FBF08957E 59 | :1003A0003FB7F89480910A0390910B03A0910C033E 60 | :1003B000B0910D0326B5A89B05C02F3F19F00196FB 61 | :1003C000A11DB11D3FBF6627782F892F9A2F620F7D 62 | :1003D000711D811D911D42E0660F771F881F991FB7 63 | :1003E0004A95D1F70895CF92DF92EF92FF92CF9383 64 | :1003F000DF936B017C010E94D001EB01C114D10499 65 | :10040000E104F10489F00E94E80B0E94D0016C1B0A 66 | :100410007D0B683E734090F381E0C81AD108E10873 67 | :10042000F108C851DC4FEACFDF91CF91FF90EF90F8 68 | :10043000DF90CF900895789484B5826084BD84B5B0 69 | :10044000816084BD85B5826085BD85B5816085BDCF 70 | :10045000EEE6F0E0808181608083E1E8F0E01082E8 71 | :10046000808182608083808181608083E0E8F0E029 72 | :10047000808181608083E1EBF0E080818460808313 73 | :10048000E0EBF0E0808181608083EAE7F0E080814A 74 | :1004900084608083808182608083808181608083AA 75 | :1004A0008081806880831092C10008951F920F920E 76 | :1004B0000FB60F9211242F938F939F93EF93FF9377 77 | :1004C000E0911E03F0911F038081E0912403F091DD 78 | :1004D000250382FD12C09081809127038F5F8F7367 79 | :1004E00020912803821751F0E0912703F0E0E25FAA 80 | :1004F000FC4F958F8093270301C08081FF91EF917E 81 | :100500009F918F912F910F900FBE0F901F90189574 82 | :100510001F920F920FB60F9211242F933F934F9378 83 | :100520005F936F937F938F939F93AF93BF93EF935B 84 | :10053000FF938EE093E00E943603FF91EF91BF910D 85 | :10054000AF919F918F917F916F915F914F913F916B 86 | :100550002F910F900FBE0F901F9018958EE093E093 87 | :100560000E94FB0221E0892B09F420E0822F0895EC 88 | :10057000109211031092100388EE93E0A0E0B0E017 89 | :100580008093120390931303A0931403B093150365 90 | :100590008FED91E090930F0380930E0385EC90E034 91 | :1005A00090931B0380931A0384EC90E090931D03B7 92 | :1005B00080931C0380EC90E090931F0380931E03B4 93 | :1005C00081EC90E0909321038093200382EC90E0F3 94 | :1005D000909323038093220386EC90E0909325036D 95 | :1005E000809324031092270310922803109229036A 96 | :1005F00010922A030895FC01818D228D90E0805C89 97 | :100600009F4F821B91098F7399270895FC01918D4B 98 | :10061000828D981731F0828DE80FF11D858D90E065 99 | :1006200008958FEF9FEF0895FC01918D828D9817AB 100 | :1006300061F0828DDF01A80FB11D5D968C91928DC6 101 | :100640009F5F9F73928F90E008958FEF9FEF0895C3 102 | :100650008EEA92E0892B49F080E090E0892B29F026 103 | :100660000E94AE0281110C9400000895FC01848D5B 104 | :10067000DF01A80FB11DA35ABF4F2C91848D90E0CC 105 | :1006800001968F739927848FA689B7892C93A089A7 106 | :10069000B1898C9180648C93938D848D981306C05E 107 | :1006A0000288F389E02D80818F7D80830895CF9328 108 | :1006B000DF93EC01888D8823C9F0EA89FB8980816A 109 | :1006C00085FD05C0A889B9898C9186FD0FC00FB63C 110 | :1006D00007FCF5CF808185FFF2CFA889B9898C917D 111 | :1006E00085FFEDCFCE010E943603E7CFDF91CF919A 112 | :1006F0000895CF92DF92FF920F931F93CF93DF93D2 113 | :100700001F92CDB7DEB76C0181E0D60158968C936D 114 | :1007100058975B969C915B975C968C915C9798132D 115 | :1007200007C05096ED91FC915197808185FD2EC0B8 116 | :10073000F601038D10E00F5F1F4F0F731127F02E8E 117 | :10074000F601848DF81211C00FB607FCF9CFD6015F 118 | :100750005096ED91FC915197808185FFF1CFC601B4 119 | :1007600069830E9436036981EBCF838DE80FF11D09 120 | :10077000E35AFF4F6083D6015B960C935B975296CA 121 | :10078000ED91FC915397808180620CC0D601569602 122 | :10079000ED91FC91579760835096ED91FC915197A4 123 | :1007A00080818064808381E090E00F90DF91CF9121 124 | :1007B0001F910F91FF90DF90CF900895BF92CF923D 125 | :1007C000DF92EF92FF92CF93DF93EC016A017B01FE 126 | :1007D000B22EE889F98982E08083411581EE5807BD 127 | :1007E00061057105A1F060E079E08DE390E0A7017B 128 | :1007F00096010E94E90B2150310941095109569592 129 | :10080000479537952795211580E1380798F0E889B5 130 | :10081000F989108260E874E88EE190E0A701960102 131 | :100820000E94E90B2150310941095109569547951C 132 | :1008300037952795EC85FD853083EE85FF852083F0 133 | :10084000188EEC89FD89B082EA89FB8980818061FC 134 | :100850008083EA89FB89808188608083EA89FB89BB 135 | :10086000808180688083EA89FB8980818F7D808395 136 | :10087000DF91CF91FF90EF90DF90CF90BF900895E0 137 | :1008800008950E941B020E9440040E949600C8E244 138 | :10089000D3E00E9405012097E1F30E942803F9CFDD 139 | :1008A000CF92DF92EF92FF920F931F93CF93DF933C 140 | :1008B0006C017A01EB01E60EF71E00E010E0CE15A8 141 | :1008C000DF0561F06991D601ED91FC910190F08115 142 | :1008D000E02DC6010995080F191FF1CFC801DF915E 143 | :1008E000CF911F910F91FF90EF90DF90CF900895DF 144 | :1008F0006115710581F0DB010D900020E9F7AD0174 145 | :1009000041505109461B570BDC01ED91FC910280CF 146 | :10091000F381E02D099480E090E008950C94780430 147 | :10092000DC01ED91FC910190F081E02D09946BEEDA 148 | :1009300071E00C9478040F931F93CF93DF93EC0135 149 | :100940000E9478048C01CE010E949704800F911FB1 150 | :10095000DF91CF911F910F9108958F929F92AF9247 151 | :10096000BF92CF92DF92EF92FF920F931F93CF939C 152 | :10097000DF93CDB7DEB7A1970FB6F894DEBF0FBEF9 153 | :10098000CDBF7C01C42EE52FCB01D22E19A221E0D0 154 | :100990002D1510F02AE0D22E8E010F5D1F4F8D2CE9 155 | :1009A000912CA12CB12C6C2D7E2FA50194010E94BD 156 | :1009B000E90B8C2DD29E80191124015011098A3027 157 | :1009C00010F4805D01C0895CF80180832115310538 158 | :1009D0004105510521F0C22EE32FCA01E4CFB80131 159 | :1009E000C7010E947804A1960FB6F894DEBF0FBE2F 160 | :1009F000CDBFDF91CF911F910F91FF90EF90DF90CE 161 | :100A0000CF90BF90AF909F908F900895CF92DF923C 162 | :100A1000EF92FF920F931F93CF93DF93EC016A0144 163 | :100A20007B012115310579F4E881F9810190F0818C 164 | :100A3000E02D642FDF91CF911F910F91FF90EF90E8 165 | :100A4000DF90CF9009942A303105E9F477FF1AC07E 166 | :100A50006DE20E9490048C0144275527BA014C197D 167 | :100A60005D096E097F092AE0CE010E94AD04800F66 168 | :100A7000911FDF91CF911F910F91FF90EF90DF9029 169 | :100A8000CF9008952AE0B701A601CE01DF91CF9162 170 | :100A90001F910F91FF90EF90DF90CF900C94AD04D9 171 | :100AA0000F931F93CF93DF93EC019A01AB0166275D 172 | :100AB00057FD6095762F0E9406058C01CE010E949D 173 | :100AC0009704800F911FDF91CF911F910F9108958F 174 | :100AD0002115310541F4DC01ED91FC910190F0818B 175 | :100AE000E02D642F09940C94AD049A01462F50E038 176 | :100AF00060E070E00C9468050F931F93CF93DF9331 177 | :100B0000EC019A01462F50E060E070E00E94680519 178 | :100B10008C01CE010E949704800F911FDF91CF912D 179 | :100B20001F910F9108959A01AB0160E070E00C9461 180 | :100B300068050F931F93CF93DF93EC019A01AB01EC 181 | :100B400060E070E00E9468058C01CE010E9497046D 182 | :100B5000800F911FDF91CF911F910F9108950F93F7 183 | :100B60001F93CF93DF93EC010E9468058C01CE01A7 184 | :100B70000E949704800F911FDF91CF911F910F91D9 185 | :100B80000895CF93DF93EC0188859985603CA1F0AF 186 | :100B90006B3D21F5DC01ED91FC910190F081E02DA0 187 | :100BA0006BED099588859985DC01ED91FC910190AB 188 | :100BB000F081E02D6DED18C0DC01ED91FC9101900C 189 | :100BC000F081E02D6BED099588859985DC01ED912B 190 | :100BD000FC910190F081E02D6CED06C0DC01ED91FF 191 | :100BE000FC910190F081E02DDF91CF910994EF927B 192 | :100BF000FF920F931F93CF93DF937C018A01EB0148 193 | :100C0000060F171FC017D10729F06991C7010E946D 194 | :100C1000C105F8CFDF91CF911F910F91FF90EF9019 195 | :100C20000895CF93DF93EC01BC01655F7F4F42E0F5 196 | :100C300050E00E94F70588859985DC01ED91FC91D3 197 | :100C40000190F081E02D60ECDF91CF9109940F933A 198 | :100C50001F93CF93DF93EC018B01FC0141935193E0 199 | :100C6000CF010E94A90B1987088781E08A87CE01EE 200 | :100C700044969E878D8780E890E0988B8F871A8AAC 201 | :100C8000198A1B8ADF91CF911F910F910895FC0162 202 | :100C90002285222321F0808191810C949B04089568 203 | :100CA00046275427452754279A01222784E0220FFC 204 | :100CB000331F8A95E1F724273527C901892F992702 205 | :100CC00082958F70822793279C01222755E03695C5 206 | :100CD00027955A95E1F7822793270895EF92FF927F 207 | :100CE0000F931F93CF93DF937C018A01C901EB011E 208 | :100CF000060F171FC017D10731F06991AC01C7016A 209 | :100D00000E945006F7CFDF91CF911F910F91FF9076 210 | :100D1000EF900895AF92BF92CF92DF92EF92FF9241 211 | :100D20000F931F93CF93DF9300D000D000D0CDB7A7 212 | :100D3000DEB78C01DC011D96ED90FC901E971A9693 213 | :100D40008C911A97882309F47DC06CEF71E08D9126 214 | :100D50009C910E948E04F801618972894AE050E0FA 215 | :100D6000808191810E94930566E072E0D8018D91A7 216 | :100D70009C910E948E04F80145855685662757FD93 217 | :100D80006095762F20E130E0808191810E94680596 218 | :100D90006AE272E0D8018D919C910E948E04F70165 219 | :100DA0006081718140E150E0D8018D919C910E9459 220 | :100DB00093056BE272E0F801808191810E948E04BC 221 | :100DC000D70114964D915D916D917C91179720E11B 222 | :100DD00030E0F801808191810E9468056BE272E049 223 | :100DE000D8018D919C910E948E04F70162817381DC 224 | :100DF00040E150E0D8018D919C910E94930568E0FC 225 | :100E0000C62ED12CF8012189328980819181C216A8 226 | :100E1000D306B0F46BE272E00E948E04D8011D96F6 227 | :100E2000ED91FC911E97EC0DFD1D40E150E06081BD 228 | :100E30008D919C910E947505BFEFCB1ADB0AE2CF22 229 | :100E40000E949704D8015196CD90DC905297B2E061 230 | :100E5000CB1AD108F801A584B68420E030E0A601C1 231 | :100E6000B501C8010E946E06F501EC0DFD1D208143 232 | :100E700031818217930731F069E072E0C8010E9466 233 | :100E800047065BC0D7012D913C91F801808191818B 234 | :100E900022303105A1F46AE172E00E948E04D7018C 235 | :100EA00014964D915D916D917C9117972AE030E0F9 236 | :100EB000F801808191810E94AF05C70140C02330B5 237 | :100EC0003105B9F563E272E00E948E04D7011496F1 238 | :100ED0004D915D916D917C9117972AE030E0F8017A 239 | :100EE000808191810E9468056BE272E0D8018D914A 240 | :100EF0009C910E948E04F701628173814AE050E068 241 | :100F0000D8018D919C910E949905F701048115816A 242 | :100F1000C8010E94DA0B882381F0B701CE01019647 243 | :100F20000E948A09BE016F5F7F4FC8010E94B30B08 244 | :100F300004C06DE272E00E949B0480E090E026967F 245 | :100F40000FB6F894DEBF0FBECDBFDF91CF911F91DA 246 | :100F50000F91FF90EF90DF90CF90BF90AF900895EA 247 | :100F60001F93CF93DF93EC0111E088859985DC0115 248 | :100F7000ED91FC910480F581E02D0995892B09F410 249 | :100F800042C088859985DC01ED91FC910680F7814E 250 | :100F9000E02D09958B3D910511F41B8BE6CF298936 251 | :100FA0003A89803C910579F42830310520F0CE0152 252 | :100FB0000E948A0602C080E090E01A8A198A1B8A81 253 | :100FC000009799F222C04B89442361F08C3D910532 254 | :100FD00031F08D3D910529F48BED90E002C080EC5D 255 | :100FE00090E01B8A4F8558892417350708F0BDCF3C 256 | :100FF000ED85FE85A9014F5F5F4F5A8B498BE20F4C 257 | :10100000F31F8083B2CF80E090E0DF91CF911F91FA 258 | :1010100008958F929F92AF92BF92CF92DF92EF92FC 259 | :10102000FF92CF93DF93EC016A017B010E94C40120 260 | :101030004B015C010E94C401681979098A099B0966 261 | :101040006C157D058E059F0530F4CE010E94B0071A 262 | :10105000009781F302C080E090E0DF91CF91FF9094 263 | :10106000EF90DF90CF90BF90AF909F908F900895BA 264 | :10107000EF92FF920F931F93CF93DF93CDB7DEB71D 265 | :1010800028970FB6F894DEBF0FBECDBF7C017A83E0 266 | :1010900069832B833C834D835E8318870F83DC0138 267 | :1010A0001C961C921E921B9718968D919C911997D5 268 | :1010B000DC01ED91FC910190F081E02D60EC09954F 269 | :1010C00042E050E0BE016F5F7F4FC7010E94F7050D 270 | :1010D000F7012385348542E050E0BE016F5F7F4F0A 271 | :1010E000C7010E946E06D7011C969C938E931B9796 272 | :1010F00042E050E0BE01695F7F4FC7010E94F705E3 273 | :10110000F7012385348542E050E0BE01695F7F4FDF 274 | :10111000C7010E946E06D7011C969C938E931B9765 275 | :1011200044E050E0BE016D5F7F4FC7010E94F705AC 276 | :10113000F7012385348544E050E0BE016D5F7F4FA9 277 | :10114000C7010E946E06D7011C969C938E931B9735 278 | :1011500028960FB6F894DEBF0FBECDBFDF91CF91BA 279 | :101160001F910F91FF90EF900895CF92DF92EF9231 280 | :10117000FF920F931F93CF93DF9300D0CDB7DEB7CD 281 | :101180008C017B015A83498342E050E0BE016F5FCE 282 | :101190007F4F0E94F705F8012385348542E050E037 283 | :1011A000BE016F5F7F4FC8010E946E06F8019487F1 284 | :1011B0008387C980DA80CE0CDF1CEC14FD0491F02B 285 | :1011C000F7016081C8010E94C105F801438554857B 286 | :1011D000F70161917F01C8010E945006F8019487D0 287 | :1011E0008387EBCFE980FA80F194E194F108F3E092 288 | :1011F000EF22FF24E114F10491F060E0C8010E94A5 289 | :10120000C105F8014385548560E0C8010E9450067D 290 | :10121000F80194878387F1E0EF1AF108EBCF0F9084 291 | :101220000F90DF91CF911F910F91FF90EF90DF9082 292 | :10123000CF9008958F929F92AF92BF92CF92DF92FC 293 | :10124000EF92FF920F931F93CF93DF93EC014A012C 294 | :101250005B016C0182E0C80ED11CEE24D7FCE09447 295 | :10126000FE2C00E010E0A701960161E070E0CE01E5 296 | :101270000E943808CE010E941106B501A401CE01DA 297 | :101280000E9409088C01009711F1F80144815581F1 298 | :1012900066817781888199814C155D056E057F0592 299 | :1012A00031F463E372E00E949B0481E011C069E3C2 300 | :1012B00072E00E948E04F801448155816681778135 301 | :1012C0002AE030E0888199810E94AF05D6CF80E086 302 | :1012D000DF91CF911F910F91FF90EF90DF90CF9012 303 | :1012E000BF90AF909F908F9008950F931F93CF93CF 304 | :1012F000DF93EC0100E010E020E030E0A90164E0C1 305 | :1013000070E00E943808CE01DF91CF911F910F91BC 306 | :101310000C941106FC0175836483685F7F4F7383AF 307 | :101320006283118210820895CF93DF93FC01808144 308 | :101330009181A481B58112962D913C9113978217CA 309 | :101340009307E0F4A281B3812D913D91B383A283F1 310 | :10135000019691838083EB01B983A8838EEF9FEF81 311 | :10136000821B930B83709927820F931F42815381B5 312 | :10137000480F591F53834283C90102C08FEF9FEF6B 313 | :10138000DF91CF9108950F931F93CF93DF93FC01CB 314 | :10139000A081B181C481D5818A819B81A817B907B9 315 | :1013A00050F5C281D381299139918EEF9FEF821B35 316 | :1013B000930B83709927D383C2831196B183A08343 317 | :1013C0008E01EB01DA012417350708F4D9016A0F01 318 | :1013D0007B1FC617D70729F0D8014D918D0149937E 319 | :1013E000F8CF820F931F42815381480F591F5383B7 320 | :1013F0004283C90102C08FEF9FEFDF91CF911F9110 321 | :101400000F9108950F931F93CF93DF93EC018B01FE 322 | :101410006115710511F1BC01645F7F4F42E050E03E 323 | :10142000C8010E94C309EC81FD816FE372E08081F5 324 | :1014300091810E948E046C857D85EC81FD814AE05E 325 | :1014400050E0808191810E945005BE01605F7F4F16 326 | :10145000C8010E9494099F878E87DF91CF911F91C9 327 | :101460000F9108950F931F93CF93DF93EC018B019E 328 | :1014700006960E94A90B1D830C834FEF5FEFBA0104 329 | :10148000488359836A837B83DF91CF911F910F91AA 330 | :101490000895CF92DF92EF92FF920F931F93CF9315 331 | :1014A000DF9300D01F92CDB7DEB77C016B015B8369 332 | :1014B0004A832983FC019783868342E05AE060E0F7 333 | :1014C00070E040875187628773879C012A5F3F4F96 334 | :1014D000442737FD4095542F03E010E064E170E0AD 335 | :1014E000848195810E943808F60101900020E9F777 336 | :1014F000AF01415051094C195D09B601F7018481D2 337 | :1015000095810E94B50842E050E0BE016E5F7F4FBA 338 | :10151000F701848195810E94B50841E050E0BE0149 339 | :101520006F5F7F4FF701848195810E94B508F701B5 340 | :10153000848195810E94110640ED57E060E070E0E3 341 | :10154000F701848195810E940908009779F0FC01D8 342 | :10155000448155816681778177FD08C0F70140831A 343 | :1015600051836283738380E090E003C0FC01848137 344 | :1015700095810F900F900F90DF91CF911F910F9158 345 | :10158000FF90EF90DF90CF9008958F929F92AF924F 346 | :10159000BF92CF92DF92EF92FF920F931F93CF9360 347 | :1015A000DF93EC015B014A01790168011D861C860D 348 | :1015B000288139814A815B8157FD49C08C819D8199 349 | :1015C000E114F10431F0101611061CF403E010E0F0 350 | :1015D00002C002E010E065E170E00E943808F4010A 351 | :1015E00001900020E9F7AF0141505109481959090C 352 | :1015F000B4018C819D810E94B508F5010190002005 353 | :10160000E9F7AF01415051094A195B09B5018C81D5 354 | :101610009D810E94B508E114F10449F01C141D04D9 355 | :1016200034F4A601B7018C819D810E94B5088C819C 356 | :101630009D81DF91CF911F910F91FF90EF90DF90EF 357 | :10164000CF90BF90AF909F908F900C941106DF9138 358 | :10165000CF911F910F91FF90EF90DF90CF90BF90AF 359 | :10166000AF909F908F9008950F931F93F901019071 360 | :101670000020E9F78F0101501109021B130B0E9492 361 | :10168000C50A1F910F9108959A014AE452E00C9403 362 | :10169000340BCF93DF93EC01CB012C853D85232BBD 363 | :1016A00089F0EE85FF859A01E417F50708F49F019C 364 | :1016B00068897989A9010E94110C8C859D851D86F8 365 | :1016C0001C8602C080E090E0DF91CF9108954F9298 366 | :1016D0005F926F927F928F929F92AF92BF92CF92C2 367 | :1016E000DF92EF92FF920F931F93CF93DF93EC0162 368 | :1016F0005B014A01280139010E94C4016B017C0190 369 | :101700008C859D85892BA9F0A401B501CE01DF91BF 370 | :10171000CF911F910F91FF90EF90DF90CF90BF90EE 371 | :10172000AF909F908F907F906F905F904F900C94B0 372 | :10173000490B0E94C4016C197D098E099F0964152B 373 | :1017400075058605970500F78C819D810E94B0077D 374 | :10175000D7CFFC0111821082138212820895FC01FE 375 | :10176000738362830895DC011296ED91FC911397C7 376 | :101770003097F9F02D913C91119721153105B9F071 377 | :1017800014968D919C911597AC015595479580FFC6 378 | :101790000AC0D901A40FB51F0D90BC91A02DAE0FAA 379 | :1017A000BF1FED91FC91C901840F951F0994CB01D6 380 | :1017B00009940895FC0180819181892B39F481E09D 381 | :1017C00022813381232B19F480E0089581E008956C 382 | :1017D0000895A1E21A2EAA1BBB1BFD010DC0AA1F72 383 | :1017E000BB1FEE1FFF1FA217B307E407F50720F08A 384 | :1017F000A21BB30BE40BF50B661F771F881F991F05 385 | :101800001A9469F760957095809590959B01AC014D 386 | :10181000BD01CF010895EE0FFF1F0590F491E02D5B 387 | :101820000994FB01DC0102C001900D92415050402F 388 | :08183000D8F70895F894FFCFEA 389 | :101838000000AB0380005749464920434F4E4E45B0 390 | :10184800435445440057494649204E4F5420524579 391 | :101858004144593A2000454C2D436C69656E74200B 392 | :101868007374617274696E672100454C2D436C690D 393 | :10187800656E742073796E63206661696C65642196 394 | :101888000057696669207374617475733A2000772C 395 | :1018980077772E74696D656170692E6F7267005273 396 | :1018A80045535420626567696E206661696C65649A 397 | :1018B8003A2000454C2D5245535420726561647995 398 | :1018C80000454C2D436C69656E742073796E6365B1 399 | :1018D8006421002F7574632F6E6F77004152445551 400 | :1018E800494E4F3A204745542073756363657373B7 401 | :1018F80066756C3A0041524455494E4F3A20474567 402 | :1019080054206661696C65643A2000000000007923 403 | :10191800035004FB021403060357030D0A006E610B 404 | :101928006E00696E66006F7666002E00454C433A7D 405 | :1019380020676F742000204000454C433A20496ED0 406 | :1019480076616C69642043524300524553505F5698 407 | :101958003A2000524553505F43423A2000434D44D9 408 | :101968003F3F0053594E4321004241443A20005220 409 | :1019780045535420636F6465200047455400504F19 410 | :0E1988005354005055540044454C45544500FE 411 | :00000001FF 412 | -------------------------------------------------------------------------------- /ELClient/examples/rest/rest.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple example to demo the El-Client REST calls 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | // Initialize a connection to esp-link using the normal hardware serial port both for 9 | // SLIP and for debug messages. 10 | ELClient esp(&Serial, &Serial); 11 | 12 | // Initialize a REST client on the connection to esp-link 13 | ELClientRest rest(&esp); 14 | 15 | boolean wifiConnected = false; 16 | 17 | // Callback made from esp-link to notify of wifi status changes 18 | // Here we print something out and set a global flag 19 | void wifiCb(void *response) { 20 | ELClientResponse *res = (ELClientResponse*)response; 21 | if (res->argc() == 1) { 22 | uint8_t status; 23 | res->popArg(&status, 1); 24 | 25 | if(status == STATION_GOT_IP) { 26 | Serial.println("WIFI CONNECTED"); 27 | wifiConnected = true; 28 | } else { 29 | Serial.print("WIFI NOT READY: "); 30 | Serial.println(status); 31 | wifiConnected = false; 32 | } 33 | } 34 | } 35 | 36 | void setup() { 37 | Serial.begin(115200); // the baud rate here needs to match the esp-link config 38 | Serial.println("EL-Client starting!"); 39 | 40 | // Sync-up with esp-link, this is required at the start of any sketch and initializes the 41 | // callbacks to the wifi status change callback. The callback gets called with the initial 42 | // status right after Sync() below completes. 43 | esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired) 44 | bool ok; 45 | do { 46 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 47 | if (!ok) Serial.println("EL-Client sync failed!"); 48 | } while(!ok); 49 | Serial.println("EL-Client synced!"); 50 | 51 | // Get immediate wifi status info for demo purposes. This is not normally used because the 52 | // wifi status callback registered above gets called immediately. 53 | esp.GetWifiStatus(); 54 | ELClientPacket *packet; 55 | if ((packet=esp.WaitReturn()) != NULL) { 56 | Serial.print("Wifi status: "); 57 | Serial.println(packet->value); 58 | } 59 | 60 | // Set up the REST client to talk to www.timeapi.org, this doesn't connect to that server, 61 | // it just sets-up stuff on the esp-link side 62 | int err = rest.begin("www.timeapi.org"); 63 | if (err != 0) { 64 | Serial.print("REST begin failed: "); 65 | Serial.println(err); 66 | while(1) ; 67 | } 68 | Serial.println("EL-REST ready"); 69 | } 70 | 71 | #define BUFLEN 266 72 | 73 | void loop() { 74 | // process any callbacks coming from esp_link 75 | esp.Process(); 76 | 77 | // if we're connected make an HTTP request 78 | if(wifiConnected) { 79 | // Request /utc/now from the previously set-up server 80 | rest.get("/utc/now"); 81 | 82 | char response[BUFLEN]; 83 | memset(response, 0, BUFLEN); 84 | uint16_t code = rest.waitResponse(response, BUFLEN); 85 | if(code == HTTP_STATUS_OK){ 86 | Serial.println("ARDUINO: GET successful:"); 87 | Serial.println(response); 88 | } else { 89 | Serial.print("ARDUINO: GET failed: "); 90 | Serial.println(code); 91 | } 92 | delay(1000); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /ELClient/examples/tcp_client/tcp_client.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple example to demo the El-Client TCP client 3 | * This example sends out a message to a TCP socket server 4 | * and doesn't wait for a response from the server 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | // IP address for this demo is a local IP. 11 | // Replace it with the IP address where you have a TCP socket server running 12 | char * const tcpServer PROGMEM = "192.168.0.102"; 13 | // Port for this demo is the port used by the TCP socket server. 14 | // Replace it with the port that your TCP socket server is listening to 15 | uint16_t const tcpPort PROGMEM = 7001; 16 | 17 | //########################################################### 18 | // For ARDUINO UNO WIFI with I2C to serial chip! 19 | //########################################################### 20 | // Serial port to ESP8266 21 | #include 22 | SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA); 23 | 24 | // Initialize a connection to esp-link using the I2Cuart chip of the Arduino Uno WiFi board for 25 | // SLIP messages. 26 | ELClient esp(&i2cuart); 27 | 28 | //########################################################### 29 | // For boards using the hardware serial port! 30 | //########################################################### 31 | // Initialize a connection to esp-link using the normal hardware serial port both for 32 | // SLIP and for debug messages. 33 | //ELClient esp(&Serial, &Serial); 34 | 35 | // Initialize a TCP socket client on the connection to esp-link 36 | ELClientSocket tcp(&esp); 37 | // Connection number for tcp 38 | int tcpConnNum; 39 | 40 | // Timer value to send out data 41 | uint32_t wait; 42 | // Time to wait between sending out data 43 | uint32_t waitTime; 44 | // Flag for wifi connection 45 | boolean wifiConnected = false; 46 | 47 | // Parse error codes and returns error message as char * 48 | // Definitions from error values from espconn.h (Espressif SDK) 49 | // #define ESPCONN_OK 0 /**< No error, everything OK. */ 50 | // #define ESPCONN_MEM -1 /**< Out of memory. */ 51 | // #define ESPCONN_TIMEOUT -3 /**< Timeout. */ 52 | // #define ESPCONN_RTE -4 /**< Routing problem. */ 53 | // #define ESPCONN_INPROGRESS -5 /**< Operation in progress. */ 54 | // #define ESPCONN_MAXNUM -7 /**< Total number exceeds the maximum limitation. */ 55 | 56 | // #define ESPCONN_ABRT -8 /**< Connection aborted. */ 57 | // #define ESPCONN_RST -9 /**< Connection reset. */ 58 | // #define ESPCONN_CLSD -10 /**< Connection closed. */ 59 | // #define ESPCONN_CONN -11 /**< Not connected. */ 60 | 61 | // #define ESPCONN_ARG -12 /**< Illegal argument. */ 62 | // #define ESPCONN_IF -14 /**< UDP send error. */ 63 | // #define ESPCONN_ISCONN -15 /**< Already connected. */ 64 | 65 | char* const errTxt[] PROGMEM = {"No error, everything OK.","Out of memory.","Unknown code.","Timeout.","Routing problem.","Operation in progress.", 66 | "Unknown code.","Total number exceeds the maximum limitation.","Connection aborted.","Connection reset.","Connection closed.", 67 | "Not connected.","Illegal argument.","Unknown code.","UDP send error.","Already connected."}; 68 | char * getErrTxt(int16_t commError) { 69 | commError = commError*-1; 70 | if (commError <= 15) { 71 | return (char *) pgm_read_word (&errTxt[commError]); 72 | } else { 73 | return (char *) pgm_read_word (&errTxt[2]); // Unknown code 74 | } 75 | } 76 | 77 | // Callback for TCP socket, called if data was sent or received 78 | // Receives socket client number, can be reused for all initialized TCP socket connections 79 | void tcpCb(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data) { 80 | Serial.println("tcpCb connection #"+String(client_num)); 81 | if (resp_type == USERCB_SENT) { 82 | Serial.println("\tSent " + String(len) + " bytes over client#" + String(client_num)); 83 | } else if (resp_type == USERCB_RECV) { 84 | char recvData[len+1]; // Prepare buffer for the received data 85 | memcpy(recvData, data, len); // Copy received data into the buffer 86 | recvData[len] = '\0'; // Terminate the buffer with 0 for proper printout! 87 | 88 | Serial.println("\tReceived " + String(len) + " bytes over the client on connection #" + String(client_num)); 89 | Serial.println("\tReceived: " + String(recvData)); 90 | } else if (resp_type == USERCB_RECO) { 91 | if (len != -11) { // ignore "not connected" error, handled in USERCB_CONN 92 | Serial.print("\tConnection problem: "); 93 | Serial.println(getErrTxt(len)); 94 | } 95 | } else if (resp_type == USERCB_CONN) { 96 | if (len == 0) { 97 | Serial.println("\tDisconnected"); 98 | } else { 99 | Serial.println("\tConnected"); 100 | } 101 | } else { 102 | Serial.println("Received invalid response type"); 103 | } 104 | } 105 | 106 | // Callback made from esp-link to notify of wifi status changes 107 | // Here we print something out and set a global flag 108 | void wifiCb(void *response) { 109 | ELClientResponse *res = (ELClientResponse*)response; 110 | if (res->argc() == 1) { 111 | uint8_t status; 112 | res->popArg(&status, 1); 113 | 114 | if(status == STATION_GOT_IP) { 115 | Serial.println(F("WIFI CONNECTED")); 116 | wifiConnected = true; 117 | } else { 118 | Serial.print(F("WIFI NOT READY: ")); 119 | Serial.println(status); 120 | wifiConnected = false; 121 | } 122 | } 123 | } 124 | 125 | void setup() { 126 | Serial.begin(115200); 127 | //########################################################### 128 | // For ARDUINO UNO WIFI with I2C to serial chip! 129 | //########################################################### 130 | i2cuart.begin(9600); 131 | 132 | Serial.println(F("EL-Client starting!")); 133 | 134 | // Sync-up with esp-link, this is required at the start of any sketch and initializes the 135 | // callbacks to the wifi status change callback. The callback gets called with the initial 136 | // status right after Sync() below completes. 137 | esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired) 138 | bool ok; 139 | do { 140 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 141 | if (!ok) Serial.println(F("EL-Client sync failed!")); 142 | } while(!ok); 143 | Serial.println(F("EL-Client synced!")); 144 | 145 | // Wit for WiFi to be connected. 146 | esp.GetWifiStatus(); 147 | ELClientPacket *packet; 148 | Serial.print(F("Waiting for WiFi ")); 149 | if ((packet=esp.WaitReturn()) != NULL) { 150 | Serial.print(F(".")); 151 | Serial.println(packet->value); 152 | } 153 | Serial.println(""); 154 | 155 | // Set up the TCP socket client for a connection to on port <>, this doesn't connect to that server, 156 | // it just sets-up stuff on the esp-link side and waits until we send some data 157 | tcpConnNum = tcp.begin(tcpServer, tcpPort, SOCKET_TCP_CLIENT, tcpCb); // SOCKET_CLIENT ==> we don't expect a response 158 | if (tcpConnNum < 0) { 159 | Serial.println(F("TCP socket setup failed, try again in 10 seconds after reboot")); 160 | delay(10000); 161 | asm volatile (" jmp 0"); 162 | } else { 163 | Serial.println(String(tcpServer)+":"+String(tcpPort)+" is served over connection number # = "+String(tcpConnNum)); 164 | } 165 | 166 | Serial.println(F("EL-TCP ready")); 167 | wait = millis()+29000; // Start first sending in 1 second 168 | } 169 | 170 | void loop() { 171 | // process any callbacks coming from esp_link 172 | esp.Process(); 173 | 174 | // if we're connected send data over TCP socket 175 | if(wifiConnected) { 176 | if (millis() - wait > 30000) { // Send some data every 30 seconds 177 | wait = millis(); 178 | 179 | // Send message to the previously set-up server #1 180 | Serial.print(F("Sending message to ")); 181 | Serial.print(tcpServer); 182 | Serial.print(":"); 183 | Serial.println(tcpPort); 184 | tcp.send("Message from Arduino Uno WiFi over TCP"); 185 | } 186 | } else { 187 | // This is just for demo, you can as well just try to reconnect 188 | // and setup the connection to esp-link again 189 | Serial.println(F("Lost WiFi connection, try to reboot")); 190 | delay(10000); 191 | asm volatile (" jmp 0"); 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /ELClient/examples/tcp_client_resp/tcp_client_resp.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple example to demo the El-Client TCP client 3 | * This example sends out a message to a TCP socket server 4 | * and waits for a response from the server 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | // IP address for this demo is a local IP. 11 | // Replace it with the IP address where you have a TCP socket server running 12 | char * const tcpServer PROGMEM = "192.168.0.102"; 13 | // Port for this demo is the port used by the TCP socket server. 14 | // Replace it with the port that your TCP socket server is listening to 15 | uint16_t const tcpPort PROGMEM = 7001; 16 | 17 | //########################################################### 18 | // For ARDUINO UNO WIFI with I2C to serial chip! 19 | //########################################################### 20 | // Serial port to ESP8266 21 | #include 22 | SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA); 23 | 24 | // Initialize a connection to esp-link using the I2Cuart chip of the Arduino Uno WiFi board for 25 | // SLIP messages. 26 | ELClient esp(&i2cuart); 27 | 28 | //########################################################### 29 | // For boards using the hardware serial port! 30 | //########################################################### 31 | // Initialize a connection to esp-link using the normal hardware serial port both for 32 | // SLIP and for debug messages. 33 | //ELClient esp(&Serial, &Serial); 34 | 35 | // Initialize a TCP socket client on the connection to esp-link 36 | ELClientSocket tcp(&esp); 37 | // Connection number for tcp 38 | int tcpConnNum; 39 | 40 | // Timer value to send out data 41 | uint32_t wait; 42 | // Time to wait between sending out data 43 | uint32_t waitTime; 44 | // Flag for wifi connection 45 | boolean wifiConnected = false; 46 | 47 | // Parse error codes and returns error message as char * 48 | // Definitions from error values from espconn.h (Espressif SDK) 49 | // #define ESPCONN_OK 0 /**< No error, everything OK. */ 50 | // #define ESPCONN_MEM -1 /**< Out of memory. */ 51 | // #define ESPCONN_TIMEOUT -3 /**< Timeout. */ 52 | // #define ESPCONN_RTE -4 /**< Routing problem. */ 53 | // #define ESPCONN_INPROGRESS -5 /**< Operation in progress. */ 54 | // #define ESPCONN_MAXNUM -7 /**< Total number exceeds the maximum limitation. */ 55 | 56 | // #define ESPCONN_ABRT -8 /**< Connection aborted. */ 57 | // #define ESPCONN_RST -9 /**< Connection reset. */ 58 | // #define ESPCONN_CLSD -10 /**< Connection closed. */ 59 | // #define ESPCONN_CONN -11 /**< Not connected. */ 60 | 61 | // #define ESPCONN_ARG -12 /**< Illegal argument. */ 62 | // #define ESPCONN_IF -14 /**< UDP send error. */ 63 | // #define ESPCONN_ISCONN -15 /**< Already connected. */ 64 | 65 | char* const errTxt[] PROGMEM = {"No error, everything OK.","Out of memory.","Unknown code.","Timeout.","Routing problem.","Operation in progress.", 66 | "Unknown code.","Total number exceeds the maximum limitation.","Connection aborted.","Connection reset.","Connection closed.", 67 | "Not connected.","Illegal argument.","Unknown code.","UDP send error.","Already connected."}; 68 | char * getErrTxt(int16_t commError) { 69 | commError = commError*-1; 70 | if (commError <= 15) { 71 | return (char *) pgm_read_word (&errTxt[commError]); 72 | } else { 73 | return (char *) pgm_read_word (&errTxt[2]); // Unknown code 74 | } 75 | } 76 | 77 | // Callback for TCP socket, called if data was sent or received 78 | // Receives socket client number, can be reused for all initialized TCP socket connections 79 | void tcpCb(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data) { 80 | Serial.println("tcpCb connection #"+String(client_num)); 81 | if (resp_type == USERCB_SENT) { 82 | Serial.println("\tSent " + String(len) + " bytes over client#" + String(client_num)); 83 | } else if (resp_type == USERCB_RECV) { 84 | char recvData[len+1]; // Prepare buffer for the received data 85 | memcpy(recvData, data, len); // Copy received data into the buffer 86 | recvData[len] = '\0'; // Terminate the buffer with 0 for proper printout! 87 | 88 | Serial.println("\tReceived " + String(len) + " bytes over the client on connection #" + String(client_num)); 89 | Serial.println("\tReceived: " + String(recvData)); 90 | } else if (resp_type == USERCB_RECO) { 91 | if (len != -11) { // ignore "not connected" error, handled in USERCB_CONN 92 | Serial.print("\tConnection problem: "); 93 | Serial.println(getErrTxt(len)); 94 | } 95 | } else if (resp_type == USERCB_CONN) { 96 | if (len == 0) { 97 | Serial.println("\tDisconnected"); 98 | } else { 99 | Serial.println("\tConnected"); 100 | } 101 | } else { 102 | Serial.println("Received invalid response type"); 103 | } 104 | } 105 | 106 | // Callback made from esp-link to notify of wifi status changes 107 | // Here we print something out and set a global flag 108 | void wifiCb(void *response) { 109 | ELClientResponse *res = (ELClientResponse*)response; 110 | if (res->argc() == 1) { 111 | uint8_t status; 112 | res->popArg(&status, 1); 113 | 114 | if(status == STATION_GOT_IP) { 115 | Serial.println(F("WIFI CONNECTED")); 116 | wifiConnected = true; 117 | } else { 118 | Serial.print(F("WIFI NOT READY: ")); 119 | Serial.println(status); 120 | wifiConnected = false; 121 | } 122 | } 123 | } 124 | 125 | void setup() { 126 | Serial.begin(115200); 127 | //########################################################### 128 | // For ARDUINO UNO WIFI with I2C to serial chip! 129 | //########################################################### 130 | i2cuart.begin(9600); 131 | 132 | Serial.println(F("EL-Client starting!")); 133 | 134 | // Sync-up with esp-link, this is required at the start of any sketch and initializes the 135 | // callbacks to the wifi status change callback. The callback gets called with the initial 136 | // status right after Sync() below completes. 137 | esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired) 138 | bool ok; 139 | do { 140 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 141 | if (!ok) Serial.println(F("EL-Client sync failed!")); 142 | } while(!ok); 143 | Serial.println(F("EL-Client synced!")); 144 | 145 | // Wit for WiFi to be connected. 146 | esp.GetWifiStatus(); 147 | ELClientPacket *packet; 148 | Serial.print(F("Waiting for WiFi ")); 149 | if ((packet=esp.WaitReturn()) != NULL) { 150 | Serial.print(F(".")); 151 | Serial.println(packet->value); 152 | } 153 | Serial.println(""); 154 | 155 | // Set up the TCP socket client for a connection to on port <>, this doesn't connect to that server, 156 | // it just sets-up stuff on the esp-link side and waits until we send some data 157 | tcpConnNum = tcp.begin(tcpServer, tcpPort, SOCKET_TCP_CLIENT_LISTEN, tcpCb); // SOCKET_CLIENT ==> we expect a response 158 | if (tcpConnNum < 0) { 159 | Serial.println(F("TCP socket setup failed, try again in 10 seconds after reboot")); 160 | delay(10000); 161 | asm volatile (" jmp 0"); 162 | } else { 163 | Serial.println(String(tcpServer)+":"+String(tcpPort)+" is served over connection number # = "+String(tcpConnNum)); 164 | } 165 | 166 | Serial.println(F("EL-TCP ready")); 167 | wait = millis()+29000; // Start first sending in 1 second 168 | } 169 | 170 | void loop() { 171 | // process any callbacks coming from esp_link 172 | esp.Process(); 173 | 174 | // if we're connected send data over TCP socket 175 | if(wifiConnected) { 176 | if (millis() - wait > 30000) { // Send some data every 30 seconds 177 | wait = millis(); 178 | 179 | // Send message to the previously set-up server #1 180 | Serial.print(F("Sending message to ")); 181 | Serial.print(tcpServer); 182 | Serial.print(":"); 183 | Serial.println(tcpPort); 184 | tcp.send("Message from Uno WiFi over TCP socket"); 185 | } 186 | } else { 187 | // This is just for demo, you can as well just try to reconnect 188 | // and setup the connection to esp-link again 189 | Serial.println(F("Lost WiFi connection, try to reboot")); 190 | delay(10000); 191 | asm volatile (" jmp 0"); 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /ELClient/examples/tcp_server/tcp_server.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple example to demo the El-Client TCP server 3 | * This example starts a TCP socket server and waits 4 | * for clients to connect 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | // IP address for this demo is a local IP. 11 | // Replace it with the IP address where you have a TCP socket server running 12 | char * const tcpServer PROGMEM = "192.168.0.102"; 13 | // Port for this demo is the port used by the TCP socket server. 14 | // Replace it with the port that your TCP socket server is listening to 15 | uint16_t const tcpPort PROGMEM = 7002; 16 | 17 | //########################################################### 18 | // For ARDUINO UNO WIFI with I2C to serial chip! 19 | //########################################################### 20 | // Serial port to ESP8266 21 | #include 22 | SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA); 23 | 24 | // Initialize a connection to esp-link using the I2Cuart chip of the Arduino Uno WiFi board for 25 | // SLIP messages. 26 | ELClient esp(&i2cuart); 27 | 28 | //########################################################### 29 | // For boards using the hardware serial port! 30 | //########################################################### 31 | // Initialize a connection to esp-link using the normal hardware serial port both for 32 | // SLIP and for debug messages. 33 | //ELClient esp(&Serial, &Serial); 34 | 35 | // Initialize a TCP socket client on the connection to esp-link 36 | ELClientSocket tcp(&esp); 37 | // Connection number for tcp 38 | int tcpConnNum; 39 | 40 | // Timer value to send out data 41 | uint32_t wait; 42 | // Time to wait between sending out data 43 | uint32_t waitTime; 44 | // Flag for wifi connection 45 | boolean wifiConnected = false; 46 | 47 | // Parse error codes and returns error message as char * 48 | // Definitions from error values from espconn.h (Espressif SDK) 49 | // #define ESPCONN_OK 0 /**< No error, everything OK. */ 50 | // #define ESPCONN_MEM -1 /**< Out of memory. */ 51 | // #define ESPCONN_TIMEOUT -3 /**< Timeout. */ 52 | // #define ESPCONN_RTE -4 /**< Routing problem. */ 53 | // #define ESPCONN_INPROGRESS -5 /**< Operation in progress. */ 54 | // #define ESPCONN_MAXNUM -7 /**< Total number exceeds the maximum limitation. */ 55 | 56 | // #define ESPCONN_ABRT -8 /**< Connection aborted. */ 57 | // #define ESPCONN_RST -9 /**< Connection reset. */ 58 | // #define ESPCONN_CLSD -10 /**< Connection closed. */ 59 | // #define ESPCONN_CONN -11 /**< Not connected. */ 60 | 61 | // #define ESPCONN_ARG -12 /**< Illegal argument. */ 62 | // #define ESPCONN_IF -14 /**< UDP send error. */ 63 | // #define ESPCONN_ISCONN -15 /**< Already connected. */ 64 | 65 | char* const errTxt[] PROGMEM = {"No error, everything OK.","Out of memory.","Unknown code.","Timeout.","Routing problem.","Operation in progress.", 66 | "Unknown code.","Total number exceeds the maximum limitation.","Connection aborted.","Connection reset.","Connection closed.", 67 | "Not connected.","Illegal argument.","Unknown code.","UDP send error.","Already connected."}; 68 | char * getErrTxt(int16_t commError) { 69 | commError = commError*-1; 70 | if (commError <= 15) { 71 | return (char *) pgm_read_word (&errTxt[commError]); 72 | } else { 73 | return (char *) pgm_read_word (&errTxt[2]); // Unknown code 74 | } 75 | } 76 | 77 | // Callback for TCP socket, called if data was sent or received 78 | // Receives socket client number, can be reused for all initialized TCP socket connections 79 | void tcpCb(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data) { 80 | Serial.println("tcpCb connection #"+String(client_num)); 81 | if (resp_type == USERCB_SENT) { 82 | Serial.println("\tSent " + String(len) + " bytes over client#" + String(client_num)); 83 | } else if (resp_type == USERCB_RECV) { 84 | char recvData[len+1]; // Prepare buffer for the received data 85 | memcpy(recvData, data, len); // Copy received data into the buffer 86 | recvData[len] = '\0'; // Terminate the buffer with 0 for proper printout! 87 | 88 | Serial.println("\tReceived " + String(len) + " bytes over the server on connection #" + String(client_num)); 89 | Serial.println("\tReceived: " + String(recvData)); 90 | // TODO add some functions to react to the received data 91 | char respData[len+11]; // Prepare buffer for the response data 92 | char *respHdr = "Received: "; 93 | memcpy (respData, respHdr, 10); 94 | memcpy(&respData[10], recvData, len); // Copy received data into the buffer 95 | respData[len+10] = '\0'; 96 | Serial.println("\tSend response: " + String(respData)); 97 | tcp.send(respData); 98 | } else if (resp_type == USERCB_RECO) { 99 | if (len != -11) { // ignore "not connected" error, handled in USERCB_CONN 100 | Serial.print("\tConnection problem: "); 101 | Serial.println(getErrTxt(len)); 102 | } 103 | } else if (resp_type == USERCB_CONN) { 104 | if (len == 0) { 105 | Serial.println("\tDisconnected"); 106 | } else { 107 | Serial.println("\tConnected"); 108 | } 109 | } else { 110 | Serial.println("Received invalid response type"); 111 | } 112 | } 113 | 114 | // Callback made from esp-link to notify of wifi status changes 115 | // Here we print something out and set a global flag 116 | void wifiCb(void *response) { 117 | ELClientResponse *res = (ELClientResponse*)response; 118 | if (res->argc() == 1) { 119 | uint8_t status; 120 | res->popArg(&status, 1); 121 | 122 | if(status == STATION_GOT_IP) { 123 | Serial.println(F("WIFI CONNECTED")); 124 | wifiConnected = true; 125 | } else { 126 | Serial.print(F("WIFI NOT READY: ")); 127 | Serial.println(status); 128 | wifiConnected = false; 129 | } 130 | } 131 | } 132 | 133 | void setup() { 134 | Serial.begin(115200); 135 | //########################################################### 136 | // For ARDUINO UNO WIFI with I2C to serial chip! 137 | //########################################################### 138 | i2cuart.begin(9600); 139 | 140 | Serial.println(F("EL-Client starting!")); 141 | 142 | // Sync-up with esp-link, this is required at the start of any sketch and initializes the 143 | // callbacks to the wifi status change callback. The callback gets called with the initial 144 | // status right after Sync() below completes. 145 | esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired) 146 | bool ok; 147 | do { 148 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 149 | if (!ok) Serial.println(F("EL-Client sync failed!")); 150 | } while(!ok); 151 | Serial.println(F("EL-Client synced!")); 152 | 153 | // Wit for WiFi to be connected. 154 | esp.GetWifiStatus(); 155 | ELClientPacket *packet; 156 | Serial.print(F("Waiting for WiFi ")); 157 | if ((packet=esp.WaitReturn()) != NULL) { 158 | Serial.print(F(".")); 159 | Serial.println(packet->value); 160 | } 161 | Serial.println(""); 162 | 163 | // Set up the TCP socket server to wait for a client on port <>, 164 | // it just sets-up stuff on the esp-link side and waits until a client sends some data 165 | tcpConnNum = tcp.begin(tcpServer, tcpPort, SOCKET_TCP_SERVER, tcpCb); // SOCKET_SERVER ==> accept connections 166 | if (tcpConnNum < 0) { 167 | Serial.println(F("TCP socket setup failed, try again in 10 seconds after reboot")); 168 | delay(10000); 169 | asm volatile (" jmp 0"); 170 | } else { 171 | Serial.println(String(tcpServer)+":"+String(tcpPort)+" is served over connection number # = "+String(tcpConnNum)); 172 | } 173 | Serial.println(F("EL-TCP ready")); 174 | } 175 | 176 | void loop() { 177 | // process any callbacks coming from esp_link 178 | esp.Process(); 179 | } 180 | -------------------------------------------------------------------------------- /ELClient/examples/test-reset/Makefile: -------------------------------------------------------------------------------- 1 | ESP_HOSTNAME ?= esp-link 2 | LIBRARYPATH = $(ARDUINODIR)/libraries ../../.. 3 | LIBRARIES = ELClient 4 | CPPFLAGS = 5 | SERIALDEV = net:$(ESP_HOSTNAME):2323 6 | include ../arduino.mk 7 | 8 | flash: all 9 | ../avrflash $(ESP_HOSTNAME) test.hex 10 | nc $(ESP_HOSTNAME) 23 11 | 12 | run: upload size 13 | nc $(ESP_HOSTNAME) 23 14 | -------------------------------------------------------------------------------- /ELClient/examples/test-reset/README.md: -------------------------------------------------------------------------------- 1 | MQTT example 2 | ============ 3 | 4 | This is a simple example of a sketch that subscribes to an mqtt topic and then publishes messages 5 | to that topic, which it subsequently receives and prints. 6 | 7 | **Important** For this sketch to work you must turn off the UART debug log in esp-link (on 8 | the Debug Log page). The reason is that otherwise esp-link prints too much to its uart andthen 9 | misses incoming characters. 10 | -------------------------------------------------------------------------------- /ELClient/examples/test-reset/test.hex: -------------------------------------------------------------------------------- 1 | :100000000C9436000C945E000C945E000C945E0020 2 | :100010000C945E000C945E000C945E000C945E00E8 3 | :100020000C945E000C945E000C945E000C945E00D8 4 | :100030000C945E000C945E000C945E000C945E00C8 5 | :100040000C9412010C945E000C94A3010C94D50145 6 | :100050000C945E000C945E000C945E000C945E00A8 7 | :100060000C945E000C945E000501050211241FBE75 8 | :10007000CFEFD8E0DEBFCDBF11E0A0E0B1E0ECE310 9 | :10008000F2E102C005900D92A83EB107D9F723E036 10 | :10009000A8EEB1E001C01D92AA32B207E1F710E06C 11 | :1000A000CCE6D0E004C02297FE010E941809C836B1 12 | :1000B000D107C9F70E948E030C941C090C94000010 13 | :1000C00066E071E08DE892E00E94E10340ED57E0C8 14 | :1000D00060E070E08EEE91E00E94F207811103C0B3 15 | :1000E0006FE171E0EFCF66E371E08DE892E00C9490 16 | :1000F000E103CF93DF931F92CDB7DEB7DC011496F7 17 | :10010000ED91FC9115972281338121303105F1F475 18 | :1001100041E050E0BE016F5F7F4F0E947608898109 19 | :10012000853039F468E471E08DE892E00E94E103E3 20 | :100130000DC067E571E08DE892E00E94DB034AE0C4 21 | :1001400050E069818DE892E00E9460040F90DF9199 22 | :10015000CF91089526E040E052EC61E070E08DE838 23 | :1001600092E00E942B0369E770E080EF91E00E942B 24 | :10017000BB0880E690E09093F7018093F6010C9421 25 | :100180006000CF92DF92EF92FF928EEE91E00E949C 26 | :10019000ED060E945C01C090E801D090E901E0907A 27 | :1001A000EA01F090EB016C197D098E099F09613A13 28 | :1001B0007F408105910520F168E671E08DE892E0CD 29 | :1001C0000E94E1038CEE91E00E94A9046B017C0186 30 | :1001D00068E771E08DE892E00E94DB032AE030E0FE 31 | :1001E000B701A6018DE892E00E9493040E945C0191 32 | :1001F0006093E8017093E9018093EA019093EB0129 33 | :10020000FF90EF90DF90CF9008954DE852E0BA0153 34 | :100210008EEE91E00E943B056EEE71E08CEE91E077 35 | :100220000C94A5041F920F920FB60F9211242F93D6 36 | :100230003F938F939F93AF93BF938091850290914B 37 | :100240008602A0918702B09188023091840223E057 38 | :10025000230F2D3720F40196A11DB11D05C026E8FE 39 | :10026000230F0296A11DB11D209384028093850265 40 | :1002700090938602A0938702B093880280918902AE 41 | :1002800090918A02A0918B02B0918C020196A11DDF 42 | :10029000B11D8093890290938A02A0938B02B09340 43 | :1002A0008C02BF91AF919F918F913F912F910F90B1 44 | :1002B0000FBE0F901F9018952FB7F894609185028C 45 | :1002C0007091860280918702909188022FBF0895D5 46 | :1002D000789484B5826084BD84B5816084BD85B521 47 | :1002E000826085BD85B5816085BDEEE6F0E08081E8 48 | :1002F00081608083E1E8F0E0108280818260808309 49 | :10030000808181608083E0E8F0E08081816080838B 50 | :10031000E1EBF0E0808184608083E0EBF0E08081BD 51 | :1003200081608083EAE7F0E080818460808380815F 52 | :100330008260808380818160808380818068808307 53 | :100340001092C10008951F920F920FB60F921124C0 54 | :100350002F938F939F93EF93FF93E0919D02F091E2 55 | :100360009E028081E091A302F091A40282FD12C05E 56 | :1003700090818091A6028F5F8F732091A7028217D0 57 | :1003800051F0E091A602F0E0E357FD4F958F809386 58 | :10039000A60201C08081FF91EF919F918F912F91D3 59 | :1003A0000F900FBE0F901F9018951F920F920FB6CF 60 | :1003B0000F9211242F933F934F935F936F937F93EB 61 | :1003C0008F939F93AF93BF93EF93FF938DE892E04A 62 | :1003D0000E948302FF91EF91BF91AF919F918F9106 63 | :1003E0007F916F915F914F913F912F910F900FBE31 64 | :1003F0000F901F9018958DE892E00E94480221E02E 65 | :10040000892B09F420E0822F089510929002109217 66 | :100410008F0288EE93E0A0E0B0E080939102909389 67 | :100420009202A0939302B093940283E891E0909398 68 | :100430008E0280938D0285EC90E090939A028093D7 69 | :10044000990284EC90E090939C0280939B0280EC54 70 | :1004500090E090939E0280939D0281EC90E09093B7 71 | :10046000A00280939F0282EC90E09093A20280937E 72 | :10047000A10286EC90E09093A4028093A3021092D4 73 | :10048000A6021092A7021092A8021092A902089543 74 | :10049000FC01818D228D90E0805C9F4F821B910931 75 | :1004A0008F7399270895FC01918D828D981731F0F3 76 | :1004B000828DE80FF11D858D90E008958FEF9FEFFD 77 | :1004C0000895FC01918D828D981761F0828DDF0176 78 | :1004D000A80FB11D5D968C91928D9F5F9F73928F37 79 | :1004E00090E008958FEF9FEF08958BEF91E0892BB7 80 | :1004F00049F080E090E0892B29F00E94FB018111F6 81 | :100500000C9400000895FC01848DDF01A80FB11D3B 82 | :10051000A35ABF4F2C91848D90E001968F73992739 83 | :10052000848FA689B7892C93A089B1898C91806426 84 | :100530008C93938D848D981306C00288F389E02DE7 85 | :1005400080818F7D80830895CF93DF93EC01888D28 86 | :100550008823C9F0EA89FB89808185FD05C0A889C7 87 | :10056000B9898C9186FD0FC00FB607FCF5CF80814D 88 | :1005700085FFF2CFA889B9898C9185FFEDCFCE0197 89 | :100580000E948302E7CFDF91CF910895CF92DF924F 90 | :10059000FF920F931F93CF93DF931F92CDB7DEB7D8 91 | :1005A0006C0181E0D60158968C9358975B969C918C 92 | :1005B0005B975C968C915C97981307C05096ED9171 93 | :1005C000FC915197808185FD2EC0F601038D10E0CE 94 | :1005D0000F5F1F4F0F731127F02EF601848DF81255 95 | :1005E00011C00FB607FCF9CFD6015096ED91FC91E2 96 | :1005F0005197808185FFF1CFC60169830E948302F4 97 | :100600006981EBCF838DE80FF11DE35AFF4F6083C3 98 | :10061000D6015B960C935B975296ED91FC915397A4 99 | :10062000808180620CC0D6015696ED91FC9157975F 100 | :1006300060835096ED91FC91519780818064808316 101 | :1006400081E090E00F90DF91CF911F910F91FF908B 102 | :10065000DF90CF900895BF92CF92DF92EF92FF92FA 103 | :10066000CF93DF93EC016A017B01B22EE889F9890F 104 | :1006700082E08083411581EE580761057105A1F084 105 | :1006800060E079E08DE390E0A70196010E94F40814 106 | :1006900021503109410951095695479537952795BC 107 | :1006A000211580E1380798F0E889F989108260E81F 108 | :1006B00074E88EE190E0A70196010E94F4082150B1 109 | :1006C0003109410951095695479537952795EC858C 110 | :1006D000FD853083EE85FF852083188EEC89FD89AA 111 | :1006E000B082EA89FB89808180618083EA89FB8905 112 | :1006F000808188608083EA89FB898081806880832B 113 | :10070000EA89FB8980818F7D8083DF91CF91FF9083 114 | :10071000EF90DF90CF90BF90089508950E946801F8 115 | :100720000E948D030E94AA00C5E7D2E00E94C1008A 116 | :100730002097E1F30E947502F9CFCF92DF92EF92FA 117 | :10074000FF920F931F93CF93DF936C017A01EB011C 118 | :10075000E60EF71E00E010E0CE15DF0561F06991AE 119 | :10076000D601ED91FC910190F081E02DC601099533 120 | :10077000080F191FF1CFC801DF91CF911F910F9181 121 | :10078000FF90EF90DF90CF9008956115710581F093 122 | :10079000DB010D900020E9F7AD0141505109461BE6 123 | :1007A000570BDC01ED91FC910280F381E02D09945F 124 | :1007B00080E090E008950C94C5036FE871E00C941C 125 | :1007C000C5030F931F93CF93DF93EC010E94C503E2 126 | :1007D0008C01CE010E94DD03800F911FDF91CF912C 127 | :1007E0001F910F9108958F929F92AF92BF92CF92D7 128 | :1007F000DF92EF92FF920F931F93CF93DF93CDB7CA 129 | :10080000DEB7A1970FB6F894DEBF0FBECDBF7C0157 130 | :10081000C42EE52FCB01D22E19A221E02D1510F008 131 | :100820002AE0D22E8E010F5D1F4F8D2C912CA12C12 132 | :10083000B12C6C2D7E2FA50194010E94F4088C2D03 133 | :10084000D29E80191124015011098A3010F4805D64 134 | :1008500001C0895CF80180832115310541055105EE 135 | :1008600021F0C22EE32FCA01E4CFB801C7010E94D4 136 | :10087000C503A1960FB6F894DEBF0FBECDBFDF91C2 137 | :10088000CF911F910F91FF90EF90DF90CF90BF908D 138 | :10089000AF909F908F9008952115310541F4DC01B0 139 | :1008A000ED91FC910190F081E02D642F09940C945E 140 | :1008B000F3039A01462F50E060E070E00C944C0482 141 | :1008C0000F931F93CF93DF93EC019A01462F50E0D3 142 | :1008D00060E070E00E944C048C01CE010E94DD03B8 143 | :1008E000800F911FDF91CF911F910F9108959A0171 144 | :1008F000AB0160E070E00C944C040F931F93CF9316 145 | :10090000DF93EC019A01AB0160E070E00E944C04BF 146 | :100910008C01CE010E94DD03800F911FDF91CF91EA 147 | :100920001F910F9108950F931F93CF93DF93EC01C5 148 | :100930000E944C048C01CE010E94DD03800F911FA8 149 | :10094000DF91CF911F910F910895FC017183608316 150 | :1009500008950F931F93CF93DF93EC0100E010E015 151 | :1009600020E030E0A90167E070E0888199810E9471 152 | :100970007507888199810E94250540ED57E060E068 153 | :1009800070E0888199810E944607009731F0FC0150 154 | :10099000648175818681978103C060E070E0CB013E 155 | :1009A000DF91CF911F910F910895CF93DF93EC01C9 156 | :1009B0008A859B85603CA1F06B3D21F5DC01ED91C2 157 | :1009C000FC910190F081E02D6BED09958A859B8566 158 | :1009D000DC01ED91FC910190F081E02D6DED18C0EE 159 | :1009E000DC01ED91FC910190F081E02D6BED09951A 160 | :1009F0008A859B85DC01ED91FC910190F081E02DD1 161 | :100A00006CED06C0DC01ED91FC910190F081E02DD0 162 | :100A1000DF91CF910994EF92FF920F931F93CF93A1 163 | :100A2000DF937C018A01EB01060F171FC017D10766 164 | :100A300029F06991C7010E94D504F8CFDF91CF91C9 165 | :100A40001F910F91FF90EF900895CF93DF93EC01EA 166 | :100A5000BC01635F7F4F42E050E00E940B058A8536 167 | :100A60009B85DC01ED91FC910190F081E02D60EC23 168 | :100A7000DF91CF9109940F931F93CF93DF93EC01F4 169 | :100A80008B01FC0141935193CF010E94B5081B8754 170 | :100A90000A8781E08C87CE014696988B8F8780E805 171 | :100AA00090E09A8B898B1C8A1B8A1D8ADF91CF91DB 172 | :100AB0001F910F910895FC012485222321F080814C 173 | :100AC00091810C94E1030895462754274527542724 174 | :100AD0009A01222784E0220F331F8A95E1F7242709 175 | :100AE0003527C901892F992782958F7082279327EF 176 | :100AF0009C01222755E0369527955A95E1F78227E4 177 | :100B000093270895EF92FF920F931F93CF93DF9354 178 | :100B10007C018A01C901EB01060F171FC017D1071D 179 | :100B200031F06991AC01C7010E946405F7CFDF91F4 180 | :100B3000CF911F910F91FF90EF900895AF92BF92C8 181 | :100B4000CF92DF92EF92FF920F931F93CF93DF9399 182 | :100B500000D000D000D0CDB7DEB78C01DC011F96ED 183 | :100B6000ED90FC9050971C968C911C97882309F46B 184 | :100B70007DC060EA71E08D919C910E94DB03F801D9 185 | :100B8000638974894AE050E0808191810E947704F2 186 | :100B90006AEA71E0D8018D919C910E94DB03F80113 187 | :100BA00047855089662757FD6095762F20E130E014 188 | :100BB000808191810E944C046EEC71E0D8018D918E 189 | :100BC0009C910E94DB03F7016081718140E150E05C 190 | :100BD000D8018D919C910E9477046FEC71E0F8012F 191 | :100BE000808191810E94DB03D70114964D915D9124 192 | :100BF0006D917C91179720E130E0F801808191811F 193 | :100C00000E944C046FEC71E0D8018D919C910E9480 194 | :100C1000DB03F7016281738140E150E0D8018D91DF 195 | :100C20009C910E94770468E0C62ED12CF80123899C 196 | :100C3000348980819181C216D306B0F46FEC71E0E3 197 | :100C40000E94DB03D8011F96ED91FC915097EC0DAB 198 | :100C5000FD1D40E150E060818D919C910E945904FE 199 | :100C6000BFEFCB1ADB0AE2CF0E94DD03D801539617 200 | :100C7000CD90DC905497B2E0CB1AD108F801A7844C 201 | :100C8000B08820E030E0A601B501C8010E948205CD 202 | :100C9000F501EC0DFD1D208131818217930731F0A4 203 | :100CA0006DEA71E0C8010E945B0582C0D7018D9199 204 | :100CB0009C918230910539F083309105F1F00197D4 205 | :100CC00009F06CC05BC0F8018485882309F473C007 206 | :100CD0006EEB71E0808191810E94DB03D701149655 207 | :100CE0004D915D916D917C9117972AE030E0F8016C 208 | :100CF000808191810E9493045EC0D8011C968C91E2 209 | :100D00001C97882329F167EC71E08D919C910E94DA 210 | :100D1000DB03F70144815581668177812AE030E069 211 | :100D2000D8018D919C910E944C046FEC71E0F80108 212 | :100D3000808191810E94DB03D70112966D917C9195 213 | :100D400013974AE050E0F801808191810E947D0470 214 | :100D5000D70114960D911C911597C8010E94E608C1 215 | :100D6000882331F1B701CE0101960E946C08BE01C3 216 | :100D70006F5F7F4FC8010E94BF081AC061ED71E02C 217 | :100D8000F801808191810E94E103D8011896ED91CC 218 | :100D9000FC911997309761F009950AC0F801848594 219 | :100DA000882331F06CED71E0808191810E94E10334 220 | :100DB00080E090E001C0C70126960FB6F894DEBF30 221 | :100DC0000FBECDBFDF91CF911F910F91FF90EF909C 222 | :100DD000DF90CF90BF90AF9008951F93CF93DF9394 223 | :100DE000EC0111E08A859B85DC01ED91FC9104808A 224 | :100DF000F581E02D0995892B09F442C08A859B85F0 225 | :100E0000DC01ED91FC910680F781E02D09958B3D89 226 | :100E1000910511F41D8BE6CF2B893C89803C91050F 227 | :100E200079F42830310520F0CE010E949E0502C0E1 228 | :100E300080E090E01C8A1B8A1D8A009799F222C0EC 229 | :100E40004D89442361F08C3D910531F08D3D910534 230 | :100E500029F48BED90E002C080EC90E01D8A498976 231 | :100E60005A892417350708F0BDCFEF85F889A90105 232 | :100E70004F5F5F4F5C8B4B8BE20FF31F8083B2CFD2 233 | :100E800080E090E0DF91CF911F9108958F929F9223 234 | :100E9000AF92BF92CF92DF92EF92FF92CF93DF9308 235 | :100EA000EC016A017B010E945C014B015C010E9424 236 | :100EB0005C01681979098A099B096C157D058E0505 237 | :100EC0009F0530F4CE010E94ED06009781F302C029 238 | :100ED00080E090E0DF91CF91FF90EF90DF90CF9096 239 | :100EE000BF90AF909F908F900895EF92FF920F93D5 240 | :100EF0001F93CF93DF93CDB7DEB728970FB6F89443 241 | :100F0000DEBF0FBECDBF7C017A8369832B833C8318 242 | :100F10004D835E8318870F83DC011E961C921E9200 243 | :100F20001D971A968D919C911B97DC01ED91FC9178 244 | :100F30000190F081E02D60EC099542E050E0BE01A7 245 | :100F40006F5F7F4FC7010E940B05F701258536852E 246 | :100F500042E050E0BE016F5F7F4FC7010E948205F3 247 | :100F6000D7011E969C938E931D9742E050E0BE01E0 248 | :100F7000695F7F4FC7010E940B05F7012585368504 249 | :100F800042E050E0BE01695F7F4FC7010E948205C9 250 | :100F9000D7011E969C938E931D9744E050E0BE01AE 251 | :100FA0006D5F7F4FC7010E940B05F70125853685D0 252 | :100FB00044E050E0BE016D5F7F4FC7010E94820593 253 | :100FC000D7011E969C938E931D9728960FB6F89482 254 | :100FD000DEBF0FBECDBFDF91CF911F910F91FF906C 255 | :100FE000EF9008956F927F928F929F92AF92BF92EF 256 | :100FF000CF92DF92EF92FF920F931F93CF93DF93E5 257 | :10100000EC014A015B018A859B85DC01ED91FC9135 258 | :101010000190F081E02D60EC09956E01B2E0CB0EFD 259 | :10102000D11CEE24D7FCE094FE2C00E010E0A701D8 260 | :10103000960161E070E0CE010E947507CE010E942A 261 | :1010400025050885198519861886B501A401CE01E4 262 | :101050000E9446073C01009769F1F3018481958164 263 | :10106000A681B7812C858C159D05AE05BF0561F461 264 | :10107000222331F066ED71E0888199810E94E103BD 265 | :101080001987088781E019C02223F9F262EE71E026 266 | :10109000888199810E94DB03D30114964D915D9163 267 | :1010A0006D917C9117972AE030E0888199810E94A8 268 | :1010B0009304CBCF1987088780E0DF91CF911F91F0 269 | :1010C0000F91FF90EF90DF90CF90BF90AF909F90E7 270 | :1010D0008F907F906F900895FC0175836483685FA3 271 | :1010E0007F4F738362831182108208950F931F9341 272 | :1010F000CF93DF93FC01A081B181C481D5818A8126 273 | :101100009B81A817B90750F5C281D38129913991E4 274 | :101110008EEF9FEF821B930B83709927D383C2833B 275 | :101120001196B183A0838E01EB01DA0124173507F4 276 | :1011300008F4D9016A0F7B1FC617D70729F0D80119 277 | :101140004D918D014993F8CF820F931F42815381B6 278 | :10115000480F591F53834283C90102C08FEF9FEF8D 279 | :10116000DF91CF911F910F910895FC0111821082A0 280 | :10117000138212820895FC01738362830895DC0157 281 | :101180001296ED91FC9113973097F9F02D913C91C7 282 | :10119000119721153105B9F014968D919C911597F1 283 | :1011A000AC015595479580FF0AC0D901A40FB51F22 284 | :1011B0000D90BC91A02DAE0FBF1FED91FC91C90108 285 | :1011C000840F951F0994CB0109940895FC01808137 286 | :1011D0009181892B39F481E022813381232B19F409 287 | :1011E00080E0089581E00895A1E21A2EAA1BBB1B9E 288 | :1011F000FD010DC0AA1FBB1FEE1FFF1FA217B307E3 289 | :10120000E407F50720F0A21BB30BE40BF50B661FF8 290 | :10121000771F881F991F1A9469F7609570958095BC 291 | :1012200090959B01AC01BD01CF010895EE0FFF1F0A 292 | :0C1230000590F491E02D0994F894FFCF94 293 | :10123C0000002A038000454C2D436C69656E7420B8 294 | :10124C002872652D297374617274696E672100456B 295 | :10125C004C2D436C69656E742073796E63206661E6 296 | :10126C00696C65642100454C2D436C69656E742076 297 | :10127C0073796E63656421005749464920434F4E8C 298 | :10128C004E45435445440057494649204E4F54203F 299 | :10129C0052454144593A2000726571756573746901 300 | :1012AC006E672074696D650054696D653A200000A5 301 | :1012BC00000000C6029D03480261025302A4020D05 302 | :1012CC000A006E616E00696E66006F7666002E0015 303 | :1012DC00454C433A20676F742000204000454C4336 304 | :1012EC003A20496E76616C69642043524300524542 305 | :1012FC0053505F563A2000524553505F43423A20B8 306 | :10130C00004E4545445F53594E432100434D443FE5 307 | :08131C003F004241443A200069 308 | :00000001FF 309 | -------------------------------------------------------------------------------- /ELClient/examples/test-reset/test.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple example to test resetting either arduino or esp-link while doing MQTT 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | // Initialize a connection to esp-link using the normal hardware serial port both for 9 | // SLIP and for debug messages. Esp-link will show the debug messages in the uC console 10 | // because they are not SLIP framed. 11 | ELClient esp(&Serial, &Serial); 12 | 13 | // Initialize CMD client (for GetTime) 14 | ELClientCmd cmd(&esp); 15 | 16 | // Callback made from esp-link to notify of wifi status changes 17 | // Here we just print something out for grins 18 | void wifiCb(void* response) { 19 | ELClientResponse *res = (ELClientResponse*)response; 20 | if (res->argc() == 1) { 21 | uint8_t status; 22 | res->popArg(&status, 1); 23 | 24 | if(status == STATION_GOT_IP) { 25 | Serial.println("WIFI CONNECTED"); 26 | } else { 27 | Serial.print("WIFI NOT READY: "); 28 | Serial.println(status); 29 | } 30 | } 31 | } 32 | 33 | // Callback made form esp-link to notify that it has just come out of a reset. This means we 34 | // need to initialize it! 35 | void resetCb(void) { 36 | Serial.println("EL-Client (re-)starting!"); 37 | bool ok = false; 38 | do { 39 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 40 | if (!ok) Serial.println("EL-Client sync failed!"); 41 | } while(!ok); 42 | Serial.println("EL-Client synced!"); 43 | } 44 | 45 | void setup() { 46 | Serial.begin(115200); 47 | 48 | // Sync-up with esp-link, this is required at the start of any sketch and initializes the 49 | // callbacks to the wifi status change callback. The callback gets called with the initial 50 | // status right after Sync() below completes. 51 | esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired) 52 | esp.resetCb = resetCb; 53 | resetCb(); 54 | } 55 | 56 | static uint32_t last; 57 | 58 | void loop() { 59 | esp.Process(); 60 | 61 | if ((millis()-last) > 4000) { 62 | Serial.println("requesting time"); 63 | uint32_t t = cmd.GetTime(); 64 | Serial.print("Time: "); Serial.println(t); 65 | 66 | last = millis(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /ELClient/examples/thingspeak/README.md: -------------------------------------------------------------------------------- 1 | Thingspeak example 2 | ================== 3 | 4 | **WARNING: this example has not been updated for EL-Client!** 5 | -------------------------------------------------------------------------------- /ELClient/examples/thingspeak/thingspeak.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * ESP8266 RESTful Thingspeak example 4 | * \author 5 | * BeeGee 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | //########################################################### 12 | // For ARDUINO UNO WIFI with I2C to serial chip! 13 | //########################################################### 14 | // Serial port to ESP8266 15 | // #include 16 | // SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA); 17 | 18 | // Initialize a connection to esp-link using the I2Cuart chip of the Arduino Uno WiFi board for 19 | // SLIP messages. 20 | // ELClient esp(&i2cuart); 21 | 22 | //########################################################### 23 | // For boards using the hardware serial port! 24 | //########################################################### 25 | // Initialize a connection to esp-link using the normal hardware serial port both for 26 | // SLIP and for debug messages. 27 | ELClient esp(&Serial, &Serial); 28 | 29 | // Initialize a REST client on the connection to esp-link 30 | ELClientRest rest(&esp); 31 | 32 | boolean wifiConnected = false; 33 | 34 | // Callback made from esp-link to notify of wifi status changes 35 | // Here we print something out and set a global flag 36 | void wifiCb(void *response) { 37 | ELClientResponse *res = (ELClientResponse*)response; 38 | if (res->argc() == 1) { 39 | uint8_t status; 40 | res->popArg(&status, 1); 41 | 42 | if(status == STATION_GOT_IP) { 43 | Serial.println("WIFI CONNECTED"); 44 | wifiConnected = true; 45 | } else { 46 | Serial.print("WIFI NOT READY: "); 47 | Serial.println(status); 48 | wifiConnected = false; 49 | } 50 | } 51 | } 52 | 53 | void setup() { 54 | Serial.begin(9600); 55 | //########################################################### 56 | // For ARDUINO UNO WIFI with I2C to serial chip! 57 | //########################################################### 58 | // i2cuart.begin(9600); 59 | 60 | Serial.println(""); 61 | Serial.println("EL-Client starting!"); 62 | 63 | // Sync-up with esp-link, this is required at the start of any sketch and initializes the 64 | // callbacks to the wifi status change callback. The callback gets called with the initial 65 | // status right after Sync() below completes. 66 | esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired) 67 | bool ok; 68 | do { 69 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 70 | if (!ok) { 71 | Serial.print("\nEL-Client sync failed! err: "); 72 | Serial.println(ok); 73 | } 74 | } while(!ok); 75 | Serial.println("EL-Client synced!"); 76 | 77 | // Wait for WiFi to be connected. 78 | Serial.println("esp.GetWifiStatus()"); 79 | esp.GetWifiStatus(); 80 | ELClientPacket *packet; 81 | Serial.println("Waiting for WiFi "); 82 | if ((packet=esp.WaitReturn()) != NULL) { 83 | Serial.print("."); 84 | Serial.println(packet->value); 85 | } 86 | Serial.println(""); 87 | 88 | // Set up the REST client to talk to api.thingspeak.com, this doesn't connect to that server, 89 | // it just sets-up stuff on the esp-link side 90 | // int err = rest.begin("api.thingspeak.com"); 91 | int err = rest.begin("184.106.153.149"); 92 | if (err != 0) { 93 | Serial.print("REST begin failed: "); 94 | Serial.println(err); 95 | while(1) ; 96 | } 97 | Serial.println("EL-REST ready"); 98 | } 99 | 100 | float solarValue = 99.5; 101 | // Change to your own Thingspeak API key 102 | char *api_key = "K9LDRXS7BXSN8X1J"; 103 | // expand buffer size to your needs 104 | #define BUFLEN 266 105 | 106 | void loop() { 107 | // process any callbacks coming from esp_link 108 | esp.Process(); 109 | 110 | // if we're connected make an REST request 111 | if(wifiConnected) { 112 | 113 | // Generate a fake value starting from 100 going up to 300 114 | solarValue = solarValue + 0.5; 115 | if (solarValue == 300) { 116 | solarValue = 100; 117 | } 118 | String solarValString = String(solarValue); 119 | const char *solarValChar = solarValString.c_str(); 120 | 121 | // Reserve a buffer for sending the data 122 | char path_data[BUFLEN]; 123 | // Copy the path and API key into the buffer 124 | sprintf(path_data, "%s", "/update?api_key="); 125 | sprintf(path_data + strlen(path_data), "%s", api_key); 126 | 127 | // Copy the field number and value into the buffer 128 | // If you have more than one field to update, 129 | // repeat and change field1 to field2, field3, ... 130 | sprintf(path_data + strlen(path_data), "%s", "&field1="); 131 | sprintf(path_data + strlen(path_data), "%s", solarValChar); 132 | 133 | // Send PUT request to thingspeak.com 134 | rest.post(path_data,""); 135 | 136 | // Reserve a buffer for the response from Thingspeak 137 | char response[BUFLEN]; 138 | // Clear the buffer 139 | memset(response, 0, BUFLEN); 140 | // Wait for response from Thingspeak 141 | uint16_t code = rest.waitResponse(response, BUFLEN-1); 142 | // Check the response from Thingspeak 143 | if(code == HTTP_STATUS_OK){ 144 | Serial.println("Thingspeak: POST successful:"); 145 | Serial.print("Response: "); 146 | Serial.println(response); 147 | } else { 148 | Serial.print("Thingspeak: POST failed with error "); 149 | Serial.println(code); 150 | Serial.print("Response: "); 151 | Serial.println(response); 152 | } 153 | // Send next data in 20 seconds 154 | delay(20000); 155 | } 156 | } -------------------------------------------------------------------------------- /ELClient/examples/udp/udp.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple example to demo the El-Client UDP calls 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | // IP address for this demo is a local IP. 9 | // Replace it with the IP address where you have a UDP socket server running 10 | char * const udpServer PROGMEM = "192.168.0.102"; // Send to single ip address 11 | char * const udpServer2 PROGMEM = "192.168.0.255"; // Broadcast to given network ip mask 12 | // Port for this demo is the port used by the UDP socket server. 13 | // Replace it with the port that your UDP socket server is listening to 14 | uint16_t const udpPort PROGMEM = 5000; 15 | uint16_t const udpPort2 PROGMEM = 7000; 16 | 17 | //########################################################### 18 | // For ARDUINO UNO WIFI with I2C to serial chip! 19 | //########################################################### 20 | // Serial port to ESP8266 21 | #include 22 | SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA); 23 | 24 | // Initialize a connection to esp-link using the I2Cuart chip of the Arduino Uno WiFi board for 25 | // SLIP messages. 26 | ELClient esp(&i2cuart); 27 | 28 | //########################################################### 29 | // For boards using the hardware serial port! 30 | //########################################################### 31 | // Initialize a connection to esp-link using the normal hardware serial port both for 32 | // SLIP and for debug messages. 33 | //ELClient esp(&Serial, &Serial); 34 | 35 | // Initialize a UDP client on the connection to esp-link 36 | ELClientSocket udp(&esp); 37 | // Initialize a UDP client on the connection to esp-link 38 | ELClientSocket udp2(&esp); 39 | 40 | // Timer value to send out data 41 | uint32_t wait; 42 | // Time to wait between sending out data 43 | uint32_t waitTime; 44 | // Flag for wifi connection 45 | boolean wifiConnected = false; 46 | 47 | // Parse error codes and returns error message as char * 48 | // Definitions from error values from espconn.h (Espressif SDK) 49 | // #define ESPCONN_OK 0 /**< No error, everything OK. */ 50 | // #define ESPCONN_MEM -1 /**< Out of memory. */ 51 | // #define ESPCONN_TIMEOUT -3 /**< Timeout. */ 52 | // #define ESPCONN_RTE -4 /**< Routing problem. */ 53 | // #define ESPCONN_INPROGRESS -5 /**< Operation in progress. */ 54 | // #define ESPCONN_MAXNUM -7 /**< Total number exceeds the maximum limitation. */ 55 | 56 | // #define ESPCONN_ABRT -8 /**< Connection aborted. */ 57 | // #define ESPCONN_RST -9 /**< Connection reset. */ 58 | // #define ESPCONN_CLSD -10 /**< Connection closed. */ 59 | // #define ESPCONN_CONN -11 /**< Not connected. */ 60 | 61 | // #define ESPCONN_ARG -12 /**< Illegal argument. */ 62 | // #define ESPCONN_IF -14 /**< UDP send error. */ 63 | // #define ESPCONN_ISCONN -15 /**< Already connected. */ 64 | 65 | char* const errTxt[] PROGMEM = {"No error, everything OK.","Out of memory.","Unknown code.","Timeout.","Routing problem.","Operation in progress.", 66 | "Unknown code.","Total number exceeds the maximum limitation.","Connection aborted.","Connection reset.","Connection closed.", 67 | "Not connected.","Illegal argument.","Unknown code.","UDP send error.","Already connected."}; 68 | char * getErrTxt(int16_t commError) { 69 | commError = commError*-1; 70 | if (commError <= 15) { 71 | return (char *) pgm_read_word (&errTxt[commError]); 72 | } else { 73 | return (char *) pgm_read_word (&errTxt[2]); // Unknown code 74 | } 75 | } 76 | 77 | // Callback for UDP socket, called if data was sent or received 78 | // Receives socket client number, can be reused for all initialized UDP socket connections 79 | // !!! UDP doesn't check if the data was received or if the receiver IP/socket is available !!! You need to implement your own 80 | // error control! 81 | void udpCb(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data) { 82 | Serial.println("udpCb is called"); 83 | if (len > 0) { // sending complete (no confirmation that it was received!) or we received something 84 | if (resp_type == USERCB_SENT) { 85 | Serial.println("\tSent " + String(len) + " bytes over connection #" + String(client_num)); 86 | } else if (resp_type == USERCB_RECV) { 87 | char recvData[len+1]; // Prepare buffer for the received data 88 | memcpy(recvData, data, len); // Copy received data into the buffer 89 | recvData[len] = '\0'; // Terminate the buffer with 0 for proper printout! 90 | 91 | Serial.println("\tReceived " + String(len) + " bytes over client#" + String(client_num)); 92 | Serial.println("\tReceived: " + String(recvData)); 93 | } else { 94 | Serial.println("Received invalid response type"); 95 | } 96 | } else if (len < 0) { // negative result means there was a problem 97 | Serial.print(F("Send error: ")); 98 | Serial.println(getErrTxt(len)); 99 | } 100 | } 101 | 102 | // Callback made from esp-link to notify of wifi status changes 103 | // Here we print something out and set a global flag 104 | void wifiCb(void *response) { 105 | ELClientResponse *res = (ELClientResponse*)response; 106 | if (res->argc() == 1) { 107 | uint8_t status; 108 | res->popArg(&status, 1); 109 | 110 | if(status == STATION_GOT_IP) { 111 | Serial.println(F("WIFI CONNECTED")); 112 | wifiConnected = true; 113 | } else { 114 | Serial.print(F("WIFI NOT READY: ")); 115 | Serial.println(status); 116 | wifiConnected = false; 117 | } 118 | } 119 | } 120 | 121 | void setup() { 122 | Serial.begin(115200); 123 | i2cuart.begin(9600); 124 | Serial.println(F("EL-Client starting!")); 125 | 126 | // Sync-up with esp-link, this is required at the start of any sketch and initializes the 127 | // callbacks to the wifi status change callback. The callback gets called with the initial 128 | // status right after Sync() below completes. 129 | esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired) 130 | bool ok; 131 | do { 132 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 133 | if (!ok) Serial.println(F("EL-Client sync failed!")); 134 | } while(!ok); 135 | Serial.println(F("EL-Client synced!")); 136 | 137 | // Get immediate wifi status info for demo purposes. This is not normally used because the 138 | // wifi status callback registered above gets called immediately. 139 | esp.GetWifiStatus(); 140 | ELClientPacket *packet; 141 | if ((packet=esp.WaitReturn()) != NULL) { 142 | Serial.print(F("Wifi status: ")); 143 | Serial.println(packet->value); 144 | } 145 | 146 | // Set up the UDP socket client to send a short message to on port <>, this doesn't connect to that server, 147 | // it just sets-up stuff on the esp-link side 148 | int err = udp.begin(udpServer, udpPort, SOCKET_UDP, udpCb); 149 | if (err < 0) { 150 | Serial.print(F("UDP begin failed: ")); 151 | Serial.println(err); 152 | delay(10000); 153 | asm volatile (" jmp 0"); 154 | } 155 | 156 | err = udp2.begin(udpServer2, udpPort2, SOCKET_UDP, udpCb); 157 | if (err < 0) { 158 | Serial.print(F("UDP2 begin failed: ")); 159 | Serial.println(err); 160 | delay(10000); 161 | asm volatile (" jmp 0"); 162 | } 163 | 164 | Serial.println(F("EL-Client ready!")); 165 | wait = millis()+29000; // Start first sending in 1 second 166 | } 167 | 168 | void loop() { 169 | // process any callbacks coming from esp_link 170 | esp.Process(); 171 | 172 | // if we're connected send data over UDP socket 173 | if(wifiConnected) { 174 | if (millis() - wait > 30000) { // Send some data every 30 seconds 175 | wait = millis(); 176 | // Send message to the previously set-up server #1 177 | Serial.print(F("Sending message to ")); 178 | Serial.println(udpServer); 179 | udp.send("Message from your Arduino Uno WiFi over UDP socket"); 180 | 181 | // Send message to the previously set-up server #2 182 | Serial.print(F("Sending broadcast to ")); 183 | Serial.println(udpServer2); 184 | udp2.send("Broadcast from your Arduino Uno WiFi over UDP socket"); 185 | } 186 | } else { 187 | // This is just for demo, you can as well just try to reconnect 188 | // and setup the connection to esp-link again 189 | Serial.println(F("Lost connection, try to reboot")); 190 | delay(10000); 191 | asm volatile (" jmp 0"); 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_controls/LED.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

LED configuration

5 |
6 | 7 |
8 |
9 |
10 |

Control

11 | 12 | 13 | 14 |

15 |

16 |
17 |

Frequency and duty

18 |
19 | Duty:
20 | 25% on 75% off
21 | 50% on 50% off
22 | 75% on 25% off
23 | 24 | Frequency:
25 |
26 | 27 |
28 |
29 |
30 |
31 |

Logs

32 |
    33 |
34 |
35 |
36 | 37 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_controls/LedPage.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // the PIN to flash 4 | #define LED_PIN 13 5 | 6 | int8_t blinking = 0; // whether LED is blinking 7 | uint8_t blinking_duty = 2; // blinking duty 8 | int8_t blinking_frequency = 10; // blinking frequency 9 | 10 | uint32_t blinking_next_ts = 0; // the next timestamp to blink 11 | uint16_t blinking_phase = 100; // blinking phase 12 | uint16_t blinking_period = 200; // blinking period (2000 / frequency) 13 | 14 | #define MAX_LOGS 5 15 | uint32_t log_ts[MAX_LOGS]; // log timestamp 16 | uint8_t log_msg[MAX_LOGS]; // log message 17 | uint8_t log_ptr = 0; // log pointer 18 | 19 | typedef enum 20 | { 21 | LOG_DUTY_25_75 = 0xE1, 22 | LOG_DUTY_50_50, 23 | LOG_DUTY_75_25, 24 | LOG_SET_LED_ON = 0xF0, 25 | LOG_SET_LED_BLINKING, 26 | LOG_SET_LED_OFF, 27 | } LogMessage; 28 | 29 | // LED loop code 30 | void ledLoop() 31 | { 32 | if( blinking ) // if blinking is enabled 33 | { 34 | if( blinking_next_ts <= millis() ) 35 | { 36 | digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // blink LED 37 | blinking_next_ts += blinking_phase; 38 | blinking_phase = blinking_period - blinking_phase; 39 | } 40 | } 41 | } 42 | 43 | // adds a new log message 44 | void ledAddLog(uint8_t msg) 45 | { 46 | // check if max log is reached 47 | if( log_ptr >= MAX_LOGS ) 48 | log_ptr = MAX_LOGS - 1; 49 | 50 | // move logs back with one and delete the oldest log 51 | for(int8_t i=log_ptr-1; i >= 0; i--) 52 | { 53 | log_ts[i+1] = log_ts[i]; 54 | log_msg[i+1] = log_msg[i]; 55 | } 56 | 57 | log_msg[0] = msg; // log message 58 | log_ts[0] = millis(); // log timestamp 59 | log_ptr++; // a new log was added 60 | } 61 | 62 | // create log messages to string 63 | String ledHistoryToLog() 64 | { 65 | String str = "["; 66 | 67 | for(uint8_t i=0; i < log_ptr; i++) 68 | { 69 | if( i != 0 ) 70 | str += ','; 71 | 72 | str += '\"'; 73 | str += (log_ts[i] / 1000); 74 | str += "s: "; 75 | 76 | switch(log_msg[i]) // log message 77 | { 78 | case LOG_DUTY_25_75: 79 | str += F("set duty to 25%-75%"); 80 | break; 81 | case LOG_DUTY_50_50: 82 | str += F("set duty to 50%-50%"); 83 | break; 84 | case LOG_DUTY_75_25: 85 | str += F("set duty to 75%-25%"); 86 | break; 87 | case LOG_SET_LED_ON: 88 | str += F("set led on"); 89 | break; 90 | case LOG_SET_LED_BLINKING: 91 | str += F("set led blinking"); 92 | break; 93 | case LOG_SET_LED_OFF: 94 | str += F("set led off"); 95 | break; 96 | default: 97 | str += F("set frequency to "); 98 | str += (int)log_msg[i]; 99 | str += F(" Hz"); 100 | break; 101 | } 102 | str += '\"'; 103 | } 104 | str += ']'; 105 | 106 | return str; 107 | } 108 | 109 | // called at button pressing 110 | void ledButtonPressCb(const char * button) 111 | { 112 | String btn = button; 113 | if( btn == F("btn_on") ) 114 | { 115 | if( blinking || digitalRead(LED_PIN) == false ) 116 | ledAddLog(LOG_SET_LED_ON); 117 | blinking = 0; 118 | digitalWrite(LED_PIN, true); 119 | } 120 | else if( btn == F("btn_off") ) 121 | { 122 | if( blinking || digitalRead(LED_PIN) == true ) 123 | ledAddLog(LOG_SET_LED_OFF); 124 | blinking = 0; 125 | digitalWrite(LED_PIN, false); 126 | } 127 | else if( btn == F("btn_blink") ) 128 | { 129 | if( !blinking ) 130 | ledAddLog(LOG_SET_LED_BLINKING); 131 | blinking = 1; 132 | blinking_next_ts = millis() + blinking_phase; 133 | } 134 | } 135 | 136 | // setting the value of a field 137 | // 138 | // handle data as fast as possible 139 | // - huge HTML forms can arrive in multiple packets 140 | // - if this method is slow, UART receive buffer may overrun 141 | void ledSetFieldCb(const char * field) 142 | { 143 | String fld = field; 144 | if( fld == F("frequency") ) 145 | { 146 | int8_t oldf = blinking_frequency; 147 | blinking_frequency = webServer.getArgInt(); 148 | 149 | blinking_period = 2000 / blinking_frequency; 150 | blinking_phase = blinking_duty * blinking_period / 4; 151 | 152 | if( oldf != blinking_frequency ) 153 | { 154 | ledAddLog(blinking_frequency); 155 | if( blinking ) 156 | digitalWrite(LED_PIN, false); 157 | } 158 | } 159 | else if( fld == F("duty") ) 160 | { 161 | int8_t oldp = blinking_duty; 162 | String arg = webServer.getArgString(); 163 | 164 | if( arg == F("25_75") ) 165 | blinking_duty = 1; 166 | else if( arg == F("50_50") ) 167 | blinking_duty = 2; 168 | else if( arg == F("75_25") ) 169 | blinking_duty = 3; 170 | 171 | if( blinking ) 172 | digitalWrite(LED_PIN, false); 173 | 174 | blinking_phase = blinking_duty * blinking_period / 4; 175 | 176 | if( oldp != blinking_duty ) 177 | ledAddLog(LOG_DUTY_25_75 - 1 + blinking_duty); 178 | } 179 | } 180 | 181 | // called at page refreshing 182 | void ledRefreshCb(const char * url) 183 | { 184 | if( blinking ) 185 | webServer.setArgString(F("text"), F("LED is blinking")); 186 | else 187 | webServer.setArgString(F("text"), digitalRead(LED_PIN) ? F("LED is turned on") : F("LED is turned off")); 188 | 189 | String log = ledHistoryToLog(); 190 | webServer.setArgJson(F("led_history"), log.begin()); 191 | } 192 | 193 | // called at page loading 194 | void ledLoadCb(const char * url) 195 | { 196 | webServer.setArgInt(F("frequency"), blinking_frequency); 197 | 198 | switch(blinking_duty) 199 | { 200 | case 1: 201 | webServer.setArgString(F("duty"), F("25_75")); 202 | break; 203 | case 2: 204 | webServer.setArgString(F("duty"), F("50_50")); 205 | break; 206 | case 3: 207 | webServer.setArgString(F("duty"), F("75_25")); 208 | break; 209 | } 210 | 211 | ledRefreshCb( url ); 212 | } 213 | 214 | // LED setup code 215 | void ledInit() 216 | { 217 | // set mode to output and turn LED off 218 | pinMode(LED_PIN, OUTPUT); 219 | digitalWrite(LED_PIN, false); 220 | 221 | URLHandler *ledHandler = webServer.createURLHandler(F("/LED.html.json")); 222 | ledHandler->buttonCb.attach(ledButtonPressCb); 223 | ledHandler->setFieldCb.attach(ledSetFieldCb); 224 | ledHandler->loadCb.attach(ledLoadCb); 225 | ledHandler->refreshCb.attach(ledRefreshCb); 226 | } 227 | 228 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_controls/Pages.h: -------------------------------------------------------------------------------- 1 | #ifndef PAGES_H 2 | #define PAGES_H 3 | 4 | void ledLoop(); 5 | void ledInit(); 6 | 7 | void userInit(); 8 | 9 | void voltageLoop(); 10 | void voltageInit(); 11 | 12 | #endif /* PAGES_H */ 13 | 14 | 15 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_controls/User.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

User setup

5 |
6 | 7 |
8 |
9 | First name:
10 | Last name:
11 | Age: 12 | 13 | Gender: 14 | 18 |
19 | Notifications 20 |
21 | 22 |
23 |
24 | 25 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_controls/UserPage.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAGIC 0xABEF 5 | #define MAX_STR_LEN 32 6 | 7 | // EEPROM content 8 | #define EEPROM_POS_MAGIC 0 9 | #define EEPROM_POS_FIRST_NAME (EEPROM_POS_MAGIC + 2) 10 | #define EEPROM_POS_LAST_NAME (EEPROM_POS_FIRST_NAME + MAX_STR_LEN) 11 | #define EEPROM_POS_AGE (EEPROM_POS_LAST_NAME + MAX_STR_LEN) 12 | #define EEPROM_POS_GENDER (EEPROM_POS_AGE+1) 13 | #define EEPROM_POS_NOTIFICATIONS (EEPROM_POS_GENDER+1) 14 | 15 | // write a string to EEPROM 16 | void userWriteStr(char * str, int ndx) 17 | { 18 | for(uint8_t i=0; i < MAX_STR_LEN-1; i++) 19 | { 20 | EEPROM.update(ndx + i, str[i]); 21 | if( str[i] == 0 ) 22 | break; 23 | } 24 | EEPROM.update(ndx + MAX_STR_LEN - 1, 0); 25 | } 26 | 27 | 28 | // read a string from EEPROM 29 | void userReadStr(char * str, int ndx) 30 | { 31 | for(uint8_t i=0; i < MAX_STR_LEN; i++) 32 | { 33 | str[i] = EEPROM[ndx + i]; 34 | } 35 | } 36 | 37 | 38 | // setting the value of a field 39 | // 40 | // handle data as fast as possible 41 | // - huge HTML forms can arrive in multiple packets 42 | // - if this method is slow, UART receive buffer may overrun 43 | void userSetFieldCb(const char * field) 44 | { 45 | String fld = field; 46 | if( fld == F("first_name")) 47 | userWriteStr(webServer.getArgString(), EEPROM_POS_FIRST_NAME); 48 | else if( fld == F("last_name")) 49 | userWriteStr(webServer.getArgString(), EEPROM_POS_LAST_NAME); 50 | else if( fld == F("age")) 51 | EEPROM.update(EEPROM_POS_AGE, (uint8_t)webServer.getArgInt()); 52 | else if( fld == F("gender")) 53 | { 54 | String gender = webServer.getArgString(); 55 | EEPROM.update(EEPROM_POS_GENDER, (gender == F("male")) ? 'm' : 'f'); 56 | } 57 | else if( fld == F("notifications")) 58 | EEPROM.update(EEPROM_POS_NOTIFICATIONS, webServer.getArgBoolean()); 59 | } 60 | 61 | // called at page loading 62 | void userLoadCb(const char * url) 63 | { 64 | char buf[MAX_STR_LEN]; 65 | userReadStr( buf, EEPROM_POS_FIRST_NAME ); 66 | webServer.setArgString(F("first_name"), buf); 67 | userReadStr( buf, EEPROM_POS_LAST_NAME ); 68 | webServer.setArgString(F("last_name"), buf); 69 | webServer.setArgInt(F("age"), (uint8_t)EEPROM[EEPROM_POS_AGE]); 70 | webServer.setArgString(F("gender"), (EEPROM[EEPROM_POS_GENDER] == 'm') ? F("male") : F("female")); 71 | webServer.setArgBoolean(F("notifications"), EEPROM[EEPROM_POS_NOTIFICATIONS] != 0); 72 | } 73 | 74 | // initialization 75 | void userInit() 76 | { 77 | uint16_t magic; 78 | EEPROM.get(EEPROM_POS_MAGIC, magic); 79 | 80 | if( magic != MAGIC ) // EEPROM is uninitialized? 81 | { 82 | magic = MAGIC; 83 | // set default values 84 | EEPROM.put(EEPROM_POS_MAGIC, magic); 85 | EEPROM.update(EEPROM_POS_FIRST_NAME, 0); 86 | EEPROM.update(EEPROM_POS_LAST_NAME, 0); 87 | EEPROM.update(EEPROM_POS_AGE, 0); 88 | EEPROM.update(EEPROM_POS_GENDER, 'f'); 89 | EEPROM.update(EEPROM_POS_NOTIFICATIONS, 0); 90 | } 91 | 92 | URLHandler *userPageHandler = webServer.createURLHandler(F("/User.html.json")); 93 | userPageHandler->setFieldCb.attach(userSetFieldCb); 94 | userPageHandler->loadCb.attach(userLoadCb); 95 | } 96 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_controls/Voltage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |

Voltage measurement

7 |
8 | 9 |
10 |

11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_controls/VoltagePage.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SAMPLE_COUNT 100 5 | #define PERIOD_COUNT (135 * SAMPLE_COUNT) 6 | 7 | uint16_t adc_min = 0xFFFF; // min value of ADC 8 | uint16_t adc_max = 0; // max value of ADC 9 | uint32_t adc_avg = 0; // AVG average 10 | 11 | uint16_t sample_count; // collected sample 12 | uint32_t voltage_avg = 0; // AVG used for voltage measurement 13 | uint16_t measured_voltage = 0; // measured voltage 14 | 15 | #define MAX_HISTORY 3 // max history count 16 | 17 | uint8_t history_cnt = 0; // number of histories 18 | uint32_t history_ts[MAX_HISTORY]; // timestamp 19 | uint16_t history_min[MAX_HISTORY]; // min 20 | uint16_t history_max[MAX_HISTORY]; // max 21 | uint16_t history_avg[MAX_HISTORY]; // avg 22 | 23 | uint16_t calibrate = 0x128; // calibrate this manually 24 | 25 | // voltage measuring loop 26 | void voltageLoop() 27 | { 28 | uint16_t adc = analogRead(A0); // read ADC 29 | 30 | // set min/max/avg 31 | if( adc < adc_min ) 32 | adc_min = adc; 33 | if( adc > adc_max ) 34 | adc_max = adc; 35 | adc_avg += adc; 36 | 37 | voltage_avg += adc; 38 | sample_count++; 39 | 40 | if( (sample_count % SAMPLE_COUNT) == 0 ) // max samples reached? 41 | { 42 | // calculate measured voltage 43 | voltage_avg /= SAMPLE_COUNT; 44 | measured_voltage = voltage_avg * calibrate / 256; 45 | voltage_avg = 0; 46 | } 47 | if( sample_count == PERIOD_COUNT ) 48 | { 49 | // calculate min/max/avg and put into history 50 | 51 | for(int8_t i=MAX_HISTORY-2; i >=0; i-- ) 52 | { 53 | history_ts[i+1] = history_ts[i]; 54 | history_min[i+1] = history_min[i]; 55 | history_max[i+1] = history_max[i]; 56 | history_avg[i+1] = history_avg[i]; 57 | } 58 | 59 | history_ts[0] = millis(); 60 | history_min[0] = (uint32_t)adc_min * calibrate / 256; 61 | history_max[0] = (uint32_t)adc_max * calibrate / 256; 62 | history_avg[0] = (adc_avg / PERIOD_COUNT) * calibrate / 256; 63 | 64 | adc_min = 0xFFFF; 65 | adc_max = 0; 66 | adc_avg = 0; 67 | 68 | if( history_cnt < MAX_HISTORY ) 69 | history_cnt++; 70 | sample_count = 0; 71 | } 72 | } 73 | 74 | // sprintf %f is not supported on Arduino... 75 | String floatToString(float f) 76 | { 77 | int16_t intg = (int16_t)(f * 100.f); 78 | int16_t int_part = intg / 100; 79 | int16_t fract_part = intg % 100; 80 | 81 | char buf[20]; 82 | sprintf(buf, "%d.%02d", int_part, fract_part); 83 | 84 | return String(buf); 85 | } 86 | 87 | void voltageRefreshCb(const char * url) 88 | { 89 | // calculate voltage value 90 | String v = floatToString((float)measured_voltage / 256.f); 91 | v += " V"; 92 | webServer.setArgString(F("voltage"), v.begin()); 93 | 94 | char buf[20]; 95 | // calculate history table 96 | String table = F("[[\"Time\",\"Min\",\"AVG\",\"Max\"]"); 97 | 98 | for(uint8_t i=0; i < history_cnt; i++ ) 99 | { 100 | float min_f = (float)history_min[i] / 256.f; 101 | float max_f = (float)history_max[i] / 256.f; 102 | float avg_f = (float)history_avg[i] / 256.f; 103 | 104 | table += F(",[\""); 105 | table += (history_ts[i] / 1000); 106 | table += F(" s\",\""); 107 | table += floatToString(min_f); 108 | table += " V\",\""; 109 | table += floatToString(avg_f); 110 | table += " V\",\""; 111 | table += floatToString(max_f); 112 | table += " V\"]"; 113 | } 114 | 115 | table += ']'; 116 | webServer.setArgJson(F("table"), table.begin()); 117 | } 118 | 119 | // page setup 120 | void voltageInit() 121 | { 122 | analogReference(DEFAULT); 123 | sample_count = 0; 124 | 125 | URLHandler *voltageHandler = webServer.createURLHandler(F("/Voltage.html.json")); 126 | 127 | voltageHandler->loadCb.attach(voltageRefreshCb); 128 | voltageHandler->refreshCb.attach(voltageRefreshCb); 129 | } 130 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_controls/webserver_controls.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a sample for trying out each HTML control 3 | * 4 | * Test board: 5 | * ESP8266 RX <--level shifter--> Arduino TX 6 | * ESP8266 TX <--level shifter--> Arduino RX 7 | * ESP8266 GPIO0 <--level shifter--> Arduino RESET (optional) 8 | * 9 | * Arduino LED is on PIN 13 10 | * Connect an 1K trimmer to Arduino (voltage): VCC <-> A0 <-> GND 11 | * 12 | * 13 | * Video: 14 | * https://www.youtube.com/watch?v=vBESCO0UhYI 15 | */ 16 | 17 | #include 18 | #include 19 | #include "Pages.h" 20 | 21 | // Initialize a connection to esp-link using the normal hardware serial port 22 | // 23 | // DEBUG is disasbled as 24 | // - packet logging is slow and UART receive buffer can overrun (HTML form submission) 25 | ELClient esp(&Serial, &Serial); 26 | 27 | // Initialize the Web-Server client 28 | ELClientWebServer webServer(&esp); 29 | 30 | 31 | // Callback made form esp-link to notify that it has just come out of a reset. This means we 32 | // need to initialize it! 33 | void resetCb(void) { 34 | Serial.println("EL-Client (re-)starting!"); 35 | bool ok = false; 36 | do { 37 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 38 | if (!ok) Serial.println("EL-Client sync failed!"); 39 | } while(!ok); 40 | Serial.println("EL-Client synced!"); 41 | 42 | webServer.setup(); 43 | } 44 | 45 | void setup() 46 | { 47 | Serial.begin(115200); 48 | 49 | esp.resetCb = resetCb; 50 | 51 | ledInit(); 52 | userInit(); 53 | voltageInit(); 54 | 55 | resetCb(); 56 | } 57 | 58 | void loop() 59 | { 60 | esp.Process(); 61 | 62 | ledLoop(); 63 | voltageLoop(); 64 | } 65 | 66 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_led/Makefile: -------------------------------------------------------------------------------- 1 | HOST ?= esp-link 2 | LIBRARYPATH = $(ARDUINODIR)/libraries ../../.. 3 | LIBRARIES = ELClient 4 | CPPFLAGS = 5 | SERIALDEV = net:$(HOST):2323 6 | include ../arduino.mk 7 | 8 | flash: all 9 | ../avrflash $(HOST) webserver_led.hex 10 | nc $(HOST) 23 11 | 12 | run: upload size 13 | nc $(HOST) 23 14 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_led/SimpleLED.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Simple LED control

4 |

5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ELClient/examples/webserver_led/webserver_led.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple example for LED flashing using web-server 3 | * 4 | * Test board: 5 | * ESP8266 RX <--level shifter--> Arduino TX 6 | * ESP8266 TX <--level shifter--> Arduino RX 7 | * ESP8266 GPIO0 <--level shifter--> Arduino RESET (optional) 8 | * 9 | * Arduino LED is on PIN 13 10 | * 11 | * Video: 12 | * https://www.youtube.com/watch?v=vBESCO0UhYI 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | // flash LED on PIN 13 19 | #define LED_PIN 13 20 | 21 | // Initialize a connection to esp-link using the normal hardware serial port 22 | // 23 | // DEBUG is disasbled as 24 | // - packet logging is slow and UART receive buffer can overrun (HTML form submission) 25 | ELClient esp(&Serial); 26 | 27 | // Initialize the Web-Server client 28 | ELClientWebServer webServer(&esp); 29 | 30 | void ledPageLoadAndRefreshCb(char * url) 31 | { 32 | if( digitalRead(LED_PIN) ) 33 | webServer.setArgString(F("text"), F("LED is on")); 34 | else 35 | webServer.setArgString(F("text"), F("LED is off")); 36 | } 37 | 38 | void ledButtonPressCb(char * btnId) 39 | { 40 | String id = btnId; 41 | if( id == F("btn_on") ) 42 | digitalWrite(LED_PIN, true); 43 | else if( id == F("btn_off") ) 44 | digitalWrite(LED_PIN, false); 45 | } 46 | 47 | // Callback made form esp-link to notify that it has just come out of a reset. This means we 48 | // need to initialize it! 49 | void resetCb(void) { 50 | Serial.println("EL-Client (re-)starting!"); 51 | bool ok = false; 52 | do { 53 | ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds 54 | if (!ok) Serial.println("EL-Client sync failed!"); 55 | } while(!ok); 56 | Serial.println("EL-Client synced!"); 57 | 58 | webServer.setup(); 59 | } 60 | 61 | void setup() 62 | { 63 | Serial.begin(115200); 64 | 65 | URLHandler *ledHandler = webServer.createURLHandler(F("/SimpleLED.html.json")); 66 | ledHandler->loadCb.attach(&ledPageLoadAndRefreshCb); 67 | ledHandler->refreshCb.attach(&ledPageLoadAndRefreshCb); 68 | ledHandler->buttonCb.attach(&ledButtonPressCb); 69 | 70 | esp.resetCb = resetCb; 71 | resetCb(); 72 | } 73 | 74 | void loop() 75 | { 76 | esp.Process(); 77 | } 78 | -------------------------------------------------------------------------------- /ELClient/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ELClient", 3 | "keywords": "wifi, mqtt, rest, socket", 4 | "description": "Wifi library (Chip ESP8266 Wifi SoC) using SLIP protocol via Serial port", 5 | "url": "https://github.com/jeelabs/esp-link", 6 | "repository": 7 | { 8 | "type": "git", 9 | "url": "https://github.com/jeelabs/esp-link" 10 | }, 11 | "include": "ELClient", 12 | "frameworks": "arduino", 13 | "platforms": [ 14 | "atmelavr", 15 | "atmelsam", 16 | "teensy" 17 | ] 18 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Thorsten von Eicken, 2015-2016 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ELClient 2 | ======== 3 | This is a Wifi library for arduino that uses the SLIP protocol to communicate via serial with 4 | an ESP8266 module running the [esp-link firmware](https://github.com/jeelabs/esp-link). 5 | 6 | This library requires esp-link v2.2.beta2 or later. 7 | 8 | Features 9 | ======== 10 | - C++ classes to manage the communication with esp-link 11 | - Support outbound REST requests 12 | - Support MQTT pub/sub 13 | - Support additional commands to query esp-link about wifi and such 14 | 15 | - MQTT functionality: 16 | + MQTT protocol itself implemented by esp-link 17 | + Support subscribing, publishing, LWT, keep alive pings and all QoS levels 0&1 18 | 19 | - REST functionality: 20 | + Support methods GET, POST, PUT, DELETE 21 | + setContent type, set header, set User Agent 22 | 23 | - UDP socket functionality: 24 | + Support sending and receiving UDP socket packets and broadcasting UDP socket packets 25 | 26 | - TCP socket functionality: 27 | + Support TCP socket clients to send packets to a TCP server 28 | + Support TCP socket server to receive packets from TCP socket clients and send back responses 29 | 30 | Examples 31 | ======== 32 | Currently two examples are provided that are known to work and that come with HEX files ready 33 | to load into an Atmega 328 based arduino: 34 | - A REST example that fetches the current time from a server on the internet and prints it. 35 | This example is in `./ELClient/examples/rest`. 36 | - An MQTT example that publishes messages to an MQTT server and subscribes so it receives and 37 | prints its own messages. This example is in `./ELClient/examples/mqtt`. 38 | - An UDP socket client example to connect to a UDP socket server or broadcast to a local network. This example is in `./ELClient/examples/udp`. 39 | - A simple TCP socket client example that sends data to a TCP server without waiting for response. This example is in `./ELClient/examples/tcp-client`. 40 | - A TCP socket client example that sends data to a TCP server and waits for a response. This example is in `./ELClient/examples/tcp-client_resp`. 41 | - A TCP socket server example that waits for connections from a TCP socket client. This example is in `./ELClient/examples/tcp-server`. 42 | - A Thingspeak example to use REST POST to send data to thingspeak. This example is in `./ELClient/examples/udp`. 43 | 44 | The "demo" example are currently not maintained and therefore won't work as-is. 45 | 46 | API documentation 47 | ======== 48 | A prelimenary documentation for the library is available on [ELClient API Doc](http://desire.giesecke.tk/docs/el-client/). --------------------------------------------------------------------------------