├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md ├── .gitlab-ci.yml ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── examples ├── ETH_LAN8720 │ └── ETH_LAN8720.ino ├── ETH_LAN8720_internal_clock │ └── ETH_LAN8720_internal_clock.ino ├── ETH_TLK110 │ └── ETH_TLK110.ino ├── SimpleWiFiServer │ └── SimpleWiFiServer.ino ├── WPS │ ├── README.md │ └── WPS.ino ├── WiFiAccessPoint │ └── WiFiAccessPoint.ino ├── WiFiBlueToothSwitch │ └── WiFiBlueToothSwitch.ino ├── WiFiClient │ └── WiFiClient.ino ├── WiFiClientBasic │ └── WiFiClientBasic.ino ├── WiFiClientEnterprise │ ├── README.md │ └── WiFiClientEnterprise.ino ├── WiFiClientEvents │ └── WiFiClientEvents.ino ├── WiFiClientStaticIP │ └── WiFiClientStaticIP.ino ├── WiFiIPv6 │ └── WiFiIPv6.ino ├── WiFiMulti │ └── WiFiMulti.ino ├── WiFiScan │ └── WiFiScan.ino ├── WiFiSmartConfig │ └── WiFiSmartConfig.ino ├── WiFiTelnetToSerial │ └── WiFiTelnetToSerial.ino └── WiFiUDPClient │ ├── WiFiUDPClient.ino │ ├── udp_server.py │ └── udp_server.rb ├── keywords.txt ├── library.properties └── src ├── AtWiFi.h ├── ETH.cpp ├── ETH.h ├── WiFi.cpp ├── WiFi.h ├── WiFiAP.cpp ├── WiFiAP.h ├── WiFiClient.cpp ├── WiFiClient.h ├── WiFiGeneric.cpp ├── WiFiGeneric.h ├── WiFiMulti.cpp ├── WiFiMulti.h ├── WiFiSTA.cpp ├── WiFiSTA.h ├── WiFiScan.cpp ├── WiFiScan.h ├── WiFiServer.cpp ├── WiFiServer.h ├── WiFiType.h ├── WiFiUdp.cpp └── WiFiUdp.h /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | build: 2 | tags: 3 | - nas 4 | script: 5 | - wget -c https://files.seeedstudio.com/arduino/seeed-arduino-ci.sh 6 | - chmod +x seeed-arduino-ci.sh 7 | - bash $PWD/seeed-arduino-ci.sh test 8 | 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: generic 3 | dist: bionic 4 | sudo: false 5 | cache: 6 | directories: 7 | - ~/arduino_ide 8 | - ~/.arduino15/packages/ 9 | 10 | before_install: 11 | - wget -c https://github.com/Seeed-Studio/Seeed_Arduino_atUnified/raw/master/seeed-arduino-ci.sh 12 | 13 | script: 14 | - chmod +x seeed-arduino-ci.sh 15 | - cat $PWD/seeed-arduino-ci.sh 16 | - $PWD/seeed-arduino-ci.sh -b "Seeeduino:samd:seeed_wio_terminal" -s SimpleWiFiServer/WiFiAccessPoint/WiFiClient/WiFiClientBasic/WiFiClientEvents/WiFiMulti/WiFiScan/WiFiTelnetToSerial Seeed-Studio/esp-at-lib.git Seeed-Studio/Seeed_Arduino_FreeRTOS.git Seeed-Studio/Seeed_Arduino_atUnified.git 17 | 18 | notifications: 19 | email: 20 | on_success: change 21 | on_failure: change 22 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at zuobaozhu@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing guidelines 2 | 3 | All guidelines for contributing to the Seeed_Arduino_atWiFi repository can be found at [`How to contribute guideline`](https://github.com/Seeed-Studio/Seeed_Arduino_atWiFi/wiki/How_to_contribute). 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Seeed Studio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | !!!Deprecation Warning!!! 2 | =================== 3 | This library has been deprecated in favor of [our rpcWifi library](https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi). We have replaced all of the functions that use this repo with rpcWifi libraries that are ESP32 compatible. 4 | Visit https://wiki.seeedstudio.com/Wio-Terminal-Wi-Fi/ for more information 5 | 6 | 7 | !!!Deprecation Warning!!! 8 | =================== 9 | # Seeed_Arduino_atWiFi [![Build Status](https://travis-ci.com/Seeed-Studio/Seeed_Arduino_atWiFi.svg?branch=master)](https://travis-ci.com/Seeed-Studio/Seeed_Arduino_atWiFi) 10 | -------------------------------------------------------------------------------- /examples/ETH_LAN8720/ETH_LAN8720.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch shows the Ethernet event usage 3 | 4 | */ 5 | 6 | #include 7 | 8 | static bool eth_connected = false; 9 | 10 | void WiFiEvent(WiFiEvent_t event) { 11 | switch (event) { 12 | case SYSTEM_EVENT_ETH_START: 13 | Serial.println("ETH Started"); 14 | //set eth hostname here 15 | ETH.setHostname("esp32-ethernet"); 16 | break; 17 | case SYSTEM_EVENT_ETH_CONNECTED: 18 | Serial.println("ETH Connected"); 19 | break; 20 | case SYSTEM_EVENT_ETH_GOT_IP: 21 | Serial.print("ETH MAC: "); 22 | Serial.print(ETH.macAddress()); 23 | Serial.print(", IPv4: "); 24 | Serial.print(ETH.localIP()); 25 | if (ETH.fullDuplex()) { 26 | Serial.print(", FULL_DUPLEX"); 27 | } 28 | Serial.print(", "); 29 | Serial.print(ETH.linkSpeed()); 30 | Serial.println("Mbps"); 31 | eth_connected = true; 32 | break; 33 | case SYSTEM_EVENT_ETH_DISCONNECTED: 34 | Serial.println("ETH Disconnected"); 35 | eth_connected = false; 36 | break; 37 | case SYSTEM_EVENT_ETH_STOP: 38 | Serial.println("ETH Stopped"); 39 | eth_connected = false; 40 | break; 41 | default: 42 | break; 43 | } 44 | } 45 | 46 | void testClient(const char* host, uint16_t port) { 47 | Serial.print("\nconnecting to "); 48 | Serial.println(host); 49 | 50 | WiFiClient client; 51 | if (!client.connect(host, port)) { 52 | Serial.println("connection failed"); 53 | return; 54 | } 55 | client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host); 56 | while (client.connected() && !client.available()); 57 | while (client.available()) { 58 | Serial.write(client.read()); 59 | } 60 | 61 | Serial.println("closing connection\n"); 62 | client.stop(); 63 | } 64 | 65 | void setup() { 66 | Serial.begin(115200); 67 | WiFi.onEvent(WiFiEvent); 68 | ETH.begin(); 69 | } 70 | 71 | 72 | void loop() { 73 | if (eth_connected) { 74 | testClient("google.com", 80); 75 | } 76 | delay(10000); 77 | } 78 | -------------------------------------------------------------------------------- /examples/ETH_LAN8720_internal_clock/ETH_LAN8720_internal_clock.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch shows how to configure different external or internal clock sources for the Ethernet PHY 3 | */ 4 | 5 | #include 6 | 7 | /* 8 | ETH_CLOCK_GPIO0_IN - default: external clock from crystal oscillator 9 | ETH_CLOCK_GPIO0_OUT - 50MHz clock from internal APLL output on GPIO0 - possibly an inverter is needed for LAN8720 10 | ETH_CLOCK_GPIO16_OUT - 50MHz clock from internal APLL output on GPIO16 - possibly an inverter is needed for LAN8720 11 | ETH_CLOCK_GPIO17_OUT - 50MHz clock from internal APLL inverted output on GPIO17 - tested with LAN8720 12 | */ 13 | #ifdef ETH_CLK_MODE 14 | #undef ETH_CLK_MODE 15 | #endif 16 | #define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT 17 | 18 | // Pin# of the enable signal for the external crystal oscillator (-1 to disable for internal APLL source) 19 | #define ETH_POWER_PIN -1 20 | 21 | // Type of the Ethernet PHY (LAN8720 or TLK110) 22 | #define ETH_TYPE ETH_PHY_LAN8720 23 | 24 | // I²C-address of Ethernet PHY (0 or 1 for LAN8720, 31 for TLK110) 25 | #define ETH_ADDR 0 26 | 27 | // Pin# of the I²C clock signal for the Ethernet PHY 28 | #define ETH_MDC_PIN 15 29 | 30 | // Pin# of the I²C IO signal for the Ethernet PHY 31 | #define ETH_MDIO_PIN 2 32 | 33 | 34 | static bool eth_connected = false; 35 | 36 | void WiFiEvent(WiFiEvent_t event) { 37 | switch (event) { 38 | case SYSTEM_EVENT_ETH_START: 39 | Serial.println("ETH Started"); 40 | //set eth hostname here 41 | ETH.setHostname("esp32-ethernet"); 42 | break; 43 | case SYSTEM_EVENT_ETH_CONNECTED: 44 | Serial.println("ETH Connected"); 45 | break; 46 | case SYSTEM_EVENT_ETH_GOT_IP: 47 | Serial.print("ETH MAC: "); 48 | Serial.print(ETH.macAddress()); 49 | Serial.print(", IPv4: "); 50 | Serial.print(ETH.localIP()); 51 | if (ETH.fullDuplex()) { 52 | Serial.print(", FULL_DUPLEX"); 53 | } 54 | Serial.print(", "); 55 | Serial.print(ETH.linkSpeed()); 56 | Serial.println("Mbps"); 57 | eth_connected = true; 58 | break; 59 | case SYSTEM_EVENT_ETH_DISCONNECTED: 60 | Serial.println("ETH Disconnected"); 61 | eth_connected = false; 62 | break; 63 | case SYSTEM_EVENT_ETH_STOP: 64 | Serial.println("ETH Stopped"); 65 | eth_connected = false; 66 | break; 67 | default: 68 | break; 69 | } 70 | } 71 | 72 | void testClient(const char* host, uint16_t port) { 73 | Serial.print("\nconnecting to "); 74 | Serial.println(host); 75 | 76 | WiFiClient client; 77 | if (!client.connect(host, port)) { 78 | Serial.println("connection failed"); 79 | return; 80 | } 81 | client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host); 82 | while (client.connected() && !client.available()); 83 | while (client.available()) { 84 | Serial.write(client.read()); 85 | } 86 | 87 | Serial.println("closing connection\n"); 88 | client.stop(); 89 | } 90 | 91 | void setup() { 92 | Serial.begin(115200); 93 | WiFi.onEvent(WiFiEvent); 94 | ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE); 95 | } 96 | 97 | 98 | void loop() { 99 | if (eth_connected) { 100 | testClient("google.com", 80); 101 | } 102 | delay(10000); 103 | } 104 | -------------------------------------------------------------------------------- /examples/ETH_TLK110/ETH_TLK110.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch shows the Ethernet event usage 3 | 4 | */ 5 | 6 | #include 7 | 8 | #define ETH_ADDR 31 9 | #define ETH_POWER_PIN 17 10 | #define ETH_MDC_PIN 23 11 | #define ETH_MDIO_PIN 18 12 | #define ETH_TYPE ETH_PHY_TLK110 13 | 14 | static bool eth_connected = false; 15 | 16 | void WiFiEvent(WiFiEvent_t event) { 17 | switch (event) { 18 | case SYSTEM_EVENT_ETH_START: 19 | Serial.println("ETH Started"); 20 | //set eth hostname here 21 | ETH.setHostname("esp32-ethernet"); 22 | break; 23 | case SYSTEM_EVENT_ETH_CONNECTED: 24 | Serial.println("ETH Connected"); 25 | break; 26 | case SYSTEM_EVENT_ETH_GOT_IP: 27 | Serial.print("ETH MAC: "); 28 | Serial.print(ETH.macAddress()); 29 | Serial.print(", IPv4: "); 30 | Serial.print(ETH.localIP()); 31 | if (ETH.fullDuplex()) { 32 | Serial.print(", FULL_DUPLEX"); 33 | } 34 | Serial.print(", "); 35 | Serial.print(ETH.linkSpeed()); 36 | Serial.println("Mbps"); 37 | eth_connected = true; 38 | break; 39 | case SYSTEM_EVENT_ETH_DISCONNECTED: 40 | Serial.println("ETH Disconnected"); 41 | eth_connected = false; 42 | break; 43 | case SYSTEM_EVENT_ETH_STOP: 44 | Serial.println("ETH Stopped"); 45 | eth_connected = false; 46 | break; 47 | default: 48 | break; 49 | } 50 | } 51 | 52 | void testClient(const char* host, uint16_t port) { 53 | Serial.print("\nconnecting to "); 54 | Serial.println(host); 55 | 56 | WiFiClient client; 57 | if (!client.connect(host, port)) { 58 | Serial.println("connection failed"); 59 | return; 60 | } 61 | client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host); 62 | while (client.connected() && !client.available()); 63 | while (client.available()) { 64 | Serial.write(client.read()); 65 | } 66 | 67 | Serial.println("closing connection\n"); 68 | client.stop(); 69 | } 70 | 71 | void setup() { 72 | Serial.begin(115200); 73 | WiFi.onEvent(WiFiEvent); 74 | ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE); 75 | } 76 | 77 | 78 | void loop() { 79 | if (eth_connected) { 80 | testClient("google.com", 80); 81 | } 82 | delay(10000); 83 | } 84 | -------------------------------------------------------------------------------- /examples/SimpleWiFiServer/SimpleWiFiServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | WiFi Web Server LED Blink 3 | 4 | A simple web server that lets you blink an LED via the web. 5 | This sketch will print the IP address of your WiFi Shield (once connected) 6 | to the Serial monitor. From there, you can open that address in a web browser 7 | to turn on and off the LED on pin 5. 8 | 9 | If the IP address of your shield is yourAddress: 10 | http://yourAddress/H turns the LED on 11 | http://yourAddress/L turns it off 12 | 13 | This example is written for a network using WPA encryption. For 14 | WEP or WPA, change the Wifi.begin() call accordingly. 15 | 16 | Circuit: 17 | WiFi shield attached 18 | LED attached to pin 5 19 | 20 | created for arduino 25 Nov 2012 21 | by Tom Igoe 22 | 23 | ported for sparkfun esp32 24 | 31.01.2017 by Jan Hendrik Berlin 25 | 26 | */ 27 | 28 | #include 29 | 30 | const char* ssid = "yourssid"; 31 | const char* password = "yourpasswd"; 32 | 33 | WiFiServer server(80); 34 | 35 | void setup() { 36 | Serial.begin(115200); 37 | pinMode(5, OUTPUT); // set the LED pin mode 38 | 39 | delay(10); 40 | 41 | // We start by connecting to a WiFi network 42 | 43 | Serial.println(); 44 | Serial.println(); 45 | Serial.print("Connecting to "); 46 | Serial.println(ssid); 47 | 48 | WiFi.begin(ssid, password); 49 | 50 | while (WiFi.status() != WL_CONNECTED) { 51 | delay(500); 52 | Serial.print("."); 53 | } 54 | 55 | Serial.println(""); 56 | Serial.println("WiFi connected."); 57 | Serial.println("IP address: "); 58 | Serial.println(WiFi.localIP()); 59 | 60 | server.begin(); 61 | 62 | } 63 | 64 | int value = 0; 65 | 66 | void loop() { 67 | WiFiClient client = server.available(); // listen for incoming clients 68 | 69 | if (client) { // if you get a client, 70 | Serial.println("New Client."); // print a message out the serial port 71 | String currentLine = ""; // make a String to hold incoming data from the client 72 | while (client.connected()) { // loop while the client's connected 73 | if (client.available()) { // if there's bytes to read from the client, 74 | char c = client.read(); // read a byte, then 75 | Serial.write(c); // print it out the serial monitor 76 | if (c == '\n') { // if the byte is a newline character 77 | 78 | // if the current line is blank, you got two newline characters in a row. 79 | // that's the end of the client HTTP request, so send a response: 80 | if (currentLine.length() == 0) { 81 | // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) 82 | // and a content-type so the client knows what's coming, then a blank line: 83 | client.println("HTTP/1.1 200 OK"); 84 | client.println("Content-type:text/html"); 85 | client.println(); 86 | 87 | // the content of the HTTP response follows the header: 88 | client.print("Click here to turn the LED on pin 5 on.
"); 89 | client.print("Click here to turn the LED on pin 5 off.
"); 90 | 91 | // The HTTP response ends with another blank line: 92 | client.println(); 93 | // break out of the while loop: 94 | break; 95 | } else { // if you got a newline, then clear currentLine: 96 | currentLine = ""; 97 | } 98 | } else if (c != '\r') { // if you got anything else but a carriage return character, 99 | currentLine += c; // add it to the end of the currentLine 100 | } 101 | 102 | // Check to see if the client request was "GET /H" or "GET /L": 103 | if (currentLine.endsWith("GET /H")) { 104 | digitalWrite(5, HIGH); // GET /H turns the LED on 105 | } 106 | if (currentLine.endsWith("GET /L")) { 107 | digitalWrite(5, LOW); // GET /L turns the LED off 108 | } 109 | } 110 | } 111 | // close the connection: 112 | client.stop(); 113 | Serial.println("Client Disconnected."); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /examples/WPS/README.md: -------------------------------------------------------------------------------- 1 | Example Serial Logs For Various Cases 2 | ====================================== 3 | 4 | For WPS Push Button method,after the ESP32 boots up and prints that WPS has started, press the button that looks something like [this](https://www.verizon.com/supportresources/images/fqgrouter-frontview-wps-button.png) on your router. In case you dont find anything similar, check your router specs if it does really support WPS Push functionality. 5 | 6 | As for WPS Pin Mode, it will output a 8 digit Pin on the Serial Monitor that will change every 2 minutes if it hasn't connected. You need to log in to your router (generally reaching 192.168.0.1) and enter the pin shown in Serial Monitor in the WPS Settings of your router. 7 | 8 | #### WPS Push Button Failure 9 | 10 | ``` 11 | ets Jun 8 2016 00:22:57 12 | 13 | rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) 14 | configsip: 0, SPIWP:0xee 15 | clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 16 | mode:DIO, clock div:1 17 | load:0x3fff0010,len:4 18 | load:0x3fff0014,len:732 19 | load:0x40078000,len:0 20 | load:0x40078000,len:11572 21 | entry 0x40078a14 22 | 23 | Starting WPS 24 | Station Mode Started 25 | WPS Timedout, retrying 26 | WPS Timedout, retrying 27 | ``` 28 | 29 | #### WPS Push Button Successfull 30 | 31 | ``` 32 | ets Jun 8 2016 00:22:57 33 | 34 | rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) 35 | ets Jun 8 2016 00:22:57 36 | 37 | rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) 38 | configsip: 0, SPIWP:0xee 39 | clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 40 | mode:DIO, clock div:1 41 | load:0x3fff0010,len:4 42 | load:0x3fff0014,len:732 43 | load:0x40078000,len:0 44 | load:0x40078000,len:11572 45 | entry 0x40078a14 46 | 47 | Starting WPS 48 | Station Mode Started 49 | WPS Successfull, stopping WPS and connecting to: < Your Router SSID > 50 | Disconnected from station, attempting reconnection 51 | Connected to : < Your Router SSID > 52 | Got IP: 192.168.1.100 53 | ``` 54 | 55 | #### WPS PIN Failure 56 | 57 | ``` 58 | ets Jun 8 2016 00:22:57 59 | 60 | rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) 61 | ets Jun 8 2016 00:22:57 62 | 63 | rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) 64 | configsip: 0, SPIWP:0xee 65 | clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 66 | mode:DIO, clock div:1 67 | load:0x3fff0010,len:4 68 | load:0x3fff0014,len:732 69 | load:0x40078000,len:0 70 | load:0x40078000,len:11572 71 | entry 0x40078a14 72 | 73 | Starting WPS 74 | Station Mode Started 75 | WPS_PIN = 94842104 76 | WPS Timedout, retrying 77 | WPS_PIN = 55814171 78 | WPS Timedout, retrying 79 | WPS_PIN = 71321622 80 | ``` 81 | 82 | #### WPS PIN Successfull 83 | 84 | ``` 85 | ets Jun 8 2016 00:22:57 86 | 87 | rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) 88 | configsip: 0, SPIWP:0xee 89 | clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 90 | mode:DIO, clock div:1 91 | load:0x3fff0010,len:4 92 | load:0x3fff0014,len:732 93 | load:0x40078000,len:0 94 | load:0x40078000,len:11572 95 | entry 0x40078a14 96 | 97 | Starting WPS 98 | Station Mode Started 99 | WPS_PIN = 36807581 100 | WPS Successfull, stopping WPS and connecting to: 101 | Disconnected from station, attempting reconnection 102 | Connected to : 103 | Got IP: 192.168.1.100 104 | ``` 105 | -------------------------------------------------------------------------------- /examples/WPS/WPS.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Example Code To Get ESP32 To Connect To A Router Using WPS 3 | =========================================================== 4 | This example code provides both Push Button method and Pin 5 | based WPS entry to get your ESP connected to your WiFi router. 6 | 7 | Hardware Requirements 8 | ======================== 9 | ESP32 and a Router having atleast one WPS functionality 10 | 11 | This code is under Public Domain License. 12 | 13 | Author: 14 | Pranav Cherukupalli 15 | */ 16 | 17 | #include "AtWiFi.h" 18 | #include "esp_wps.h" 19 | /* 20 | Change the definition of the WPS mode 21 | from WPS_TYPE_PBC to WPS_TYPE_PIN in 22 | the case that you are using pin type 23 | WPS 24 | */ 25 | #define ESP_WPS_MODE WPS_TYPE_PBC 26 | #define ESP_MANUFACTURER "ESPRESSIF" 27 | #define ESP_MODEL_NUMBER "ESP32" 28 | #define ESP_MODEL_NAME "ESPRESSIF IOT" 29 | #define ESP_DEVICE_NAME "ESP STATION" 30 | 31 | static esp_wps_config_t config; 32 | 33 | void wpsInitConfig() { 34 | config.wps_type = ESP_WPS_MODE; 35 | strcpy(config.factory_info.manufacturer, ESP_MANUFACTURER); 36 | strcpy(config.factory_info.model_number, ESP_MODEL_NUMBER); 37 | strcpy(config.factory_info.model_name, ESP_MODEL_NAME); 38 | strcpy(config.factory_info.device_name, ESP_DEVICE_NAME); 39 | } 40 | 41 | String wpspin2string(uint8_t a[]) { 42 | char wps_pin[9]; 43 | for (int i = 0; i < 8; i++) { 44 | wps_pin[i] = a[i]; 45 | } 46 | wps_pin[8] = '\0'; 47 | return (String)wps_pin; 48 | } 49 | 50 | void WiFiEvent(WiFiEvent_t event, system_event_info_t info) { 51 | switch (event) { 52 | case SYSTEM_EVENT_STA_START: 53 | Serial.println("Station Mode Started"); 54 | break; 55 | case SYSTEM_EVENT_STA_GOT_IP: 56 | Serial.println("Connected to :" + String(WiFi.SSID())); 57 | Serial.print("Got IP: "); 58 | Serial.println(WiFi.localIP()); 59 | break; 60 | case SYSTEM_EVENT_STA_DISCONNECTED: 61 | Serial.println("Disconnected from station, attempting reconnection"); 62 | WiFi.reconnect(); 63 | break; 64 | case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: 65 | Serial.println("WPS Successfull, stopping WPS and connecting to: " + String(WiFi.SSID())); 66 | esp_wifi_wps_disable(); 67 | delay(10); 68 | WiFi.begin(); 69 | break; 70 | case SYSTEM_EVENT_STA_WPS_ER_FAILED: 71 | Serial.println("WPS Failed, retrying"); 72 | esp_wifi_wps_disable(); 73 | esp_wifi_wps_enable(&config); 74 | esp_wifi_wps_start(0); 75 | break; 76 | case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: 77 | Serial.println("WPS Timedout, retrying"); 78 | esp_wifi_wps_disable(); 79 | esp_wifi_wps_enable(&config); 80 | esp_wifi_wps_start(0); 81 | break; 82 | case SYSTEM_EVENT_STA_WPS_ER_PIN: 83 | Serial.println("WPS_PIN = " + wpspin2string(info.sta_er_pin.pin_code)); 84 | break; 85 | default: 86 | break; 87 | } 88 | } 89 | 90 | void setup() { 91 | Serial.begin(115200); 92 | delay(10); 93 | 94 | Serial.println(); 95 | 96 | WiFi.onEvent(WiFiEvent); 97 | WiFi.mode(WIFI_MODE_STA); 98 | 99 | Serial.println("Starting WPS"); 100 | 101 | wpsInitConfig(); 102 | esp_wifi_wps_enable(&config); 103 | esp_wifi_wps_start(0); 104 | } 105 | 106 | void loop() { 107 | //nothing to do here 108 | } -------------------------------------------------------------------------------- /examples/WiFiAccessPoint/WiFiAccessPoint.ino: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiAccessPoint.ino creates a WiFi access point and provides a web server on it. 3 | 4 | Steps: 5 | 1. Connect to the access point "yourAp" 6 | 2. Point your web browser to http:///H to turn the LED on or http:///L to turn it off 7 | ( should be replaced with the IP got in terminal/SerilPort, see Note 1) 8 | OR 9 | Run raw TCP "GET /H" and "GET /L" on PuTTY terminal with IP address (see Note 1) and 80 as port 10 | 11 | Created for arduino-esp32 on 04 July, 2018 12 | by Elochukwu Ifediora (fedy0) 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #define LED_BUILTIN 2 // Set the GPIO pin where you connected your test LED 20 | // or comment this line out if your dev board has a built-in LED 21 | 22 | // Set these to your desired credentials. 23 | const char* ssid = "yourAP"; 24 | const char* password = "yourPassword"; 25 | 26 | WiFiServer server(80); 27 | 28 | 29 | void setup() { 30 | pinMode(LED_BUILTIN, OUTPUT); 31 | 32 | Serial.begin(115200); 33 | Serial.println(); 34 | Serial.println("Configuring access point..."); 35 | 36 | // You can remove the password parameter if you want the AP to be open. 37 | WiFi.softAP(ssid, password); 38 | IPAddress myIP = WiFi.softAPIP(); 39 | /* 40 | * Note 1 41 | * Record this IP, will used by Client (such as Web Browser) 42 | */ 43 | Serial.print("AP IP address: "); 44 | Serial.println(myIP); 45 | server.begin(); 46 | 47 | Serial.println("Server started"); 48 | } 49 | 50 | void loop() { 51 | WiFiClient client = server.available(); // listen for incoming clients 52 | 53 | if (client) { // if you get a client, 54 | Serial.println("New Client."); // print a message out the serial port 55 | String currentLine = ""; // make a String to hold incoming data from the client 56 | while (client.connected()) { // loop while the client's connected 57 | if (client.available()) { // if there's bytes to read from the client, 58 | char c = client.read(); // read a byte, then 59 | Serial.write(c); // print it out the serial monitor 60 | if (c == '\n') { // if the byte is a newline character 61 | 62 | // if the current line is blank, you got two newline characters in a row. 63 | // that's the end of the client HTTP request, so send a response: 64 | if (currentLine.length() == 0) { 65 | // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) 66 | // and a content-type so the client knows what's coming, then a blank line: 67 | client.println("HTTP/1.1 200 OK"); 68 | client.println("Content-type:text/html"); 69 | client.println(); 70 | 71 | // the content of the HTTP response follows the header: 72 | client.print("Click here to turn ON the LED.
"); 73 | client.print("Click here to turn OFF the LED.
"); 74 | 75 | // The HTTP response ends with another blank line: 76 | client.println(); 77 | // break out of the while loop: 78 | break; 79 | } else { // if you got a newline, then clear currentLine: 80 | currentLine = ""; 81 | } 82 | } else if (c != '\r') { // if you got anything else but a carriage return character, 83 | currentLine += c; // add it to the end of the currentLine 84 | } 85 | 86 | // Check to see if the client request was "GET /H" or "GET /L": 87 | if (currentLine.endsWith("GET /H")) { 88 | digitalWrite(LED_BUILTIN, HIGH); // GET /H turns the LED on 89 | } 90 | if (currentLine.endsWith("GET /L")) { 91 | digitalWrite(LED_BUILTIN, LOW); // GET /L turns the LED off 92 | } 93 | } 94 | } 95 | // close the connection: 96 | client.stop(); 97 | Serial.println("Client Disconnected."); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /examples/WiFiBlueToothSwitch/WiFiBlueToothSwitch.ino: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Sketch shows how to switch between WiFi and BlueTooth or use both 16 | // Button is attached between GPIO 0 and GND and modes are switched with each press 17 | 18 | #include "AtWiFi.h" 19 | #define STA_SSID "your-ssid" 20 | #define STA_PASS "your-pass" 21 | #define AP_SSID "esp32" 22 | 23 | enum { STEP_BTON, STEP_BTOFF, STEP_STA, STEP_AP, STEP_AP_STA, STEP_OFF, STEP_BT_STA, STEP_END }; 24 | 25 | void onButton() { 26 | static uint32_t step = STEP_BTON; 27 | switch (step) { 28 | case STEP_BTON://BT Only 29 | Serial.println("** Starting BT"); 30 | btStart(); 31 | break; 32 | case STEP_BTOFF://All Off 33 | Serial.println("** Stopping BT"); 34 | btStop(); 35 | break; 36 | case STEP_STA://STA Only 37 | Serial.println("** Starting STA"); 38 | WiFi.begin(STA_SSID, STA_PASS); 39 | break; 40 | case STEP_AP://AP Only 41 | Serial.println("** Stopping STA"); 42 | WiFi.mode(WIFI_AP); 43 | Serial.println("** Starting AP"); 44 | WiFi.softAP(AP_SSID); 45 | break; 46 | case STEP_AP_STA://AP+STA 47 | Serial.println("** Starting STA"); 48 | WiFi.begin(STA_SSID, STA_PASS); 49 | break; 50 | case STEP_OFF://All Off 51 | Serial.println("** Stopping WiFi"); 52 | WiFi.mode(WIFI_OFF); 53 | break; 54 | case STEP_BT_STA://BT+STA 55 | Serial.println("** Starting STA+BT"); 56 | WiFi.begin(STA_SSID, STA_PASS); 57 | btStart(); 58 | break; 59 | case STEP_END://All Off 60 | Serial.println("** Stopping WiFi+BT"); 61 | WiFi.mode(WIFI_OFF); 62 | btStop(); 63 | break; 64 | default: 65 | break; 66 | } 67 | if (step == STEP_END) { 68 | step = STEP_BTON; 69 | } else { 70 | step++; 71 | } 72 | //little debounce 73 | delay(100); 74 | } 75 | 76 | void WiFiEvent(WiFiEvent_t event) { 77 | switch (event) { 78 | case SYSTEM_EVENT_AP_START: 79 | Serial.println("AP Started"); 80 | WiFi.softAPsetHostname(AP_SSID); 81 | break; 82 | case SYSTEM_EVENT_AP_STOP: 83 | Serial.println("AP Stopped"); 84 | break; 85 | case SYSTEM_EVENT_STA_START: 86 | Serial.println("STA Started"); 87 | WiFi.setHostname(AP_SSID); 88 | break; 89 | case SYSTEM_EVENT_STA_CONNECTED: 90 | Serial.println("STA Connected"); 91 | WiFi.enableIpV6(); 92 | break; 93 | case SYSTEM_EVENT_AP_STA_GOT_IP6: 94 | Serial.print("STA IPv6: "); 95 | Serial.println(WiFi.localIPv6()); 96 | break; 97 | case SYSTEM_EVENT_STA_GOT_IP: 98 | Serial.print("STA IPv4: "); 99 | Serial.println(WiFi.localIP()); 100 | break; 101 | case SYSTEM_EVENT_STA_DISCONNECTED: 102 | Serial.println("STA Disconnected"); 103 | break; 104 | case SYSTEM_EVENT_STA_STOP: 105 | Serial.println("STA Stopped"); 106 | break; 107 | default: 108 | break; 109 | } 110 | } 111 | 112 | void setup() { 113 | Serial.begin(115200); 114 | pinMode(0, INPUT_PULLUP); 115 | WiFi.onEvent(WiFiEvent); 116 | Serial.print("ESP32 SDK: "); 117 | Serial.println(ESP.getSdkVersion()); 118 | Serial.println("Press the button to select the next mode"); 119 | } 120 | 121 | void loop() { 122 | static uint8_t lastPinState = 1; 123 | uint8_t pinState = digitalRead(0); 124 | if (!pinState && lastPinState) { 125 | onButton(); 126 | } 127 | lastPinState = pinState; 128 | } 129 | -------------------------------------------------------------------------------- /examples/WiFiClient/WiFiClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch sends data via HTTP GET requests to data.sparkfun.com service. 3 | 4 | You need to get streamId and privateKey at data.sparkfun.com and paste them 5 | below. Or just customize this script to talk to other HTTP servers. 6 | 7 | */ 8 | 9 | #include 10 | 11 | const char* ssid = "your-ssid"; 12 | const char* password = "your-password"; 13 | 14 | const char* host = "data.sparkfun.com"; 15 | const char* streamId = "...................."; 16 | const char* privateKey = "...................."; 17 | 18 | void setup() { 19 | Serial.begin(115200); 20 | delay(10); 21 | 22 | // We start by connecting to a WiFi network 23 | 24 | Serial.println(); 25 | Serial.println(); 26 | Serial.print("Connecting to "); 27 | Serial.println(ssid); 28 | 29 | WiFi.begin(ssid, password); 30 | 31 | while (WiFi.status() != WL_CONNECTED) { 32 | delay(500); 33 | Serial.print("."); 34 | } 35 | 36 | Serial.println(""); 37 | Serial.println("WiFi connected"); 38 | Serial.println("IP address: "); 39 | Serial.println(WiFi.localIP()); 40 | } 41 | 42 | int value = 0; 43 | 44 | void loop() { 45 | delay(5000); 46 | ++value; 47 | 48 | Serial.print("connecting to "); 49 | Serial.println(host); 50 | 51 | // Use WiFiClient class to create TCP connections 52 | WiFiClient client; 53 | const int httpPort = 80; 54 | if (!client.connect(host, httpPort)) { 55 | Serial.println("connection failed"); 56 | return; 57 | } 58 | 59 | // We now create a URI for the request 60 | String url = "/input/"; 61 | url += streamId; 62 | url += "?private_key="; 63 | url += privateKey; 64 | url += "&value="; 65 | url += value; 66 | 67 | Serial.print("Requesting URL: "); 68 | Serial.println(url); 69 | 70 | // This will send the request to the server 71 | client.print(String("GET ") + url + " HTTP/1.1\r\n" + 72 | "Host: " + host + "\r\n" + 73 | "Connection: close\r\n\r\n"); 74 | unsigned long timeout = millis(); 75 | while (client.available() == 0) { 76 | if (millis() - timeout > 5000) { 77 | Serial.println(">>> Client Timeout !"); 78 | client.stop(); 79 | return; 80 | } 81 | } 82 | 83 | // Read all the lines of the reply from server and print them to Serial 84 | while (client.available()) { 85 | String line = client.readStringUntil('\r'); 86 | // Proceed various line-endings 87 | line.replace("\r\n", "\n"); 88 | line.replace('\r', '\n'); 89 | line.replace("\n", "\r\n"); 90 | Serial.print(line); 91 | } 92 | 93 | Serial.println(); 94 | Serial.println("closing connection"); 95 | } 96 | 97 | -------------------------------------------------------------------------------- /examples/WiFiClientBasic/WiFiClientBasic.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch sends a message to a TCP server 3 | 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | WiFiMulti WiFiMulti; 10 | 11 | void setup() { 12 | Serial.begin(115200); 13 | delay(10); 14 | 15 | // We start by connecting to a WiFi network 16 | WiFiMulti.addAP("SSID", "passpasspass"); 17 | 18 | Serial.println(); 19 | Serial.println(); 20 | Serial.print("Waiting for WiFi... "); 21 | 22 | while (WiFiMulti.run() != WL_CONNECTED) { 23 | Serial.print("."); 24 | delay(500); 25 | } 26 | 27 | Serial.println(""); 28 | Serial.println("WiFi connected"); 29 | Serial.println("IP address: "); 30 | Serial.println(WiFi.localIP()); 31 | 32 | delay(500); 33 | } 34 | 35 | 36 | void loop() { 37 | // const uint16_t port = 80; 38 | // const char * host = "192.168.1.1"; // ip or dns 39 | const uint16_t port = 1337; 40 | const char* host = "192.168.1.10"; // ip or dns 41 | 42 | Serial.print("Connecting to "); 43 | Serial.println(host); 44 | 45 | // Use WiFiClient class to create TCP connections 46 | WiFiClient client; 47 | 48 | if (!client.connect(host, port)) { 49 | Serial.println("Connection failed."); 50 | Serial.println("Waiting 5 seconds before retrying..."); 51 | delay(5000); 52 | return; 53 | } 54 | 55 | // This will send a request to the server 56 | //uncomment this line to send an arbitrary string to the server 57 | //client.print("Send this data to the server"); 58 | //uncomment this line to send a basic document request to the server 59 | client.print("GET /index.html HTTP/1.1\n\n"); 60 | 61 | int maxloops = 0; 62 | 63 | //wait for the server's reply to become available 64 | while (!client.available() && maxloops < 1000) { 65 | maxloops++; 66 | delay(1); //delay 1 msec 67 | } 68 | if (client.available() > 0) { 69 | //read back one line from the server 70 | String line = client.readStringUntil('\r'); 71 | // Proceed various line-endings 72 | line.replace("\r\n", "\n"); 73 | line.replace('\r', '\n'); 74 | line.replace("\n", "\r\n"); 75 | Serial.println(line); 76 | } else { 77 | Serial.println("client.available() timed out "); 78 | } 79 | 80 | Serial.println("Closing connection."); 81 | client.stop(); 82 | 83 | Serial.println("Waiting 5 seconds before restarting..."); 84 | delay(5000); 85 | } 86 | -------------------------------------------------------------------------------- /examples/WiFiClientEnterprise/README.md: -------------------------------------------------------------------------------- 1 | # ESP32-Eduroam 2 | * Eduroam wifi connection with university login identity 3 | * Working under Eduroam networks worldwide 4 | * Methods: PEAP + MsCHAPv2 5 | 6 | # Format 7 | * IDENTITY = youridentity --> if connecting from different university, use youridentity@youruniversity.domain format 8 | * PASSWORD = yourpassword 9 | 10 | # Usage 11 | * Change IDENTITY 12 | * Change password 13 | * Upload sketch and enjoy! 14 | * After sucessful assign of IP address, board will connect to HTTP page on internet to verify your authentification 15 | * Board will auto reconnect to Eduroam if it lost connection 16 | 17 | # Tested locations 18 | |University|Board|Method|Result| 19 | |-------------|-------------| -----|------| 20 | |Technical University in Košice (Slovakia)|ESP32 Devkit v1|PEAP + MsCHAPv2|Working| 21 | |Technical University in Košice (Slovakia)|ESP32 Devmodule v4|PEAP + MsCHAPv2|Working on 6th attempt in loop| 22 | |Slovak Technical University in Bratislava (Slovakia)|ESP32 Devkit v1|PEAP + MsCHAPv2|Working| 23 | |University of Antwerp (Belgium)|Lolin32|PEAP + MsCHAPv2|Working| 24 | |UPV Universitat Politècnica de València (Spain)|ESP32 Devmodule v4|PEAP + MsCHAPv2|Working| 25 | |Local Zeroshell powered network|ESP32 Devkit v1|PEAP + MsCHAPv2|*Not working*| 26 | |Hasselt University (Belgium)|xxx|PEAP + MsCHAPv2|Working with fix sketch| 27 | |Universidad de Granada (Spain)|Lolin D32 Pro|PEAP + MsCHAPv2|Working| 28 | |Universidad de Granada (Spain)|Lolin D32|PEAP + MsCHAPv2|Working| 29 | |Universidade Federal de Santa Catarina (Brazil)|xxx|EAP-TTLS + MsCHAPv2|Working| 30 | |University of Central Florida (Orlando, Florida)|ESP32 Built-in OLED – Heltec WiFi Kit 32|PEAP + MsCHAPv2|Working| 31 | |Université de Montpellier (France)|NodeMCU-32S|PEAP + MsCHAPv2|Working| 32 | 33 | # Common errors - Switch to Debug mode for Serial monitor prints 34 | |Error|Appearance|Solution| 35 | |-------------|-------------|-------------| 36 | |wifi: Set status to INIT|Frequent|Hold EN button for few seconds| 37 | |HANDSHAKE_TIMEOUT|Rare|Bug was found under Zeroshell RADIUS authentization - Unsucessful connection| 38 | |AUTH_EXPIRE|Common|In the case of weak wifi network signal, this error is quite common, bring your device closer to AP| 39 | |ASSOC_EXPIRE|Rare|-| 40 | # Sucessful connection example 41 | ![alt text](https://i.nahraj.to/f/24Kc.png) 42 | # Unsucessful connection example 43 | ![alt text](https://camo.githubusercontent.com/87e47d1b27f4e8ace87423e40e8edbce7983bafa/68747470733a2f2f692e6e616872616a2e746f2f662f323435572e504e47) 44 | -------------------------------------------------------------------------------- /examples/WiFiClientEnterprise/WiFiClientEnterprise.ino: -------------------------------------------------------------------------------- 1 | #include //Wifi library 2 | #include "esp_wpa2.h" //wpa2 library for connections to Enterprise networks 3 | #define EAP_IDENTITY "login" //if connecting from another corporation, use identity@organisation.domain in Eduroam 4 | #define EAP_PASSWORD "password" //your Eduroam password 5 | const char* ssid = "eduroam"; // Eduroam SSID 6 | const char* host = "arduino.php5.sk"; //external server domain for HTTP connection after authentification 7 | int counter = 0; 8 | void setup() { 9 | Serial.begin(115200); 10 | delay(10); 11 | Serial.println(); 12 | Serial.print("Connecting to network: "); 13 | Serial.println(ssid); 14 | WiFi.disconnect(true); //disconnect form wifi to set new wifi connection 15 | WiFi.mode(WIFI_STA); //init wifi mode 16 | esp_wifi_sta_wpa2_ent_set_identity((uint8_t*)EAP_IDENTITY, strlen(EAP_IDENTITY)); //provide identity 17 | esp_wifi_sta_wpa2_ent_set_username((uint8_t*)EAP_IDENTITY, 18 | strlen(EAP_IDENTITY)); //provide username --> identity and username is same 19 | esp_wifi_sta_wpa2_ent_set_password((uint8_t*)EAP_PASSWORD, strlen(EAP_PASSWORD)); //provide password 20 | esp_wpa2_config_t config = WPA2_CONFIG_INIT_DEFAULT(); //set config settings to default 21 | esp_wifi_sta_wpa2_ent_enable(&config); //set config settings to enable function 22 | WiFi.begin(ssid); //connect to wifi 23 | while (WiFi.status() != WL_CONNECTED) { 24 | delay(500); 25 | Serial.print("."); 26 | counter++; 27 | if (counter >= 60) { //after 30 seconds timeout - reset board 28 | ESP.restart(); 29 | } 30 | } 31 | Serial.println(""); 32 | Serial.println("WiFi connected"); 33 | Serial.println("IP address set: "); 34 | Serial.println(WiFi.localIP()); //print LAN IP 35 | } 36 | void loop() { 37 | if (WiFi.status() == WL_CONNECTED) { //if we are connected to Eduroam network 38 | counter = 0; //reset counter 39 | Serial.println("Wifi is still connected with IP: "); 40 | Serial.println(WiFi.localIP()); //inform user about his IP address 41 | } else if (WiFi.status() != WL_CONNECTED) { //if we lost connection, retry 42 | WiFi.begin(ssid); 43 | } 44 | while (WiFi.status() != WL_CONNECTED) { //during lost connection, print dots 45 | delay(500); 46 | Serial.print("."); 47 | counter++; 48 | if (counter >= 60) { //30 seconds timeout - reset board 49 | ESP.restart(); 50 | } 51 | } 52 | Serial.print("Connecting to website: "); 53 | Serial.println(host); 54 | WiFiClient client; 55 | if (client.connect(host, 80)) { 56 | String url = "/rele/rele1.txt"; 57 | client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: ESP32\r\n" + 58 | "Connection: close\r\n\r\n"); 59 | 60 | while (client.connected()) { 61 | String line = client.readStringUntil('\n'); 62 | if (line == "\r") { 63 | break; 64 | } 65 | } 66 | String line = client.readStringUntil('\n'); 67 | Serial.println(line); 68 | } else { 69 | Serial.println("Connection unsucessful"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /examples/WiFiClientEvents/WiFiClientEvents.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch shows the WiFi event usage 3 | 4 | */ 5 | 6 | /* 7 | WiFi Events 8 | 9 | 0 SYSTEM_EVENT_WIFI_READY < ESP32 WiFi ready 10 | 1 SYSTEM_EVENT_SCAN_DONE < ESP32 finish scanning AP 11 | 2 SYSTEM_EVENT_STA_START < ESP32 station start 12 | 3 SYSTEM_EVENT_STA_STOP < ESP32 station stop 13 | 4 SYSTEM_EVENT_STA_CONNECTED < ESP32 station connected to AP 14 | 5 SYSTEM_EVENT_STA_DISCONNECTED < ESP32 station disconnected from AP 15 | 6 SYSTEM_EVENT_STA_AUTHMODE_CHANGE < the auth mode of AP connected by ESP32 station changed 16 | 7 SYSTEM_EVENT_STA_GOT_IP < ESP32 station got IP from connected AP 17 | 8 SYSTEM_EVENT_STA_LOST_IP < ESP32 station lost IP and the IP is reset to 0 18 | 9 SYSTEM_EVENT_STA_WPS_ER_SUCCESS < ESP32 station wps succeeds in enrollee mode 19 | 10 SYSTEM_EVENT_STA_WPS_ER_FAILED < ESP32 station wps fails in enrollee mode 20 | 11 SYSTEM_EVENT_STA_WPS_ER_TIMEOUT < ESP32 station wps timeout in enrollee mode 21 | 12 SYSTEM_EVENT_STA_WPS_ER_PIN < ESP32 station wps pin code in enrollee mode 22 | 13 SYSTEM_EVENT_AP_START < ESP32 soft-AP start 23 | 14 SYSTEM_EVENT_AP_STOP < ESP32 soft-AP stop 24 | 15 SYSTEM_EVENT_AP_STACONNECTED < a station connected to ESP32 soft-AP 25 | 16 SYSTEM_EVENT_AP_STADISCONNECTED < a station disconnected from ESP32 soft-AP 26 | 17 SYSTEM_EVENT_AP_STAIPASSIGNED < ESP32 soft-AP assign an IP to a connected station 27 | 18 SYSTEM_EVENT_AP_PROBEREQRECVED < Receive probe request packet in soft-AP interface 28 | 19 SYSTEM_EVENT_GOT_IP6 < ESP32 station or ap or ethernet interface v6IP addr is preferred 29 | 20 SYSTEM_EVENT_ETH_START < ESP32 ethernet start 30 | 21 SYSTEM_EVENT_ETH_STOP < ESP32 ethernet stop 31 | 22 SYSTEM_EVENT_ETH_CONNECTED < ESP32 ethernet phy link up 32 | 23 SYSTEM_EVENT_ETH_DISCONNECTED < ESP32 ethernet phy link down 33 | 24 SYSTEM_EVENT_ETH_GOT_IP < ESP32 ethernet got IP from connected AP 34 | 25 SYSTEM_EVENT_MAX 35 | */ 36 | 37 | #include 38 | 39 | const char* ssid = "your-ssid"; 40 | const char* password = "your-password"; 41 | 42 | 43 | void WiFiEvent(WiFiEvent_t event) { 44 | Serial.printf("[WiFi-event] event: %d\n", event); 45 | 46 | switch (event) { 47 | case SYSTEM_EVENT_WIFI_READY: 48 | Serial.println("WiFi interface ready"); 49 | break; 50 | case SYSTEM_EVENT_SCAN_DONE: 51 | Serial.println("Completed scan for access points"); 52 | break; 53 | case SYSTEM_EVENT_STA_START: 54 | Serial.println("WiFi client started"); 55 | break; 56 | case SYSTEM_EVENT_STA_STOP: 57 | Serial.println("WiFi clients stopped"); 58 | break; 59 | case SYSTEM_EVENT_STA_CONNECTED: 60 | Serial.println("Connected to access point"); 61 | break; 62 | case SYSTEM_EVENT_STA_DISCONNECTED: 63 | Serial.println("Disconnected from WiFi access point"); 64 | break; 65 | case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: 66 | Serial.println("Authentication mode of access point has changed"); 67 | break; 68 | case SYSTEM_EVENT_STA_GOT_IP: 69 | Serial.print("Obtained IP address: "); 70 | Serial.println(WiFi.localIP()); 71 | break; 72 | case SYSTEM_EVENT_STA_LOST_IP: 73 | Serial.println("Lost IP address and IP address is reset to 0"); 74 | break; 75 | case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: 76 | Serial.println("WiFi Protected Setup (WPS): succeeded in enrollee mode"); 77 | break; 78 | case SYSTEM_EVENT_STA_WPS_ER_FAILED: 79 | Serial.println("WiFi Protected Setup (WPS): failed in enrollee mode"); 80 | break; 81 | case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: 82 | Serial.println("WiFi Protected Setup (WPS): timeout in enrollee mode"); 83 | break; 84 | case SYSTEM_EVENT_STA_WPS_ER_PIN: 85 | Serial.println("WiFi Protected Setup (WPS): pin code in enrollee mode"); 86 | break; 87 | case SYSTEM_EVENT_AP_START: 88 | Serial.println("WiFi access point started"); 89 | break; 90 | case SYSTEM_EVENT_AP_STOP: 91 | Serial.println("WiFi access point stopped"); 92 | break; 93 | case SYSTEM_EVENT_AP_STACONNECTED: 94 | Serial.println("Client connected"); 95 | break; 96 | case SYSTEM_EVENT_AP_STADISCONNECTED: 97 | Serial.println("Client disconnected"); 98 | break; 99 | case SYSTEM_EVENT_AP_STAIPASSIGNED: 100 | Serial.println("Assigned IP address to client"); 101 | break; 102 | case SYSTEM_EVENT_AP_PROBEREQRECVED: 103 | Serial.println("Received probe request"); 104 | break; 105 | case SYSTEM_EVENT_GOT_IP6: 106 | Serial.println("IPv6 is preferred"); 107 | break; 108 | case SYSTEM_EVENT_ETH_START: 109 | Serial.println("Ethernet started"); 110 | break; 111 | case SYSTEM_EVENT_ETH_STOP: 112 | Serial.println("Ethernet stopped"); 113 | break; 114 | case SYSTEM_EVENT_ETH_CONNECTED: 115 | Serial.println("Ethernet connected"); 116 | break; 117 | case SYSTEM_EVENT_ETH_DISCONNECTED: 118 | Serial.println("Ethernet disconnected"); 119 | break; 120 | case SYSTEM_EVENT_ETH_GOT_IP: 121 | Serial.println("Obtained IP address"); 122 | break; 123 | default: break; 124 | } 125 | } 126 | 127 | void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) { 128 | Serial.println("WiFi connected"); 129 | Serial.println("IP address: "); 130 | Serial.println(IPAddress(info.got_ip.ip_info.ip.addr)); 131 | } 132 | 133 | void setup() { 134 | Serial.begin(115200); 135 | 136 | // delete old config 137 | WiFi.disconnect(true); 138 | 139 | delay(1000); 140 | 141 | // Examples of different ways to register wifi events 142 | WiFi.onEvent(WiFiEvent); 143 | WiFi.onEvent(WiFiGotIP, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP); 144 | WiFiEventId_t eventID = WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info) { 145 | Serial.print("WiFi lost connection. Reason: "); 146 | Serial.println(info.disconnected.reason); 147 | }, WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED); 148 | 149 | // Remove WiFi event 150 | Serial.print("WiFi Event ID: "); 151 | Serial.println(eventID); 152 | // WiFi.removeEvent(eventID); 153 | 154 | WiFi.begin(ssid, password); 155 | 156 | Serial.println(); 157 | Serial.println(); 158 | Serial.println("Wait for WiFi... "); 159 | } 160 | 161 | void loop() { 162 | delay(1000); 163 | } 164 | -------------------------------------------------------------------------------- /examples/WiFiClientStaticIP/WiFiClientStaticIP.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Example of connection using Static IP 3 | by Evandro Luis Copercini 4 | Public domain - 2017 5 | */ 6 | 7 | #include 8 | 9 | const char* ssid = "your_network_name"; 10 | const char* password = "your_network_password"; 11 | const char* host = "example.com"; 12 | const char* url = "/index.html"; 13 | 14 | IPAddress local_IP(192, 168, 31, 115); 15 | // Take care this gateway/subnet address 16 | // Must follow with the Access Point configuration. 17 | IPAddress gateway(192, 168, 31, 1); 18 | IPAddress subnet(255, 255, 255, 0); 19 | IPAddress primaryDNS(8, 8, 8, 8); //optional 20 | IPAddress secondaryDNS(8, 8, 4, 4); //optional 21 | 22 | void setup() { 23 | Serial.begin(115200); 24 | 25 | if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) { 26 | Serial.println("STA Failed to configure"); 27 | } 28 | 29 | Serial.print("Connecting to "); 30 | Serial.println(ssid); 31 | 32 | WiFi.begin(ssid, password); 33 | 34 | while (WiFi.status() != WL_CONNECTED) { 35 | delay(500); 36 | Serial.print("."); 37 | } 38 | 39 | Serial.println(""); 40 | Serial.println("WiFi connected!"); 41 | Serial.print("IP address: "); 42 | Serial.println(WiFi.localIP()); 43 | Serial.print("ESP Mac Address: "); 44 | Serial.println(WiFi.macAddress()); 45 | Serial.print("Subnet Mask: "); 46 | Serial.println(WiFi.subnetMask()); 47 | Serial.print("Gateway IP: "); 48 | Serial.println(WiFi.gatewayIP()); 49 | Serial.print("DNS: "); 50 | Serial.println(WiFi.dnsIP()); 51 | } 52 | 53 | void loop() { 54 | delay(5000); 55 | 56 | Serial.print("connecting to "); 57 | Serial.println(host); 58 | 59 | // Use WiFiClient class to create TCP connections 60 | WiFiClient client; 61 | const int httpPort = 80; 62 | if (!client.connect(host, httpPort)) { 63 | Serial.println("connection failed"); 64 | return; 65 | } 66 | 67 | Serial.print("Requesting URL: "); 68 | Serial.println(url); 69 | 70 | // This will send the request to the server 71 | client.print(String("GET ") + url + " HTTP/1.1\r\n" + 72 | "Host: " + host + "\r\n" + 73 | "Connection: close\r\n\r\n"); 74 | unsigned long timeout = millis(); 75 | while (client.available() == 0) { 76 | if (millis() - timeout > 5000) { 77 | Serial.println(">>> Client Timeout !"); 78 | client.stop(); 79 | return; 80 | } 81 | } 82 | 83 | // Read all the lines of the reply from server and print them to Serial 84 | while (client.available()) { 85 | String line = client.readStringUntil('\r'); 86 | // Proceed various line-endings 87 | line.replace("\r\n", "\n"); 88 | line.replace('\r', '\n'); 89 | line.replace("\n", "\r\n"); 90 | Serial.print(line); 91 | } 92 | 93 | Serial.println(); 94 | Serial.println("closing connection"); 95 | } 96 | 97 | -------------------------------------------------------------------------------- /examples/WiFiIPv6/WiFiIPv6.ino: -------------------------------------------------------------------------------- 1 | #include "AtWiFi.h" 2 | 3 | #define STA_SSID "**********" 4 | #define STA_PASS "**********" 5 | #define AP_SSID "esp32-v6" 6 | 7 | static volatile bool wifi_connected = false; 8 | 9 | WiFiUDP ntpClient; 10 | 11 | void wifiOnConnect() { 12 | Serial.println("STA Connected"); 13 | Serial.print("STA IPv4: "); 14 | Serial.println(WiFi.localIP()); 15 | 16 | ntpClient.begin(2390); 17 | } 18 | 19 | void wifiOnDisconnect() { 20 | Serial.println("STA Disconnected"); 21 | delay(1000); 22 | WiFi.begin(STA_SSID, STA_PASS); 23 | } 24 | 25 | void wifiConnectedLoop() { 26 | //lets check the time 27 | const int NTP_PACKET_SIZE = 48; 28 | byte ntpPacketBuffer[NTP_PACKET_SIZE]; 29 | 30 | IPAddress address; 31 | WiFi.hostByName("time.nist.gov", address); 32 | memset(ntpPacketBuffer, 0, NTP_PACKET_SIZE); 33 | ntpPacketBuffer[0] = 0b11100011; // LI, Version, Mode 34 | ntpPacketBuffer[1] = 0; // Stratum, or type of clock 35 | ntpPacketBuffer[2] = 6; // Polling Interval 36 | ntpPacketBuffer[3] = 0xEC; // Peer Clock Precision 37 | // 8 bytes of zero for Root Delay & Root Dispersion 38 | ntpPacketBuffer[12] = 49; 39 | ntpPacketBuffer[13] = 0x4E; 40 | ntpPacketBuffer[14] = 49; 41 | ntpPacketBuffer[15] = 52; 42 | ntpClient.beginPacket(address, 123); //NTP requests are to port 123 43 | ntpClient.write(ntpPacketBuffer, NTP_PACKET_SIZE); 44 | ntpClient.endPacket(); 45 | 46 | delay(1000); 47 | 48 | int packetLength = ntpClient.parsePacket(); 49 | if (packetLength) { 50 | if (packetLength >= NTP_PACKET_SIZE) { 51 | ntpClient.read(ntpPacketBuffer, NTP_PACKET_SIZE); 52 | } 53 | ntpClient.flush(); 54 | uint32_t secsSince1900 = (uint32_t)ntpPacketBuffer[40] << 24 | (uint32_t)ntpPacketBuffer[41] << 16 | 55 | (uint32_t)ntpPacketBuffer[42] << 8 | ntpPacketBuffer[43]; 56 | //Serial.printf("Seconds since Jan 1 1900: %u\n", secsSince1900); 57 | uint32_t epoch = secsSince1900 - 2208988800UL; 58 | //Serial.printf("EPOCH: %u\n", epoch); 59 | uint8_t h = (epoch % 86400L) / 3600; 60 | uint8_t m = (epoch % 3600) / 60; 61 | uint8_t s = (epoch % 60); 62 | Serial.printf("UTC: %02u:%02u:%02u (GMT)\n", h, m, s); 63 | } 64 | 65 | delay(9000); 66 | } 67 | 68 | void WiFiEvent(WiFiEvent_t event) { 69 | switch (event) { 70 | 71 | case SYSTEM_EVENT_AP_START: 72 | //can set ap hostname here 73 | WiFi.softAPsetHostname(AP_SSID); 74 | //enable ap ipv6 here 75 | WiFi.softAPenableIpV6(); 76 | break; 77 | 78 | case SYSTEM_EVENT_STA_START: 79 | //set sta hostname here 80 | WiFi.setHostname(AP_SSID); 81 | break; 82 | case SYSTEM_EVENT_STA_CONNECTED: 83 | //enable sta ipv6 here 84 | WiFi.enableIpV6(); 85 | break; 86 | case SYSTEM_EVENT_AP_STA_GOT_IP6: 87 | //both interfaces get the same event 88 | Serial.print("STA IPv6: "); 89 | Serial.println(WiFi.localIPv6()); 90 | Serial.print("AP IPv6: "); 91 | Serial.println(WiFi.softAPIPv6()); 92 | break; 93 | case SYSTEM_EVENT_STA_GOT_IP: 94 | wifiOnConnect(); 95 | wifi_connected = true; 96 | break; 97 | case SYSTEM_EVENT_STA_DISCONNECTED: 98 | wifi_connected = false; 99 | wifiOnDisconnect(); 100 | break; 101 | default: 102 | break; 103 | } 104 | } 105 | 106 | void setup() { 107 | Serial.begin(115200); 108 | WiFi.disconnect(true); 109 | WiFi.onEvent(WiFiEvent); 110 | WiFi.mode(WIFI_MODE_APSTA); 111 | WiFi.softAP(AP_SSID); 112 | WiFi.begin(STA_SSID, STA_PASS); 113 | } 114 | 115 | void loop() { 116 | if (wifi_connected) { 117 | wifiConnectedLoop(); 118 | } 119 | while (Serial.available()) { 120 | Serial.write(Serial.read()); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /examples/WiFiMulti/WiFiMulti.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch trys to Connect to the best AP based on a given list 3 | 4 | */ 5 | 6 | #include "AtWiFi.h" 7 | #include 8 | 9 | WiFiMulti wifiMulti; 10 | 11 | void setup() { 12 | Serial.begin(115200); 13 | delay(10); 14 | 15 | wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1"); 16 | wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); 17 | wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); 18 | 19 | Serial.println("Connecting Wifi..."); 20 | if (wifiMulti.run() == WL_CONNECTED) { 21 | Serial.println(""); 22 | Serial.println("WiFi connected"); 23 | Serial.println("IP address: "); 24 | Serial.println(WiFi.localIP()); 25 | } 26 | } 27 | 28 | void loop() { 29 | if (wifiMulti.run() != WL_CONNECTED) { 30 | Serial.println("WiFi not connected!"); 31 | delay(1000); 32 | } 33 | } -------------------------------------------------------------------------------- /examples/WiFiScan/WiFiScan.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch demonstrates how to scan WiFi networks. 3 | The API is almost the same as with the WiFi Shield library, 4 | the most obvious difference being the different file you need to include: 5 | */ 6 | #include "AtWiFi.h" 7 | 8 | void setup() { 9 | Serial.begin(115200); 10 | 11 | // Set WiFi to station mode and disconnect from an AP if it was previously connected 12 | WiFi.mode(WIFI_STA); 13 | WiFi.disconnect(); 14 | delay(100); 15 | 16 | Serial.println("Setup done"); 17 | } 18 | 19 | void loop() { 20 | Serial.println("scan start"); 21 | 22 | // WiFi.scanNetworks will return the number of networks found 23 | int n = WiFi.scanNetworks(); 24 | Serial.println("scan done"); 25 | if (n == 0) { 26 | Serial.println("no networks found"); 27 | } else { 28 | Serial.print(n); 29 | Serial.println(" networks found"); 30 | for (int i = 0; i < n; ++i) { 31 | // Print SSID and RSSI for each network found 32 | Serial.print(i + 1); 33 | Serial.print(": "); 34 | Serial.print(WiFi.SSID(i)); 35 | Serial.print(" ("); 36 | Serial.print(WiFi.RSSI(i)); 37 | Serial.print(")"); 38 | Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*"); 39 | delay(10); 40 | } 41 | } 42 | Serial.println(""); 43 | 44 | // Wait a bit before scanning again 45 | delay(5000); 46 | } 47 | -------------------------------------------------------------------------------- /examples/WiFiSmartConfig/WiFiSmartConfig.ino: -------------------------------------------------------------------------------- 1 | #include "AtWiFi.h" 2 | 3 | void setup() { 4 | Serial.begin(115200); 5 | 6 | //Init WiFi as Station, start SmartConfig 7 | WiFi.mode(WIFI_AP_STA); 8 | WiFi.beginSmartConfig(); 9 | 10 | //Wait for SmartConfig packet from mobile 11 | Serial.println("Waiting for SmartConfig."); 12 | while (!WiFi.smartConfigDone()) { 13 | delay(500); 14 | Serial.print("."); 15 | } 16 | 17 | Serial.println(""); 18 | Serial.println("SmartConfig received."); 19 | 20 | //Wait for WiFi to connect to AP 21 | Serial.println("Waiting for WiFi"); 22 | while (WiFi.status() != WL_CONNECTED) { 23 | delay(500); 24 | Serial.print("."); 25 | } 26 | 27 | Serial.println("WiFi Connected."); 28 | 29 | Serial.print("IP Address: "); 30 | Serial.println(WiFi.localIP()); 31 | } 32 | 33 | void loop() { 34 | // put your main code here, to run repeatedly: 35 | 36 | } 37 | -------------------------------------------------------------------------------- /examples/WiFiTelnetToSerial/WiFiTelnetToSerial.ino: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiTelnetToSerial - Example Transparent UART to Telnet Server for ESP32 3 | 4 | Copyright (c) 2017 Hristo Gochkov. All rights reserved. 5 | This file is part of the ESP32 WiFi library for Arduino environment. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | #include 22 | #include 23 | #undef Serial 24 | #undef Serial2 25 | WiFiMulti wifiMulti; 26 | 27 | //how many clients should be able to telnet to this ESP32 28 | #define MAX_SRV_CLIENTS 1 29 | const char* ssid = "**********"; 30 | const char* password = "**********"; 31 | 32 | WiFiServer server(23); 33 | WiFiClient serverClients[MAX_SRV_CLIENTS]; 34 | 35 | void setup() { 36 | Serial.begin(115200); 37 | Serial.println("\nConnecting"); 38 | 39 | wifiMulti.addAP(ssid, password); 40 | wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); 41 | wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); 42 | 43 | Serial.println("Connecting Wifi "); 44 | for (int loops = 10; loops > 0; loops--) { 45 | if (wifiMulti.run() == WL_CONNECTED) { 46 | Serial.println(""); 47 | Serial.print("WiFi connected "); 48 | Serial.print("IP address: "); 49 | Serial.println(WiFi.localIP()); 50 | break; 51 | } else { 52 | Serial.println(loops); 53 | delay(1000); 54 | } 55 | } 56 | if (wifiMulti.run() != WL_CONNECTED) { 57 | Serial.println("WiFi connect failed"); 58 | delay(1000); 59 | } 60 | 61 | //start UART and the server 62 | Serial2.begin(115200); 63 | server.begin(); 64 | server.setNoDelay(true); 65 | 66 | Serial.print("Ready! Use 'telnet "); 67 | Serial.print(WiFi.localIP()); 68 | Serial.println(" 23' to connect"); 69 | } 70 | 71 | void loop() { 72 | uint8_t i; 73 | if (wifiMulti.run() == WL_CONNECTED) { 74 | //check if there are any new clients 75 | if (server.hasClient()) { 76 | for (i = 0; i < MAX_SRV_CLIENTS; i++) { 77 | //find free/disconnected spot 78 | if (!serverClients[i] || !serverClients[i].connected()) { 79 | if (serverClients[i]) { 80 | serverClients[i].stop(); 81 | } 82 | serverClients[i] = server.available(); 83 | if (!serverClients[i]) { 84 | Serial.println("available broken"); 85 | } 86 | Serial.print("New client: "); 87 | Serial.print(i); Serial.print(' '); 88 | Serial.println(serverClients[i].remoteIP()); 89 | break; 90 | } 91 | } 92 | if (i >= MAX_SRV_CLIENTS) { 93 | //no free/disconnected spot so reject 94 | server.available().stop(); 95 | } 96 | } 97 | //check clients for data 98 | for (i = 0; i < MAX_SRV_CLIENTS; i++) { 99 | if (serverClients[i] && serverClients[i].connected()) { 100 | if (serverClients[i].available()) { 101 | //get data from the telnet client and push it to the UART 102 | while (serverClients[i].available()) { 103 | Serial2.write(serverClients[i].read()); 104 | } 105 | } 106 | } else { 107 | if (serverClients[i]) { 108 | serverClients[i].stop(); 109 | } 110 | } 111 | } 112 | //check UART for data 113 | if (Serial2.available()) { 114 | size_t len = Serial2.available(); 115 | uint8_t sbuf[len]; 116 | Serial2.readBytes(sbuf, len); 117 | //push UART data to all connected telnet clients 118 | for (i = 0; i < MAX_SRV_CLIENTS; i++) { 119 | if (serverClients[i] && serverClients[i].connected()) { 120 | serverClients[i].write(sbuf, len); 121 | delay(1); 122 | } 123 | } 124 | } 125 | } else { 126 | Serial.println("WiFi not connected!"); 127 | for (i = 0; i < MAX_SRV_CLIENTS; i++) { 128 | if (serverClients[i]) { 129 | serverClients[i].stop(); 130 | } 131 | } 132 | delay(1000); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /examples/WiFiUDPClient/WiFiUDPClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch sends random data over UDP on a ESP32 device 3 | 4 | */ 5 | #include 6 | #include 7 | 8 | // WiFi network name and password: 9 | const char* networkName = "your-ssid"; 10 | const char* networkPswd = "your-password"; 11 | 12 | //IP address to send UDP data to: 13 | // either use the ip address of the server or 14 | // a network broadcast address 15 | const char* udpAddress = "192.168.0.255"; 16 | const int udpPort = 3333; 17 | 18 | //Are we currently connected? 19 | boolean connected = false; 20 | 21 | //The udp library class 22 | WiFiUDP udp; 23 | 24 | void setup() { 25 | // Initilize hardware serial: 26 | Serial.begin(115200); 27 | 28 | //Connect to the WiFi network 29 | connectToWiFi(networkName, networkPswd); 30 | } 31 | 32 | void loop() { 33 | //only send data when connected 34 | if (connected) { 35 | //Send a packet 36 | udp.beginPacket(udpAddress, udpPort); 37 | udp.printf("Seconds since boot: %lu", millis() / 1000); 38 | udp.endPacket(); 39 | } 40 | //Wait for 1 second 41 | delay(1000); 42 | } 43 | 44 | void connectToWiFi(const char* ssid, const char* pwd) { 45 | Serial.println("Connecting to WiFi network: " + String(ssid)); 46 | 47 | // delete old config 48 | WiFi.disconnect(true); 49 | //register event handler 50 | WiFi.onEvent(WiFiEvent); 51 | 52 | //Initiate connection 53 | WiFi.begin(ssid, pwd); 54 | 55 | Serial.println("Waiting for WIFI connection..."); 56 | } 57 | 58 | //wifi event handler 59 | void WiFiEvent(WiFiEvent_t event) { 60 | switch (event) { 61 | case SYSTEM_EVENT_STA_GOT_IP: 62 | //When connected set 63 | Serial.print("WiFi connected! IP address: "); 64 | Serial.println(WiFi.localIP()); 65 | //initializes the UDP state 66 | //This initializes the transfer buffer 67 | udp.begin(WiFi.localIP(), udpPort); 68 | connected = true; 69 | break; 70 | case SYSTEM_EVENT_STA_DISCONNECTED: 71 | Serial.println("WiFi lost connection"); 72 | connected = false; 73 | break; 74 | default: break; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /examples/WiFiUDPClient/udp_server.py: -------------------------------------------------------------------------------- 1 | # This python script listens on UDP port 3333 2 | # for messages from the ESP32 board and prints them 3 | import socket 4 | import sys 5 | 6 | try : 7 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 8 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 9 | except(socket.error, msg): 10 | print('Failed to create socket. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]) 11 | sys.exit() 12 | 13 | try: 14 | s.bind(('', 3333)) 15 | except(socket.error, msg): 16 | print('Bind failed. Error: ' + str(msg[0]) + ': ' + msg[1]) 17 | sys.exit() 18 | 19 | print('Server listening') 20 | 21 | while True: 22 | d = s.recvfrom(1024) 23 | data = d[0] 24 | 25 | if not data: 26 | break 27 | 28 | print(data.strip().decode('ascii')) 29 | 30 | s.close() 31 | -------------------------------------------------------------------------------- /examples/WiFiUDPClient/udp_server.rb: -------------------------------------------------------------------------------- 1 | # This ruby script listens on UDP port 3333 2 | # for messages from the ESP32 board and prints them 3 | 4 | require 'socket' 5 | include Socket::Constants 6 | 7 | udp_socket = UDPSocket.new(AF_INET) 8 | 9 | #bind 10 | udp_socket.bind("", 3333) 11 | puts 'Server listening' 12 | 13 | while true do 14 | message, sender = udp_socket.recvfrom(1024) 15 | puts message 16 | end -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For WiFi 3 | ####################################### 4 | 5 | ####################################### 6 | # Library (KEYWORD3) 7 | ####################################### 8 | 9 | WiFi KEYWORD3 10 | 11 | ####################################### 12 | # Datatypes (KEYWORD1) 13 | ####################################### 14 | 15 | WiFi KEYWORD1 16 | WiFiClient KEYWORD1 17 | WiFiServer KEYWORD1 18 | WiFiUDP KEYWORD1 19 | WiFiClientSecure KEYWORD1 20 | 21 | ####################################### 22 | # Methods and Functions (KEYWORD2) 23 | ####################################### 24 | 25 | status KEYWORD2 26 | mode KEYWORD2 27 | connect KEYWORD2 28 | write KEYWORD2 29 | available KEYWORD2 30 | config KEYWORD2 31 | setDNS KEYWORD2 32 | read KEYWORD2 33 | flush KEYWORD2 34 | stop KEYWORD2 35 | connected KEYWORD2 36 | begin KEYWORD2 37 | beginMulticast KEYWORD2 38 | disconnect KEYWORD2 39 | macAddress KEYWORD2 40 | localIP KEYWORD2 41 | subnetMask KEYWORD2 42 | gatewayIP KEYWORD2 43 | SSID KEYWORD2 44 | psk KEYWORD2 45 | BSSID KEYWORD2 46 | RSSI KEYWORD2 47 | encryptionType KEYWORD2 48 | beginPacket KEYWORD2 49 | beginPacketMulticast KEYWORD2 50 | endPacket KEYWORD2 51 | parsePacket KEYWORD2 52 | destinationIP KEYWORD2 53 | remoteIP KEYWORD2 54 | remotePort KEYWORD2 55 | softAP KEYWORD2 56 | softAPIP KEYWORD2 57 | softAPmacAddress KEYWORD2 58 | softAPConfig KEYWORD2 59 | printDiag KEYWORD2 60 | hostByName KEYWORD2 61 | scanNetworks KEYWORD2 62 | 63 | ####################################### 64 | # Constants (LITERAL1) 65 | ####################################### 66 | WIFI_AP LITERAL1 67 | WIFI_STA LITERAL1 68 | WIFI_AP_STA LITERAL1 69 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Seeed_Arduino_atWiFi 2 | version=1.0 3 | author=Hristo Gochkov 4 | maintainer=Hristo Gochkov 5 | sentence=Enables network connection (local and Internet) using the ESP32 built-in WiFi. 6 | paragraph=With this library you can instantiate Servers, Clients and send/receive UDP packets through WiFi. The shield can connect either to open or encrypted networks (WEP, WPA). The IP address can be assigned statically or through a DHCP. The library can also manage DNS. 7 | category=Communication 8 | url= 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/AtWiFi.h: -------------------------------------------------------------------------------- 1 | #include "WiFi.h" 2 | -------------------------------------------------------------------------------- /src/ETH.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ETH.h - espre ETH PHY support. 3 | Based on WiFi.h from Arduino WiFi shield library. 4 | Copyright (c) 2011-2014 Arduino. All right reserved. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #if 0 22 | #include "ETH.h" 23 | #include "eth_phy/phy.h" 24 | #include "lwip_err.h" 25 | #include "lwip_dns.h" 26 | 27 | extern void tcpipInit(); 28 | 29 | static int _eth_phy_mdc_pin = -1; 30 | static int _eth_phy_mdio_pin = -1; 31 | static int _eth_phy_power_pin = -1; 32 | static eth_phy_power_enable_func _eth_phy_power_enable_orig = NULL; 33 | 34 | static void _eth_phy_config_gpio(void) { 35 | if (_eth_phy_mdc_pin < 0 || _eth_phy_mdio_pin < 0) { 36 | log_e("MDC and MDIO pins are not configured!"); 37 | return; 38 | } 39 | phy_rmii_configure_data_interface_pins(); 40 | phy_rmii_smi_configure_pins(_eth_phy_mdc_pin, _eth_phy_mdio_pin); 41 | } 42 | 43 | static void _eth_phy_power_enable(bool enable) { 44 | pinMode(_eth_phy_power_pin, OUTPUT); 45 | digitalWrite(_eth_phy_power_pin, enable); 46 | delay(1); 47 | } 48 | 49 | ETHClass::ETHClass(): initialized(false), started(false), staticIP(false) { 50 | } 51 | 52 | ETHClass::~ETHClass() 53 | {} 54 | 55 | bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t type, eth_clock_mode_t clock_mode) { 56 | esp_err_t err; 57 | if (initialized) { 58 | err = esp_eth_enable(); 59 | if (err) { 60 | log_e("esp_eth_enable error: %d", err); 61 | return false; 62 | } 63 | started = true; 64 | return true; 65 | } 66 | _eth_phy_mdc_pin = mdc; 67 | _eth_phy_mdio_pin = mdio; 68 | _eth_phy_power_pin = power; 69 | 70 | if (type == ETH_PHY_LAN8720) { 71 | eth_config_t config = phy_lan8720_default_ethernet_config; 72 | memcpy(ð_config, &config, sizeof(eth_config_t)); 73 | } else if (type == ETH_PHY_TLK110) { 74 | eth_config_t config = phy_tlk110_default_ethernet_config; 75 | memcpy(ð_config, &config, sizeof(eth_config_t)); 76 | } else { 77 | log_e("Bad ETH_PHY type: %u", (uint8_t)type); 78 | return false; 79 | } 80 | 81 | eth_config.phy_addr = (eth_phy_base_t)phy_addr; 82 | eth_config.clock_mode = clock_mode; 83 | eth_config.gpio_config = _eth_phy_config_gpio; 84 | eth_config.tcpip_input = tcpip_adapter_eth_input; 85 | if (_eth_phy_power_pin >= 0) { 86 | _eth_phy_power_enable_orig = eth_config.phy_power_enable; 87 | eth_config.phy_power_enable = _eth_phy_power_enable; 88 | } 89 | 90 | tcpipInit(); 91 | err = esp_eth_init(ð_config); 92 | if (!err) { 93 | initialized = true; 94 | err = esp_eth_enable(); 95 | if (err) { 96 | log_e("esp_eth_enable error: %d", err); 97 | } else { 98 | started = true; 99 | return true; 100 | } 101 | } else { 102 | log_e("esp_eth_init error: %d", err); 103 | } 104 | return false; 105 | } 106 | 107 | bool ETHClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) { 108 | esp_err_t err = ESP_OK; 109 | tcpip_adapter_ip_info_t info; 110 | 111 | if (local_ip != (uint32_t)0x00000000) { 112 | info.ip.addr = static_cast(local_ip); 113 | info.gw.addr = static_cast(gateway); 114 | info.netmask.addr = static_cast(subnet); 115 | } else { 116 | info.ip.addr = 0; 117 | info.gw.addr = 0; 118 | info.netmask.addr = 0; 119 | } 120 | 121 | err = tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_ETH); 122 | if (err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) { 123 | log_e("DHCP could not be stopped! Error: %d", err); 124 | return false; 125 | } 126 | 127 | err = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_ETH, &info); 128 | if (err != ERR_OK) { 129 | log_e("STA IP could not be configured! Error: %d", err); 130 | return false; 131 | } 132 | if (info.ip.addr) { 133 | staticIP = true; 134 | } else { 135 | err = tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_ETH); 136 | if (err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED) { 137 | log_w("DHCP could not be started! Error: %d", err); 138 | return false; 139 | } 140 | staticIP = false; 141 | } 142 | 143 | ip_addr_t d; 144 | d.type = IPADDR_TYPE_V4; 145 | 146 | if (dns1 != (uint32_t)0x00000000) { 147 | // Set DNS1-Server 148 | d.u_addr.ip4.addr = static_cast(dns1); 149 | dns_setserver(0, &d); 150 | } 151 | 152 | if (dns2 != (uint32_t)0x00000000) { 153 | // Set DNS2-Server 154 | d.u_addr.ip4.addr = static_cast(dns2); 155 | dns_setserver(1, &d); 156 | } 157 | 158 | return true; 159 | } 160 | 161 | IPAddress ETHClass::localIP() { 162 | tcpip_adapter_ip_info_t ip; 163 | if (tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)) { 164 | return IPAddress(); 165 | } 166 | return IPAddress(ip.ip.addr); 167 | } 168 | 169 | IPAddress ETHClass::subnetMask() { 170 | tcpip_adapter_ip_info_t ip; 171 | if (tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)) { 172 | return IPAddress(); 173 | } 174 | return IPAddress(ip.netmask.addr); 175 | } 176 | 177 | IPAddress ETHClass::gatewayIP() { 178 | tcpip_adapter_ip_info_t ip; 179 | if (tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)) { 180 | return IPAddress(); 181 | } 182 | return IPAddress(ip.gw.addr); 183 | } 184 | 185 | IPAddress ETHClass::dnsIP(uint8_t dns_no) { 186 | ip_addr_t dns_ip = dns_getserver(dns_no); 187 | return IPAddress(dns_ip.u_addr.ip4.addr); 188 | } 189 | 190 | IPAddress ETHClass::broadcastIP() { 191 | tcpip_adapter_ip_info_t ip; 192 | if (tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)) { 193 | return IPAddress(); 194 | } 195 | return WiFiGenericClass::calculateBroadcast(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr)); 196 | } 197 | 198 | IPAddress ETHClass::networkID() { 199 | tcpip_adapter_ip_info_t ip; 200 | if (tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)) { 201 | return IPAddress(); 202 | } 203 | return WiFiGenericClass::calculateNetworkID(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr)); 204 | } 205 | 206 | uint8_t ETHClass::subnetCIDR() { 207 | tcpip_adapter_ip_info_t ip; 208 | if (tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)) { 209 | return (uint8_t)0; 210 | } 211 | return WiFiGenericClass::calculateSubnetCIDR(IPAddress(ip.netmask.addr)); 212 | } 213 | 214 | const char* ETHClass::getHostname() { 215 | const char* hostname; 216 | if (tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_ETH, &hostname)) { 217 | return NULL; 218 | } 219 | return hostname; 220 | } 221 | 222 | bool ETHClass::setHostname(const char* hostname) { 223 | return tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_ETH, hostname) == 0; 224 | } 225 | 226 | bool ETHClass::fullDuplex() { 227 | return eth_config.phy_get_duplex_mode(); 228 | } 229 | 230 | bool ETHClass::linkUp() { 231 | return eth_config.phy_check_link(); 232 | } 233 | 234 | uint8_t ETHClass::linkSpeed() { 235 | return eth_config.phy_get_speed_mode() ? 100 : 10; 236 | } 237 | 238 | bool ETHClass::enableIpV6() { 239 | return tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_ETH) == 0; 240 | } 241 | 242 | IPv6Address ETHClass::localIPv6() { 243 | static ip6_addr_t addr; 244 | if (tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_ETH, &addr)) { 245 | return IPv6Address(); 246 | } 247 | return IPv6Address(addr.addr); 248 | } 249 | 250 | uint8_t* macAddress(uint8_t* mac) { 251 | if (!mac) { 252 | return NULL; 253 | } 254 | esp_eth_get_mac(mac); 255 | return mac; 256 | } 257 | 258 | String ETHClass::macAddress(void) { 259 | uint8_t mac[6]; 260 | char macStr[18] = { 0 }; 261 | esp_eth_get_mac(mac); 262 | sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 263 | return String(macStr); 264 | } 265 | 266 | ETHClass ETH; 267 | #endif -------------------------------------------------------------------------------- /src/ETH.h: -------------------------------------------------------------------------------- 1 | /* 2 | ETH.h - espre ETH PHY support. 3 | Based on WiFi.h from Ardiono WiFi shield library. 4 | Copyright (c) 2011-2014 Arduino. All right reserved. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef _ETH_H_ 22 | #define _ETH_H_ 23 | 24 | #include "WiFi.h" 25 | #include "esp_eth.h" 26 | 27 | #ifndef ETH_PHY_ADDR 28 | #define ETH_PHY_ADDR 0 29 | #endif 30 | 31 | #ifndef ETH_PHY_TYPE 32 | #define ETH_PHY_TYPE ETH_PHY_LAN8720 33 | #endif 34 | 35 | #ifndef ETH_PHY_POWER 36 | #define ETH_PHY_POWER -1 37 | #endif 38 | 39 | #ifndef ETH_PHY_MDC 40 | #define ETH_PHY_MDC 23 41 | #endif 42 | 43 | #ifndef ETH_PHY_MDIO 44 | #define ETH_PHY_MDIO 18 45 | #endif 46 | 47 | #ifndef ETH_CLK_MODE 48 | #define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN 49 | #endif 50 | 51 | typedef enum { ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_MAX } eth_phy_type_t; 52 | 53 | class ETHClass { 54 | private: 55 | bool initialized; 56 | bool started; 57 | bool staticIP; 58 | eth_config_t eth_config; 59 | public: 60 | ETHClass(); 61 | ~ETHClass(); 62 | 63 | bool begin(uint8_t phy_addr = ETH_PHY_ADDR, int power = ETH_PHY_POWER, int mdc = ETH_PHY_MDC, int mdio = ETH_PHY_MDIO, 64 | eth_phy_type_t type = ETH_PHY_TYPE, eth_clock_mode_t clk_mode = ETH_CLK_MODE); 65 | 66 | bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, 67 | IPAddress dns2 = (uint32_t)0x00000000); 68 | 69 | const char* getHostname(); 70 | bool setHostname(const char* hostname); 71 | 72 | bool fullDuplex(); 73 | bool linkUp(); 74 | uint8_t linkSpeed(); 75 | 76 | bool enableIpV6(); 77 | IPv6Address localIPv6(); 78 | 79 | IPAddress localIP(); 80 | IPAddress subnetMask(); 81 | IPAddress gatewayIP(); 82 | IPAddress dnsIP(uint8_t dns_no = 0); 83 | 84 | IPAddress broadcastIP(); 85 | IPAddress networkID(); 86 | uint8_t subnetCIDR(); 87 | 88 | uint8_t* macAddress(uint8_t* mac); 89 | String macAddress(); 90 | 91 | friend class WiFiClient; 92 | friend class WiFiServer; 93 | }; 94 | 95 | extern ETHClass ETH; 96 | 97 | #endif /* _ETH_H_ */ 98 | -------------------------------------------------------------------------------- /src/WiFi.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266WiFi.cpp - WiFi library for esp8266 3 | 4 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 5 | This file is part of the esp8266 core for Arduino environment. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | 21 | Reworked on 28 Dec 2015 by Markus Sattler 22 | 23 | */ 24 | #include "WiFi.h" 25 | #include "Seeed_atUnified.h" 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | // ----------------------------------------------------------------------------------------------------------------------- 35 | // ---------------------------------------------------------- Debug ------------------------------------------------------ 36 | // ----------------------------------------------------------------------------------------------------------------------- 37 | 38 | 39 | /** 40 | Output WiFi settings to an object derived from Print interface (like Serial). 41 | @param p Print interface 42 | */ 43 | void WiFiClass::printDiag(Print& p) { 44 | const char* modes[] = { "NULL", "STA", "AP", "STA+AP" }; 45 | 46 | wifi_mode_t mode; 47 | esp_wifi_get_mode(&mode); 48 | 49 | uint8_t primaryChan; 50 | wifi_second_chan_t secondChan; 51 | esp_wifi_get_channel(&primaryChan, &secondChan); 52 | 53 | p.print("Mode: "); 54 | p.println(modes[mode]); 55 | 56 | p.print("Channel: "); 57 | p.println(primaryChan); 58 | /* 59 | p.print("AP id: "); 60 | p.println(wifi_station_get_current_ap_id()); 61 | 62 | p.print("Status: "); 63 | p.println(wifi_station_get_connect_status()); 64 | */ 65 | 66 | wifi_config_t conf; 67 | esp_wifi_get_config(WIFI_IF_STA, &conf); 68 | 69 | const char* ssid = reinterpret_cast(conf.sta.ssid); 70 | p.print("SSID ("); 71 | p.print(strlen(ssid)); 72 | p.print("): "); 73 | p.println(ssid); 74 | 75 | const char* passphrase = reinterpret_cast(conf.sta.password); 76 | p.print("Passphrase ("); 77 | p.print(strlen(passphrase)); 78 | p.print("): "); 79 | p.println(passphrase); 80 | 81 | p.print("BSSID set: "); 82 | p.println(conf.sta.bssid_set); 83 | } 84 | 85 | WiFiClass WiFi; 86 | -------------------------------------------------------------------------------- /src/WiFi.h: -------------------------------------------------------------------------------- 1 | /* 2 | AtWiFi.h - esp32 Wifi support. 3 | Based on WiFi.h from Arduino WiFi shield library. 4 | Copyright (c) 2011-2014 Arduino. All right reserved. 5 | Modified by Ivan Grokhotkov, December 2014 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef AtWiFi_h 23 | #define AtWiFi_h 24 | 25 | #include 26 | 27 | #include "Print.h" 28 | #include "IPAddress.h" 29 | #include "IPv6Address.h" 30 | 31 | #include "WiFiType.h" 32 | #include "WiFiSTA.h" 33 | #include "WiFiAP.h" 34 | #include "WiFiScan.h" 35 | #include "WiFiGeneric.h" 36 | 37 | #include "WiFiClient.h" 38 | #include "WiFiServer.h" 39 | #include "WiFiUdp.h" 40 | 41 | class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanClass, public WiFiAPClass { 42 | public: 43 | using WiFiGenericClass::channel; 44 | 45 | using WiFiSTAClass::SSID; 46 | using WiFiSTAClass::RSSI; 47 | using WiFiSTAClass::BSSID; 48 | using WiFiSTAClass::BSSIDstr; 49 | 50 | using WiFiScanClass::SSID; 51 | using WiFiScanClass::encryptionType; 52 | using WiFiScanClass::RSSI; 53 | using WiFiScanClass::BSSID; 54 | using WiFiScanClass::BSSIDstr; 55 | using WiFiScanClass::channel; 56 | 57 | public: 58 | void printDiag(Print& dest); 59 | friend class WiFiClient; 60 | friend class WiFiServer; 61 | friend class WiFiUDP; 62 | }; 63 | 64 | extern WiFiClass WiFi; 65 | 66 | #endif//AtWiFi_h 67 | -------------------------------------------------------------------------------- /src/WiFiAP.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266WiFiSTA.cpp - WiFi library for esp8266 3 | 4 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 5 | This file is part of the esp8266 core for Arduino environment. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | 21 | Reworked on 28 Dec 2015 by Markus Sattler 22 | 23 | */ 24 | 25 | #include "WiFi.h" 26 | #include "WiFiGeneric.h" 27 | #include "WiFiAP.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "Seeed_atUnified.h" 36 | 37 | 38 | 39 | 40 | // ----------------------------------------------------------------------------------------------------------------------- 41 | // ---------------------------------------------------- Private functions ------------------------------------------------ 42 | // ----------------------------------------------------------------------------------------------------------------------- 43 | 44 | static bool softap_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs); 45 | 46 | 47 | 48 | /** 49 | compare two AP configurations 50 | @param lhs softap_config 51 | @param rhs softap_config 52 | @return equal 53 | */ 54 | static bool softap_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs) { 55 | if (strcmp(reinterpret_cast(lhs.ap.ssid), reinterpret_cast(rhs.ap.ssid)) != 0) { 56 | return false; 57 | } 58 | if (strcmp(reinterpret_cast(lhs.ap.password), reinterpret_cast(rhs.ap.password)) != 0) { 59 | return false; 60 | } 61 | if (lhs.ap.channel != rhs.ap.channel) { 62 | return false; 63 | } 64 | if (lhs.ap.ssid_hidden != rhs.ap.ssid_hidden) { 65 | return false; 66 | } 67 | if (lhs.ap.max_connection != rhs.ap.max_connection) { 68 | return false; 69 | } 70 | return true; 71 | } 72 | 73 | // ----------------------------------------------------------------------------------------------------------------------- 74 | // ----------------------------------------------------- AP function ----------------------------------------------------- 75 | // ----------------------------------------------------------------------------------------------------------------------- 76 | 77 | 78 | /** 79 | Set up an access point 80 | @param ssid Pointer to the SSID (max 63 char). 81 | @param passphrase (for WPA2 min 8 char, for open use NULL) 82 | @param channel WiFi channel number, 1 - 13. 83 | @param ssid_hidden Network cloaking (0 = broadcast SSID, 1 = hide SSID) 84 | @param max_connection Max simultaneous connected clients, 1 - 4. 85 | */ 86 | bool WiFiAPClass::softAP(const char* ssid, const char* passphrase, int channel, int ssid_hidden, int max_connection) { 87 | 88 | if (!WiFi.enableAP(true)) { 89 | // enable AP failed 90 | log_e("enable AP first!"); 91 | return false; 92 | } 93 | 94 | if (!ssid || *ssid == 0) { 95 | // fail SSID missing 96 | log_e("SSID missing!"); 97 | return false; 98 | } 99 | 100 | if (passphrase && (strlen(passphrase) > 0 && strlen(passphrase) < 8)) { 101 | // fail passphrase too short 102 | log_e("passphrase too short!"); 103 | return false; 104 | } 105 | 106 | esp_wifi_start(); 107 | 108 | wifi_config_t conf; 109 | strlcpy(reinterpret_cast(conf.ap.ssid), ssid, sizeof(conf.ap.ssid)); 110 | conf.ap.channel = channel; 111 | conf.ap.ssid_len = strlen(reinterpret_cast(conf.ap.ssid)); 112 | conf.ap.ssid_hidden = ssid_hidden; 113 | conf.ap.max_connection = max_connection; 114 | conf.ap.beacon_interval = 100; 115 | 116 | if (!passphrase || strlen(passphrase) == 0) { 117 | conf.ap.authmode = WIFI_AUTH_OPEN; 118 | *conf.ap.password = 0; 119 | } else { 120 | conf.ap.authmode = WIFI_AUTH_WPA2_PSK; 121 | strlcpy(reinterpret_cast(conf.ap.password), passphrase, sizeof(conf.ap.password)); 122 | } 123 | 124 | wifi_config_t conf_current; 125 | esp_wifi_get_config(WIFI_IF_AP, &conf_current); 126 | if (!softap_config_equal(conf, conf_current) && esp_wifi_set_config(WIFI_IF_AP, &conf) != ESP_OK) { 127 | return false; 128 | } 129 | 130 | return true; 131 | } 132 | 133 | 134 | /** 135 | Configure access point 136 | @param local_ip access point IP 137 | @param gateway gateway IP 138 | @param subnet subnet mask 139 | */ 140 | bool WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { 141 | 142 | if (!WiFi.enableAP(true)) { 143 | // enable AP failed 144 | return false; 145 | } 146 | 147 | esp_wifi_start(); 148 | 149 | tcpip_adapter_ip_info_t info; 150 | info.ip.addr = static_cast(local_ip); 151 | info.gw.addr = static_cast(gateway); 152 | info.netmask.addr = static_cast(subnet); 153 | tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP); 154 | if (tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &info) == ESP_OK) { 155 | dhcps_lease_t lease; 156 | lease.enable = true; 157 | lease.start_ip.addr = static_cast(local_ip) + (1 << 24); 158 | lease.end_ip.addr = static_cast(local_ip) + (11 << 24); 159 | 160 | tcpip_adapter_dhcps_option( 161 | (tcpip_adapter_option_mode_t)TCPIP_ADAPTER_OP_SET, 162 | (tcpip_adapter_option_id_t)TCPIP_ADAPTER_REQUESTED_IP_ADDRESS, 163 | (void*)&lease, sizeof(dhcps_lease_t) 164 | ); 165 | 166 | return tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP) == ESP_OK; 167 | } 168 | return false; 169 | } 170 | 171 | 172 | 173 | /** 174 | Disconnect from the network (close AP) 175 | @param wifioff disable mode? 176 | @return one value of wl_status_t enum 177 | */ 178 | bool WiFiAPClass::softAPdisconnect(bool wifioff) { 179 | bool ret; 180 | wifi_config_t conf; 181 | 182 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 183 | return ESP_ERR_INVALID_STATE; 184 | } 185 | 186 | *conf.ap.ssid = 0; 187 | *conf.ap.password = 0; 188 | conf.ap.authmode = WIFI_AUTH_OPEN; // auth must be open if pass=0 189 | ret = esp_wifi_set_config(WIFI_IF_AP, &conf) == ESP_OK; 190 | 191 | if (wifioff) { 192 | ret = WiFi.enableAP(false) == ESP_OK; 193 | } 194 | 195 | return ret; 196 | } 197 | 198 | 199 | /** 200 | Get the count of the Station / client that are connected to the softAP interface 201 | @return Stations count 202 | */ 203 | uint8_t WiFiAPClass::softAPgetStationNum() { 204 | wifi_sta_list_t clients; 205 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 206 | return 0; 207 | } 208 | if (esp_wifi_ap_get_sta_list(&clients) == ESP_OK) { 209 | return clients.num; 210 | } 211 | return 0; 212 | } 213 | 214 | /** 215 | Get the softAP interface IP address. 216 | @return IPAddress softAP IP 217 | */ 218 | IPAddress WiFiAPClass::softAPIP() { 219 | tcpip_adapter_ip_info_t ip; 220 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 221 | return IPAddress(); 222 | } 223 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip); 224 | return IPAddress(ip.ip.addr); 225 | } 226 | 227 | /** 228 | Get the softAP broadcast IP address. 229 | @return IPAddress softAP broadcastIP 230 | */ 231 | IPAddress WiFiAPClass::softAPBroadcastIP() { 232 | tcpip_adapter_ip_info_t ip; 233 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 234 | return IPAddress(); 235 | } 236 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip); 237 | return WiFiGenericClass::calculateBroadcast(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr)); 238 | } 239 | 240 | /** 241 | Get the softAP network ID. 242 | @return IPAddress softAP networkID 243 | */ 244 | IPAddress WiFiAPClass::softAPNetworkID() { 245 | tcpip_adapter_ip_info_t ip; 246 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 247 | return IPAddress(); 248 | } 249 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip); 250 | return WiFiGenericClass::calculateNetworkID(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr)); 251 | } 252 | 253 | /** 254 | Get the softAP subnet CIDR. 255 | @return uint8_t softAP subnetCIDR 256 | */ 257 | uint8_t WiFiAPClass::softAPSubnetCIDR() { 258 | tcpip_adapter_ip_info_t ip; 259 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 260 | return (uint8_t)0; 261 | } 262 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip); 263 | return WiFiGenericClass::calculateSubnetCIDR(IPAddress(ip.netmask.addr)); 264 | } 265 | 266 | /** 267 | Get the softAP interface MAC address. 268 | @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH 269 | @return pointer to uint8_t 270 | */ 271 | uint8_t* WiFiAPClass::softAPmacAddress(uint8_t* mac) { 272 | if (WiFiGenericClass::getMode() != WIFI_MODE_NULL) { 273 | esp_wifi_get_mac(WIFI_IF_AP, mac); 274 | } 275 | return mac; 276 | } 277 | 278 | /** 279 | Get the softAP interface MAC address. 280 | @return String mac 281 | */ 282 | String WiFiAPClass::softAPmacAddress(void) { 283 | uint8_t mac[6]; 284 | char macStr[18] = { 0 }; 285 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 286 | return String(); 287 | } 288 | esp_wifi_get_mac(WIFI_IF_AP, mac); 289 | 290 | sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 291 | return String(macStr); 292 | } 293 | 294 | /** 295 | Get the softAP interface Host name. 296 | @return char array hostname 297 | */ 298 | const char* WiFiAPClass::softAPgetHostname() { 299 | const char* hostname = NULL; 300 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 301 | return hostname; 302 | } 303 | if (tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_AP, &hostname)) { 304 | return hostname; 305 | } 306 | return hostname; 307 | } 308 | 309 | /** 310 | Set the softAP interface Host name. 311 | @param hostname pointer to const string 312 | @return true on success 313 | */ 314 | bool WiFiAPClass::softAPsetHostname(const char* hostname) { 315 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 316 | return false; 317 | } 318 | return tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_AP, hostname) == ESP_OK; 319 | } 320 | 321 | /** 322 | Enable IPv6 on the softAP interface. 323 | @return true on success 324 | */ 325 | bool WiFiAPClass::softAPenableIpV6() { 326 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 327 | return false; 328 | } 329 | return tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_AP) == ESP_OK; 330 | } 331 | 332 | /** 333 | Get the softAP interface IPv6 address. 334 | @return IPv6Address softAP IPv6 335 | */ 336 | IPv6Address WiFiAPClass::softAPIPv6() { 337 | static ip6_addr_t addr; 338 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 339 | return IPv6Address(); 340 | } 341 | if (tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_AP, &addr)) { 342 | return IPv6Address(); 343 | } 344 | return IPv6Address(addr.addr); 345 | } 346 | -------------------------------------------------------------------------------- /src/WiFiAP.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266WiFiAP.h - esp8266 Wifi support. 3 | Based on WiFi.h from Arduino WiFi shield library. 4 | Copyright (c) 2011-2014 Arduino. All right reserved. 5 | Modified by Ivan Grokhotkov, December 2014 6 | Reworked by Markus Sattler, December 2015 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with this library; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | #ifndef ESP32WIFIAP_H_ 24 | #define ESP32WIFIAP_H_ 25 | 26 | 27 | #include "WiFiType.h" 28 | #include "WiFiGeneric.h" 29 | 30 | 31 | class WiFiAPClass { 32 | 33 | // ---------------------------------------------------------------------------------------------- 34 | // ----------------------------------------- AP function ---------------------------------------- 35 | // ---------------------------------------------------------------------------------------------- 36 | 37 | public: 38 | 39 | bool softAP(const char* ssid, const char* passphrase = NULL, int channel = 1, int ssid_hidden = 0, 40 | int max_connection = 4); 41 | bool softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet); 42 | bool softAPdisconnect(bool wifioff = false); 43 | 44 | uint8_t softAPgetStationNum(); 45 | 46 | IPAddress softAPIP(); 47 | 48 | IPAddress softAPBroadcastIP(); 49 | IPAddress softAPNetworkID(); 50 | uint8_t softAPSubnetCIDR(); 51 | 52 | bool softAPenableIpV6(); 53 | IPv6Address softAPIPv6(); 54 | 55 | const char* softAPgetHostname(); 56 | bool softAPsetHostname(const char* hostname); 57 | 58 | uint8_t* softAPmacAddress(uint8_t* mac); 59 | String softAPmacAddress(void); 60 | 61 | protected: 62 | 63 | }; 64 | 65 | #endif /* ESP32WIFIAP_H_*/ 66 | -------------------------------------------------------------------------------- /src/WiFiClient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Client.h - Client class for Raspberry Pi 3 | Copyright (c) 2016 Hristo Gochkov All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "WiFiClient.h" 21 | #include "WiFi.h" 22 | #include "Seeed_atUnified.h" 23 | #include 24 | 25 | #define WIFI_CLIENT_MAX_WRITE_RETRY (10) 26 | #define WIFI_CLIENT_SELECT_TIMEOUT_US (1000000) 27 | #define WIFI_CLIENT_FLUSH_BUFFER_SIZE (1024) 28 | 29 | #undef connect 30 | #undef write 31 | #undef read 32 | 33 | class WiFiClientRxBuffer { 34 | private: 35 | size_t _size; 36 | uint8_t* _buffer; 37 | size_t _pos; 38 | size_t _fill; 39 | int _fd; 40 | bool _failed; 41 | 42 | size_t r_available() { 43 | if (_fd < 0) { 44 | return 0; 45 | } 46 | int count; 47 | int res = atu_ioctl_r(_fd, FIONREAD, &count); 48 | if (res < 0) { 49 | _failed = true; 50 | return 0; 51 | } 52 | return count; 53 | } 54 | 55 | size_t fillBuffer() { 56 | if (!_buffer) { 57 | _buffer = (uint8_t*)malloc(_size); 58 | if (!_buffer) { 59 | log_e("Not enough memory to allocate buffer"); 60 | _failed = true; 61 | return 0; 62 | } 63 | } 64 | if (_fill && _pos == _fill) { 65 | _fill = 0; 66 | _pos = 0; 67 | } 68 | if (!_buffer || _size <= _fill || !r_available()) { 69 | return 0; 70 | } 71 | int res = recv(_fd, _buffer + _fill, _size - _fill, MSG_DONTWAIT); 72 | if (res < 0) { 73 | if (errno != EWOULDBLOCK) { 74 | _failed = true; 75 | } 76 | return 0; 77 | } 78 | _fill += res; 79 | return res; 80 | } 81 | 82 | public: 83 | WiFiClientRxBuffer(int fd, size_t size = 1436) 84 | : _size(size) 85 | , _buffer(NULL) 86 | , _pos(0) 87 | , _fill(0) 88 | , _fd(fd) 89 | , _failed(false) { 90 | //_buffer = (uint8_t *)malloc(_size); 91 | } 92 | 93 | ~WiFiClientRxBuffer() { 94 | free(_buffer); 95 | } 96 | 97 | bool failed() { 98 | return _failed; 99 | } 100 | 101 | int read(uint8_t* dst, size_t len) { 102 | if (!dst || !len || (_pos == _fill && !fillBuffer())) { 103 | return -1; 104 | } 105 | size_t a = _fill - _pos; 106 | if (len <= a || ((len - a) <= (_size - _fill) && fillBuffer() >= (len - a))) { 107 | if (len == 1) { 108 | *dst = _buffer[_pos]; 109 | } else { 110 | memcpy(dst, _buffer + _pos, len); 111 | } 112 | _pos += len; 113 | return len; 114 | } 115 | size_t left = len; 116 | size_t toRead = a; 117 | uint8_t* buf = dst; 118 | memcpy(buf, _buffer + _pos, toRead); 119 | _pos += toRead; 120 | left -= toRead; 121 | buf += toRead; 122 | while (left) { 123 | if (!fillBuffer()) { 124 | return len - left; 125 | } 126 | a = _fill - _pos; 127 | toRead = (a > left) ? left : a; 128 | memcpy(buf, _buffer + _pos, toRead); 129 | _pos += toRead; 130 | left -= toRead; 131 | buf += toRead; 132 | } 133 | return len; 134 | } 135 | 136 | int peek() { 137 | if (_pos == _fill && !fillBuffer()) { 138 | return -1; 139 | } 140 | return _buffer[_pos]; 141 | } 142 | 143 | size_t available() { 144 | if (_fill - _pos) { 145 | return _fill - _pos; 146 | } 147 | return r_available(); 148 | } 149 | }; 150 | 151 | class WiFiClientSocketHandle { 152 | private: 153 | int sockfd; 154 | 155 | public: 156 | WiFiClientSocketHandle(int fd): sockfd(fd) { 157 | } 158 | 159 | ~WiFiClientSocketHandle() { 160 | closesocket(sockfd); 161 | } 162 | 163 | int fd() { 164 | return sockfd; 165 | } 166 | }; 167 | 168 | WiFiClient::WiFiClient(): _connected(false), next(NULL) { 169 | } 170 | 171 | WiFiClient::WiFiClient(int fd): _connected(true), next(NULL) { 172 | clientSocketHandle.reset(new WiFiClientSocketHandle(fd)); 173 | _rxBuffer.reset(new WiFiClientRxBuffer(fd)); 174 | } 175 | 176 | WiFiClient::~WiFiClient() { 177 | stop(); 178 | } 179 | 180 | WiFiClient& WiFiClient::operator=(const WiFiClient& other) { 181 | stop(); 182 | clientSocketHandle = other.clientSocketHandle; 183 | _rxBuffer = other._rxBuffer; 184 | _connected = other._connected; 185 | return *this; 186 | } 187 | 188 | void WiFiClient::stop() { 189 | clientSocketHandle = NULL; 190 | _rxBuffer = NULL; 191 | _connected = false; 192 | } 193 | 194 | int WiFiClient::connect(IPAddress ip, uint16_t port) { 195 | return connect(ip, port, -1); 196 | } 197 | int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) { 198 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 199 | if (sockfd < 0) { 200 | log_e("socket: %d", errno); 201 | return 0; 202 | } 203 | fcntlsocket(sockfd, F_SETFL, fcntlsocket(sockfd, F_GETFL, 0) | O_NONBLOCK); 204 | 205 | uint32_t ip_addr = ip; 206 | struct sockaddr_in serveraddr; 207 | bzero((char*) &serveraddr, sizeof(serveraddr)); 208 | serveraddr.sin_family = AF_INET; 209 | bcopy((const void*)(&ip_addr), (void*)&serveraddr.sin_addr.s_addr, 4); 210 | serveraddr.sin_port = htons(port); 211 | fd_set fdset; 212 | struct timeval tv; 213 | FD_ZERO(&fdset); 214 | FD_SET(sockfd, &fdset); 215 | tv.tv_sec = 0; 216 | tv.tv_usec = timeout * 1000; 217 | 218 | int res = atu_connect_r(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)); 219 | if (res < 0 && errno != EINPROGRESS) { 220 | log_e("connect on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno)); 221 | closesocket(sockfd); 222 | return 0; 223 | } 224 | 225 | res = select(sockfd + 1, nullptr, &fdset, nullptr, timeout < 0 ? nullptr : &tv); 226 | if (res < 0) { 227 | log_e("select on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno)); 228 | closesocket(sockfd); 229 | return 0; 230 | } else if (res == 0) { 231 | log_i("select returned due to timeout %d ms for fd %d", timeout, sockfd); 232 | closesocket(sockfd); 233 | return 0; 234 | } else { 235 | int sockerr; 236 | socklen_t len = (socklen_t)sizeof(int); 237 | res = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &sockerr, &len); 238 | 239 | if (res < 0) { 240 | log_e("getsockopt on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno)); 241 | closesocket(sockfd); 242 | return 0; 243 | } 244 | 245 | if (sockerr != 0) { 246 | log_e("socket error on fd %d, errno: %d, \"%s\"", sockfd, sockerr, strerror(sockerr)); 247 | closesocket(sockfd); 248 | return 0; 249 | } 250 | } 251 | 252 | fcntlsocket(sockfd, F_SETFL, fcntlsocket(sockfd, F_GETFL, 0) & (~O_NONBLOCK)); 253 | clientSocketHandle.reset(new WiFiClientSocketHandle(sockfd)); 254 | _rxBuffer.reset(new WiFiClientRxBuffer(sockfd)); 255 | _connected = true; 256 | return 1; 257 | } 258 | 259 | int WiFiClient::connect(const char* host, uint16_t port) { 260 | return connect(host, port, -1); 261 | } 262 | int WiFiClient::connect(const char* host, uint16_t port, int32_t timeout) { 263 | IPAddress srv((uint32_t)0); 264 | if (!WiFiGenericClass::hostByName(host, srv)) { 265 | return 0; 266 | } 267 | return connect(srv, port, timeout); 268 | } 269 | 270 | int WiFiClient::setSocketOption(int option, char* value, size_t len) { 271 | int res = setsockopt(fd(), SOL_SOCKET, option, value, len); 272 | if (res < 0) { 273 | log_e("%X : %d", option, errno); 274 | } 275 | return res; 276 | } 277 | 278 | int WiFiClient::setTimeout(uint32_t seconds) { 279 | Client::setTimeout(seconds * 1000); 280 | struct timeval tv; 281 | tv.tv_sec = seconds; 282 | tv.tv_usec = 0; 283 | if (setSocketOption(SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval)) < 0) { 284 | return -1; 285 | } 286 | return setSocketOption(SO_SNDTIMEO, (char*)&tv, sizeof(struct timeval)); 287 | } 288 | 289 | int WiFiClient::setOption(int option, int* value) { 290 | int res = setsockopt(fd(), IPPROTO_TCP, option, (char*) value, sizeof(int)); 291 | if (res < 0) { 292 | log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno)); 293 | } 294 | return res; 295 | } 296 | 297 | int WiFiClient::getOption(int option, int* value) { 298 | size_t size = sizeof(int); 299 | int res = getsockopt(fd(), IPPROTO_TCP, option, (char*)value, &size); 300 | if (res < 0) { 301 | log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno)); 302 | } 303 | return res; 304 | } 305 | 306 | int WiFiClient::setNoDelay(bool nodelay) { 307 | int flag = nodelay; 308 | return setOption(TCP_NODELAY, &flag); 309 | } 310 | 311 | bool WiFiClient::getNoDelay() { 312 | int flag = 0; 313 | getOption(TCP_NODELAY, &flag); 314 | return flag; 315 | } 316 | 317 | size_t WiFiClient::write(uint8_t data) { 318 | return write(&data, 1); 319 | } 320 | 321 | int WiFiClient::read() { 322 | uint8_t data = 0; 323 | int res = read(&data, 1); 324 | if (res < 0) { 325 | return res; 326 | } 327 | return data; 328 | } 329 | 330 | size_t WiFiClient::write(const uint8_t* buf, size_t size) { 331 | int res = 0; 332 | int retry = WIFI_CLIENT_MAX_WRITE_RETRY; 333 | int socketFileDescriptor = fd(); 334 | size_t totalBytesSent = 0; 335 | size_t bytesRemaining = size; 336 | 337 | if (!_connected || (socketFileDescriptor < 0)) { 338 | return 0; 339 | } 340 | 341 | while (retry) { 342 | //use select to make sure the socket is ready for writing 343 | fd_set set; 344 | struct timeval tv; 345 | FD_ZERO(&set); // empties the set 346 | FD_SET(socketFileDescriptor, &set); // adds FD to the set 347 | tv.tv_sec = 0; 348 | tv.tv_usec = WIFI_CLIENT_SELECT_TIMEOUT_US; 349 | retry--; 350 | 351 | if (select(socketFileDescriptor + 1, NULL, &set, NULL, &tv) < 0) { 352 | return 0; 353 | } 354 | 355 | if (FD_ISSET(socketFileDescriptor, &set)) { 356 | res = send(socketFileDescriptor, (void*) buf, bytesRemaining, MSG_DONTWAIT); 357 | if (res > 0) { 358 | totalBytesSent += res; 359 | if (totalBytesSent >= size) { 360 | //completed successfully 361 | retry = 0; 362 | } else { 363 | buf += res; 364 | bytesRemaining -= res; 365 | retry = WIFI_CLIENT_MAX_WRITE_RETRY; 366 | } 367 | } else if (res < 0) { 368 | log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno)); 369 | if (errno != EAGAIN) { 370 | //if resource was busy, can try again, otherwise give up 371 | stop(); 372 | res = 0; 373 | retry = 0; 374 | } 375 | } else { 376 | // Try again 377 | } 378 | } 379 | } 380 | return totalBytesSent; 381 | } 382 | 383 | size_t WiFiClient::write_P(PGM_P buf, size_t size) { 384 | return write(buf, size); 385 | } 386 | 387 | size_t WiFiClient::write(Stream& stream) { 388 | uint8_t* buf = (uint8_t*)malloc(1360); 389 | if (!buf) { 390 | return 0; 391 | } 392 | size_t toRead = 0, toWrite = 0, written = 0; 393 | size_t available = stream.available(); 394 | while (available) { 395 | toRead = (available > 1360) ? 1360 : available; 396 | toWrite = stream.readBytes(buf, toRead); 397 | written += write(buf, toWrite); 398 | available = stream.available(); 399 | } 400 | free(buf); 401 | return written; 402 | } 403 | 404 | int WiFiClient::read(uint8_t* buf, size_t size) { 405 | int res = -1; 406 | 407 | if (!_rxBuffer) { 408 | return res; 409 | } 410 | res = _rxBuffer->read(buf, size); 411 | if (_rxBuffer->failed()) { 412 | log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno)); 413 | stop(); 414 | } 415 | return res; 416 | } 417 | 418 | int WiFiClient::peek() { 419 | if (!_rxBuffer) { 420 | return -1; 421 | } 422 | 423 | int res = _rxBuffer->peek(); 424 | if (_rxBuffer->failed()) { 425 | log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno)); 426 | stop(); 427 | } 428 | return res; 429 | } 430 | 431 | int WiFiClient::available() { 432 | if (!_rxBuffer) { 433 | return 0; 434 | } 435 | int res = _rxBuffer->available(); 436 | if (_rxBuffer->failed()) { 437 | log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno)); 438 | stop(); 439 | } 440 | return res; 441 | } 442 | 443 | // Though flushing means to send all pending data, 444 | // seems that in Arduino it also means to clear RX 445 | void WiFiClient::flush() { 446 | int res; 447 | size_t a = available(), toRead = 0; 448 | if (!a) { 449 | return;//nothing to flush 450 | } 451 | uint8_t* buf = (uint8_t*)malloc(WIFI_CLIENT_FLUSH_BUFFER_SIZE); 452 | if (!buf) { 453 | return;//memory error 454 | } 455 | while (a) { 456 | toRead = (a > WIFI_CLIENT_FLUSH_BUFFER_SIZE) ? WIFI_CLIENT_FLUSH_BUFFER_SIZE : a; 457 | res = recv(fd(), buf, toRead, MSG_DONTWAIT); 458 | if (res < 0) { 459 | log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno)); 460 | stop(); 461 | break; 462 | } 463 | a -= res; 464 | } 465 | free(buf); 466 | } 467 | 468 | uint8_t WiFiClient::connected() { 469 | if (_connected) { 470 | uint8_t dummy; 471 | int res = recv(fd(), &dummy, 0, MSG_DONTWAIT); 472 | // avoid unused var warning by gcc 473 | (void)res; 474 | switch (errno) { 475 | case EWOULDBLOCK: 476 | case ENOENT: //caused by vfs 477 | _connected = true; 478 | break; 479 | case ENOTCONN: 480 | case EPIPE: 481 | case ECONNRESET: 482 | case ECONNREFUSED: 483 | case ECONNABORTED: 484 | _connected = false; 485 | log_d("Disconnected: RES: %d, ERR: %d", res, errno); 486 | break; 487 | default: 488 | log_i("Unexpected: RES: %d, ERR: %d", res, errno); 489 | _connected = true; 490 | break; 491 | } 492 | } 493 | return _connected; 494 | } 495 | 496 | IPAddress WiFiClient::remoteIP(int fd) const { 497 | struct sockaddr_storage addr; 498 | socklen_t len = sizeof addr; 499 | getpeername(fd, (struct sockaddr*)&addr, &len); 500 | struct sockaddr_in* s = (struct sockaddr_in*)&addr; 501 | return IPAddress((uint32_t)(s->sin_addr.s_addr)); 502 | } 503 | 504 | uint16_t WiFiClient::remotePort(int fd) const { 505 | struct sockaddr_storage addr; 506 | socklen_t len = sizeof addr; 507 | getpeername(fd, (struct sockaddr*)&addr, &len); 508 | struct sockaddr_in* s = (struct sockaddr_in*)&addr; 509 | return ntohs(s->sin_port); 510 | } 511 | 512 | IPAddress WiFiClient::remoteIP() const { 513 | return remoteIP(fd()); 514 | } 515 | 516 | uint16_t WiFiClient::remotePort() const { 517 | return remotePort(fd()); 518 | } 519 | 520 | IPAddress WiFiClient::localIP(int fd) const { 521 | struct sockaddr_storage addr; 522 | socklen_t len = sizeof addr; 523 | getsockname(fd, (struct sockaddr*)&addr, &len); 524 | struct sockaddr_in* s = (struct sockaddr_in*)&addr; 525 | return IPAddress((uint32_t)(s->sin_addr.s_addr)); 526 | } 527 | 528 | uint16_t WiFiClient::localPort(int fd) const { 529 | struct sockaddr_storage addr; 530 | socklen_t len = sizeof addr; 531 | getsockname(fd, (struct sockaddr*)&addr, &len); 532 | struct sockaddr_in* s = (struct sockaddr_in*)&addr; 533 | return ntohs(s->sin_port); 534 | } 535 | 536 | IPAddress WiFiClient::localIP() const { 537 | return localIP(fd()); 538 | } 539 | 540 | uint16_t WiFiClient::localPort() const { 541 | return localPort(fd()); 542 | } 543 | 544 | bool WiFiClient::operator==(const WiFiClient& rhs) { 545 | return clientSocketHandle == rhs.clientSocketHandle && remotePort() == rhs.remotePort() && remoteIP() == rhs.remoteIP(); 546 | } 547 | 548 | int WiFiClient::fd() const { 549 | if (clientSocketHandle == NULL) { 550 | return -1; 551 | } else { 552 | return clientSocketHandle->fd(); 553 | } 554 | } 555 | 556 | -------------------------------------------------------------------------------- /src/WiFiClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | Client.h - Base class that provides Client 3 | Copyright (c) 2011 Adrian McEwen. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _WIFICLIENT_H_ 21 | #define _WIFICLIENT_H_ 22 | 23 | 24 | #include "Arduino.h" 25 | #include "Client.h" 26 | #undef max 27 | #undef min 28 | #include 29 | 30 | class WiFiClientSocketHandle; 31 | class WiFiClientRxBuffer; 32 | 33 | class ESPLwIPClient : public Client { 34 | public: 35 | virtual int connect(IPAddress ip, uint16_t port, int32_t timeout) = 0; 36 | virtual int connect(const char* host, uint16_t port, int32_t timeout) = 0; 37 | virtual int setTimeout(uint32_t seconds) = 0; 38 | }; 39 | 40 | class WiFiClient : public ESPLwIPClient { 41 | protected: 42 | std::shared_ptr clientSocketHandle; 43 | std::shared_ptr _rxBuffer; 44 | bool _connected; 45 | 46 | public: 47 | WiFiClient* next; 48 | WiFiClient(); 49 | WiFiClient(int fd); 50 | ~WiFiClient(); 51 | int connect(IPAddress ip, uint16_t port); 52 | int connect(IPAddress ip, uint16_t port, int32_t timeout); 53 | int connect(const char* host, uint16_t port); 54 | int connect(const char* host, uint16_t port, int32_t timeout); 55 | size_t write(uint8_t data); 56 | size_t write(const uint8_t* buf, size_t size); 57 | size_t write_P(PGM_P buf, size_t size); 58 | size_t write(Stream& stream); 59 | int available(); 60 | int read(); 61 | int read(uint8_t* buf, size_t size); 62 | int peek(); 63 | void flush(); 64 | void stop(); 65 | uint8_t connected(); 66 | 67 | operator bool() { 68 | return connected(); 69 | } 70 | WiFiClient& operator=(const WiFiClient& other); 71 | bool operator==(const bool value) { 72 | return bool() == value; 73 | } 74 | bool operator!=(const bool value) { 75 | return bool() != value; 76 | } 77 | bool operator==(const WiFiClient&); 78 | bool operator!=(const WiFiClient& rhs) { 79 | return !this->operator==(rhs); 80 | }; 81 | 82 | int fd() const; 83 | 84 | int setSocketOption(int option, char* value, size_t len); 85 | int setOption(int option, int* value); 86 | int getOption(int option, int* value); 87 | int setTimeout(uint32_t seconds); 88 | int setNoDelay(bool nodelay); 89 | bool getNoDelay(); 90 | 91 | IPAddress remoteIP() const; 92 | IPAddress remoteIP(int fd) const; 93 | uint16_t remotePort() const; 94 | uint16_t remotePort(int fd) const; 95 | IPAddress localIP() const; 96 | IPAddress localIP(int fd) const; 97 | uint16_t localPort() const; 98 | uint16_t localPort(int fd) const; 99 | 100 | //friend class WiFiServer; 101 | using Print::write; 102 | }; 103 | 104 | #endif /* _WIFICLIENT_H_ */ 105 | -------------------------------------------------------------------------------- /src/WiFiGeneric.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266WiFiGeneric.h - esp8266 Wifi support. 3 | Based on WiFi.h from Ardiono WiFi shield library. 4 | Copyright (c) 2011-2014 Arduino. All right reserved. 5 | Modified by Ivan Grokhotkov, December 2014 6 | Reworked by Markus Sattler, December 2015 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with this library; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | #ifndef ESP32WIFIGENERIC_H_ 24 | #define ESP32WIFIGENERIC_H_ 25 | 26 | #include "Seeed_atUnified.h" 27 | #undef max 28 | #undef min 29 | #include 30 | #include "WiFiType.h" 31 | 32 | typedef void (*WiFiEventCb)(system_event_id_t event); 33 | typedef std::function WiFiEventFuncCb; 34 | typedef void (*WiFiEventSysCb)(system_event_t* event); 35 | 36 | typedef size_t wifi_event_id_t; 37 | 38 | typedef enum { 39 | WIFI_POWER_19_5dBm = 78,// 19.5dBm 40 | WIFI_POWER_19dBm = 76,// 19dBm 41 | WIFI_POWER_18_5dBm = 74,// 18.5dBm 42 | WIFI_POWER_17dBm = 68,// 17dBm 43 | WIFI_POWER_15dBm = 60,// 15dBm 44 | WIFI_POWER_13dBm = 52,// 13dBm 45 | WIFI_POWER_11dBm = 44,// 11dBm 46 | WIFI_POWER_8_5dBm = 34,// 8.5dBm 47 | WIFI_POWER_7dBm = 28,// 7dBm 48 | WIFI_POWER_5dBm = 20,// 5dBm 49 | WIFI_POWER_2dBm = 8,// 2dBm 50 | WIFI_POWER_MINUS_1dBm = -4// -1dBm 51 | } wifi_power_t; 52 | 53 | static const int AP_STARTED_BIT = BIT0; 54 | static const int AP_HAS_IP6_BIT = BIT1; 55 | static const int AP_HAS_CLIENT_BIT = BIT2; 56 | static const int STA_STARTED_BIT = BIT3; 57 | static const int STA_CONNECTED_BIT = BIT4; 58 | static const int STA_HAS_IP_BIT = BIT5; 59 | static const int STA_HAS_IP6_BIT = BIT6; 60 | static const int ETH_STARTED_BIT = BIT7; 61 | static const int ETH_CONNECTED_BIT = BIT8; 62 | static const int ETH_HAS_IP_BIT = BIT9; 63 | static const int ETH_HAS_IP6_BIT = BIT10; 64 | static const int WIFI_SCANNING_BIT = BIT11; 65 | static const int WIFI_SCAN_DONE_BIT = BIT12; 66 | static const int WIFI_DNS_IDLE_BIT = BIT13; 67 | static const int WIFI_DNS_DONE_BIT = BIT14; 68 | 69 | class WiFiGenericClass { 70 | public: 71 | WiFiGenericClass(); 72 | 73 | wifi_event_id_t onEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); 74 | wifi_event_id_t onEvent(WiFiEventFuncCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); 75 | wifi_event_id_t onEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); 76 | void removeEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); 77 | void removeEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); 78 | void removeEvent(wifi_event_id_t id); 79 | 80 | static int getStatusBits(); 81 | static int waitStatusBits(int bits, uint32_t timeout_ms); 82 | 83 | int32_t channel(void); 84 | 85 | void persistent(bool persistent); 86 | void enableLongRange(bool enable); 87 | 88 | static bool mode(wifi_mode_t); 89 | static wifi_mode_t getMode(); 90 | 91 | static bool country(wifi_country_t); 92 | static wifi_country_t getCountry(); 93 | 94 | bool enableSTA(bool enable); 95 | bool enableAP(bool enable); 96 | 97 | bool setSleep(bool enable); 98 | bool getSleep(); 99 | 100 | bool setTxPower(wifi_power_t power); 101 | wifi_power_t getTxPower(); 102 | 103 | static esp_err_t _eventCallback(void* arg, system_event_t* event); 104 | 105 | protected: 106 | static bool _persistent; 107 | static bool _long_range; 108 | static wifi_mode_t _forceSleepLastMode; 109 | 110 | static int setStatusBits(int bits); 111 | static int clearStatusBits(int bits); 112 | 113 | public: 114 | static int hostByName(const char* aHostname, IPAddress& aResult); 115 | 116 | static IPAddress calculateNetworkID(IPAddress ip, IPAddress subnet); 117 | static IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet); 118 | static uint8_t calculateSubnetCIDR(IPAddress subnetMask); 119 | 120 | protected: 121 | friend class WiFiSTAClass; 122 | friend class WiFiScanClass; 123 | friend class WiFiAPClass; 124 | }; 125 | 126 | #endif /* ESP32WIFIGENERIC_H_ */ 127 | -------------------------------------------------------------------------------- /src/WiFiMulti.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @file WiFiMulti.cpp 4 | @date 16.05.2015 5 | @author Markus Sattler 6 | 7 | Copyright (c) 2015 Markus Sattler. All rights reserved. 8 | This file is part of the esp8266 core for Arduino environment. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | 24 | */ 25 | 26 | #include "WiFiMulti.h" 27 | #include 28 | #include 29 | #include "Seeed_atUnified.h" 30 | 31 | WiFiMulti::WiFiMulti() { 32 | } 33 | 34 | WiFiMulti::~WiFiMulti() { 35 | for (uint32_t i = 0; i < APlist.size(); i++) { 36 | WifiAPlist_t entry = APlist[i]; 37 | if (entry.ssid) { 38 | free(entry.ssid); 39 | } 40 | if (entry.passphrase) { 41 | free(entry.passphrase); 42 | } 43 | } 44 | APlist.clear(); 45 | } 46 | 47 | bool WiFiMulti::addAP(const char* ssid, const char* passphrase) { 48 | WifiAPlist_t newAP; 49 | 50 | if (!ssid || *ssid == 0x00 || strlen(ssid) > 31) { 51 | // fail SSID too long or missing! 52 | log_e("[WIFI][APlistAdd] no ssid or ssid too long"); 53 | return false; 54 | } 55 | 56 | if (passphrase && strlen(passphrase) > 63) { 57 | // fail passphrase too long! 58 | log_e("[WIFI][APlistAdd] passphrase too long"); 59 | return false; 60 | } 61 | 62 | newAP.ssid = strdup(ssid); 63 | 64 | if (!newAP.ssid) { 65 | log_e("[WIFI][APlistAdd] fail newAP.ssid == 0"); 66 | return false; 67 | } 68 | 69 | if (passphrase && *passphrase != 0x00) { 70 | newAP.passphrase = strdup(passphrase); 71 | if (!newAP.passphrase) { 72 | log_e("[WIFI][APlistAdd] fail newAP.passphrase == 0"); 73 | free(newAP.ssid); 74 | return false; 75 | } 76 | } else { 77 | newAP.passphrase = NULL; 78 | } 79 | 80 | APlist.push_back(newAP); 81 | log_i("[WIFI][APlistAdd] add SSID: %s", newAP.ssid); 82 | return true; 83 | } 84 | 85 | uint8_t WiFiMulti::run(uint32_t connectTimeout) { 86 | int8_t scanResult; 87 | uint8_t status = WiFi.status(); 88 | if (status == WL_CONNECTED) { 89 | for (uint32_t x = 0; x < APlist.size(); x++) { 90 | if (WiFi.SSID() == APlist[x].ssid) { 91 | return status; 92 | } 93 | } 94 | WiFi.disconnect(false, false); 95 | delay(10); 96 | status = WiFi.status(); 97 | } 98 | 99 | scanResult = WiFi.scanNetworks(); 100 | if (scanResult == WIFI_SCAN_RUNNING) { 101 | // scan is running 102 | return WL_NO_SSID_AVAIL; 103 | } else if (scanResult >= 0) { 104 | // scan done analyze 105 | WifiAPlist_t bestNetwork { NULL, NULL }; 106 | int bestNetworkDb = INT_MIN; 107 | uint8_t bestBSSID[6]; 108 | int32_t bestChannel = 0; 109 | 110 | log_i("[WIFI] scan done"); 111 | 112 | if (scanResult == 0) { 113 | log_e("[WIFI] no networks found"); 114 | } else { 115 | log_i("[WIFI] %d networks found", scanResult); 116 | for (int8_t i = 0; i < scanResult; ++i) { 117 | 118 | String ssid_scan; 119 | int32_t rssi_scan; 120 | uint8_t sec_scan; 121 | uint8_t* BSSID_scan; 122 | int32_t chan_scan; 123 | 124 | WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan); 125 | 126 | bool known = false; 127 | for (uint32_t x = 0; x < APlist.size(); x++) { 128 | WifiAPlist_t entry = APlist[x]; 129 | 130 | if (ssid_scan == entry.ssid) { // SSID match 131 | known = true; 132 | if (rssi_scan > bestNetworkDb) { // best network 133 | if (sec_scan == WIFI_AUTH_OPEN || entry.passphrase) { // check for passphrase if not open wlan 134 | bestNetworkDb = rssi_scan; 135 | bestChannel = chan_scan; 136 | memcpy((void*) &bestNetwork, (void*) &entry, sizeof(bestNetwork)); 137 | memcpy((void*) &bestBSSID, (void*) BSSID_scan, sizeof(bestBSSID)); 138 | } 139 | } 140 | break; 141 | } 142 | } 143 | 144 | if (known) { 145 | log_d(" ---> %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c", i, chan_scan, BSSID_scan[0], BSSID_scan[1], 146 | BSSID_scan[2], BSSID_scan[3], BSSID_scan[4], BSSID_scan[5], ssid_scan.c_str(), rssi_scan, 147 | (sec_scan == WIFI_AUTH_OPEN) ? ' ' : '*'); 148 | } else { 149 | log_d(" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c", i, chan_scan, BSSID_scan[0], BSSID_scan[1], 150 | BSSID_scan[2], BSSID_scan[3], BSSID_scan[4], BSSID_scan[5], ssid_scan.c_str(), rssi_scan, 151 | (sec_scan == WIFI_AUTH_OPEN) ? ' ' : '*'); 152 | } 153 | } 154 | } 155 | 156 | // clean up ram 157 | WiFi.scanDelete(); 158 | 159 | if (bestNetwork.ssid) { 160 | log_i("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channal: %d (%d)", bestBSSID[0], bestBSSID[1], 161 | bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); 162 | 163 | WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); 164 | status = WiFi.status(); 165 | 166 | auto startTime = millis(); 167 | // wait for connection, fail, or timeout 168 | while (status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED 169 | && (millis() - startTime) <= connectTimeout) { 170 | delay(10); 171 | status = WiFi.status(); 172 | } 173 | 174 | switch (status) { 175 | case WL_CONNECTED: 176 | log_i("[WIFI] Connecting done."); 177 | log_d("[WIFI] SSID: %s", WiFi.SSID().c_str()); 178 | log_d("[WIFI] IP: %s", WiFi.localIP().toString().c_str()); 179 | log_d("[WIFI] MAC: %s", WiFi.BSSIDstr().c_str()); 180 | log_d("[WIFI] Channel: %d", WiFi.channel()); 181 | break; 182 | case WL_NO_SSID_AVAIL: 183 | log_e("[WIFI] Connecting Failed AP not found."); 184 | break; 185 | case WL_CONNECT_FAILED: 186 | log_e("[WIFI] Connecting Failed."); 187 | break; 188 | default: 189 | log_e("[WIFI] Connecting Failed (%d).", status); 190 | break; 191 | } 192 | } else { 193 | log_e("[WIFI] no matching wifi found!"); 194 | } 195 | } else { 196 | // start scan 197 | log_d("[WIFI] delete old wifi config..."); 198 | WiFi.disconnect(); 199 | 200 | log_d("[WIFI] start scan"); 201 | // scan wifi async mode 202 | WiFi.scanNetworks(true); 203 | } 204 | 205 | return status; 206 | } 207 | -------------------------------------------------------------------------------- /src/WiFiMulti.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @file ESP8266WiFiMulti.h 4 | @date 16.05.2015 5 | @author Markus Sattler 6 | 7 | Copyright (c) 2015 Markus Sattler. All rights reserved. 8 | This file is part of the esp8266 core for Arduino environment. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | 24 | */ 25 | 26 | #ifndef WIFICLIENTMULTI_H_ 27 | #define WIFICLIENTMULTI_H_ 28 | 29 | #include "WiFi.h" 30 | #include 31 | 32 | typedef struct { 33 | char* ssid; 34 | char* passphrase; 35 | } WifiAPlist_t; 36 | 37 | class WiFiMulti { 38 | public: 39 | WiFiMulti(); 40 | ~WiFiMulti(); 41 | 42 | bool addAP(const char* ssid, const char* passphrase = NULL); 43 | 44 | uint8_t run(uint32_t connectTimeout = 5000); 45 | 46 | private: 47 | std::vector APlist; 48 | }; 49 | 50 | #endif /* WIFICLIENTMULTI_H_ */ 51 | -------------------------------------------------------------------------------- /src/WiFiSTA.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiSTA.cpp - WiFi library for esp32 3 | 4 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 5 | This file is part of the esp8266 core for Arduino environment. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | 21 | Reworked on 28 Dec 2015 by Markus Sattler 22 | 23 | */ 24 | 25 | #include "WiFi.h" 26 | #include "WiFiGeneric.h" 27 | #include "WiFiSTA.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "Seeed_atUnified.h" 37 | 38 | // ----------------------------------------------------------------------------------------------------------------------- 39 | // ---------------------------------------------------- Private functions ------------------------------------------------ 40 | // ----------------------------------------------------------------------------------------------------------------------- 41 | 42 | 43 | /** 44 | compare two STA configurations 45 | @param lhs station_config 46 | @param rhs station_config 47 | @return equal 48 | */ 49 | static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs) { 50 | if (strcmp((char*)lhs.sta.ssid, (char*)rhs.sta.ssid) 51 | // || memcmp((char*)lhs.sta.bssid, (char*)rhs.sta.bssid, sizeof rhs.sta.bssid) 52 | ) { 53 | return false; 54 | } 55 | return true; 56 | } 57 | 58 | // ----------------------------------------------------------------------------------------------------------------------- 59 | // ---------------------------------------------------- STA function ----------------------------------------------------- 60 | // ----------------------------------------------------------------------------------------------------------------------- 61 | 62 | bool WiFiSTAClass::_autoReconnect = true; 63 | bool WiFiSTAClass::_useStaticIp = false; 64 | 65 | static wl_status_t _sta_status = WL_NO_SHIELD; 66 | static EventGroupHandle_t _sta_status_group = NULL; 67 | 68 | void WiFiSTAClass::_setStatus(wl_status_t status) { 69 | if (!_sta_status_group) { 70 | _sta_status_group = xEventGroupCreate(); 71 | if (!_sta_status_group) { 72 | log_e("STA Status Group Create Failed!"); 73 | _sta_status = status; 74 | return; 75 | } 76 | } 77 | xEventGroupClearBits(_sta_status_group, 0x00FFFFFF); 78 | xEventGroupSetBits(_sta_status_group, status); 79 | } 80 | 81 | /** 82 | Return Connection status. 83 | @return one of the value defined in wl_status_t 84 | 85 | */ 86 | wl_status_t WiFiSTAClass::status() { 87 | if (!_sta_status_group) { 88 | return _sta_status; 89 | } 90 | return (wl_status_t)xEventGroupClearBits(_sta_status_group, 0); 91 | } 92 | 93 | /** 94 | Start Wifi connection 95 | if passphrase is set the most secure supported mode will be automatically selected 96 | @param ssid const char* Pointer to the SSID string. 97 | @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal). 98 | @param bssid uint8_t[6] Optional. BSSID / MAC of AP 99 | @param channel Optional. Channel of AP 100 | @param connect Optional. call connect 101 | @return 102 | */ 103 | wl_status_t WiFiSTAClass::begin(const char* ssid, const char* passphrase, int32_t channel, const uint8_t* bssid, 104 | bool connect) { 105 | 106 | if (!WiFi.enableSTA(true)) { 107 | log_e("STA enable failed!"); 108 | return WL_CONNECT_FAILED; 109 | } 110 | 111 | if (!ssid || *ssid == 0x00 || strlen(ssid) > 31) { 112 | log_e("SSID too long or missing!"); 113 | return WL_CONNECT_FAILED; 114 | } 115 | 116 | if (passphrase && strlen(passphrase) > 64) { 117 | log_e("passphrase too long!"); 118 | return WL_CONNECT_FAILED; 119 | } 120 | 121 | wifi_config_t conf; 122 | memset(&conf, 0, sizeof(wifi_config_t)); 123 | strcpy(reinterpret_cast(conf.sta.ssid), ssid); 124 | 125 | if (passphrase) { 126 | if (strlen(passphrase) == 64) { // it's not a passphrase, is the PSK 127 | memcpy(reinterpret_cast(conf.sta.password), passphrase, 64); 128 | } else { 129 | strcpy(reinterpret_cast(conf.sta.password), passphrase); 130 | } 131 | } 132 | 133 | if (bssid) { 134 | conf.sta.bssid_set = 1; 135 | memcpy((void*) &conf.sta.bssid[0], (void*) bssid, 6); 136 | } 137 | 138 | if (channel > 0 && channel <= 13) { 139 | conf.sta.channel = channel; 140 | } 141 | 142 | wifi_config_t current_conf; 143 | esp_wifi_get_config(WIFI_IF_STA, ¤t_conf); 144 | if (!sta_config_equal(current_conf, conf)) { 145 | if (esp_wifi_disconnect()) { 146 | log_e("disconnect failed!"); 147 | return WL_CONNECT_FAILED; 148 | } 149 | 150 | esp_wifi_set_config(WIFI_IF_STA, &conf); 151 | } else if (status() == WL_CONNECTED) { 152 | return WL_CONNECTED; 153 | } else { 154 | esp_wifi_set_config(WIFI_IF_STA, &conf); 155 | } 156 | 157 | if (!_useStaticIp) { 158 | if (tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA) == ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED) { 159 | log_e("dhcp client start failed!"); 160 | return WL_CONNECT_FAILED; 161 | } 162 | } else { 163 | tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); 164 | } 165 | 166 | if (connect && esp_wifi_connect()) { 167 | log_e("connect failed!"); 168 | return WL_CONNECT_FAILED; 169 | } 170 | 171 | return status(); 172 | } 173 | 174 | wl_status_t WiFiSTAClass::begin(char* ssid, char* passphrase, int32_t channel, const uint8_t* bssid, bool connect) { 175 | return begin((const char*) ssid, (const char*) passphrase, channel, bssid, connect); 176 | } 177 | 178 | /** 179 | Use to connect to SDK config. 180 | @return wl_status_t 181 | */ 182 | wl_status_t WiFiSTAClass::begin() { 183 | 184 | if (!WiFi.enableSTA(true)) { 185 | log_e("STA enable failed!"); 186 | return WL_CONNECT_FAILED; 187 | } 188 | 189 | wifi_config_t current_conf; 190 | if (esp_wifi_get_config(WIFI_IF_STA, ¤t_conf) != ESP_OK 191 | || esp_wifi_set_config(WIFI_IF_STA, ¤t_conf) != ESP_OK) { 192 | log_e("config failed"); 193 | return WL_CONNECT_FAILED; 194 | } 195 | 196 | if (!_useStaticIp) { 197 | if (tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA) == ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED) { 198 | log_e("dhcp client start failed!"); 199 | return WL_CONNECT_FAILED; 200 | } 201 | } else { 202 | tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); 203 | } 204 | 205 | if (status() != WL_CONNECTED && esp_wifi_connect()) { 206 | log_e("connect failed!"); 207 | return WL_CONNECT_FAILED; 208 | } 209 | 210 | return status(); 211 | } 212 | 213 | /** 214 | will force a disconnect an then start reconnecting to AP 215 | @return ok 216 | */ 217 | bool WiFiSTAClass::reconnect() { 218 | if (WiFi.getMode() & WIFI_MODE_STA) { 219 | if (esp_wifi_disconnect() == ESP_OK) { 220 | return esp_wifi_connect() == ESP_OK; 221 | } 222 | } 223 | return false; 224 | } 225 | 226 | /** 227 | Disconnect from the network 228 | @param wifioff 229 | @return one value of wl_status_t enum 230 | */ 231 | bool WiFiSTAClass::disconnect(bool wifioff, bool eraseap) { 232 | wifi_config_t conf; 233 | 234 | if (WiFi.getMode() & WIFI_MODE_STA) { 235 | if (eraseap) { 236 | memset(&conf, 0, sizeof(wifi_config_t)); 237 | if (esp_wifi_set_config(WIFI_IF_STA, &conf)) { 238 | log_e("clear config failed!"); 239 | } 240 | } 241 | if (esp_wifi_disconnect()) { 242 | log_e("disconnect failed!"); 243 | return false; 244 | } 245 | if (wifioff) { 246 | return WiFi.enableSTA(false); 247 | } 248 | return true; 249 | } 250 | 251 | return false; 252 | } 253 | 254 | /** 255 | Change IP configuration settings disabling the dhcp client 256 | @param local_ip Static ip configuration 257 | @param gateway Static gateway configuration 258 | @param subnet Static Subnet mask 259 | @param dns1 Static DNS server 1 260 | @param dns2 Static DNS server 2 261 | */ 262 | bool WiFiSTAClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) { 263 | esp_err_t err = ESP_OK; 264 | 265 | if (!WiFi.enableSTA(true)) { 266 | return false; 267 | } 268 | 269 | tcpip_adapter_ip_info_t info; 270 | 271 | if (local_ip != (uint32_t)0x00000000) { 272 | info.ip.addr = static_cast(local_ip); 273 | info.gw.addr = static_cast(gateway); 274 | info.netmask.addr = static_cast(subnet); 275 | } else { 276 | info.ip.addr = 0; 277 | info.gw.addr = 0; 278 | info.netmask.addr = 0; 279 | } 280 | 281 | err = tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); 282 | if (err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) { 283 | log_e("DHCP could not be stopped! Error: %d", err); 284 | return false; 285 | } 286 | 287 | err = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &info); 288 | if (err != ERR_OK) { 289 | log_e("STA IP could not be configured! Error: %d", err); 290 | return false; 291 | } 292 | 293 | if (info.ip.addr) { 294 | _useStaticIp = true; 295 | } else { 296 | err = tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); 297 | if (err == ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED) { 298 | log_e("dhcp client start failed!"); 299 | return false; 300 | } 301 | _useStaticIp = false; 302 | } 303 | 304 | ip_addr_t d; 305 | d.type = IPADDR_TYPE_V4; 306 | 307 | if (dns1 != (uint32_t)0x00000000) { 308 | // Set DNS1-Server 309 | d.u_addr.ip4.addr = static_cast(dns1); 310 | dns_setserver(0, &d); 311 | } 312 | 313 | if (dns2 != (uint32_t)0x00000000) { 314 | // Set DNS2-Server 315 | d.u_addr.ip4.addr = static_cast(dns2); 316 | dns_setserver(1, &d); 317 | } 318 | 319 | return true; 320 | } 321 | 322 | /** 323 | is STA interface connected? 324 | @return true if STA is connected to an AD 325 | */ 326 | bool WiFiSTAClass::isConnected() { 327 | return (status() == WL_CONNECTED); 328 | } 329 | 330 | 331 | /** 332 | Setting the ESP32 station to connect to the AP (which is recorded) 333 | automatically or not when powered on. Enable auto-connect by default. 334 | @param autoConnect bool 335 | @return if saved 336 | */ 337 | bool WiFiSTAClass::setAutoConnect(bool autoConnect) { 338 | /* bool ret; 339 | ret = esp_wifi_set_auto_connect(autoConnect); 340 | return ret;*/ 341 | return false;//now deprecated 342 | } 343 | 344 | /** 345 | Checks if ESP32 station mode will connect to AP 346 | automatically or not when it is powered on. 347 | @return auto connect 348 | */ 349 | bool WiFiSTAClass::getAutoConnect() { 350 | /* bool autoConnect; 351 | esp_wifi_get_auto_connect(&autoConnect); 352 | return autoConnect;*/ 353 | return false;//now deprecated 354 | } 355 | 356 | bool WiFiSTAClass::setAutoReconnect(bool autoReconnect) { 357 | _autoReconnect = autoReconnect; 358 | return true; 359 | } 360 | 361 | bool WiFiSTAClass::getAutoReconnect() { 362 | return _autoReconnect; 363 | } 364 | 365 | /** 366 | Wait for WiFi connection to reach a result 367 | returns the status reached or disconnect if STA is off 368 | @return wl_status_t 369 | */ 370 | uint8_t WiFiSTAClass::waitForConnectResult() { 371 | //1 and 3 have STA enabled 372 | if ((WiFiGenericClass::getMode() & WIFI_MODE_STA) == 0) { 373 | return WL_DISCONNECTED; 374 | } 375 | int i = 0; 376 | while ((!status() || status() >= WL_DISCONNECTED) && i++ < 100) { 377 | delay(100); 378 | } 379 | return status(); 380 | } 381 | 382 | /** 383 | Get the station interface IP address. 384 | @return IPAddress station IP 385 | */ 386 | IPAddress WiFiSTAClass::localIP() { 387 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 388 | return IPAddress(); 389 | } 390 | tcpip_adapter_ip_info_t ip; 391 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); 392 | return IPAddress(ip.ip.addr); 393 | } 394 | 395 | 396 | /** 397 | Get the station interface MAC address. 398 | @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH 399 | @return pointer to uint8_t 400 | */ 401 | uint8_t* WiFiSTAClass::macAddress(uint8_t* mac) { 402 | if (WiFiGenericClass::getMode() != WIFI_MODE_NULL) { 403 | esp_wifi_get_mac(WIFI_IF_STA, mac); 404 | } else { 405 | esp_read_mac(mac, ESP_MAC_WIFI_STA); 406 | } 407 | return mac; 408 | } 409 | 410 | /** 411 | Get the station interface MAC address. 412 | @return String mac 413 | */ 414 | String WiFiSTAClass::macAddress(void) { 415 | uint8_t mac[6]; 416 | char macStr[18] = { 0 }; 417 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 418 | esp_read_mac(mac, ESP_MAC_WIFI_STA); 419 | } else { 420 | esp_wifi_get_mac(WIFI_IF_STA, mac); 421 | } 422 | sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 423 | return String(macStr); 424 | } 425 | 426 | /** 427 | Get the interface subnet mask address. 428 | @return IPAddress subnetMask 429 | */ 430 | IPAddress WiFiSTAClass::subnetMask() { 431 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 432 | return IPAddress(); 433 | } 434 | tcpip_adapter_ip_info_t ip; 435 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); 436 | return IPAddress(ip.netmask.addr); 437 | } 438 | 439 | /** 440 | Get the gateway ip address. 441 | @return IPAddress gatewayIP 442 | */ 443 | IPAddress WiFiSTAClass::gatewayIP() { 444 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 445 | return IPAddress(); 446 | } 447 | tcpip_adapter_ip_info_t ip; 448 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); 449 | return IPAddress(ip.gw.addr); 450 | } 451 | 452 | /** 453 | Get the DNS ip address. 454 | @param dns_no 455 | @return IPAddress DNS Server IP 456 | */ 457 | IPAddress WiFiSTAClass::dnsIP(uint8_t dns_no) { 458 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 459 | return IPAddress(); 460 | } 461 | ip_addr_t dns_ip = dns_getserver(dns_no); 462 | return IPAddress(dns_ip.u_addr.ip4.addr); 463 | } 464 | 465 | /** 466 | Get the broadcast ip address. 467 | @return IPAddress broadcastIP 468 | */ 469 | IPAddress WiFiSTAClass::broadcastIP() { 470 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 471 | return IPAddress(); 472 | } 473 | tcpip_adapter_ip_info_t ip; 474 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); 475 | return WiFiGenericClass::calculateBroadcast(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr)); 476 | } 477 | 478 | /** 479 | Get the network id. 480 | @return IPAddress networkID 481 | */ 482 | IPAddress WiFiSTAClass::networkID() { 483 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 484 | return IPAddress(); 485 | } 486 | tcpip_adapter_ip_info_t ip; 487 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); 488 | return WiFiGenericClass::calculateNetworkID(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr)); 489 | } 490 | 491 | /** 492 | Get the subnet CIDR. 493 | @return uint8_t subnetCIDR 494 | */ 495 | uint8_t WiFiSTAClass::subnetCIDR() { 496 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 497 | return (uint8_t)0; 498 | } 499 | tcpip_adapter_ip_info_t ip; 500 | tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); 501 | return WiFiGenericClass::calculateSubnetCIDR(IPAddress(ip.netmask.addr)); 502 | } 503 | 504 | /** 505 | Return the current SSID associated with the network 506 | @return SSID 507 | */ 508 | String WiFiSTAClass::SSID() const { 509 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 510 | return String(); 511 | } 512 | wifi_ap_record_t info; 513 | if (!esp_wifi_sta_get_ap_info(&info)) { 514 | return String(reinterpret_cast(info.ssid)); 515 | } 516 | return String(); 517 | } 518 | 519 | /** 520 | Return the current pre shared key associated with the network 521 | @return psk string 522 | */ 523 | String WiFiSTAClass::psk() const { 524 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 525 | return String(); 526 | } 527 | wifi_config_t conf; 528 | esp_wifi_get_config(WIFI_IF_STA, &conf); 529 | return String(reinterpret_cast(conf.sta.password)); 530 | } 531 | 532 | /** 533 | Return the current bssid / mac associated with the network if configured 534 | @return bssid uint8_t 535 | */ 536 | uint8_t* WiFiSTAClass::BSSID(void) { 537 | static uint8_t bssid[6]; 538 | wifi_ap_record_t info; 539 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 540 | return NULL; 541 | } 542 | if (!esp_wifi_sta_get_ap_info(&info)) { 543 | memcpy(bssid, info.bssid, 6); 544 | return reinterpret_cast(bssid); 545 | } 546 | return NULL; 547 | } 548 | 549 | /** 550 | Return the current bssid / mac associated with the network if configured 551 | @return String bssid mac 552 | */ 553 | String WiFiSTAClass::BSSIDstr(void) { 554 | uint8_t* bssid = BSSID(); 555 | if (!bssid) { 556 | return String(); 557 | } 558 | char mac[18] = { 0 }; 559 | sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); 560 | return String(mac); 561 | } 562 | 563 | /** 564 | Return the current network RSSI. 565 | @return RSSI value 566 | */ 567 | int8_t WiFiSTAClass::RSSI(void) { 568 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 569 | return 0; 570 | } 571 | wifi_ap_record_t info; 572 | if (!esp_wifi_sta_get_ap_info(&info)) { 573 | return info.rssi; 574 | } 575 | return 0; 576 | } 577 | 578 | /** 579 | Get the station interface Host name. 580 | @return char array hostname 581 | */ 582 | const char* WiFiSTAClass::getHostname() { 583 | const char* hostname = NULL; 584 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 585 | return hostname; 586 | } 587 | if (tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &hostname)) { 588 | return NULL; 589 | } 590 | return hostname; 591 | } 592 | 593 | /** 594 | Set the station interface Host name. 595 | @param hostname pointer to const string 596 | @return true on success 597 | */ 598 | bool WiFiSTAClass::setHostname(const char* hostname) { 599 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 600 | return false; 601 | } 602 | return tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, hostname) == 0; 603 | } 604 | 605 | /** 606 | Enable IPv6 on the station interface. 607 | @return true on success 608 | */ 609 | bool WiFiSTAClass::enableIpV6() { 610 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 611 | return false; 612 | } 613 | return tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA) == 0; 614 | } 615 | 616 | /** 617 | Get the station interface IPv6 address. 618 | @return IPv6Address 619 | */ 620 | IPv6Address WiFiSTAClass::localIPv6() { 621 | static ip6_addr_t addr; 622 | if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) { 623 | return IPv6Address(); 624 | } 625 | if (tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_STA, &addr)) { 626 | return IPv6Address(); 627 | } 628 | return IPv6Address(addr.addr); 629 | } 630 | 631 | 632 | bool WiFiSTAClass::_smartConfigStarted = false; 633 | bool WiFiSTAClass::_smartConfigDone = false; 634 | 635 | 636 | bool WiFiSTAClass::beginSmartConfig() { 637 | if (_smartConfigStarted) { 638 | return false; 639 | } 640 | 641 | if (!WiFi.mode(WIFI_STA)) { 642 | return false; 643 | } 644 | 645 | esp_wifi_disconnect(); 646 | 647 | esp_err_t err; 648 | err = esp_smartconfig_start(reinterpret_cast(&WiFiSTAClass::_smartConfigCallback), 1); 649 | if (err == ESP_OK) { 650 | _smartConfigStarted = true; 651 | _smartConfigDone = false; 652 | return true; 653 | } 654 | return false; 655 | } 656 | 657 | bool WiFiSTAClass::stopSmartConfig() { 658 | if (!_smartConfigStarted) { 659 | return true; 660 | } 661 | 662 | if (esp_smartconfig_stop() == ESP_OK) { 663 | _smartConfigStarted = false; 664 | return true; 665 | } 666 | 667 | return false; 668 | } 669 | 670 | bool WiFiSTAClass::smartConfigDone() { 671 | if (!_smartConfigStarted) { 672 | return false; 673 | } 674 | 675 | return _smartConfigDone; 676 | } 677 | 678 | #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG 679 | const char* sc_status_strings[] = { 680 | "WAIT", 681 | "FIND_CHANNEL", 682 | "GETTING_SSID_PSWD", 683 | "LINK", 684 | "LINK_OVER" 685 | }; 686 | 687 | const char* sc_type_strings[] = { 688 | "ESPTOUCH", 689 | "AIRKISS", 690 | "ESPTOUCH_AIRKISS" 691 | }; 692 | #endif 693 | 694 | void WiFiSTAClass::_smartConfigCallback(uint32_t st, void* result) { 695 | smartconfig_status_t status = (smartconfig_status_t) st; 696 | log_d("Status: %s", sc_status_strings[st % 5]); 697 | if (status == SC_STATUS_GETTING_SSID_PSWD) { 698 | #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG 699 | smartconfig_type_t* type = (smartconfig_type_t*)result; 700 | log_d("Type: %s", sc_type_strings[*type % 3]); 701 | #endif 702 | } else if (status == SC_STATUS_LINK) { 703 | wifi_sta_config_t* sta_conf = reinterpret_cast(result); 704 | log_d("SSID: %s", (char*)(sta_conf->ssid)); 705 | sta_conf->bssid_set = 0; 706 | esp_wifi_set_config(WIFI_IF_STA, (wifi_config_t*)sta_conf); 707 | esp_wifi_connect(); 708 | _smartConfigDone = true; 709 | } else if (status == SC_STATUS_LINK_OVER) { 710 | if (result) { 711 | #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG 712 | ip4_addr_t* ip = (ip4_addr_t*)result; 713 | log_d("Sender IP: " IPSTR, IP2STR(ip)); 714 | #endif 715 | } 716 | WiFi.stopSmartConfig(); 717 | } 718 | } 719 | -------------------------------------------------------------------------------- /src/WiFiSTA.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266WiFiSTA.h - esp8266 Wifi support. 3 | Based on WiFi.h from Ardiono WiFi shield library. 4 | Copyright (c) 2011-2014 Arduino. All right reserved. 5 | Modified by Ivan Grokhotkov, December 2014 6 | Reworked by Markus Sattler, December 2015 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with this library; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | #ifndef ESP32WIFISTA_H_ 24 | #define ESP32WIFISTA_H_ 25 | 26 | 27 | #include "WiFiType.h" 28 | #include "WiFiGeneric.h" 29 | 30 | 31 | class WiFiSTAClass { 32 | // ---------------------------------------------------------------------------------------------- 33 | // ---------------------------------------- STA function ---------------------------------------- 34 | // ---------------------------------------------------------------------------------------------- 35 | 36 | public: 37 | 38 | wl_status_t begin(const char* ssid, const char* passphrase = NULL, int32_t channel = 0, const uint8_t* bssid = NULL, 39 | bool connect = true); 40 | wl_status_t begin(char* ssid, char* passphrase = NULL, int32_t channel = 0, const uint8_t* bssid = NULL, 41 | bool connect = true); 42 | wl_status_t begin(); 43 | 44 | bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, 45 | IPAddress dns2 = (uint32_t)0x00000000); 46 | 47 | bool reconnect(); 48 | bool disconnect(bool wifioff = false, bool eraseap = false); 49 | 50 | bool isConnected(); 51 | 52 | bool setAutoConnect(bool autoConnect); 53 | bool getAutoConnect(); 54 | 55 | bool setAutoReconnect(bool autoReconnect); 56 | bool getAutoReconnect(); 57 | 58 | uint8_t waitForConnectResult(); 59 | 60 | // STA network info 61 | IPAddress localIP(); 62 | 63 | uint8_t* macAddress(uint8_t* mac); 64 | String macAddress(); 65 | 66 | IPAddress subnetMask(); 67 | IPAddress gatewayIP(); 68 | IPAddress dnsIP(uint8_t dns_no = 0); 69 | 70 | IPAddress broadcastIP(); 71 | IPAddress networkID(); 72 | uint8_t subnetCIDR(); 73 | 74 | bool enableIpV6(); 75 | IPv6Address localIPv6(); 76 | 77 | const char* getHostname(); 78 | bool setHostname(const char* hostname); 79 | 80 | // STA WiFi info 81 | static wl_status_t status(); 82 | String SSID() const; 83 | String psk() const; 84 | 85 | uint8_t* BSSID(); 86 | String BSSIDstr(); 87 | 88 | int8_t RSSI(); 89 | 90 | static void _setStatus(wl_status_t status); 91 | protected: 92 | static bool _useStaticIp; 93 | static bool _autoReconnect; 94 | 95 | public: 96 | bool beginSmartConfig(); 97 | bool stopSmartConfig(); 98 | bool smartConfigDone(); 99 | 100 | protected: 101 | static bool _smartConfigStarted; 102 | static bool _smartConfigDone; 103 | static void _smartConfigCallback(uint32_t status, void* result); 104 | 105 | }; 106 | 107 | 108 | #endif /* ESP32WIFISTA_H_ */ 109 | -------------------------------------------------------------------------------- /src/WiFiScan.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266WiFiScan.cpp - WiFi library for esp8266 3 | 4 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 5 | This file is part of the esp8266 core for Arduino environment. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | 21 | Reworked on 28 Dec 2015 by Markus Sattler 22 | 23 | */ 24 | 25 | 26 | #include "WiFi.h" 27 | #include "WiFiGeneric.h" 28 | #include "WiFiScan.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "Seeed_atUnified.h" 37 | 38 | bool WiFiScanClass::_scanAsync = false; 39 | uint32_t WiFiScanClass::_scanStarted = 0; 40 | uint32_t WiFiScanClass::_scanTimeout = 10000; 41 | uint16_t WiFiScanClass::_scanCount = 0; 42 | void* WiFiScanClass::_scanResult = 0; 43 | 44 | /** 45 | Start scan WiFi networks available 46 | @param async run in async mode 47 | @param show_hidden show hidden networks 48 | @return Number of discovered networks 49 | */ 50 | int16_t WiFiScanClass::scanNetworks(bool async, bool show_hidden, bool passive, uint32_t max_ms_per_chan) { 51 | if (WiFiGenericClass::getStatusBits() & WIFI_SCANNING_BIT) { 52 | return WIFI_SCAN_RUNNING; 53 | } 54 | 55 | WiFiScanClass::_scanTimeout = max_ms_per_chan * 20; 56 | WiFiScanClass::_scanAsync = async; 57 | 58 | WiFi.enableSTA(true); 59 | 60 | scanDelete(); 61 | 62 | wifi_scan_config_t config; 63 | config.ssid = 0; 64 | config.bssid = 0; 65 | config.channel = 0; 66 | config.show_hidden = show_hidden; 67 | if (passive) { 68 | config.scan_type = WIFI_SCAN_TYPE_PASSIVE; 69 | config.scan_time.passive = max_ms_per_chan; 70 | } else { 71 | config.scan_type = WIFI_SCAN_TYPE_ACTIVE; 72 | config.scan_time.active.min = 100; 73 | config.scan_time.active.max = max_ms_per_chan; 74 | } 75 | if (esp_wifi_scan_start(&config, false) == ESP_OK) { 76 | _scanStarted = millis(); 77 | if (!_scanStarted) { //Prevent 0 from millis overflow 78 | ++_scanStarted; 79 | } 80 | 81 | WiFiGenericClass::clearStatusBits(WIFI_SCAN_DONE_BIT); 82 | WiFiGenericClass::setStatusBits(WIFI_SCANNING_BIT); 83 | 84 | if (WiFiScanClass::_scanAsync) { 85 | return WIFI_SCAN_RUNNING; 86 | } 87 | if (WiFiGenericClass::waitStatusBits(WIFI_SCAN_DONE_BIT, 10000)) { 88 | return (int16_t) WiFiScanClass::_scanCount; 89 | } 90 | } 91 | return WIFI_SCAN_FAILED; 92 | } 93 | 94 | 95 | /** 96 | private 97 | scan callback 98 | @param result void *arg 99 | @param status STATUS 100 | */ 101 | void WiFiScanClass::_scanDone() { 102 | esp_wifi_scan_get_ap_num(&(WiFiScanClass::_scanCount)); 103 | if (WiFiScanClass::_scanCount) { 104 | WiFiScanClass::_scanResult = new wifi_ap_record_t[WiFiScanClass::_scanCount]; 105 | if (!WiFiScanClass::_scanResult 106 | || esp_wifi_scan_get_ap_records(&(WiFiScanClass::_scanCount), (wifi_ap_record_t*)_scanResult) != ESP_OK) { 107 | WiFiScanClass::_scanCount = 0; 108 | } 109 | } 110 | WiFiScanClass::_scanStarted = 0; //Reset after a scan is completed for normal behavior 111 | WiFiGenericClass::setStatusBits(WIFI_SCAN_DONE_BIT); 112 | WiFiGenericClass::clearStatusBits(WIFI_SCANNING_BIT); 113 | } 114 | 115 | /** 116 | 117 | @param i specify from which network item want to get the information 118 | @return bss_info 119 | */ 120 | void* WiFiScanClass::_getScanInfoByIndex(int i) { 121 | if (!WiFiScanClass::_scanResult || (size_t) i >= WiFiScanClass::_scanCount) { 122 | return 0; 123 | } 124 | return reinterpret_cast(WiFiScanClass::_scanResult) + i; 125 | } 126 | 127 | /** 128 | called to get the scan state in Async mode 129 | @return scan result or status 130 | -1 if scan not fin 131 | -2 if scan not triggered 132 | */ 133 | int16_t WiFiScanClass::scanComplete() { 134 | if (WiFiScanClass::_scanStarted 135 | && (millis() - WiFiScanClass::_scanStarted) > 136 | WiFiScanClass::_scanTimeout) { //Check is scan was started and if the delay expired, return WIFI_SCAN_FAILED in this case 137 | WiFiGenericClass::clearStatusBits(WIFI_SCANNING_BIT); 138 | return WIFI_SCAN_FAILED; 139 | } 140 | 141 | if (WiFiGenericClass::getStatusBits() & WIFI_SCAN_DONE_BIT) { 142 | return WiFiScanClass::_scanCount; 143 | } 144 | 145 | if (WiFiGenericClass::getStatusBits() & WIFI_SCANNING_BIT) { 146 | return WIFI_SCAN_RUNNING; 147 | } 148 | 149 | return WIFI_SCAN_FAILED; 150 | } 151 | 152 | /** 153 | delete last scan result from RAM 154 | */ 155 | void WiFiScanClass::scanDelete() { 156 | WiFiGenericClass::clearStatusBits(WIFI_SCAN_DONE_BIT); 157 | if (WiFiScanClass::_scanResult) { 158 | delete[] reinterpret_cast(WiFiScanClass::_scanResult); 159 | WiFiScanClass::_scanResult = 0; 160 | WiFiScanClass::_scanCount = 0; 161 | } 162 | } 163 | 164 | 165 | /** 166 | loads all infos from a scanned wifi in to the ptr parameters 167 | @param networkItem uint8_t 168 | @param ssid const char* 169 | @param encryptionType uint8_t 170 | @param RSSI int32_t 171 | @param BSSID uint8_t * 172 | @param channel int32_t 173 | @return (true if ok) 174 | */ 175 | bool WiFiScanClass::getNetworkInfo(uint8_t i, String& ssid, uint8_t& encType, int32_t& rssi, uint8_t*& bssid, 176 | int32_t& channel) { 177 | wifi_ap_record_t* it = reinterpret_cast(_getScanInfoByIndex(i)); 178 | if (!it) { 179 | return false; 180 | } 181 | ssid = (const char*) it->ssid; 182 | encType = it->authmode; 183 | rssi = it->rssi; 184 | bssid = it->bssid; 185 | channel = it->primary; 186 | return true; 187 | } 188 | 189 | 190 | /** 191 | Return the SSID discovered during the network scan. 192 | @param i specify from which network item want to get the information 193 | @return ssid string of the specified item on the networks scanned list 194 | */ 195 | String WiFiScanClass::SSID(uint8_t i) { 196 | wifi_ap_record_t* it = reinterpret_cast(_getScanInfoByIndex(i)); 197 | if (!it) { 198 | return String(); 199 | } 200 | return String(reinterpret_cast(it->ssid)); 201 | } 202 | 203 | 204 | /** 205 | Return the encryption type of the networks discovered during the scanNetworks 206 | @param i specify from which network item want to get the information 207 | @return encryption type (enum wl_enc_type) of the specified item on the networks scanned list 208 | */ 209 | wifi_auth_mode_t WiFiScanClass::encryptionType(uint8_t i) { 210 | wifi_ap_record_t* it = reinterpret_cast(_getScanInfoByIndex(i)); 211 | if (!it) { 212 | return WIFI_AUTH_OPEN; 213 | } 214 | return it->authmode; 215 | } 216 | 217 | /** 218 | Return the RSSI of the networks discovered during the scanNetworks 219 | @param i specify from which network item want to get the information 220 | @return signed value of RSSI of the specified item on the networks scanned list 221 | */ 222 | int32_t WiFiScanClass::RSSI(uint8_t i) { 223 | wifi_ap_record_t* it = reinterpret_cast(_getScanInfoByIndex(i)); 224 | if (!it) { 225 | return 0; 226 | } 227 | return it->rssi; 228 | } 229 | 230 | 231 | /** 232 | return MAC / BSSID of scanned wifi 233 | @param i specify from which network item want to get the information 234 | @return uint8_t * MAC / BSSID of scanned wifi 235 | */ 236 | uint8_t* WiFiScanClass::BSSID(uint8_t i) { 237 | wifi_ap_record_t* it = reinterpret_cast(_getScanInfoByIndex(i)); 238 | if (!it) { 239 | return 0; 240 | } 241 | return it->bssid; 242 | } 243 | 244 | /** 245 | return MAC / BSSID of scanned wifi 246 | @param i specify from which network item want to get the information 247 | @return String MAC / BSSID of scanned wifi 248 | */ 249 | String WiFiScanClass::BSSIDstr(uint8_t i) { 250 | char mac[18] = { 0 }; 251 | wifi_ap_record_t* it = reinterpret_cast(_getScanInfoByIndex(i)); 252 | if (!it) { 253 | return String(); 254 | } 255 | sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", it->bssid[0], it->bssid[1], it->bssid[2], it->bssid[3], it->bssid[4], 256 | it->bssid[5]); 257 | return String(mac); 258 | } 259 | 260 | int32_t WiFiScanClass::channel(uint8_t i) { 261 | wifi_ap_record_t* it = reinterpret_cast(_getScanInfoByIndex(i)); 262 | if (!it) { 263 | return 0; 264 | } 265 | return it->primary; 266 | } 267 | 268 | -------------------------------------------------------------------------------- /src/WiFiScan.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266WiFiScan.h - esp8266 Wifi support. 3 | Based on WiFi.h from Ardiono WiFi shield library. 4 | Copyright (c) 2011-2014 Arduino. All right reserved. 5 | Modified by Ivan Grokhotkov, December 2014 6 | Reworked by Markus Sattler, December 2015 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with this library; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | #ifndef ESP32WIFISCAN_H_ 24 | #define ESP32WIFISCAN_H_ 25 | 26 | #include "WiFiType.h" 27 | #include "WiFiGeneric.h" 28 | 29 | class WiFiScanClass { 30 | 31 | public: 32 | 33 | int16_t scanNetworks(bool async = false, bool show_hidden = false, bool passive = false, 34 | uint32_t max_ms_per_chan = 300); 35 | 36 | int16_t scanComplete(); 37 | void scanDelete(); 38 | 39 | // scan result 40 | bool getNetworkInfo(uint8_t networkItem, String& ssid, uint8_t& encryptionType, int32_t& RSSI, uint8_t*& BSSID, 41 | int32_t& channel); 42 | 43 | String SSID(uint8_t networkItem); 44 | wifi_auth_mode_t encryptionType(uint8_t networkItem); 45 | int32_t RSSI(uint8_t networkItem); 46 | uint8_t* BSSID(uint8_t networkItem); 47 | String BSSIDstr(uint8_t networkItem); 48 | int32_t channel(uint8_t networkItem); 49 | static void* getScanInfoByIndex(int i) { 50 | return _getScanInfoByIndex(i); 51 | }; 52 | 53 | static void _scanDone(); 54 | protected: 55 | 56 | static bool _scanAsync; 57 | 58 | static uint32_t _scanStarted; 59 | static uint32_t _scanTimeout; 60 | static uint16_t _scanCount; 61 | 62 | static void* _scanResult; 63 | 64 | static void* _getScanInfoByIndex(int i); 65 | 66 | }; 67 | 68 | 69 | #endif /* ESP32WIFISCAN_H_ */ 70 | -------------------------------------------------------------------------------- /src/WiFiServer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Server.cpp - Server class for Raspberry Pi 3 | Copyright (c) 2016 Hristo Gochkov All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | #include "WiFiServer.h" 20 | #include "Seeed_atUnified.h" 21 | 22 | #undef write 23 | #undef close 24 | 25 | int WiFiServer::setTimeout(uint32_t seconds) { 26 | struct timeval tv; 27 | tv.tv_sec = seconds; 28 | tv.tv_usec = 0; 29 | if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval)) < 0) { 30 | return -1; 31 | } 32 | return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(struct timeval)); 33 | } 34 | 35 | size_t WiFiServer::write(const uint8_t* data, size_t len) { 36 | return 0; 37 | } 38 | 39 | void WiFiServer::stopAll() {} 40 | 41 | WiFiClient WiFiServer::available() { 42 | if (!_listening) { 43 | return WiFiClient(); 44 | } 45 | int client_sock; 46 | if (_accepted_sockfd >= 0) { 47 | client_sock = _accepted_sockfd; 48 | _accepted_sockfd = -1; 49 | } else { 50 | struct sockaddr_in _client; 51 | int cs = sizeof(struct sockaddr_in); 52 | client_sock = atu_accept_r(sockfd, (struct sockaddr*)&_client, (socklen_t*)&cs); 53 | } 54 | if (client_sock >= 0) { 55 | int val = 1; 56 | if (setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(int)) == ESP_OK) { 57 | val = _noDelay; 58 | if (setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(int)) == ESP_OK) { 59 | return WiFiClient(client_sock); 60 | } 61 | } 62 | } 63 | return WiFiClient(); 64 | } 65 | 66 | void WiFiServer::begin(uint16_t port) { 67 | if (_listening) { 68 | return; 69 | } 70 | if (port) { 71 | _port = port; 72 | } 73 | struct sockaddr_in server; 74 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 75 | if (sockfd < 0) { 76 | return; 77 | } 78 | server.sin_family = AF_INET; 79 | server.sin_addr.s_addr = INADDR_ANY; 80 | server.sin_port = htons(_port); 81 | if (bind(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0) { 82 | return; 83 | } 84 | if (listen(sockfd, _max_clients) < 0) { 85 | return; 86 | } 87 | fcntlsocket(sockfd, F_SETFL, O_NONBLOCK); 88 | _listening = true; 89 | _noDelay = false; 90 | _accepted_sockfd = -1; 91 | } 92 | 93 | void WiFiServer::setNoDelay(bool nodelay) { 94 | _noDelay = nodelay; 95 | } 96 | 97 | bool WiFiServer::getNoDelay() { 98 | return _noDelay; 99 | } 100 | 101 | bool WiFiServer::hasClient() { 102 | if (_accepted_sockfd >= 0) { 103 | return true; 104 | } 105 | struct sockaddr_in _client; 106 | int cs = sizeof(struct sockaddr_in); 107 | _accepted_sockfd = atu_accept_r(sockfd, (struct sockaddr*)&_client, (socklen_t*)&cs); 108 | if (_accepted_sockfd >= 0) { 109 | return true; 110 | } 111 | return false; 112 | } 113 | 114 | void WiFiServer::end() { 115 | closesocket(sockfd); 116 | sockfd = -1; 117 | _listening = false; 118 | } 119 | 120 | void WiFiServer::close() { 121 | end(); 122 | } 123 | 124 | void WiFiServer::stop() { 125 | end(); 126 | } 127 | 128 | -------------------------------------------------------------------------------- /src/WiFiServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Server.h - Server class for Raspberry Pi 3 | Copyright (c) 2016 Hristo Gochkov All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | #ifndef _WIFISERVER_H_ 20 | #define _WIFISERVER_H_ 21 | 22 | #include "Arduino.h" 23 | #include "Server.h" 24 | #include "WiFiClient.h" 25 | 26 | class WiFiServer : public Server { 27 | private: 28 | int sockfd; 29 | int _accepted_sockfd = -1; 30 | uint16_t _port; 31 | uint8_t _max_clients; 32 | bool _listening; 33 | bool _noDelay = false; 34 | 35 | public: 36 | void listenOnLocalhost() {} 37 | 38 | WiFiServer(uint16_t port = 80, uint8_t max_clients = 4): sockfd(-1), _accepted_sockfd(-1), _port(port), 39 | _max_clients(max_clients), _listening(false), _noDelay(false) {} 40 | ~WiFiServer() { 41 | end(); 42 | } 43 | WiFiClient available(); 44 | WiFiClient accept() { 45 | return available(); 46 | } 47 | void begin(uint16_t port); 48 | /* 49 | function: begin(uint16_t port = 0) 50 | could not implement virtual function: begin() = 0 51 | */ 52 | void begin() { 53 | begin(0); 54 | }; 55 | void setNoDelay(bool nodelay); 56 | bool getNoDelay(); 57 | bool hasClient(); 58 | size_t write(const uint8_t* data, size_t len); 59 | size_t write(uint8_t data) { 60 | return write(&data, 1); 61 | } 62 | using Print::write; 63 | 64 | void end(); 65 | void close(); 66 | void stop(); 67 | operator bool() { 68 | return _listening; 69 | } 70 | int setTimeout(uint32_t seconds); 71 | void stopAll(); 72 | }; 73 | 74 | #endif /* _WIFISERVER_H_ */ 75 | -------------------------------------------------------------------------------- /src/WiFiType.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266WiFiType.h - esp8266 Wifi support. 3 | Copyright (c) 2011-2014 Arduino. All right reserved. 4 | Modified by Ivan Grokhotkov, December 2014 5 | Reworked by Markus Sattler, December 2015 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | 23 | #ifndef ESP32WIFITYPE_H_ 24 | #define ESP32WIFITYPE_H_ 25 | 26 | #define WIFI_SCAN_RUNNING (-1) 27 | #define WIFI_SCAN_FAILED (-2) 28 | 29 | #define WiFiMode_t wifi_mode_t 30 | #define WIFI_OFF WIFI_MODE_NULL 31 | #define WIFI_STA WIFI_MODE_STA 32 | #define WIFI_AP WIFI_MODE_AP 33 | #define WIFI_AP_STA WIFI_MODE_APSTA 34 | 35 | #define WiFiEvent_t system_event_id_t 36 | #define WiFiEventInfo_t system_event_info_t 37 | #define WiFiEventId_t wifi_event_id_t 38 | 39 | 40 | typedef enum { 41 | WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library 42 | WL_IDLE_STATUS = 0, 43 | WL_NO_SSID_AVAIL = 1, 44 | WL_SCAN_COMPLETED = 2, 45 | WL_CONNECTED = 3, 46 | WL_CONNECT_FAILED = 4, 47 | WL_CONNECTION_LOST = 5, 48 | WL_DISCONNECTED = 6 49 | } wl_status_t; 50 | 51 | #endif /* ESP32WIFITYPE_H_ */ 52 | -------------------------------------------------------------------------------- /src/WiFiUdp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Udp.cpp - UDP class for Raspberry Pi 3 | Copyright (c) 2016 Hristo Gochkov All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | #include "WiFiUdp.h" 20 | #include "Seeed_atUnified.h" 21 | #include 22 | 23 | #undef write 24 | #undef read 25 | 26 | WiFiUDP::WiFiUDP() 27 | : udp_server(-1) 28 | , server_port(0) 29 | , remote_port(0) 30 | , tx_buffer(0) 31 | , tx_buffer_len(0) 32 | , rx_buffer(0) 33 | {} 34 | 35 | WiFiUDP::~WiFiUDP() { 36 | stop(); 37 | } 38 | 39 | uint8_t WiFiUDP::begin(IPAddress address, uint16_t port) { 40 | stop(); 41 | 42 | server_port = port; 43 | 44 | tx_buffer = new char[1460]; 45 | if (!tx_buffer) { 46 | log_e("could not create tx buffer: %d", errno); 47 | return 0; 48 | } 49 | 50 | if ((udp_server = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 51 | log_e("could not create socket: %d", errno); 52 | return 0; 53 | } 54 | 55 | int yes = 1; 56 | if (setsockopt(udp_server, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { 57 | log_e("could not set socket option: %d", errno); 58 | stop(); 59 | return 0; 60 | } 61 | 62 | struct sockaddr_in addr; 63 | memset((char*) &addr, 0, sizeof(addr)); 64 | addr.sin_family = AF_INET; 65 | addr.sin_port = htons(server_port); 66 | addr.sin_addr.s_addr = (in_addr_t)address; 67 | if (bind(udp_server, (struct sockaddr*)&addr, sizeof(addr)) == -1) { 68 | log_e("could not bind socket: %d", errno); 69 | stop(); 70 | return 0; 71 | } 72 | fcntlsocket(udp_server, F_SETFL, O_NONBLOCK); 73 | return 1; 74 | } 75 | 76 | uint8_t WiFiUDP::begin(uint16_t p) { 77 | return begin(IPAddress(INADDR_ANY), p); 78 | } 79 | 80 | uint8_t WiFiUDP::beginMulticast(IPAddress a, uint16_t p) { 81 | if (begin(IPAddress(INADDR_ANY), p)) { 82 | if (a != 0) { 83 | struct ip_mreq mreq; 84 | mreq.imr_multiaddr.s_addr = (in_addr_t)a; 85 | mreq.imr_interface.s_addr = INADDR_ANY; 86 | if (setsockopt(udp_server, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { 87 | log_e("could not join igmp: %d", errno); 88 | stop(); 89 | return 0; 90 | } 91 | multicast_ip = a; 92 | } 93 | return 1; 94 | } 95 | return 0; 96 | } 97 | 98 | void WiFiUDP::stop() { 99 | if (tx_buffer) { 100 | delete[] tx_buffer; 101 | tx_buffer = NULL; 102 | } 103 | tx_buffer_len = 0; 104 | if (rx_buffer) { 105 | cbuf* b = rx_buffer; 106 | rx_buffer = NULL; 107 | delete b; 108 | } 109 | if (udp_server == -1) { 110 | return; 111 | } 112 | if (multicast_ip != 0) { 113 | struct ip_mreq mreq; 114 | mreq.imr_multiaddr.s_addr = (in_addr_t)multicast_ip; 115 | mreq.imr_interface.s_addr = (in_addr_t)0; 116 | setsockopt(udp_server, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); 117 | multicast_ip = IPAddress(INADDR_ANY); 118 | } 119 | closesocket(udp_server); 120 | udp_server = -1; 121 | } 122 | 123 | int WiFiUDP::beginMulticastPacket() { 124 | if (!server_port || multicast_ip == IPAddress(INADDR_ANY)) { 125 | return 0; 126 | } 127 | remote_ip = multicast_ip; 128 | remote_port = server_port; 129 | return beginPacket(); 130 | } 131 | 132 | int WiFiUDP::beginPacket() { 133 | if (!remote_port) { 134 | return 0; 135 | } 136 | 137 | // allocate tx_buffer if is necessary 138 | if (!tx_buffer) { 139 | tx_buffer = new char[1460]; 140 | if (!tx_buffer) { 141 | log_e("could not create tx buffer: %d", errno); 142 | return 0; 143 | } 144 | } 145 | 146 | tx_buffer_len = 0; 147 | 148 | // check whereas socket is already open 149 | if (udp_server != -1) { 150 | return 1; 151 | } 152 | 153 | if ((udp_server = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 154 | log_e("could not create socket: %d", errno); 155 | return 0; 156 | } 157 | 158 | fcntlsocket(udp_server, F_SETFL, O_NONBLOCK); 159 | 160 | return 1; 161 | } 162 | 163 | int WiFiUDP::beginPacket(IPAddress ip, uint16_t port) { 164 | remote_ip = ip; 165 | remote_port = port; 166 | return beginPacket(); 167 | } 168 | 169 | int WiFiUDP::beginPacket(const char* host, uint16_t port) { 170 | struct hostent* server; 171 | server = gethostbyname(host); 172 | if (server == NULL) { 173 | log_e("could not get host from dns: %d", errno); 174 | return 0; 175 | } 176 | return beginPacket(IPAddress((const uint8_t*)(server->h_addr_list[0])), port); 177 | } 178 | 179 | int WiFiUDP::endPacket() { 180 | struct sockaddr_in recipient; 181 | recipient.sin_addr.s_addr = (uint32_t)remote_ip; 182 | recipient.sin_family = AF_INET; 183 | recipient.sin_port = htons(remote_port); 184 | int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient)); 185 | if (sent < 0) { 186 | log_e("could not send data: %d", errno); 187 | return 0; 188 | } 189 | return 1; 190 | } 191 | 192 | size_t WiFiUDP::write(uint8_t data) { 193 | if (tx_buffer_len == 1460) { 194 | endPacket(); 195 | tx_buffer_len = 0; 196 | } 197 | tx_buffer[tx_buffer_len++] = data; 198 | return 1; 199 | } 200 | 201 | size_t WiFiUDP::write(const uint8_t* buffer, size_t size) { 202 | size_t i; 203 | for (i = 0; i < size; i++) { 204 | write(buffer[i]); 205 | } 206 | return i; 207 | } 208 | 209 | int WiFiUDP::parsePacket() { 210 | if (rx_buffer) { 211 | return 0; 212 | } 213 | struct sockaddr_in si_other; 214 | int slen = sizeof(si_other), len; 215 | char* buf = new char[1460]; 216 | if (!buf) { 217 | return 0; 218 | } 219 | if ((len = recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr*) &si_other, (socklen_t*)&slen)) == -1) { 220 | delete[] buf; 221 | if (errno == EWOULDBLOCK) { 222 | return 0; 223 | } 224 | log_e("could not receive data: %d", errno); 225 | return 0; 226 | } 227 | remote_ip = IPAddress(si_other.sin_addr.s_addr); 228 | remote_port = ntohs(si_other.sin_port); 229 | if (len > 0) { 230 | rx_buffer = new cbuf(len); 231 | rx_buffer->write(buf, len); 232 | } 233 | delete[] buf; 234 | return len; 235 | } 236 | 237 | int WiFiUDP::available() { 238 | if (!rx_buffer) { 239 | return 0; 240 | } 241 | return rx_buffer->available(); 242 | } 243 | 244 | int WiFiUDP::read() { 245 | if (!rx_buffer) { 246 | return -1; 247 | } 248 | int out = rx_buffer->read(); 249 | if (!rx_buffer->available()) { 250 | cbuf* b = rx_buffer; 251 | rx_buffer = 0; 252 | delete b; 253 | } 254 | return out; 255 | } 256 | 257 | int WiFiUDP::read(unsigned char* buffer, size_t len) { 258 | return read((char*)buffer, len); 259 | } 260 | 261 | int WiFiUDP::read(char* buffer, size_t len) { 262 | if (!rx_buffer) { 263 | return 0; 264 | } 265 | int out = rx_buffer->read(buffer, len); 266 | if (!rx_buffer->available()) { 267 | cbuf* b = rx_buffer; 268 | rx_buffer = 0; 269 | delete b; 270 | } 271 | return out; 272 | } 273 | 274 | int WiFiUDP::peek() { 275 | if (!rx_buffer) { 276 | return -1; 277 | } 278 | return rx_buffer->peek(); 279 | } 280 | 281 | void WiFiUDP::flush() { 282 | if (!rx_buffer) { 283 | return; 284 | } 285 | cbuf* b = rx_buffer; 286 | rx_buffer = 0; 287 | delete b; 288 | } 289 | 290 | IPAddress WiFiUDP::remoteIP() { 291 | return remote_ip; 292 | } 293 | 294 | uint16_t WiFiUDP::remotePort() { 295 | return remote_port; 296 | } 297 | -------------------------------------------------------------------------------- /src/WiFiUdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Udp.cpp: Library to send/receive UDP packets. 3 | 4 | NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) 5 | 1) UDP does not guarantee the order in which assembled UDP packets are received. This 6 | might not happen often in practice, but in larger network topologies, a UDP 7 | packet can be received out of sequence. 8 | 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being 9 | aware of it. Again, this may not be a concern in practice on small local networks. 10 | For more information, see http://www.cafeaulait.org/course/week12/35.html 11 | 12 | MIT License: 13 | Copyright (c) 2008 Bjoern Hartmann 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in 22 | all copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 | THE SOFTWARE. 31 | 32 | bjoern@cs.stanford.edu 12/30/2008 33 | */ 34 | 35 | #ifndef _WIFIUDP_H_ 36 | #define _WIFIUDP_H_ 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | class WiFiUDP : public UDP { 43 | private: 44 | int udp_server; 45 | IPAddress multicast_ip; 46 | IPAddress remote_ip; 47 | uint16_t server_port; 48 | uint16_t remote_port; 49 | char* tx_buffer; 50 | size_t tx_buffer_len; 51 | cbuf* rx_buffer; 52 | public: 53 | WiFiUDP(); 54 | ~WiFiUDP(); 55 | uint8_t begin(IPAddress a, uint16_t p); 56 | uint8_t begin(uint16_t p); 57 | uint8_t beginMulticast(IPAddress a, uint16_t p); 58 | void stop(); 59 | int beginMulticastPacket(); 60 | int beginPacket(); 61 | int beginPacket(IPAddress ip, uint16_t port); 62 | int beginPacket(const char* host, uint16_t port); 63 | int endPacket(); 64 | size_t write(uint8_t); 65 | size_t write(const uint8_t* buffer, size_t size); 66 | int parsePacket(); 67 | int available(); 68 | int read(); 69 | int read(unsigned char* buffer, size_t len); 70 | int read(char* buffer, size_t len); 71 | int peek(); 72 | void flush(); 73 | IPAddress remoteIP(); 74 | uint16_t remotePort(); 75 | }; 76 | 77 | #endif /* _WIFIUDP_H_ */ 78 | --------------------------------------------------------------------------------