├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── githubci.yml ├── Adafruit_ESP8266.cpp ├── Adafruit_ESP8266.h ├── README.md ├── examples └── webclient │ └── webclient.ino ├── library.properties └── previous └── Adafruit_ESP8266.ino /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Arduino library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Arduino projects check these very common issues to ensure they don't apply**: 17 | 18 | - For uploading sketches or communicating with the board make sure you're using 19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes 20 | very hard to tell the difference between a data and charge cable! Try using the 21 | cable with other devices or swapping to another cable to confirm it is not 22 | the problem. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and plug in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't 33 | guarantee a clone board will have the same functionality and work as expected 34 | with this code and don't support them. 35 | 36 | If you're sure this issue is a defect in the code and checked the steps above 37 | please fill in the following fields to provide enough troubleshooting information. 38 | You may delete the guideline and text above to just leave the following details: 39 | 40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** 41 | 42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO 43 | VERSION HERE** 44 | 45 | - List the steps to reproduce the problem below (if possible attach a sketch or 46 | copy the sketch code in too): **LIST REPRO STEPS BELOW** 47 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Arduino Library CI 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/setup-python@v4 11 | with: 12 | python-version: '3.x' 13 | - uses: actions/checkout@v3 14 | - uses: actions/checkout@v3 15 | with: 16 | repository: adafruit/ci-arduino 17 | path: ci 18 | 19 | - name: pre-install 20 | run: bash ci/actions_install.sh 21 | 22 | - name: test platforms 23 | run: python3 ci/build_platform.py uno leonardo mega2560 24 | 25 | - name: clang 26 | run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . 27 | 28 | - name: doxygen 29 | env: 30 | GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 31 | PRETTYNAME : "Adafruit ESP8266 Library" 32 | run: bash ci/doxy_gen_and_deploy.sh 33 | -------------------------------------------------------------------------------- /Adafruit_ESP8266.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file Adafruit_ESP8266.cpp 3 | * 4 | * @mainpage Adafruit ESP8266 library 5 | * 6 | * @section intro_sec Introduction 7 | * 8 | * An Arduino library for the ESP8266 WiFi-serial bridge 9 | * 10 | * https://www.adafruit.com/product/2282 11 | * 12 | * The ESP8266 is a 3.3V device. Safe operation with 5V devices (most 13 | * Arduino boards) requires a logic-level shifter for TX and RX signals. 14 | * 15 | * Adafruit invests time and resources providing this open source code, 16 | * please support Adafruit and open-source hardware by purchasing 17 | * products from Adafruit! 18 | * 19 | * @section author Author 20 | * 21 | * Written by Limor Fried and Phil Burgess for Adafruit Industries. 22 | * 23 | * @section license License 24 | * 25 | * MIT license, all text above must be included in any redistribution. 26 | */ 27 | 28 | #include "Adafruit_ESP8266.h" 29 | 30 | /**************************************************************************/ 31 | /*! 32 | @brief Constructor 33 | @param serial_stream 34 | Pointer to Stream (Hardware or Software Serial) for the ESP8266 35 | @param debug_stream 36 | Pointer to Stream (Hardware or Software Serial) for debug out 37 | @param resetpin Reset pin 38 | */ 39 | /**************************************************************************/ 40 | Adafruit_ESP8266::Adafruit_ESP8266(Stream *serial_stream, Stream *debug_stream, 41 | int8_t resetpin) 42 | : stream(serial_stream), debug(debug_stream), reset_pin(resetpin), 43 | host(NULL), writing(false) { 44 | setTimeouts(); 45 | }; 46 | 47 | // 48 | /**************************************************************************/ 49 | /*! 50 | @brief Override various timings.Passing 0 for an item keeps current 51 | setting. 52 | @param rcv Receive data timeout 53 | @param rst Reset response timeout 54 | @param con Connection timeout 55 | @param ipd IPD response timeout 56 | */ 57 | /**************************************************************************/ 58 | void Adafruit_ESP8266::setTimeouts(uint32_t rcv, uint32_t rst, uint32_t con, 59 | uint32_t ipd) { 60 | if (rcv) { 61 | stream->setTimeout(rcv); 62 | receiveTimeout = rcv; 63 | } 64 | if (rst) 65 | resetTimeout = rst; 66 | if (con) 67 | connectTimeout = con; 68 | if (ipd) 69 | ipdTimeout = ipd; 70 | } 71 | 72 | /**************************************************************************/ 73 | /*! 74 | @brief Override boot marker string, or pass NULL to restore default. 75 | @param str 76 | The bootmarker string to look for 77 | */ 78 | /**************************************************************************/ 79 | void Adafruit_ESP8266::setBootMarker(Fstr *str) { 80 | bootMarker = str ? str : defaultBootMarker; 81 | } 82 | 83 | /**************************************************************************/ 84 | /*! 85 | @brief Send one byte character. Anything printed to the EPS8266 object will 86 | be split to both the WiFi and debug streams. Saves having to print 87 | everything twice in debug code. 88 | @param c 89 | The character 90 | */ 91 | /**************************************************************************/ 92 | size_t Adafruit_ESP8266::write(uint8_t c) { 93 | if (debug) { 94 | if (!writing) { 95 | debug->print(F("---> ")); 96 | writing = true; 97 | } 98 | debug->write(c); 99 | } 100 | return stream->write(c); 101 | } 102 | 103 | /**************************************************************************/ 104 | /*! 105 | @brief 106 | Equivalent to Arduino Stream find() function, but with search string in 107 | flash/PROGMEM rather than RAM-resident. Can optionally pass NULL (or no 108 | argument) to read/purge the OK+CR/LF returned by most AT commands. The ipd 109 | flag indicates this call follows a CIPSEND request and might be broken into 110 | multiple sections with +IPD delimiters, which must be parsed and handled (as 111 | the search string may cross these delimiters and/or contain \\r or \\n 112 | itself). 113 | @param str The Flash string to find 114 | @param ipd If we're looking for IPD data 115 | @returns Returns true if string found 116 | (any further pending input remains in stream), false if timeout occurs. 117 | */ 118 | /**************************************************************************/ 119 | boolean Adafruit_ESP8266::find(Fstr *str, boolean ipd) { 120 | uint8_t stringLength, matchedLength = 0; 121 | int c; 122 | boolean found = false; 123 | uint32_t t, save; 124 | uint16_t bytesToGo = 0; 125 | 126 | if (ipd) { // IPD stream stalls really long occasionally, what gives? 127 | save = receiveTimeout; 128 | setTimeouts(ipdTimeout); 129 | } 130 | 131 | if (str == NULL) 132 | str = F("OK\r\n"); 133 | stringLength = strlen_P((Pchr *)str); 134 | 135 | if (debug && writing) { 136 | debug->print(F("<--- '")); 137 | writing = false; 138 | } 139 | 140 | for (t = millis();;) { 141 | if (ipd && !bytesToGo) { // Expecting next IPD marker? 142 | if (find(F("+IPD,"))) { // Find marker in stream 143 | for (;;) { 144 | if ((c = stream->read()) > 0) { // Read subsequent chars... 145 | if (debug) 146 | debug->write(c); 147 | if (c == ':') 148 | break; // ...until delimiter. 149 | bytesToGo = (bytesToGo * 10) + (c - '0'); // Keep count 150 | t = millis(); // Timeout resets w/each byte received 151 | } else if (c < 0) { // No data on stream, check for timeout 152 | if ((millis() - t) > receiveTimeout) 153 | goto bail; 154 | } else 155 | goto bail; // EOD on stream 156 | } 157 | } else 158 | break; // OK (EOD) or ERROR 159 | } 160 | 161 | if ((c = stream->read()) > 0) { // Character received? 162 | if (debug) 163 | debug->write(c); // Copy to debug stream 164 | bytesToGo--; 165 | if (c == pgm_read_byte((Pchr *)str + matchedLength)) { // Match next byte? 166 | if (++matchedLength == stringLength) { // Matched whole string? 167 | found = true; // Winner! 168 | break; 169 | } 170 | } else { // Character mismatch; reset match pointer+counter 171 | matchedLength = 0; 172 | } 173 | t = millis(); // Timeout resets w/each byte received 174 | } else if (c < 0) { // No data on stream, check for timeout 175 | if ((millis() - t) > receiveTimeout) 176 | break; // You lose, good day sir 177 | } else 178 | break; // End-of-data on stream 179 | } 180 | 181 | bail: // Sorry, dreaded goto. Because nested loops. 182 | if (debug) 183 | debug->println('\''); 184 | if (ipd) 185 | setTimeouts(save); 186 | return found; 187 | } 188 | 189 | /**************************************************************************/ 190 | /*! 191 | @brief Read from ESP8266 stream into RAM, up to a given size. Max number of 192 | chars read is 1 less than this, so NUL can be appended on string. 193 | @param buf Where to put streamed in data 194 | @param bufSiz The max allocated buffer size 195 | @returns Bytes read 196 | */ 197 | /**************************************************************************/ 198 | int Adafruit_ESP8266::readLine(char *buf, int bufSiz) { 199 | if (debug && writing) { 200 | debug->print(F("<--- '")); 201 | writing = false; 202 | } 203 | int bytesRead = stream->readBytesUntil('\r', buf, bufSiz - 1); 204 | buf[bytesRead] = 0; 205 | if (debug) { 206 | debug->print(buf); 207 | debug->println('\''); 208 | } 209 | while (stream->read() != '\n') 210 | ; // Discard thru newline 211 | return bytesRead; 212 | } 213 | 214 | /**************************************************************************/ 215 | /*! 216 | @brief ESP8266 is reset by momentarily connecting RST to GND. Level 217 | shifting is not necessary provided you don't accidentally set the pin to HIGH 218 | output. It's generally safe-ish as the default Arduino pin state is INPUT 219 | (w/no pullup) -- setting to LOW provides an open-drain for reset. 220 | @returns true if expected boot message is received (or if RST is unused) 221 | false otherwise. 222 | */ 223 | /**************************************************************************/ 224 | boolean Adafruit_ESP8266::hardReset(void) { 225 | if (reset_pin < 0) 226 | return true; 227 | digitalWrite(reset_pin, LOW); 228 | pinMode(reset_pin, OUTPUT); // Open drain; reset -> GND 229 | delay(10); // Hold a moment 230 | pinMode(reset_pin, INPUT); // Back to high-impedance pin state 231 | return find(bootMarker); // Purge boot message from stream 232 | } 233 | 234 | /**************************************************************************/ 235 | /*! 236 | @brief Software reset 237 | @returns true if expected boot message is received (or if RST is unused) 238 | false otherwise. 239 | */ 240 | /**************************************************************************/ 241 | boolean Adafruit_ESP8266::softReset(void) { 242 | boolean found = false; 243 | uint32_t save = receiveTimeout; // Temporarily override recveive timeout, 244 | receiveTimeout = resetTimeout; // reset time is longer than normal I/O. 245 | println(F("AT+RST")); // Issue soft-reset command 246 | if (find(bootMarker)) { // Wait for boot message 247 | println(F("ATE0")); // Turn off echo 248 | found = find(); // OK? 249 | } 250 | receiveTimeout = save; // Restore normal receive timeout 251 | return found; 252 | } 253 | 254 | /**************************************************************************/ 255 | /*! 256 | @brief For interactive debugging...shuttle data between Serial Console <-> 257 | WiFi 258 | */ 259 | /**************************************************************************/ 260 | void Adafruit_ESP8266::debugLoop(void) { 261 | if (!debug) 262 | for (;;) 263 | ; // If no debug connection, nothing to do. 264 | 265 | debug->println(F("\n========================")); 266 | for (;;) { 267 | if (debug->available()) 268 | stream->write(debug->read()); 269 | if (stream->available()) 270 | debug->write(stream->read()); 271 | } 272 | } 273 | 274 | /**************************************************************************/ 275 | /*! 276 | @brief Connect to WiFi access point. SSID and password are flash-resident 277 | strings. May take several seconds to execute, this is normal. 278 | @param ssid Flash string of AP SSID 279 | @param pass Flash string of AP password 280 | @returns true on successful connection, false otherwise. 281 | */ 282 | /**************************************************************************/ 283 | boolean Adafruit_ESP8266::connectToAP(Fstr *ssid, Fstr *pass) { 284 | char buf[256]; 285 | 286 | println(F("AT+CWMODE=1")); // WiFi mode = Sta 287 | readLine(buf, sizeof(buf)); 288 | if (!(strstr_P(buf, (Pchr *)F("OK")) || 289 | strstr_P(buf, (Pchr *)F("no change")))) 290 | return false; 291 | 292 | print(F("AT+CWJAP=\"")); // Join access point 293 | print(ssid); 294 | print(F("\",\"")); 295 | print(pass); 296 | println('\"'); 297 | uint32_t save = receiveTimeout; // Temporarily override recv timeout, 298 | receiveTimeout = connectTimeout; // connection time is much longer! 299 | boolean found = find(); // Await 'OK' message 300 | receiveTimeout = save; // Restore normal receive timeout 301 | if (found) { 302 | println(F("AT+CIPMUX=0")); // Set single-client mode 303 | found = find(); // Await 'OK' 304 | } 305 | 306 | return found; 307 | } 308 | 309 | /**************************************************************************/ 310 | /*! 311 | @brief Close current connection 312 | */ 313 | /**************************************************************************/ 314 | void Adafruit_ESP8266::closeAP(void) { 315 | println(F("AT+CWQAP")); // Quit access point 316 | find(); // Purge 'OK' 317 | } 318 | 319 | /**************************************************************************/ 320 | /*! 321 | @brief Open TCP connection. Hostname is flash-resident string. 322 | @param hoststr Hostname string 323 | @param port TCP port on host 324 | @returns true on successful connection, else false. 325 | */ 326 | /**************************************************************************/ 327 | boolean Adafruit_ESP8266::connectTCP(Fstr *hoststr, int port) { 328 | 329 | print(F("AT+CIPSTART=\"TCP\",\"")); 330 | print(hoststr); 331 | print(F("\",")); 332 | println(port); 333 | 334 | if (find(F("Linked"))) { 335 | host = hoststr; 336 | return true; 337 | } 338 | return false; 339 | } 340 | /**************************************************************************/ 341 | /*! 342 | @brief Close current connection 343 | */ 344 | /**************************************************************************/ 345 | void Adafruit_ESP8266::closeTCP(void) { 346 | println(F("AT+CIPCLOSE")); 347 | find(F("Unlink\r\n")); 348 | } 349 | 350 | /**************************************************************************/ 351 | /*! 352 | @brief Requests page from currently-open TCP connection. URL is 353 | flash-resident string. 354 | @param url The flash string URL to request 355 | @returns true if request issued successfully, else false. 356 | */ 357 | /**************************************************************************/ 358 | boolean Adafruit_ESP8266::requestURL(Fstr *url) { 359 | print(F("AT+CIPSEND=")); 360 | println(25 + strlen_P((Pchr *)url) + strlen_P((Pchr *)host)); 361 | if (find(F("> "))) { // Wait for prompt 362 | print(F("GET ")); // 4 363 | print(url); 364 | print(F(" HTTP/1.1\r\nHost: ")); // 17 365 | print(host); 366 | print(F("\r\n\r\n")); // 4 367 | return (find()); // Gets 'SEND OK' line 368 | } 369 | return false; 370 | } 371 | 372 | /**************************************************************************/ 373 | /*! 374 | @brief Requests page from cur 375 | rently-open TCP connection. URL is character string in SRAM. Calling function 376 | should then handle data returned, may need to parse IPD delimiters (see notes in 377 | find() function. (Can call find(F("Unlink"), true) to dump to debug.) 378 | @param url The SRAM string URL to request 379 | @returns true if request issued successfully, else false. 380 | */ 381 | /**************************************************************************/ 382 | boolean Adafruit_ESP8266::requestURL(char *url) { 383 | print(F("AT+CIPSEND=")); 384 | println(25 + strlen(url) + strlen_P((Pchr *)host)); 385 | if (find(F("> "))) { // Wait for prompt 386 | print(F("GET ")); // 4 387 | print(url); 388 | print(F(" HTTP/1.1\r\nHost: ")); // 17 389 | print(host); 390 | print(F("\r\n\r\n")); // 4 391 | return (find()); // Gets 'SEND OK' line 392 | } 393 | return false; 394 | } 395 | -------------------------------------------------------------------------------- /Adafruit_ESP8266.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file Adafruit_ESP8266.h 3 | */ 4 | 5 | #ifndef _ADAFRUIT_ESP8266_H_ 6 | #define _ADAFRUIT_ESP8266_H_ 7 | 8 | #include 9 | 10 | #define ESP_RECEIVE_TIMEOUT 1000L //!< Receive timeout for ESP8266 11 | #define ESP_RESET_TIMEOUT 5000L //!< Reset timeout for ESP8266 12 | #define ESP_CONNECT_TIMEOUT 15000L //!< Connection timeout for ESP8266 13 | #define ESP_IPD_TIMEOUT 120000L //!< Receive network data timeout for ESP8266 14 | 15 | typedef const __FlashStringHelper Fstr; //!< PROGMEM/flash-resident string 16 | typedef const PROGMEM char Pchr; //!< Ditto, kindasorta 17 | 18 | #define defaultBootMarker F("ready\r\n") //!< Default ESP8266 boot marker string 19 | 20 | /*! Subclassing Print makes debugging easier -- output en route to WiFi module 21 | * can be duplicated on a second stream (e.g. Serial). !*/ 22 | class Adafruit_ESP8266 : public Print { 23 | public: 24 | Adafruit_ESP8266(Stream *s = &Serial, Stream *d = NULL, int8_t r = -1); 25 | boolean hardReset(void), softReset(void), 26 | find(Fstr *str = NULL, boolean ipd = false), 27 | connectToAP(Fstr *ssid, Fstr *pass), connectTCP(Fstr *host, int port), 28 | requestURL(Fstr *url), requestURL(char *url); 29 | int readLine(char *buf, int bufSiz); 30 | void closeAP(void), closeTCP(void), debugLoop(void), 31 | setTimeouts(uint32_t rcv = ESP_RECEIVE_TIMEOUT, 32 | uint32_t rst = ESP_RESET_TIMEOUT, 33 | uint32_t con = ESP_CONNECT_TIMEOUT, 34 | uint32_t ipd = ESP_IPD_TIMEOUT), 35 | setBootMarker(Fstr *s = NULL); 36 | 37 | private: 38 | Stream *stream, // -> ESP8266, e.g. SoftwareSerial or Serial1 39 | *debug; // -> host, e.g. Serial 40 | uint32_t receiveTimeout, resetTimeout, connectTimeout, ipdTimeout; 41 | int8_t reset_pin; // -1 if RST not connected 42 | Fstr *host, // Non-NULL when TCP connection open 43 | *bootMarker; // String indicating successful boot 44 | boolean writing; 45 | virtual size_t write(uint8_t); // Because Print subclass 46 | }; 47 | 48 | #endif // _ADAFRUIT_ESP8266_H_ 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit_ESP8266 [![Build Status](https://github.com/adafruit/Adafruit_ESP8266/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_ESP8266/actions) 2 | 3 | Example code for ESP8266 chipset 4 | -------------------------------------------------------------------------------- /examples/webclient/webclient.ino: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------ 2 | Simple ESP8266 test. Requires SoftwareSerial and an ESP8266 that's been 3 | flashed with recent 'AT' firmware operating at 9600 baud. Only tested 4 | w/Adafruit-programmed modules: https://www.adafruit.com/product/2282 5 | 6 | The ESP8266 is a 3.3V device. Safe operation with 5V devices (most 7 | Arduino boards) requires a logic-level shifter for TX and RX signals. 8 | ------------------------------------------------------------------------*/ 9 | 10 | #include 11 | #include 12 | 13 | #define ARD_RX_ESP_TX 2 14 | #define ARD_TX_ESP_RX 3 15 | #define ESP_RST 4 16 | SoftwareSerial softser(ARD_RX_ESP_TX, ARD_TX_ESP_RX); // Arduino RX = ESP TX, Arduino TX = ESP RX 17 | 18 | // Must declare output stream before Adafruit_ESP8266 constructor; can be 19 | // a SoftwareSerial stream, or Serial/Serial1/etc. for UART. 20 | Adafruit_ESP8266 wifi(&softser, &Serial, ESP_RST); 21 | // Must call begin() on the stream(s) before using Adafruit_ESP8266 object. 22 | 23 | #define ESP_SSID "SSIDNAME" // Your network name here 24 | #define ESP_PASS "PASSWORD" // Your network password here 25 | 26 | #define HOST "wifitest.adafruit.com" // Host to contact 27 | #define PAGE "/testwifi/index.html" // Web page to request 28 | #define PORT 80 // 80 = HTTP default port 29 | 30 | #define LED_PIN 13 31 | 32 | void setup() { 33 | char buffer[50]; 34 | 35 | // Flash LED on power-up 36 | pinMode(LED_PIN, OUTPUT); 37 | for(uint8_t i=0; i<3; i++) { 38 | digitalWrite(LED_PIN, HIGH); delay(50); 39 | digitalWrite(LED_PIN, LOW); delay(100); 40 | } 41 | 42 | // This might work with other firmware versions (no guarantees) 43 | // by providing a string to ID the tail end of the boot message: 44 | 45 | // comment/replace this if you are using something other than v 0.9.2.4! 46 | wifi.setBootMarker(F("Version:0.9.2.4]\r\n\r\nready")); 47 | 48 | softser.begin(9600); // Soft serial connection to ESP8266 49 | Serial.begin(57600); while(!Serial); // UART serial debug 50 | 51 | Serial.println(F("Adafruit ESP8266 Demo")); 52 | 53 | // Test if module is ready 54 | Serial.print(F("Hard reset...")); 55 | if(!wifi.hardReset()) { 56 | Serial.println(F("no response from module.")); 57 | for(;;); 58 | } 59 | Serial.println(F("OK.")); 60 | 61 | Serial.print(F("Soft reset...")); 62 | if(!wifi.softReset()) { 63 | Serial.println(F("no response from module.")); 64 | for(;;); 65 | } 66 | Serial.println(F("OK.")); 67 | 68 | Serial.print(F("Checking firmware version...")); 69 | wifi.println(F("AT+GMR")); 70 | if(wifi.readLine(buffer, sizeof(buffer))) { 71 | Serial.println(buffer); 72 | wifi.find(); // Discard the 'OK' that follows 73 | } else { 74 | Serial.println(F("error")); 75 | } 76 | 77 | Serial.print(F("Connecting to WiFi...")); 78 | if(wifi.connectToAP(F(ESP_SSID), F(ESP_PASS))) { 79 | 80 | // IP addr check isn't part of library yet, but 81 | // we can manually request and place in a string. 82 | Serial.print(F("OK\nChecking IP addr...")); 83 | wifi.println(F("AT+CIFSR")); 84 | if(wifi.readLine(buffer, sizeof(buffer))) { 85 | Serial.println(buffer); 86 | wifi.find(); // Discard the 'OK' that follows 87 | 88 | Serial.print(F("Connecting to host...")); 89 | if(wifi.connectTCP(F(HOST), PORT)) { 90 | Serial.print(F("OK\nRequesting page...")); 91 | if(wifi.requestURL(F(PAGE))) { 92 | Serial.println("OK\nSearching for string..."); 93 | // Search for a phrase in the open stream. 94 | // Must be a flash-resident string (F()). 95 | if(wifi.find(F("working"), true)) { 96 | Serial.println(F("found!")); 97 | } else { 98 | Serial.println(F("not found.")); 99 | } 100 | } else { // URL request failed 101 | Serial.println(F("error")); 102 | } 103 | wifi.closeTCP(); 104 | } else { // TCP connect failed 105 | Serial.println(F("D'oh!")); 106 | } 107 | } else { // IP addr check failed 108 | Serial.println(F("error")); 109 | } 110 | wifi.closeAP(); 111 | } else { // WiFi connection failed 112 | Serial.println(F("FAIL")); 113 | } 114 | } 115 | 116 | void loop() { 117 | } 118 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit ESP8266 2 | version=1.1.2 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=Example code for ESP8266 chipset 6 | paragraph=Example code for ESP8266 chipset 7 | category=Communication 8 | url=https://github.com/adafruit/Adafruit_ESP8266 9 | architectures=* 10 | -------------------------------------------------------------------------------- /previous/Adafruit_ESP8266.ino: -------------------------------------------------------------------------------- 1 | // This is a super simple demo program for ESP8266's that can use software serial 2 | // @ 9600 baud. Requires firmware that runs at 9600 baud, only tested with Adafruit 3 | // programmed modules! 4 | 5 | #include 6 | #define SSID "SSIDNAME" //your wifi ssid here 7 | #define PASS "PASSWORD" //your wifi key here 8 | 9 | // wifitest.adafruit.com/testwifi/index.html 10 | #define HOST "wifitest.adafruit.com" 11 | #define WEBPAGE "/testwifi/index.html" 12 | #define PORT "80" 13 | 14 | #define ESP_RST 4 15 | 16 | // Use software serial (check to make sure these are valid softserial pins!) 17 | #define ESP_RX 2 18 | #define ESP_TX 3 19 | SoftwareSerial softser(ESP_RX, ESP_TX); // RX, TX 20 | Stream *esp = &softser; 21 | 22 | // can also do 23 | // Stream *esp = &Serial1; 24 | 25 | #define REPLYBUFFSIZ 255 26 | char replybuffer[REPLYBUFFSIZ]; 27 | uint8_t getReply(char *send, uint16_t timeout = 500, boolean echo = true); 28 | uint8_t espreadline(uint16_t timeout = 500, boolean multiline = false); 29 | boolean sendCheckReply(char *send, char *reply, uint16_t timeout = 500); 30 | 31 | 32 | enum {WIFI_ERROR_NONE=0, WIFI_ERROR_AT, WIFI_ERROR_RST, WIFI_ERROR_SSIDPWD, WIFI_ERROR_SERVER, WIFI_ERROR_UNKNOWN}; 33 | 34 | void setup() 35 | { 36 | pinMode(9, OUTPUT); 37 | pinMode(13, OUTPUT); 38 | 39 | //blink led13 to indicate power up 40 | for(int i = 0; i<3; i++) 41 | { 42 | digitalWrite(13,HIGH); 43 | delay(50); 44 | digitalWrite(13,LOW); 45 | delay(100); 46 | } 47 | 48 | // Serial debug console 49 | Serial.begin(115200); 50 | // Set time to wait for response strings to be found 51 | 52 | //Open software serial for chatting to ESP 53 | softser.begin(9600); // requires new firmware! 54 | // OR use hardware serial 55 | //Serial1.begin(9600); 56 | 57 | Serial.println(F("Adafruit's ESP8266 Demo")); 58 | 59 | Serial.println(F("Hard reset...")); 60 | // hard reset if you can 61 | pinMode(ESP_RST, INPUT); 62 | digitalWrite(ESP_RST, LOW); 63 | pinMode(ESP_RST, OUTPUT); 64 | delay(100); 65 | pinMode(ESP_RST, INPUT); 66 | delay(2000); 67 | 68 | //test if the module is ready 69 | if(! espReset()) { 70 | Serial.println("Module didn't respond :("); 71 | debugLoop(); 72 | } 73 | 74 | Serial.println(F("ESP Module is ready! :)")); 75 | 76 | //connect to the wifi 77 | byte err = setupWiFi(); 78 | 79 | if (err) { 80 | // error, print error code 81 | Serial.print("setup error:"); Serial.println((int)err); 82 | 83 | debugLoop(); 84 | } 85 | 86 | // success, print IP 87 | uint32_t ip = getIP(); 88 | Serial.print("ESP setup success, my IP addr:"); 89 | if (ip) { 90 | Serial.println(ip, HEX); 91 | } else { 92 | Serial.println("none"); 93 | } 94 | 95 | sendCheckReply("AT+CIPSTO=0", "OK"); 96 | 97 | //set the single connection mode 98 | } 99 | 100 | boolean ESP_GETpage(char *host, uint16_t port, char *page) { 101 | String cmd = "AT+CIPSTART=\"TCP\",\""; 102 | cmd += host; 103 | cmd += "\","; 104 | cmd += port; 105 | cmd.toCharArray(replybuffer, REPLYBUFFSIZ); 106 | 107 | getReply(replybuffer); 108 | 109 | if (strcmp(replybuffer, "OK") != 0) { 110 | // this is OK! could be a version that says "Linked" 111 | if (strcmp(replybuffer, "Linked") != 0) { 112 | sendCheckReply("AT+CIPCLOSE", "OK"); 113 | return false; 114 | } 115 | } 116 | 117 | String request = "GET "; 118 | request += page; 119 | request += " HTTP/1.1\r\nHost: "; 120 | request += host; 121 | request += "\r\n\r\n"; 122 | 123 | cmd = "AT+CIPSEND="; 124 | cmd += request.length(); 125 | cmd.toCharArray(replybuffer, REPLYBUFFSIZ); 126 | sendCheckReply(replybuffer, ">"); 127 | 128 | Serial.print("Sending: "); Serial.println(request.length()); 129 | Serial.println(F("*********SENDING*********")); 130 | Serial.print(request); 131 | Serial.println(F("*************************")); 132 | 133 | request.toCharArray(replybuffer, REPLYBUFFSIZ); 134 | 135 | esp->println(request); 136 | 137 | while (true) { 138 | espreadline(3000); // this is the 'echo' from the data 139 | Serial.print(">"); Serial.println(replybuffer); // probably the 'busy s...' 140 | 141 | // LOOK AT ALL THESE POSSIBLE ARBITRARY RESPONSES!!! 142 | if (strstr(replybuffer, "wrong syntax")) 143 | continue; 144 | else if (strstr(replybuffer, "ERROR")) 145 | continue; 146 | else if (strstr(replybuffer, "busy s...")) 147 | continue; 148 | else break; 149 | } 150 | 151 | if (! strstr(replybuffer, "SEND OK") ) return false; 152 | 153 | espreadline(1000); Serial.print("3>"); Serial.println(replybuffer); 154 | char *s = strstr(replybuffer, "+IPD,"); 155 | if (!s) return false; 156 | uint16_t len = atoi(s+5); 157 | //Serial.print(len); Serial.println(" bytes total"); 158 | 159 | int16_t contentlen = 0; 160 | while (1) { 161 | espreadline(50); 162 | s = strstr(replybuffer, "Content-Length: "); 163 | if (s) { 164 | //Serial.println(replybuffer); 165 | contentlen = atoi(s+16); 166 | Serial.print(F("C-Len = ")); Serial.println(contentlen); 167 | } 168 | s = strstr(replybuffer, "Content-Type: "); 169 | if (s && contentlen) { 170 | int16_t i; 171 | char c; 172 | 173 | for (i=-2; iavailable()); 175 | c = esp->read(); //UDR0 = c; 176 | if (i >= 0) { 177 | replybuffer[i] = c; 178 | } 179 | } 180 | replybuffer[i] = 0; 181 | return true; 182 | } 183 | } 184 | //while (1) { 185 | // if (esp.available()) UDR0 = esp.read(); 186 | //} 187 | } 188 | 189 | void loop() 190 | { 191 | ESP_GETpage(HOST, 80, WEBPAGE); 192 | 193 | Serial.println(F("**********REPLY***********")); 194 | Serial.print(replybuffer); 195 | Serial.println(F("**************************")); 196 | 197 | sendCheckReply("AT+CIPCLOSE", "OK"); 198 | 199 | debugLoop(); 200 | 201 | delay(1000); 202 | 203 | while (1); 204 | 205 | } 206 | 207 | boolean getVersion() { 208 | // Get version? 209 | getReply("AT+GMR", 250, true); 210 | } 211 | 212 | boolean espReset() { 213 | getReply("AT+RST", 1000, true); 214 | if (! strstr(replybuffer, "OK")) return false; 215 | delay(2000); 216 | 217 | // turn off echo 218 | getReply("ATE0", 250, true); 219 | 220 | return true; 221 | } 222 | 223 | boolean ESPconnectAP(char *s, char *p) { 224 | 225 | getReply("AT+CWMODE=1", 500, true); 226 | if (! (strstr(replybuffer, "OK") || strstr(replybuffer, "no change")) ) 227 | return false; 228 | 229 | String connectStr = "AT+CWJAP=\""; 230 | connectStr += SSID; 231 | connectStr += "\",\""; 232 | connectStr += PASS; 233 | connectStr += "\""; 234 | connectStr.toCharArray(replybuffer, REPLYBUFFSIZ); 235 | getReply(replybuffer, 500, true); 236 | espreadline(5000); 237 | Serial.print("<-- "); Serial.println(replybuffer); 238 | 239 | return (strstr(replybuffer, "OK") != 0); 240 | } 241 | 242 | 243 | byte setupWiFi() { 244 | // reset WiFi module 245 | Serial.println(F("Soft resetting...")); 246 | if (!espReset()) 247 | return WIFI_ERROR_RST; 248 | 249 | delay(1000); 250 | 251 | Serial.println(F("Checking for ESP AT response")); 252 | 253 | if (!sendCheckReply("AT", "OK")) 254 | return WIFI_ERROR_AT; 255 | 256 | getVersion(); 257 | Serial.print(F("Firmware Version #")); Serial.println(replybuffer); 258 | 259 | Serial.print(F("Connecting to ")); Serial.println(SSID); 260 | if (!ESPconnectAP(SSID, PASS)) 261 | return WIFI_ERROR_SSIDPWD; 262 | 263 | Serial.println(F("Single Client Mode")); 264 | if (!sendCheckReply("AT+CIPMUX=0", "OK")) 265 | return WIFI_ERROR_SERVER; 266 | 267 | return WIFI_ERROR_NONE; 268 | } 269 | 270 | // NOT IMPLEMENTED YET! 271 | uint32_t getIP() { 272 | getReply("AT+CIFSR", 500, true); 273 | 274 | return 0; 275 | } 276 | 277 | 278 | 279 | 280 | /************************/ 281 | uint8_t espreadline(uint16_t timeout, boolean multiline) { 282 | uint16_t replyidx = 0; 283 | 284 | while (timeout--) { 285 | if (replyidx > REPLYBUFFSIZ-1) break; 286 | 287 | while(esp->available()) { 288 | char c = esp->read(); 289 | if (c == '\r') continue; 290 | if (c == 0xA) { 291 | if (replyidx == 0) // the first 0x0A is ignored 292 | continue; 293 | 294 | if (!multiline) { 295 | timeout = 0; // the second 0x0A is the end of the line 296 | break; 297 | } 298 | } 299 | replybuffer[replyidx] = c; 300 | // Serial.print(c, HEX); Serial.print("#"); Serial.println(c); 301 | replyidx++; 302 | } 303 | 304 | if (timeout == 0) break; 305 | delay(1); 306 | } 307 | replybuffer[replyidx] = 0; // null term 308 | return replyidx; 309 | } 310 | 311 | uint8_t getReply(char *send, uint16_t timeout, boolean echo) { 312 | // flush input 313 | while(esp->available()) { 314 | esp->read(); 315 | } 316 | 317 | if (echo) { 318 | Serial.print("---> "); Serial.println(send); 319 | } 320 | esp->println(send); 321 | 322 | // eat first reply sentence (echo) 323 | uint8_t readlen = espreadline(timeout); 324 | 325 | //Serial.print("echo? "); Serial.print(readlen); Serial.print(" vs "); Serial.println(strlen(send)); 326 | 327 | if (strncmp(send, replybuffer, readlen) == 0) { 328 | // its an echo, read another line! 329 | readlen = espreadline(); 330 | } 331 | 332 | if (echo) { 333 | Serial.print ("<--- "); Serial.println(replybuffer); 334 | } 335 | return readlen; 336 | } 337 | 338 | boolean sendCheckReply(char *send, char *reply, uint16_t timeout) { 339 | getReply(send, timeout, true); 340 | 341 | /* 342 | for (uint8_t i=0; iwrite(Serial.read()); 360 | delay(1); 361 | } 362 | if (esp->available()) { 363 | Serial.write(esp->read()); 364 | delay(1); 365 | } 366 | } 367 | } 368 | --------------------------------------------------------------------------------