├── .codespellrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── stale.yml └── workflows │ ├── auto-github-actions.yml │ ├── check-arduino.yml │ ├── report-size-deltas.yml │ └── spell-check.yml ├── .gitignore ├── CONTRIBUTING.md ├── Images ├── Configuration.png ├── Configuration_AIO_MQTT.png ├── Configuration_ESP32.png ├── Configuration_Standard.png ├── Info.png ├── Info_ESP32.png ├── Info_Short.png ├── Main.png ├── Main_ESP32.png ├── Saved.png └── WiFiSave.png ├── LICENSE ├── README.md ├── changelog.md ├── esp32c3_ESPAsyncWebServer_Patch ├── AsyncWebSocket.cpp └── WebAuthentication.cpp ├── esp32s2_WebServer_Patch ├── WebServer.cpp └── WebServer.h ├── examples ├── Async_AutoConnect │ └── Async_AutoConnect.ino ├── Async_AutoConnectWithFSParameters │ └── Async_AutoConnectWithFSParameters.ino ├── Async_AutoConnectWithFSParametersAndCustomIP │ └── Async_AutoConnectWithFSParametersAndCustomIP.ino ├── Async_AutoConnectWithFeedback │ └── Async_AutoConnectWithFeedback.ino ├── Async_AutoConnectWithFeedbackLED │ └── Async_AutoConnectWithFeedbackLED.ino ├── Async_ConfigOnDRD_FS_MQTT_Ptr │ └── Async_ConfigOnDRD_FS_MQTT_Ptr.ino ├── Async_ConfigOnDRD_FS_MQTT_Ptr_Complex │ └── Async_ConfigOnDRD_FS_MQTT_Ptr_Complex.ino ├── Async_ConfigOnDRD_FS_MQTT_Ptr_Medium │ └── Async_ConfigOnDRD_FS_MQTT_Ptr_Medium.ino ├── Async_ConfigOnDoubleReset │ └── Async_ConfigOnDoubleReset.ino ├── Async_ConfigOnDoubleReset_Multi │ ├── Async_ConfigOnDoubleReset_Multi.cpp │ ├── Async_ConfigOnDoubleReset_Multi.h │ └── Async_ConfigOnDoubleReset_Multi.ino ├── Async_ConfigOnDoubleReset_TZ │ └── Async_ConfigOnDoubleReset_TZ.ino ├── Async_ConfigOnStartup │ └── Async_ConfigOnStartup.ino ├── Async_ConfigOnSwitch │ ├── Async_ConfigOnSwitch.ino │ └── README.md ├── Async_ConfigOnSwitchFS │ └── Async_ConfigOnSwitchFS.ino ├── Async_ConfigOnSwitchFS_MQTT_Ptr │ └── Async_ConfigOnSwitchFS_MQTT_Ptr.ino ├── Async_ConfigPortalParamsOnSwitch │ └── Async_ConfigPortalParamsOnSwitch.ino ├── Async_ESP32_FSWebServer │ ├── Async_ESP32_FSWebServer.ino │ ├── README.md │ ├── data │ │ ├── CanadaFlag_1.png │ │ ├── CanadaFlag_2.png │ │ ├── CanadaFlag_3.jpg │ │ ├── edit.htm.gz │ │ ├── favicon.ico │ │ ├── graphs.js.gz │ │ └── index.htm │ └── pics │ │ ├── async-esp32fs.local.png │ │ └── async-esp32fs.local_edit.png ├── Async_ESP32_FSWebServer_DRD │ ├── Async_ESP32_FSWebServer_DRD.ino │ ├── README.md │ ├── data │ │ ├── CanadaFlag_1.png │ │ ├── CanadaFlag_2.png │ │ ├── CanadaFlag_3.jpg │ │ ├── edit.htm.gz │ │ ├── favicon.ico │ │ ├── graphs.js.gz │ │ └── index.htm │ └── pics │ │ ├── async-esp32fs.local.png │ │ └── async-esp32fs.local_edit.png ├── Async_ESP_FSWebServer │ ├── Async_ESP_FSWebServer.ino │ ├── README.md │ ├── data │ │ ├── CanadaFlag_1.png │ │ ├── CanadaFlag_2.png │ │ ├── CanadaFlag_3.jpg │ │ ├── edit.htm.gz │ │ ├── favicon.ico │ │ ├── graphs.js.gz │ │ └── index.htm │ └── pics │ │ ├── async-esp8266fs.local.png │ │ └── async-esp8266fs.local_edit.png └── Async_ESP_FSWebServer_DRD │ ├── Async_ESP_FSWebServer_DRD.ino │ ├── README.md │ ├── data │ ├── CanadaFlag_1.png │ ├── CanadaFlag_2.png │ ├── CanadaFlag_3.jpg │ ├── edit.htm.gz │ ├── favicon.ico │ ├── graphs.js.gz │ └── index.htm │ └── pics │ ├── async-esp8266fs.local.png │ ├── async-esp8266fs.local_edit.png │ ├── esp8266fs.local.png │ └── esp8266fs.local_edit.png ├── keywords.txt ├── library.json ├── library.properties ├── platformio └── platformio.ini ├── src ├── ESPAsync_WiFiManager-Impl.h ├── ESPAsync_WiFiManager.h ├── ESPAsync_WiFiManager.hpp ├── ESPAsync_WiFiManager_Debug.h └── utils │ └── TZ.h ├── travis └── common.sh └── utils ├── astyle_library.conf └── restyle.sh /.codespellrc: -------------------------------------------------------------------------------- 1 | # See: https://github.com/codespell-project/codespell#using-a-config-file 2 | [codespell] 3 | # In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: 4 | ignore-words-list = , 5 | check-filenames = 6 | check-hidden = 7 | skip = ./.git,./src,./examples,./Packages_Patches,./LibraryPatches 8 | -------------------------------------------------------------------------------- /.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 | 12 | A clear and concise description of what the bug is. 13 | 14 | ### Steps to Reproduce 15 | 16 | Steps to reproduce the behavior. Including the [MRE](https://stackoverflow.com/help/minimal-reproducible-example) sketches 17 | 18 | ### Expected behavior 19 | 20 | A clear and concise description of what you expected to happen. 21 | 22 | ### Actual behavior 23 | 24 | A clear and concise description of what you expected to happen. 25 | 26 | ### Debug and AT-command log (if applicable) 27 | 28 | A clear and concise description of what you expected to happen. 29 | 30 | ### Screenshots 31 | 32 | If applicable, add screenshots to help explain your problem. 33 | 34 | ### Information 35 | 36 | Please ensure to specify the following: 37 | 38 | * Arduino IDE version (e.g. 1.8.19) or Platform.io version 39 | * `ESP8266` or `ESP32` Core Version (e.g. ESP8266 core v3.0.2 or ESP32 v2.0.4) 40 | * Contextual information (e.g. what you were trying to achieve) 41 | * Simplest possible steps to reproduce 42 | * Anything that might be relevant in your opinion, such as: 43 | * Operating system (Windows, Ubuntu, etc.) and the output of `uname -a` 44 | * Network configuration 45 | 46 | 47 | ### Example 48 | 49 | ``` 50 | Arduino IDE version: 1.8.19 51 | ESP8266 Core Version 3.0.2 52 | OS: Ubuntu 20.04 LTS 53 | Linux xy-Inspiron-3593 5.15.0-53-generic #59~20.04.1-Ubuntu SMP Thu Oct 20 15:10:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux 54 | 55 | Context: 56 | I encountered an endless loop while trying to connect to Local WiFi. 57 | 58 | Steps to reproduce: 59 | 1. ... 60 | 2. ... 61 | 3. ... 62 | 4. ... 63 | ``` 64 | 65 | ### Additional context 66 | 67 | Add any other context about the problem here 68 | 69 | --- 70 | 71 | ### Sending Feature Requests 72 | 73 | Feel free to post feature requests. It's helpful if you can explain exactly why the feature would be useful. 74 | 75 | There are usually some outstanding feature requests in the [existing issues list](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement), feel free to add comments to them. 76 | 77 | --- 78 | 79 | ### Sending Pull Requests 80 | 81 | Pull Requests with changes and fixes are also welcome! 82 | 83 | Please use the `astyle` to reformat the updated library code as follows (demo for Ubuntu Linux) 84 | 85 | 1. Change directory to the library GitHub 86 | 87 | ``` 88 | xy@xy-Inspiron-3593:~$ cd Arduino/xy/ESPAsync_WiFiManager_GitHub/ 89 | xy@xy-Inspiron-3593:~/Arduino/xy/ESPAsync_WiFiManager_GitHub$ 90 | ``` 91 | 92 | 2. Issue astyle command 93 | 94 | ``` 95 | xy@xy-Inspiron-3593:~/Arduino/xy/ESPAsync_WiFiManager_GitHub$ bash utils/restyle.sh 96 | ``` 97 | -------------------------------------------------------------------------------- /.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 | 12 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 13 | 14 | ### Describe the solution you'd like 15 | 16 | A clear and concise description of what you want to happen. 17 | 18 | ### Describe alternatives you've considered 19 | 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | ### Additional context 23 | 24 | Add any other context or screenshots about the feature request here. 25 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#about-the-dependabotyml-file 2 | version: 2 3 | 4 | updates: 5 | # Configure check for outdated GitHub Actions actions in workflows. 6 | # See: https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot 7 | - package-ecosystem: github-actions 8 | directory: / # Check the repository's workflows under /.github/workflows/ 9 | schedule: 10 | interval: daily 11 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | daysUntilStale: 60 4 | daysUntilClose: 14 5 | limitPerRun: 30 6 | staleLabel: stale 7 | exemptLabels: 8 | - pinned 9 | - security 10 | - "to be implemented" 11 | - "for reference" 12 | - "move to PR" 13 | - "enhancement" 14 | 15 | only: issues 16 | onlyLabels: [] 17 | exemptProjects: false 18 | exemptMilestones: false 19 | exemptAssignees: false 20 | 21 | markComment: > 22 | [STALE_SET] This issue has been automatically marked as stale because it has not had 23 | recent activity. It will be closed in 14 days if no further activity occurs. Thank you 24 | for your contributions. 25 | 26 | unmarkComment: > 27 | [STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it opening the future. 28 | 29 | closeComment: > 30 | [STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions. 31 | 32 | -------------------------------------------------------------------------------- /.github/workflows/auto-github-actions.yml: -------------------------------------------------------------------------------- 1 | name: auto-github-actions 2 | on: [push] 3 | jobs: 4 | check-bats-version: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v3 8 | - uses: actions/setup-node@v3 9 | with: 10 | node-version: '14' 11 | - run: npm install -g bats 12 | - run: bats -v 13 | -------------------------------------------------------------------------------- /.github/workflows/check-arduino.yml: -------------------------------------------------------------------------------- 1 | name: Check Arduino 2 | 3 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | pull_request: 7 | schedule: 8 | # Run every Tuesday at 8 AM UTC to catch breakage caused by new rules added to Arduino Lint. 9 | - cron: "0 8 * * TUE" 10 | workflow_dispatch: 11 | repository_dispatch: 12 | 13 | jobs: 14 | lint: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v3 20 | 21 | - name: Arduino Lint 22 | uses: arduino/arduino-lint-action@v1 23 | with: 24 | compliance: specification 25 | library-manager: update 26 | # Always use this setting for official repositories. Remove for 3rd party projects. 27 | official: true 28 | project-type: library 29 | -------------------------------------------------------------------------------- /.github/workflows/report-size-deltas.yml: -------------------------------------------------------------------------------- 1 | name: Report Size Deltas 2 | 3 | on: 4 | schedule: 5 | - cron: '*/5 * * * *' 6 | 7 | jobs: 8 | report: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Comment size deltas reports to PRs 13 | uses: arduino/report-size-deltas@v1 14 | with: 15 | # The name of the workflow artifact created by the "Compile Examples" workflow 16 | sketches-reports-source: sketches-reports 17 | -------------------------------------------------------------------------------- /.github/workflows/spell-check.yml: -------------------------------------------------------------------------------- 1 | name: Spell Check 2 | 3 | on: 4 | pull_request: 5 | push: 6 | schedule: 7 | # run every Tuesday at 3 AM UTC 8 | - cron: "0 3 * * 2" 9 | workflow_dispatch: 10 | repository_dispatch: 11 | 12 | jobs: 13 | spellcheck: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | 20 | # See: https://github.com/codespell-project/actions-codespell/blob/master/README.md 21 | - name: Spell check 22 | uses: codespell-project/actions-codespell@master 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Visual Studio folder and files 35 | .vs 36 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to ESPAsync_WiFiManager 2 | 3 | ### Reporting Bugs 4 | 5 | Please report bugs in ESPAsync_WiFiManager if you find them. 6 | 7 | However, before reporting a bug please check through the following: 8 | 9 | * [Existing Open Issues](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues) - someone might have already encountered this. 10 | 11 | If you don't find anything, please [open a new issue](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues/new). 12 | 13 | ### How to submit a bug report 14 | 15 | Please ensure to specify the following, or your post will be ignored and deleted: 16 | 17 | * Arduino IDE version (e.g. 1.8.19) or Platform.io version 18 | * `ESP8266` or `ESP32` Core Version (e.g. ESP8266 core v3.0.2 or ESP32 v2.0.5) 19 | * Contextual information (e.g. what you were trying to achieve) 20 | * Simplest possible steps to reproduce 21 | * Anything that might be relevant in your opinion, such as: 22 | * Operating system (Windows, Ubuntu, etc.) and the output of `uname -a` 23 | * Network configuration 24 | 25 | 26 | ### Example 27 | 28 | ``` 29 | Arduino IDE version: 1.8.19 30 | ESP8266 Core Version 3.0.2 31 | OS: Ubuntu 20.04 LTS 32 | Linux xy-Inspiron-3593 5.15.0-53-generic #59~20.04.1-Ubuntu SMP Thu Oct 20 15:10:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux 33 | 34 | Context: 35 | I encountered a crash when using this library 36 | 37 | Steps to reproduce: 38 | 1. ... 39 | 2. ... 40 | 3. ... 41 | 4. ... 42 | ``` 43 | --- 44 | 45 | ### Sending Feature Requests 46 | 47 | Feel free to post feature requests. It's helpful if you can explain exactly why the feature would be useful. 48 | 49 | There are usually some outstanding feature requests in the [existing issues list](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement), feel free to add comments to them. 50 | 51 | --- 52 | 53 | ### Sending Pull Requests 54 | 55 | Pull Requests with changes and fixes are also welcome! 56 | 57 | Please use the `astyle` to reformat the updated library code as follows (demo for Ubuntu Linux) 58 | 59 | 1. Change directory to the library GitHub 60 | 61 | ``` 62 | xy@xy-Inspiron-3593:~$ cd Arduino/xy/ESPAsync_WiFiManager_GitHub/ 63 | xy@xy-Inspiron-3593:~/Arduino/xy/ESPAsync_WiFiManager_GitHub$ 64 | ``` 65 | 66 | 2. Issue astyle command 67 | 68 | ``` 69 | xy@xy-Inspiron-3593:~/Arduino/xy/ESPAsync_WiFiManager_GitHub$ bash utils/restyle.sh 70 | ``` 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Images/Configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/Configuration.png -------------------------------------------------------------------------------- /Images/Configuration_AIO_MQTT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/Configuration_AIO_MQTT.png -------------------------------------------------------------------------------- /Images/Configuration_ESP32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/Configuration_ESP32.png -------------------------------------------------------------------------------- /Images/Configuration_Standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/Configuration_Standard.png -------------------------------------------------------------------------------- /Images/Info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/Info.png -------------------------------------------------------------------------------- /Images/Info_ESP32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/Info_ESP32.png -------------------------------------------------------------------------------- /Images/Info_Short.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/Info_Short.png -------------------------------------------------------------------------------- /Images/Main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/Main.png -------------------------------------------------------------------------------- /Images/Main_ESP32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/Main_ESP32.png -------------------------------------------------------------------------------- /Images/Saved.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/Saved.png -------------------------------------------------------------------------------- /Images/WiFiSave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/Images/WiFiSave.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Khoi Hoang 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 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # ESPAsync_WiFiManager Library 2 | 3 | [![arduino-library-badge](https://www.ardu-badge.com/badge/ESPAsync_WiFiManager.svg?)](https://www.ardu-badge.com/ESPAsync_WiFiManager) 4 | [![GitHub release](https://img.shields.io/github/release/khoih-prog/ESPAsync_WiFiManager.svg)](https://github.com/khoih-prog/ESPAsync_WiFiManager/releases) 5 | [![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/khoih-prog/ESPAsync_WiFiManager/blob/master/LICENSE) 6 | [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing) 7 | [![GitHub issues](https://img.shields.io/github/issues/khoih-prog/ESPAsync_WiFiManager.svg)](http://github.com/khoih-prog/ESPAsync_WiFiManager/issues) 8 | 9 | 10 | Donate to my libraries using BuyMeACoffee 11 | 12 | 13 | --- 14 | --- 15 | 16 | ## Table of Contents 17 | 18 | * [Changelog](#changelog) 19 | * [Releases v1.15.1](#releases-v1151) 20 | * [Releases v1.15.0](#releases-v1150) 21 | * [Releases v1.14.1](#releases-v1141) 22 | * [Releases v1.14.0](#releases-v1140) 23 | * [Releases v1.13.0](#releases-v1130) 24 | * [Releases v1.12.2](#releases-v1122) 25 | * [Releases v1.12.1](#releases-v1121) 26 | * [Releases v1.12.0](#releases-v1120) 27 | * [Releases v1.11.0](#releases-v1110) 28 | * [Releases v1.10.0](#releases-v1100) 29 | * [Releases v1.9.8](#releases-v198) 30 | * [Releases v1.9.7](#releases-v197) 31 | * [Releases v1.9.6](#releases-v196) 32 | * [Releases v1.9.5](#releases-v195) 33 | * [Releases v1.9.4](#releases-v194) 34 | * [Releases v1.9.3](#releases-v193) 35 | * [Releases v1.9.2](#releases-v192) 36 | * [Releases v1.9.1](#releases-v191) 37 | * [Releases v1.9.0](#releases-v190) 38 | * [Releases v1.8.1](#releases-v181) 39 | * [Major Releases v1.8.0](#major-releases-v180) 40 | * [Releases v1.7.1](#releases-v171) 41 | * [Releases v1.7.0](#releases-v170) 42 | * [Releases v1.6.3](#releases-v163) 43 | * [Releases v1.6.2](#releases-v162) 44 | * [Releases v1.6.1](#releases-v161) 45 | * [Releases v1.6.0](#releases-v160) 46 | * [Major Releases v1.5.0](#major-releases-v150) 47 | * [Releases v1.4.3](#releases-v143) 48 | * [Releases v1.4.2](#releases-v142) 49 | * [Releases v1.4.1](#releases-v141) 50 | * [Major Releases v1.4.0](#major-releases-v140) 51 | * [Releases v1.3.0](#releases-v130) 52 | * [Releases v1.2.0](#releases-v120) 53 | * [Releases v1.1.2](#releases-v112) 54 | * [Major Releases v1.1.1](#major-releases-v111) 55 | * [Releases v1.0.11](#releases-v1011) 56 | 57 | --- 58 | --- 59 | 60 | ## Changelog 61 | 62 | ### Releases v1.15.1 63 | 64 | 1. Using random channel for softAP without password. Check [fix: using random CH for non-password use too #118](https://github.com/khoih-prog/ESPAsync_WiFiManager/pull/118) 65 | 2. Fix bug. Check [fix: ending portal loop without processing its flags #119](https://github.com/khoih-prog/ESPAsync_WiFiManager/pull/119) 66 | 3. Add astyle using `allman` style. Restyle the library 67 | 68 | 69 | ### Releases v1.15.0 70 | 71 | 1. Optionally display Credentials (SSIDs, PWDs) in Config Portal. Check [Populate portal wifi with saved credentials #91](https://github.com/khoih-prog/ESP_WiFiManager/discussions/91) and [Prepopulating the configuration with SSID and Password from stored file #115](https://github.com/khoih-prog/ESPAsync_WiFiManager/discussions/115) 72 | 2. Display `Credentials` Hint on Config Portal 73 | 3. Periodic code clean-up 74 | 75 | ### Releases v1.14.1 76 | 77 | 1. Remove dependency on ESP_AsyncWebServer, ESPAsyncTCP and AsyncTCP in `library.properties`. Check ["no protocol" error #113](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues/113)" 78 | 2. Add notes about manual installation of above-mentioned libraries for `Arduino IDE` 79 | 80 | ### Releases v1.14.0 81 | 82 | 1. Fix `ESP32 chipID`. Check [Help for storing variables in memory (non-volatile) #87](https://github.com/khoih-prog/ESP_WiFiManager/discussions/87#discussioncomment-3593028) 83 | 2. Add ESP32 `ESP_getChipOUI()` function 84 | 3. Display new info on Config Portal for ESP32 85 | 4. Remove dependency on `LittleFS_esp32` library to prevent PIO error when using new `ESP32 core v1.0.6+` 86 | 87 | ### Releases v1.13.0 88 | 89 | 1. Using AsyncDNSServer instead of DNSServer. Check [Captive Portal hanging depending on active core for AsyncTCP #100](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues/100) 90 | 91 | 92 | ### Releases v1.12.2 93 | 94 | 1. Optimize code by using passing by `reference` instead of by `value` 95 | 2. Delete all confusing, function-lacking `minimal` examples 96 | 3. Delete all `Modeless` examples 97 | 4. Display informational warnings only when `_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3` 98 | 99 | ### Releases v1.12.1 100 | 101 | 1. Add LittleFS support to `ESP32-C3`. 102 | 2. Use ESP32-core's LittleFS library instead of Lorol's LITTLEFS library for v2.0.0+ 103 | 104 | ### Releases v1.12.0 105 | 106 | 1. Add support to `ESP32-S3` (`ESP32S3_DEV, ESP32_S3_BOX, UM TINYS3, UM PROS3, UM FEATHERS3`, etc.) using [ESP32 core, esp32-s3-support branch, v2.0.2+](https://github.com/espressif/arduino-esp32/tree/esp32-s3-support) 107 | 108 | ### Releases v1.11.0 109 | 110 | 1. Reduce the breaking effect of v1.10.0 by enabling compatibility with old code to include only `ESPAsync_WiFiManager.h`. Check [Important Breaking Change from v1.10.0](https://github.com/khoih-prog/ESPAsync_WiFiManager#Important-Breaking-Change-from-v1100) 111 | 112 | ### Releases v1.10.0 113 | 114 | 1. Fix `multiple-definitions` linker error and weird bug related to `src_cpp`. Check [Different behaviour using the src_cpp or src_h lib #80](https://github.com/khoih-prog/ESPAsync_WiFiManager/discussions/80) 115 | 2. Optimize library code by using `reference-passing` instead of `value-passing` 116 | 117 | ### Releases v1.9.8 118 | 119 | 1. Fix bug returning IP `255.255.255.255` in core v2.0.0+ when using `hostname` 120 | 121 | ### Releases v1.9.7 122 | 123 | 1. Fix bug to permit using HTTP port different from 80. Check [WiFiManager works only on port 80 #75](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues/75) 124 | 125 | ### Releases v1.9.6 126 | 127 | 1. Fix compile error for ESP32 core v1.0.5- 128 | 129 | ### Releases v1.9.5 130 | 131 | 1. Auto detect ESP32 core and use either built-in LittleFS or [LITTLEFS](https://github.com/lorol/LITTLEFS) library 132 | 2. Update `library.json` to use new `headers` for PIO 133 | 134 | 135 | ### Releases v1.9.4 136 | 137 | 1. Update `platform.ini` and `library.json` to use original `khoih-prog` instead of `khoih.prog` after PIO fix 138 | 139 | ### Releases v1.9.3 140 | 141 | 1. Add WiFi scanning of hidden SSIDs. Check [Add support for Wifi hidden SSID scanning. #66](https://github.com/khoih-prog/ESP_WiFiManager/pull/66) 142 | 143 | ### Releases v1.9.2 144 | 145 | 1. Fix MultiWiFi connection issue with ESP32 core v2.0.0-rc1+ 146 | 2. Fix AsyncWebServer library compile error with ESP32 core v2.0.0-rc1+. Check [Fix compiler error for ESP32-C3 and mbed TLS v2.7.0+ #970](https://github.com/me-no-dev/ESPAsyncWebServer/pull/970) 147 | 3. Verify compatibility with new ESP32 core v2.0.0-rc1+ 148 | 4. Verify compatibility with new ESP8266 core v3.0.2 149 | 150 | ### Releases v1.9.1 151 | 152 | 1. Fix warnings and verify compatibility with new ESP8266 core v3.0.0 153 | 2. Autodetect ESP8266 core v1.7.4- or new ESP8266 core v3.0.0 to use the new breaking features 154 | 155 | ### Releases v1.9.0 156 | 157 | 1. Add WiFi `/scan` page. 158 | 2. Fix timezoneName not displayed in Info page. 159 | 3. Clean up. 160 | 161 | ### Releases v1.8.1 162 | 163 | 1. Fix bug. 164 | 2. Don't display invalid time when not synch yet. 165 | 166 | ### Major Releases v1.8.0 167 | 168 | 1. Add auto-Timezone feature with variable `_timezoneName` (e.g. `America/New_York`) and function to retrieve TZ (e.g. `EST5EDT,M3.2.0,M11.1.0`) to use directly to configure ESP32/ESP8266 timezone. Check [How to retrieve timezone? #51](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues/51) 169 | 2. Store those `_timezoneName` and `TZ` in LittleFS or SPIFFS config file. 170 | 3. Using these new timezone feature is optional. 171 | 4. Add checksum in config file to validate data read from LittleFS or SPIFFS config file. 172 | 5. Update examples to show how to use the new TZ feature. 173 | 174 | ### Releases v1.7.1 175 | 176 | 1. Fix captive-portal bug if Config Portal AP address is not default 192.168.4.1. Check [In AP, DNS server always redirects to 192.168.4.1 no matter what APStaticIP is set to. #58](https://github.com/khoih-prog/ESP_WiFiManager/issues/58) 177 | 2. Fix MultiWiFi bug. 178 | 179 | ### Releases v1.7.0 180 | 181 | 1. Add **LittleFS and SPIFFS** support to new **ESP32-S2** boards (**Arduino ESP32C3_DEV**). Check [HOWTO Install esp32 core for ESP32-S2 (Saola, AI-Thinker ESP-12K) and ESP32-C3 boards into Arduino IDE](#howto-install-esp32-core-for-esp32-s2-saola-ai-thinker-esp-12k-and-esp32-c3-boards-into-arduino-ide). 182 | 2. Add **EEPROM and SPIFFS** support to new **ESP32-C3** boards (**Arduino ESP32C3_DEV**). Check [HOWTO Install esp32 core for ESP32-S2 (Saola, AI-Thinker ESP-12K) and ESP32-C3 boards into Arduino IDE](#howto-install-esp32-core-for-esp32-s2-saola-ai-thinker-esp-12k-and-esp32-c3-boards-into-arduino-ide). 183 | 184 | ### Releases v1.6.3 185 | 186 | 1. Fix dnsServer not closed to free up DNS port 53. Check [**Allow captive portal to run more than once by closing dnsServer cleanly.** #49](https://github.com/khoih-prog/ESPAsync_WiFiManager/pull/49) 187 | 2. Add `dnsServer can't start` error message. 188 | 189 | ### Releases v1.6.2 190 | 191 | 1. Fix example misleading messages. Check [**Minor: examples/Async_ESP32_FSWebServer/ wrongly uses FileFS.begin(true)** #47](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues/47) 192 | 193 | ### Releases v1.6.1 194 | 195 | 1. Modify multiWiFi-related timings to work better with latest esp32 core v1.0.6 196 | 197 | ### Releases v1.6.0 198 | 199 | 1. Fix WiFi Scanning bug. 200 | 201 | ### Major Releases v1.5.0 202 | 203 | 1. Add support to **ESP32-S2 (ESP32-S2 Saola, AI-Thinker ESP-12K, ESP32S2 Dev Module, UM FeatherS2, UM ProS2, microS2, etc.)** 204 | 2. Add [**Instructions to install ESP32-S2 core**](#howto-install-esp32-s2-core-for-esp32-s2-saola-ai-thinker-esp-12k-boards-into-arduino-ide) 205 | 3. Rewrite library code to be more efficient and multitask friendly 206 | 207 | ### Releases v1.4.3 208 | 209 | 1. Fix examples' bug not saving Static IP in certain cases. 210 | 2. Add feature to warn if using examples with old library versions 211 | 212 | ### Releases v1.4.2 213 | 214 | 1. Fix examples' bug not using saved WiFi Credentials after losing all WiFi connections. 215 | 2. Fix compiler warnings. 216 | 217 | ### Releases v1.4.1 218 | 219 | 1. Fix bug. 220 | 2. Fix compiler warnings. 221 | 222 | ### Major Releases v1.4.0 223 | 224 | 1. Fix staticIP not saved in examples. See [ESP32 static IP not saved after restarting the device](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues/19) 225 | 2. Add structures and functions to handle AP and STA IPs. 226 | 3. Add complex examples 227 | * [Async_ConfigOnDRD_FS_MQTT_Ptr_Complex](examples/Async_ConfigOnDRD_FS_MQTT_Ptr_Complex) to demo usage of std::map 228 | * [Async_ConfigOnDRD_FS_MQTT_Ptr_Medium](examples/Async_ConfigOnDRD_FS_MQTT_Ptr_Medium). 229 | 4. Add simple minimal examples 230 | * [Async_ConfigOnDRD_ESP32_minimal](examples/Async_ConfigOnDRD_ESP32_minimal) 231 | * [Async_ConfigOnDRD_ESP8266_minimal](examples/Async_ConfigOnDRD_ESP8266_minimal) 232 | * [Async_AutoConnect_ESP32_minimal](examples/Async_AutoConnect_ESP32_minimal) 233 | * [Async_AutoConnect_ESP8266_minimal](examples/Async_AutoConnect_ESP8266_minimal) 234 | 5. Modify Version String 235 | 6. Add Table of Contents 236 | 237 | ### Releases v1.3.0 238 | 239 | 1. Add LittleFS support to ESP32-related examples to use [**LittleFS_esp32 Library**](https://github.com/lorol/LITTLEFS) 240 | 2. Add Version String 241 | 242 | ### Releases v1.2.0 243 | 244 | 1. Restore cpp code besides Impl.h code to use in case of `multiple definition` linker error. See [`Change Implementation to separate *.h and *.cpp file instead of *.h and *-Impl.h`](https://github.com/khoih-prog/ESP_WiFiManager/issues/38) and [`Support building in PlatformIO PR`](https://github.com/khoih-prog/ESP_WiFiManager/pull/20). Also have a look at [**HOWTO Fix Multiple Definitions Linker Error**](https://github.com/khoih-prog/ESPAsync_WiFiManager#HOWTO-Fix-Multiple-Definitions-Linker-Error) 245 | 2. Fix bug [/close does not close the config portal](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues/16). 246 | 247 | ### Releases v1.1.2 248 | 249 | 1. Fix bug in examples. 250 | 251 | ### Major Releases v1.1.1 252 | 253 | 1. Add **MultiWiFi feature to auto(Re)connect to the best WiFi at runtime** 254 | 2. Fix bug, typo and minor improvement. 255 | 3. Completely enhanced examples to use new MultiWiFi feature. 256 | 4. Add setCORSHeader function to allow **configurable CORS Header**. See [Using CORS feature](https://github.com/khoih-prog/ESPAsync_WiFiManager#15-using-cors-cross-origin-resource-sharing-feature) 257 | 5. Bump up to v1.1.1 to sync with [ESP_WiFiManager v1.1.1](https://github.com/khoih-prog/ESP_WiFiManager/releases/tag/v1.1.1). 258 | 259 | ### Releases 1.0.11 260 | 261 | 1. Initial coding to use ESPAsyncWebServer instead of (ESP8266)WebServer. 262 | 2. Add more features and error checking to many examples. 263 | 3. Add example [Async_ConfigOnDRD_FS_MQTT_Ptr](examples/Async_ConfigOnDRD_FS_MQTT_Ptr) 264 | 4. Bump up to v1.0.11 to sync with ESP_WiFiManager v1.0.11. 265 | 266 | 267 | -------------------------------------------------------------------------------- /esp32c3_ESPAsyncWebServer_Patch/WebAuthentication.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Asynchronous WebServer library for Espressif MCUs 3 | 4 | Copyright (c) 2016 Hristo Gochkov. 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 | #include "WebAuthentication.h" 22 | #include 23 | #ifdef ESP32 24 | #include "mbedtls/md5.h" 25 | #include "mbedtls/version.h" 26 | #else 27 | #include "md5.h" 28 | #endif 29 | 30 | 31 | // Basic Auth hash = base64("username:password") 32 | 33 | bool checkBasicAuthentication(const char * hash, const char * username, const char * password) 34 | { 35 | if (username == NULL || password == NULL || hash == NULL) 36 | return false; 37 | 38 | size_t toencodeLen = strlen(username) + strlen(password) + 1; 39 | size_t encodedLen = base64_encode_expected_len(toencodeLen); 40 | 41 | if (strlen(hash) != encodedLen) 42 | return false; 43 | 44 | char *toencode = new char[toencodeLen + 1]; 45 | 46 | if (toencode == NULL) 47 | { 48 | return false; 49 | } 50 | 51 | char *encoded = new char[base64_encode_expected_len(toencodeLen) + 1]; 52 | 53 | if (encoded == NULL) 54 | { 55 | delete[] toencode; 56 | return false; 57 | } 58 | 59 | sprintf(toencode, "%s:%s", username, password); 60 | 61 | if (base64_encode_chars(toencode, toencodeLen, encoded) > 0 && memcmp(hash, encoded, encodedLen) == 0) 62 | { 63 | delete[] toencode; 64 | delete[] encoded; 65 | return true; 66 | } 67 | 68 | delete[] toencode; 69 | delete[] encoded; 70 | return false; 71 | } 72 | 73 | static bool getMD5(uint8_t * data, uint16_t len, char * output) //33 bytes or more 74 | { 75 | #ifdef ESP32 76 | mbedtls_md5_context _ctx; 77 | #else 78 | md5_context_t _ctx; 79 | #endif 80 | uint8_t i; 81 | uint8_t * _buf = (uint8_t*)malloc(16); 82 | 83 | if (_buf == NULL) 84 | return false; 85 | 86 | memset(_buf, 0x00, 16); 87 | #ifdef ESP32 88 | mbedtls_md5_init(&_ctx); 89 | 90 | // KH 91 | #if (MBEDTLS_VERSION_NUMBER < 0x02070000) 92 | #warning MBEDTLS_VERSION_NUMBER < 2.7.0 93 | // Superseded from v2.7.0 94 | mbedtls_md5_starts(&_ctx); 95 | mbedtls_md5_update(&_ctx, data, len); 96 | mbedtls_md5_finish(&_ctx, _buf); 97 | #else 98 | #warning MBEDTLS_VERSION_NUMBER >= 2.7.0 99 | mbedtls_md5_starts_ret(&_ctx); 100 | mbedtls_md5_update_ret(&_ctx, data, len); 101 | mbedtls_md5_finish_ret(&_ctx, _buf); 102 | #endif 103 | ////// 104 | 105 | #else 106 | MD5Init(&_ctx); 107 | MD5Update(&_ctx, data, len); 108 | MD5Final(_buf, &_ctx); 109 | #endif 110 | 111 | for (i = 0; i < 16; i++) 112 | { 113 | sprintf(output + (i * 2), "%02x", _buf[i]); 114 | } 115 | 116 | free(_buf); 117 | return true; 118 | } 119 | 120 | static String genRandomMD5() 121 | { 122 | #ifdef ESP8266 123 | uint32_t r = RANDOM_REG32; 124 | #else 125 | uint32_t r = rand(); 126 | #endif 127 | char * out = (char*)malloc(33); 128 | 129 | if (out == NULL || !getMD5((uint8_t*)(&r), 4, out)) 130 | return ""; 131 | 132 | String res = String(out); 133 | free(out); 134 | return res; 135 | } 136 | 137 | static String stringMD5(const String& in) 138 | { 139 | char * out = (char*)malloc(33); 140 | 141 | if (out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out)) 142 | return ""; 143 | 144 | String res = String(out); 145 | free(out); 146 | return res; 147 | } 148 | 149 | String generateDigestHash(const char * username, const char * password, const char * realm) 150 | { 151 | if (username == NULL || password == NULL || realm == NULL) 152 | { 153 | return ""; 154 | } 155 | 156 | char * out = (char*)malloc(33); 157 | String res = String(username); 158 | res.concat(":"); 159 | res.concat(realm); 160 | res.concat(":"); 161 | String in = res; 162 | in.concat(password); 163 | 164 | if (out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out)) 165 | return ""; 166 | 167 | res.concat(out); 168 | free(out); 169 | return res; 170 | } 171 | 172 | String requestDigestAuthentication(const char * realm) 173 | { 174 | String header = "realm=\""; 175 | 176 | if (realm == NULL) 177 | header.concat("asyncesp"); 178 | else 179 | header.concat(realm); 180 | 181 | header.concat( "\", qop=\"auth\", nonce=\""); 182 | header.concat(genRandomMD5()); 183 | header.concat("\", opaque=\""); 184 | header.concat(genRandomMD5()); 185 | header.concat("\""); 186 | return header; 187 | } 188 | 189 | bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, 190 | const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri) 191 | { 192 | if (username == NULL || password == NULL || header == NULL || method == NULL) 193 | { 194 | //os_printf("AUTH FAIL: missing required fields\n"); 195 | return false; 196 | } 197 | 198 | String myHeader = String(header); 199 | int nextBreak = myHeader.indexOf(","); 200 | 201 | if (nextBreak < 0) 202 | { 203 | //os_printf("AUTH FAIL: no variables\n"); 204 | return false; 205 | } 206 | 207 | String myUsername = String(); 208 | String myRealm = String(); 209 | String myNonce = String(); 210 | String myUri = String(); 211 | String myResponse = String(); 212 | String myQop = String(); 213 | String myNc = String(); 214 | String myCnonce = String(); 215 | 216 | myHeader += ", "; 217 | 218 | do 219 | { 220 | String avLine = myHeader.substring(0, nextBreak); 221 | avLine.trim(); 222 | myHeader = myHeader.substring(nextBreak + 1); 223 | nextBreak = myHeader.indexOf(","); 224 | 225 | int eqSign = avLine.indexOf("="); 226 | 227 | if (eqSign < 0) 228 | { 229 | //os_printf("AUTH FAIL: no = sign\n"); 230 | return false; 231 | } 232 | 233 | String varName = avLine.substring(0, eqSign); 234 | avLine = avLine.substring(eqSign + 1); 235 | 236 | if (avLine.startsWith("\"")) 237 | { 238 | avLine = avLine.substring(1, avLine.length() - 1); 239 | } 240 | 241 | if (varName.equals("username")) 242 | { 243 | if (!avLine.equals(username)) 244 | { 245 | //os_printf("AUTH FAIL: username\n"); 246 | return false; 247 | } 248 | 249 | myUsername = avLine; 250 | } 251 | else if (varName.equals("realm")) 252 | { 253 | if (realm != NULL && !avLine.equals(realm)) 254 | { 255 | //os_printf("AUTH FAIL: realm\n"); 256 | return false; 257 | } 258 | 259 | myRealm = avLine; 260 | } 261 | else if (varName.equals("nonce")) 262 | { 263 | if (nonce != NULL && !avLine.equals(nonce)) 264 | { 265 | //os_printf("AUTH FAIL: nonce\n"); 266 | return false; 267 | } 268 | 269 | myNonce = avLine; 270 | } 271 | else if (varName.equals("opaque")) 272 | { 273 | if (opaque != NULL && !avLine.equals(opaque)) 274 | { 275 | //os_printf("AUTH FAIL: opaque\n"); 276 | return false; 277 | } 278 | } 279 | else if (varName.equals("uri")) 280 | { 281 | if (uri != NULL && !avLine.equals(uri)) 282 | { 283 | //os_printf("AUTH FAIL: uri\n"); 284 | return false; 285 | } 286 | 287 | myUri = avLine; 288 | } 289 | else if (varName.equals("response")) 290 | { 291 | myResponse = avLine; 292 | } 293 | else if (varName.equals("qop")) 294 | { 295 | myQop = avLine; 296 | } 297 | else if (varName.equals("nc")) 298 | { 299 | myNc = avLine; 300 | } 301 | else if (varName.equals("cnonce")) 302 | { 303 | myCnonce = avLine; 304 | } 305 | } while (nextBreak > 0); 306 | 307 | String ha1 = (passwordIsHash) ? String(password) : stringMD5(myUsername + ":" + myRealm + ":" + String(password)); 308 | String ha2 = String(method) + ":" + myUri; 309 | String response = ha1 + ":" + myNonce + ":" + myNc + ":" + myCnonce + ":" + myQop + ":" + stringMD5(ha2); 310 | 311 | if (myResponse.equals(stringMD5(response))) 312 | { 313 | //os_printf("AUTH SUCCESS\n"); 314 | return true; 315 | } 316 | 317 | //os_printf("AUTH FAIL: password\n"); 318 | return false; 319 | } 320 | -------------------------------------------------------------------------------- /esp32s2_WebServer_Patch/WebServer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WebServer.cpp - Dead simple web-server. 3 | Supports only one simultaneous client, knows how to handle GET and POST. 4 | 5 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 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 | Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) 21 | */ 22 | 23 | // KH, Using "WebServer.handleClient delay" (https://github.com/espressif/arduino-esp32/pull/4350) 24 | 25 | #include 26 | #include 27 | #include 28 | #include "WiFiServer.h" 29 | #include "WiFiClient.h" 30 | #include "WebServer.h" 31 | #include "FS.h" 32 | #include "detail/RequestHandlersImpl.h" 33 | #include "mbedtls/md5.h" 34 | 35 | 36 | static const char AUTHORIZATION_HEADER[] = "Authorization"; 37 | static const char qop_auth[] = "qop=\"auth\""; 38 | static const char WWW_Authenticate[] = "WWW-Authenticate"; 39 | static const char Content_Length[] = "Content-Length"; 40 | 41 | 42 | WebServer::WebServer(IPAddress addr, int port) 43 | : _corsEnabled(false) 44 | , _server(addr, port) 45 | , _currentMethod(HTTP_ANY) 46 | , _currentVersion(0) 47 | , _currentStatus(HC_NONE) 48 | , _statusChange(0) 49 | , _nullDelay(true) 50 | , _currentHandler(nullptr) 51 | , _firstHandler(nullptr) 52 | , _lastHandler(nullptr) 53 | , _currentArgCount(0) 54 | , _currentArgs(nullptr) 55 | , _postArgsLen(0) 56 | , _postArgs(nullptr) 57 | , _headerKeysCount(0) 58 | , _currentHeaders(nullptr) 59 | , _contentLength(0) 60 | , _chunked(false) 61 | { 62 | } 63 | 64 | WebServer::WebServer(int port) 65 | : _corsEnabled(false) 66 | , _server(port) 67 | , _currentMethod(HTTP_ANY) 68 | , _currentVersion(0) 69 | , _currentStatus(HC_NONE) 70 | , _statusChange(0) 71 | , _nullDelay(true) 72 | , _currentHandler(nullptr) 73 | , _firstHandler(nullptr) 74 | , _lastHandler(nullptr) 75 | , _currentArgCount(0) 76 | , _currentArgs(nullptr) 77 | , _postArgsLen(0) 78 | , _postArgs(nullptr) 79 | , _headerKeysCount(0) 80 | , _currentHeaders(nullptr) 81 | , _contentLength(0) 82 | , _chunked(false) 83 | { 84 | } 85 | 86 | WebServer::~WebServer() 87 | { 88 | _server.close(); 89 | 90 | if (_currentHeaders) 91 | delete[]_currentHeaders; 92 | 93 | RequestHandler* handler = _firstHandler; 94 | 95 | while (handler) 96 | { 97 | RequestHandler* next = handler->next(); 98 | delete handler; 99 | handler = next; 100 | } 101 | } 102 | 103 | void WebServer::begin() 104 | { 105 | close(); 106 | _server.begin(); 107 | _server.setNoDelay(true); 108 | } 109 | 110 | void WebServer::begin(uint16_t port) 111 | { 112 | close(); 113 | _server.begin(port); 114 | _server.setNoDelay(true); 115 | } 116 | 117 | String WebServer::_extractParam(String& authReq, const String& param, const char delimit) 118 | { 119 | int _begin = authReq.indexOf(param); 120 | 121 | if (_begin == -1) 122 | return ""; 123 | 124 | return authReq.substring(_begin + param.length(), authReq.indexOf(delimit, _begin + param.length())); 125 | } 126 | 127 | static String md5str(String &in) 128 | { 129 | char out[33] = {0}; 130 | mbedtls_md5_context _ctx; 131 | uint8_t i; 132 | uint8_t * _buf = (uint8_t*)malloc(16); 133 | 134 | if (_buf == NULL) 135 | return String(out); 136 | 137 | memset(_buf, 0x00, 16); 138 | mbedtls_md5_init(&_ctx); 139 | mbedtls_md5_starts(&_ctx); 140 | mbedtls_md5_update(&_ctx, (const uint8_t *)in.c_str(), in.length()); 141 | mbedtls_md5_finish(&_ctx, _buf); 142 | 143 | for (i = 0; i < 16; i++) 144 | { 145 | sprintf(out + (i * 2), "%02x", _buf[i]); 146 | } 147 | 148 | out[32] = 0; 149 | free(_buf); 150 | return String(out); 151 | } 152 | 153 | bool WebServer::authenticate(const char * username, const char * password) 154 | { 155 | if (hasHeader(FPSTR(AUTHORIZATION_HEADER))) 156 | { 157 | String authReq = header(FPSTR(AUTHORIZATION_HEADER)); 158 | 159 | if (authReq.startsWith(F("Basic"))) 160 | { 161 | authReq = authReq.substring(6); 162 | authReq.trim(); 163 | char toencodeLen = strlen(username) + strlen(password) + 1; 164 | char *toencode = new char[toencodeLen + 1]; 165 | 166 | if (toencode == NULL) 167 | { 168 | authReq = ""; 169 | return false; 170 | } 171 | 172 | char *encoded = new char[base64_encode_expected_len(toencodeLen) + 1]; 173 | 174 | if (encoded == NULL) 175 | { 176 | authReq = ""; 177 | delete[] toencode; 178 | return false; 179 | } 180 | 181 | sprintf(toencode, "%s:%s", username, password); 182 | 183 | if (base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq.equalsConstantTime(encoded)) 184 | { 185 | authReq = ""; 186 | delete[] toencode; 187 | delete[] encoded; 188 | return true; 189 | } 190 | 191 | delete[] toencode; 192 | delete[] encoded; 193 | } 194 | else if (authReq.startsWith(F("Digest"))) 195 | { 196 | authReq = authReq.substring(7); 197 | log_v("%s", authReq.c_str()); 198 | String _username = _extractParam(authReq, F("username=\""), '\"'); 199 | 200 | if (!_username.length() || _username != String(username)) 201 | { 202 | authReq = ""; 203 | return false; 204 | } 205 | 206 | // extracting required parameters for RFC 2069 simpler Digest 207 | String _realm = _extractParam(authReq, F("realm=\""), '\"'); 208 | String _nonce = _extractParam(authReq, F("nonce=\""), '\"'); 209 | String _uri = _extractParam(authReq, F("uri=\""), '\"'); 210 | String _response = _extractParam(authReq, F("response=\""), '\"'); 211 | String _opaque = _extractParam(authReq, F("opaque=\""), '\"'); 212 | 213 | if ((!_realm.length()) || (!_nonce.length()) || (!_uri.length()) || (!_response.length()) || (!_opaque.length())) 214 | { 215 | authReq = ""; 216 | return false; 217 | } 218 | 219 | if ((_opaque != _sopaque) || (_nonce != _snonce) || (_realm != _srealm)) 220 | { 221 | authReq = ""; 222 | return false; 223 | } 224 | 225 | // parameters for the RFC 2617 newer Digest 226 | String _nc, _cnonce; 227 | 228 | if (authReq.indexOf(FPSTR(qop_auth)) != -1) 229 | { 230 | _nc = _extractParam(authReq, F("nc="), ','); 231 | _cnonce = _extractParam(authReq, F("cnonce=\""), '\"'); 232 | } 233 | 234 | String _H1 = md5str(String(username) + ':' + _realm + ':' + String(password)); 235 | log_v("Hash of user:realm:pass=%s", _H1.c_str()); 236 | String _H2 = ""; 237 | 238 | if (_currentMethod == HTTP_GET) 239 | { 240 | _H2 = md5str(String(F("GET:")) + _uri); 241 | } 242 | else if (_currentMethod == HTTP_POST) 243 | { 244 | _H2 = md5str(String(F("POST:")) + _uri); 245 | } 246 | else if (_currentMethod == HTTP_PUT) 247 | { 248 | _H2 = md5str(String(F("PUT:")) + _uri); 249 | } 250 | else if (_currentMethod == HTTP_DELETE) 251 | { 252 | _H2 = md5str(String(F("DELETE:")) + _uri); 253 | } 254 | else 255 | { 256 | _H2 = md5str(String(F("GET:")) + _uri); 257 | } 258 | 259 | log_v("Hash of GET:uri=%s", _H2.c_str()); 260 | String _responsecheck = ""; 261 | 262 | if (authReq.indexOf(FPSTR(qop_auth)) != -1) 263 | { 264 | _responsecheck = md5str(_H1 + ':' + _nonce + ':' + _nc + ':' + _cnonce + F(":auth:") + _H2); 265 | } 266 | else 267 | { 268 | _responsecheck = md5str(_H1 + ':' + _nonce + ':' + _H2); 269 | } 270 | 271 | log_v("The Proper response=%s", _responsecheck.c_str()); 272 | 273 | if (_response == _responsecheck) 274 | { 275 | authReq = ""; 276 | return true; 277 | } 278 | } 279 | 280 | authReq = ""; 281 | } 282 | 283 | return false; 284 | } 285 | 286 | String WebServer::_getRandomHexString() 287 | { 288 | char buffer[33]; // buffer to hold 32 Hex Digit + /0 289 | int i; 290 | 291 | for (i = 0; i < 4; i++) 292 | { 293 | sprintf (buffer + (i * 8), "%08x", esp_random()); 294 | } 295 | 296 | return String(buffer); 297 | } 298 | 299 | void WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg) 300 | { 301 | if (realm == NULL) 302 | { 303 | _srealm = String(F("Login Required")); 304 | } 305 | else 306 | { 307 | _srealm = String(realm); 308 | } 309 | 310 | if (mode == BASIC_AUTH) 311 | { 312 | sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Basic realm=\"")) + _srealm + String(F("\""))); 313 | } 314 | else 315 | { 316 | _snonce = _getRandomHexString(); 317 | _sopaque = _getRandomHexString(); 318 | sendHeader(String(FPSTR(WWW_Authenticate)), 319 | String(F("Digest realm=\"")) + _srealm + String(F("\", qop=\"auth\", nonce=\"")) + _snonce + String( 320 | F("\", opaque=\"")) + _sopaque + String(F("\""))); 321 | } 322 | 323 | using namespace mime; 324 | send(401, String(FPSTR(mimeTable[html].mimeType)), authFailMsg); 325 | } 326 | 327 | void WebServer::on(const Uri &uri, WebServer::THandlerFunction handler) 328 | { 329 | on(uri, HTTP_ANY, handler); 330 | } 331 | 332 | void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn) 333 | { 334 | on(uri, method, fn, _fileUploadHandler); 335 | } 336 | 337 | void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) 338 | { 339 | _addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method)); 340 | } 341 | 342 | void WebServer::addHandler(RequestHandler* handler) 343 | { 344 | _addRequestHandler(handler); 345 | } 346 | 347 | void WebServer::_addRequestHandler(RequestHandler* handler) 348 | { 349 | if (!_lastHandler) 350 | { 351 | _firstHandler = handler; 352 | _lastHandler = handler; 353 | } 354 | else 355 | { 356 | _lastHandler->next(handler); 357 | _lastHandler = handler; 358 | } 359 | } 360 | 361 | void WebServer::serveStatic(const char* uri, FS& fs, const char* path, const char* cache_header) 362 | { 363 | _addRequestHandler(new StaticRequestHandler(fs, path, uri, cache_header)); 364 | } 365 | 366 | void WebServer::handleClient() 367 | { 368 | if (_currentStatus == HC_NONE) 369 | { 370 | WiFiClient client = _server.available(); 371 | 372 | if (!client) 373 | { 374 | if (_nullDelay) 375 | { 376 | delay(1); 377 | } 378 | 379 | return; 380 | } 381 | 382 | log_v("New client"); 383 | 384 | _currentClient = client; 385 | _currentStatus = HC_WAIT_READ; 386 | _statusChange = millis(); 387 | } 388 | 389 | bool keepCurrentClient = false; 390 | bool callYield = false; 391 | 392 | if (_currentClient.connected()) 393 | { 394 | switch (_currentStatus) 395 | { 396 | case HC_NONE: 397 | // No-op to avoid C++ compiler warning 398 | break; 399 | 400 | case HC_WAIT_READ: 401 | 402 | // Wait for data from client to become available 403 | if (_currentClient.available()) 404 | { 405 | if (_parseRequest(_currentClient)) 406 | { 407 | // because HTTP_MAX_SEND_WAIT is expressed in milliseconds, 408 | // it must be divided by 1000 409 | _currentClient.setTimeout(HTTP_MAX_SEND_WAIT / 1000); 410 | _contentLength = CONTENT_LENGTH_NOT_SET; 411 | _handleRequest(); 412 | 413 | // Fix for issue with Chrome based browsers: https://github.com/espressif/arduino-esp32/issues/3652 414 | // if (_currentClient.connected()) { 415 | // _currentStatus = HC_WAIT_CLOSE; 416 | // _statusChange = millis(); 417 | // keepCurrentClient = true; 418 | // } 419 | } 420 | } 421 | else // !_currentClient.available() 422 | { 423 | if (millis() - _statusChange <= HTTP_MAX_DATA_WAIT) 424 | { 425 | keepCurrentClient = true; 426 | } 427 | 428 | callYield = true; 429 | } 430 | 431 | break; 432 | 433 | case HC_WAIT_CLOSE: 434 | 435 | // Wait for client to close the connection 436 | if (millis() - _statusChange <= HTTP_MAX_CLOSE_WAIT) 437 | { 438 | keepCurrentClient = true; 439 | callYield = true; 440 | } 441 | } 442 | } 443 | 444 | if (!keepCurrentClient) 445 | { 446 | _currentClient = WiFiClient(); 447 | _currentStatus = HC_NONE; 448 | _currentUpload.reset(); 449 | } 450 | 451 | if (callYield) 452 | { 453 | yield(); 454 | } 455 | } 456 | 457 | void WebServer::close() 458 | { 459 | _server.close(); 460 | _currentStatus = HC_NONE; 461 | 462 | if (!_headerKeysCount) 463 | collectHeaders(0, 0); 464 | } 465 | 466 | void WebServer::stop() 467 | { 468 | close(); 469 | } 470 | 471 | void WebServer::sendHeader(const String& name, const String& value, bool first) 472 | { 473 | String headerLine = name; 474 | headerLine += F(": "); 475 | headerLine += value; 476 | headerLine += "\r\n"; 477 | 478 | if (first) 479 | { 480 | _responseHeaders = headerLine + _responseHeaders; 481 | } 482 | else 483 | { 484 | _responseHeaders += headerLine; 485 | } 486 | } 487 | 488 | void WebServer::setContentLength(const size_t contentLength) 489 | { 490 | _contentLength = contentLength; 491 | } 492 | 493 | void WebServer::enableDelay(boolean value) 494 | { 495 | _nullDelay = value; 496 | } 497 | 498 | void WebServer::enableCORS(boolean value) 499 | { 500 | _corsEnabled = value; 501 | } 502 | 503 | void WebServer::enableCrossOrigin(boolean value) 504 | { 505 | enableCORS(value); 506 | } 507 | 508 | void WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) 509 | { 510 | response = String(F("HTTP/1.")) + String(_currentVersion) + ' '; 511 | response += String(code); 512 | response += ' '; 513 | response += _responseCodeToString(code); 514 | response += "\r\n"; 515 | 516 | using namespace mime; 517 | 518 | if (!content_type) 519 | content_type = mimeTable[html].mimeType; 520 | 521 | sendHeader(String(F("Content-Type")), String(FPSTR(content_type)), true); 522 | 523 | if (_contentLength == CONTENT_LENGTH_NOT_SET) 524 | { 525 | sendHeader(String(FPSTR(Content_Length)), String(contentLength)); 526 | } 527 | else if (_contentLength != CONTENT_LENGTH_UNKNOWN) 528 | { 529 | sendHeader(String(FPSTR(Content_Length)), String(_contentLength)); 530 | } 531 | else if (_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion) //HTTP/1.1 or above client 532 | { 533 | //let's do chunked 534 | _chunked = true; 535 | sendHeader(String(F("Accept-Ranges")), String(F("none"))); 536 | sendHeader(String(F("Transfer-Encoding")), String(F("chunked"))); 537 | } 538 | 539 | if (_corsEnabled) 540 | { 541 | sendHeader(String(FPSTR("Access-Control-Allow-Origin")), String("*")); 542 | } 543 | 544 | sendHeader(String(F("Connection")), String(F("close"))); 545 | 546 | response += _responseHeaders; 547 | response += "\r\n"; 548 | _responseHeaders = ""; 549 | } 550 | 551 | void WebServer::send(int code, const char* content_type, const String& content) 552 | { 553 | String header; 554 | // Can we assume the following? 555 | //if(code == 200 && content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET) 556 | // _contentLength = CONTENT_LENGTH_UNKNOWN; 557 | _prepareHeader(header, code, content_type, content.length()); 558 | _currentClientWrite(header.c_str(), header.length()); 559 | 560 | if (content.length()) 561 | sendContent(content); 562 | } 563 | 564 | void WebServer::send_P(int code, PGM_P content_type, PGM_P content) 565 | { 566 | size_t contentLength = 0; 567 | 568 | if (content != NULL) 569 | { 570 | contentLength = strlen_P(content); 571 | } 572 | 573 | String header; 574 | char type[64]; 575 | memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type)); 576 | _prepareHeader(header, code, (const char* )type, contentLength); 577 | _currentClientWrite(header.c_str(), header.length()); 578 | sendContent_P(content); 579 | } 580 | 581 | void WebServer::send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength) 582 | { 583 | String header; 584 | char type[64]; 585 | memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type)); 586 | _prepareHeader(header, code, (const char* )type, contentLength); 587 | sendContent(header); 588 | sendContent_P(content, contentLength); 589 | } 590 | 591 | void WebServer::send(int code, char* content_type, const String& content) 592 | { 593 | send(code, (const char*)content_type, content); 594 | } 595 | 596 | void WebServer::send(int code, const String& content_type, const String& content) 597 | { 598 | send(code, (const char*)content_type.c_str(), content); 599 | } 600 | 601 | void WebServer::sendContent(const String& content) 602 | { 603 | sendContent(content.c_str(), content.length()); 604 | } 605 | 606 | void WebServer::sendContent(const char* content, size_t contentLength) 607 | { 608 | const char * footer = "\r\n"; 609 | 610 | if (_chunked) 611 | { 612 | char * chunkSize = (char *)malloc(11); 613 | 614 | if (chunkSize) 615 | { 616 | sprintf(chunkSize, "%x%s", contentLength, footer); 617 | _currentClientWrite(chunkSize, strlen(chunkSize)); 618 | free(chunkSize); 619 | } 620 | } 621 | 622 | _currentClientWrite(content, contentLength); 623 | 624 | if (_chunked) 625 | { 626 | _currentClient.write(footer, 2); 627 | 628 | if (contentLength == 0) 629 | { 630 | _chunked = false; 631 | } 632 | } 633 | } 634 | 635 | void WebServer::sendContent_P(PGM_P content) 636 | { 637 | sendContent_P(content, strlen_P(content)); 638 | } 639 | 640 | void WebServer::sendContent_P(PGM_P content, size_t size) 641 | { 642 | const char * footer = "\r\n"; 643 | 644 | if (_chunked) 645 | { 646 | char * chunkSize = (char *)malloc(11); 647 | 648 | if (chunkSize) 649 | { 650 | sprintf(chunkSize, "%x%s", size, footer); 651 | _currentClientWrite(chunkSize, strlen(chunkSize)); 652 | free(chunkSize); 653 | } 654 | } 655 | 656 | _currentClientWrite_P(content, size); 657 | 658 | if (_chunked) 659 | { 660 | _currentClient.write(footer, 2); 661 | 662 | if (size == 0) 663 | { 664 | _chunked = false; 665 | } 666 | } 667 | } 668 | 669 | 670 | void WebServer::_streamFileCore(const size_t fileSize, const String & fileName, const String & contentType) 671 | { 672 | using namespace mime; 673 | setContentLength(fileSize); 674 | 675 | if (fileName.endsWith(String(FPSTR(mimeTable[gz].endsWith))) && 676 | contentType != String(FPSTR(mimeTable[gz].mimeType)) && 677 | contentType != String(FPSTR(mimeTable[none].mimeType))) 678 | { 679 | sendHeader(F("Content-Encoding"), F("gzip")); 680 | } 681 | 682 | send(200, contentType, ""); 683 | } 684 | 685 | String WebServer::pathArg(unsigned int i) 686 | { 687 | if (_currentHandler != nullptr) 688 | return _currentHandler->pathArg(i); 689 | 690 | return ""; 691 | } 692 | 693 | String WebServer::arg(String name) 694 | { 695 | for (int j = 0; j < _postArgsLen; ++j) 696 | { 697 | if ( _postArgs[j].key == name ) 698 | return _postArgs[j].value; 699 | } 700 | 701 | for (int i = 0; i < _currentArgCount; ++i) 702 | { 703 | if ( _currentArgs[i].key == name ) 704 | return _currentArgs[i].value; 705 | } 706 | 707 | return ""; 708 | } 709 | 710 | String WebServer::arg(int i) 711 | { 712 | if (i < _currentArgCount) 713 | return _currentArgs[i].value; 714 | 715 | return ""; 716 | } 717 | 718 | String WebServer::argName(int i) 719 | { 720 | if (i < _currentArgCount) 721 | return _currentArgs[i].key; 722 | 723 | return ""; 724 | } 725 | 726 | int WebServer::args() 727 | { 728 | return _currentArgCount; 729 | } 730 | 731 | bool WebServer::hasArg(String name) 732 | { 733 | for (int j = 0; j < _postArgsLen; ++j) 734 | { 735 | if (_postArgs[j].key == name) 736 | return true; 737 | } 738 | 739 | for (int i = 0; i < _currentArgCount; ++i) 740 | { 741 | if (_currentArgs[i].key == name) 742 | return true; 743 | } 744 | 745 | return false; 746 | } 747 | 748 | 749 | String WebServer::header(String name) 750 | { 751 | for (int i = 0; i < _headerKeysCount; ++i) 752 | { 753 | if (_currentHeaders[i].key.equalsIgnoreCase(name)) 754 | return _currentHeaders[i].value; 755 | } 756 | 757 | return ""; 758 | } 759 | 760 | void WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) 761 | { 762 | _headerKeysCount = headerKeysCount + 1; 763 | 764 | if (_currentHeaders) 765 | delete[]_currentHeaders; 766 | 767 | _currentHeaders = new RequestArgument[_headerKeysCount]; 768 | _currentHeaders[0].key = FPSTR(AUTHORIZATION_HEADER); 769 | 770 | for (int i = 1; i < _headerKeysCount; i++) 771 | { 772 | _currentHeaders[i].key = headerKeys[i - 1]; 773 | } 774 | } 775 | 776 | String WebServer::header(int i) 777 | { 778 | if (i < _headerKeysCount) 779 | return _currentHeaders[i].value; 780 | 781 | return ""; 782 | } 783 | 784 | String WebServer::headerName(int i) 785 | { 786 | if (i < _headerKeysCount) 787 | return _currentHeaders[i].key; 788 | 789 | return ""; 790 | } 791 | 792 | int WebServer::headers() 793 | { 794 | return _headerKeysCount; 795 | } 796 | 797 | bool WebServer::hasHeader(String name) 798 | { 799 | for (int i = 0; i < _headerKeysCount; ++i) 800 | { 801 | if ((_currentHeaders[i].key.equalsIgnoreCase(name)) && (_currentHeaders[i].value.length() > 0)) 802 | return true; 803 | } 804 | 805 | return false; 806 | } 807 | 808 | String WebServer::hostHeader() 809 | { 810 | return _hostHeader; 811 | } 812 | 813 | void WebServer::onFileUpload(THandlerFunction fn) 814 | { 815 | _fileUploadHandler = fn; 816 | } 817 | 818 | void WebServer::onNotFound(THandlerFunction fn) 819 | { 820 | _notFoundHandler = fn; 821 | } 822 | 823 | void WebServer::_handleRequest() 824 | { 825 | bool handled = false; 826 | 827 | if (!_currentHandler) 828 | { 829 | log_e("request handler not found"); 830 | } 831 | else 832 | { 833 | handled = _currentHandler->handle(*this, _currentMethod, _currentUri); 834 | 835 | if (!handled) 836 | { 837 | log_e("request handler failed to handle request"); 838 | } 839 | } 840 | 841 | if (!handled && _notFoundHandler) 842 | { 843 | _notFoundHandler(); 844 | handled = true; 845 | } 846 | 847 | if (!handled) 848 | { 849 | using namespace mime; 850 | send(404, String(FPSTR(mimeTable[html].mimeType)), String(F("Not found: ")) + _currentUri); 851 | handled = true; 852 | } 853 | 854 | if (handled) 855 | { 856 | _finalizeResponse(); 857 | } 858 | 859 | _currentUri = ""; 860 | } 861 | 862 | 863 | void WebServer::_finalizeResponse() 864 | { 865 | if (_chunked) 866 | { 867 | sendContent(""); 868 | } 869 | } 870 | 871 | String WebServer::_responseCodeToString(int code) 872 | { 873 | switch (code) 874 | { 875 | case 100: 876 | return F("Continue"); 877 | 878 | case 101: 879 | return F("Switching Protocols"); 880 | 881 | case 200: 882 | return F("OK"); 883 | 884 | case 201: 885 | return F("Created"); 886 | 887 | case 202: 888 | return F("Accepted"); 889 | 890 | case 203: 891 | return F("Non-Authoritative Information"); 892 | 893 | case 204: 894 | return F("No Content"); 895 | 896 | case 205: 897 | return F("Reset Content"); 898 | 899 | case 206: 900 | return F("Partial Content"); 901 | 902 | case 300: 903 | return F("Multiple Choices"); 904 | 905 | case 301: 906 | return F("Moved Permanently"); 907 | 908 | case 302: 909 | return F("Found"); 910 | 911 | case 303: 912 | return F("See Other"); 913 | 914 | case 304: 915 | return F("Not Modified"); 916 | 917 | case 305: 918 | return F("Use Proxy"); 919 | 920 | case 307: 921 | return F("Temporary Redirect"); 922 | 923 | case 400: 924 | return F("Bad Request"); 925 | 926 | case 401: 927 | return F("Unauthorized"); 928 | 929 | case 402: 930 | return F("Payment Required"); 931 | 932 | case 403: 933 | return F("Forbidden"); 934 | 935 | case 404: 936 | return F("Not Found"); 937 | 938 | case 405: 939 | return F("Method Not Allowed"); 940 | 941 | case 406: 942 | return F("Not Acceptable"); 943 | 944 | case 407: 945 | return F("Proxy Authentication Required"); 946 | 947 | case 408: 948 | return F("Request Time-out"); 949 | 950 | case 409: 951 | return F("Conflict"); 952 | 953 | case 410: 954 | return F("Gone"); 955 | 956 | case 411: 957 | return F("Length Required"); 958 | 959 | case 412: 960 | return F("Precondition Failed"); 961 | 962 | case 413: 963 | return F("Request Entity Too Large"); 964 | 965 | case 414: 966 | return F("Request-URI Too Large"); 967 | 968 | case 415: 969 | return F("Unsupported Media Type"); 970 | 971 | case 416: 972 | return F("Requested range not satisfiable"); 973 | 974 | case 417: 975 | return F("Expectation Failed"); 976 | 977 | case 500: 978 | return F("Internal Server Error"); 979 | 980 | case 501: 981 | return F("Not Implemented"); 982 | 983 | case 502: 984 | return F("Bad Gateway"); 985 | 986 | case 503: 987 | return F("Service Unavailable"); 988 | 989 | case 504: 990 | return F("Gateway Time-out"); 991 | 992 | case 505: 993 | return F("HTTP Version not supported"); 994 | 995 | default: 996 | return F(""); 997 | } 998 | } 999 | -------------------------------------------------------------------------------- /esp32s2_WebServer_Patch/WebServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | WebServer.h - Dead simple web-server. 3 | Supports only one simultaneous client, knows how to handle GET and POST. 4 | 5 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 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 | Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) 21 | */ 22 | 23 | 24 | #ifndef WEBSERVER_H 25 | #define WEBSERVER_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include "HTTP_Method.h" 31 | #include "Uri.h" 32 | 33 | enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END, 34 | UPLOAD_FILE_ABORTED 35 | }; 36 | enum HTTPClientStatus { HC_NONE, HC_WAIT_READ, HC_WAIT_CLOSE }; 37 | enum HTTPAuthMethod { BASIC_AUTH, DIGEST_AUTH }; 38 | 39 | #define HTTP_DOWNLOAD_UNIT_SIZE 1436 40 | 41 | #ifndef HTTP_UPLOAD_BUFLEN 42 | #define HTTP_UPLOAD_BUFLEN 1436 43 | #endif 44 | 45 | #define HTTP_MAX_DATA_WAIT 5000 //ms to wait for the client to send the request 46 | #define HTTP_MAX_POST_WAIT 5000 //ms to wait for POST data to arrive 47 | #define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed 48 | #define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection 49 | 50 | #define CONTENT_LENGTH_UNKNOWN ((size_t) -1) 51 | #define CONTENT_LENGTH_NOT_SET ((size_t) -2) 52 | 53 | class WebServer; 54 | 55 | typedef struct 56 | { 57 | HTTPUploadStatus status; 58 | String filename; 59 | String name; 60 | String type; 61 | size_t totalSize; // file size 62 | size_t currentSize; // size of data currently in buf 63 | uint8_t buf[HTTP_UPLOAD_BUFLEN]; 64 | } HTTPUpload; 65 | 66 | #include "detail/RequestHandler.h" 67 | 68 | namespace fs 69 | { 70 | class FS; 71 | } 72 | 73 | class WebServer 74 | { 75 | public: 76 | WebServer(IPAddress addr, int port = 80); 77 | WebServer(int port = 80); 78 | virtual ~WebServer(); 79 | 80 | virtual void begin(); 81 | virtual void begin(uint16_t port); 82 | virtual void handleClient(); 83 | 84 | virtual void close(); 85 | void stop(); 86 | 87 | bool authenticate(const char * username, const char * password); 88 | void requestAuthentication(HTTPAuthMethod mode = BASIC_AUTH, const char* realm = NULL, 89 | const String& authFailMsg = String("") ); 90 | 91 | typedef std::function THandlerFunction; 92 | void on(const Uri &uri, THandlerFunction handler); 93 | void on(const Uri &uri, HTTPMethod method, THandlerFunction fn); 94 | void on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); 95 | void addHandler(RequestHandler* handler); 96 | void serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header = NULL ); 97 | void onNotFound(THandlerFunction fn); //called when handler is not assigned 98 | void onFileUpload(THandlerFunction fn); //handle file uploads 99 | 100 | String uri() 101 | { 102 | return _currentUri; 103 | } 104 | HTTPMethod method() 105 | { 106 | return _currentMethod; 107 | } 108 | virtual WiFiClient client() 109 | { 110 | return _currentClient; 111 | } 112 | HTTPUpload& upload() 113 | { 114 | return *_currentUpload; 115 | } 116 | 117 | String pathArg(unsigned int i); // get request path argument by number 118 | String arg(String name); // get request argument value by name 119 | String arg(int i); // get request argument value by number 120 | String argName(int i); // get request argument name by number 121 | int args(); // get arguments count 122 | bool hasArg(String name); // check if argument exists 123 | void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); // set the request headers to collect 124 | String header(String name); // get request header value by name 125 | String header(int i); // get request header value by number 126 | String headerName(int i); // get request header name by number 127 | int headers(); // get header count 128 | bool hasHeader(String name); // check if header exists 129 | 130 | String hostHeader(); // get request host header if available or empty String if not 131 | 132 | // send response to the client 133 | // code - HTTP response code, can be 200 or 404 134 | // content_type - HTTP content type, like "text/plain" or "image/png" 135 | // content - actual content body 136 | void send(int code, const char* content_type = NULL, const String& content = String("")); 137 | void send(int code, char* content_type, const String& content); 138 | void send(int code, const String& content_type, const String& content); 139 | void send_P(int code, PGM_P content_type, PGM_P content); 140 | void send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength); 141 | 142 | void enableDelay(boolean value); 143 | void enableCORS(boolean value = true); 144 | void enableCrossOrigin(boolean value = true); 145 | 146 | void setContentLength(const size_t contentLength); 147 | void sendHeader(const String& name, const String& value, bool first = false); 148 | void sendContent(const String& content); 149 | void sendContent(const char* content, size_t contentLength); 150 | void sendContent_P(PGM_P content); 151 | void sendContent_P(PGM_P content, size_t size); 152 | 153 | static String urlDecode(const String& text); 154 | 155 | template 156 | size_t streamFile(T &file, const String& contentType) 157 | { 158 | _streamFileCore(file.size(), file.name(), contentType); 159 | return _currentClient.write(file); 160 | } 161 | 162 | protected: 163 | virtual size_t _currentClientWrite(const char* b, size_t l) 164 | { 165 | return _currentClient.write( b, l ); 166 | } 167 | virtual size_t _currentClientWrite_P(PGM_P b, size_t l) 168 | { 169 | return _currentClient.write_P( b, l ); 170 | } 171 | void _addRequestHandler(RequestHandler* handler); 172 | void _handleRequest(); 173 | void _finalizeResponse(); 174 | bool _parseRequest(WiFiClient& client); 175 | void _parseArguments(String data); 176 | static String _responseCodeToString(int code); 177 | bool _parseForm(WiFiClient& client, String boundary, uint32_t len); 178 | bool _parseFormUploadAborted(); 179 | void _uploadWriteByte(uint8_t b); 180 | int _uploadReadByte(WiFiClient& client); 181 | void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength); 182 | bool _collectHeader(const char* headerName, const char* headerValue); 183 | 184 | void _streamFileCore(const size_t fileSize, const String & fileName, const String & contentType); 185 | 186 | String _getRandomHexString(); 187 | // for extracting Auth parameters 188 | String _extractParam(String& authReq, const String& param, const char delimit = '"'); 189 | 190 | struct RequestArgument 191 | { 192 | String key; 193 | String value; 194 | }; 195 | 196 | boolean _corsEnabled; 197 | WiFiServer _server; 198 | 199 | WiFiClient _currentClient; 200 | HTTPMethod _currentMethod; 201 | String _currentUri; 202 | uint8_t _currentVersion; 203 | HTTPClientStatus _currentStatus; 204 | unsigned long _statusChange; 205 | bool _nullDelay; 206 | 207 | RequestHandler* _currentHandler; 208 | RequestHandler* _firstHandler; 209 | RequestHandler* _lastHandler; 210 | THandlerFunction _notFoundHandler; 211 | THandlerFunction _fileUploadHandler; 212 | 213 | int _currentArgCount; 214 | RequestArgument* _currentArgs; 215 | int _postArgsLen; 216 | RequestArgument* _postArgs; 217 | 218 | std::unique_ptr _currentUpload; 219 | 220 | int _headerKeysCount; 221 | RequestArgument* _currentHeaders; 222 | size_t _contentLength; 223 | String _responseHeaders; 224 | 225 | String _hostHeader; 226 | bool _chunked; 227 | 228 | String _snonce; // Store noance and opaque for future comparison 229 | String _sopaque; 230 | String _srealm; // Store the Auth realm between Calls 231 | 232 | }; 233 | 234 | 235 | #endif //ESP8266WEBSERVER_H 236 | -------------------------------------------------------------------------------- /examples/Async_AutoConnect/Async_AutoConnect.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Async_AutoConnect.ino 3 | For ESP8266 / ESP32 boards 4 | 5 | ESPAsync_WiFiManager is a library for the ESP8266/Arduino platform, using (ESP)AsyncWebServer to enable easy 6 | configuration and reconfiguration of WiFi credentials using a Captive Portal. 7 | 8 | Modified from 9 | 1. Tzapu (https://github.com/tzapu/WiFiManager) 10 | 2. Ken Taylor (https://github.com/kentaylor) 11 | 3. Alan Steremberg (https://github.com/alanswx/ESPAsyncWiFiManager) 12 | 4. Khoi Hoang (https://github.com/khoih-prog/ESP_WiFiManager) 13 | 14 | Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager 15 | Licensed under MIT license 16 | *****************************************************************************************************************************/ 17 | #if !( defined(ESP8266) || defined(ESP32) ) 18 | #error This code is intended to run on the ESP8266 or ESP32 platform! Please check your Tools->Board setting. 19 | #endif 20 | 21 | #define ESP_ASYNC_WIFIMANAGER_VERSION_MIN_TARGET "ESPAsync_WiFiManager v1.15.0" 22 | #define ESP_ASYNC_WIFIMANAGER_VERSION_MIN 1015000 23 | 24 | // Use from 0 to 4. Higher number, more debugging messages and memory usage. 25 | #define _ESPASYNC_WIFIMGR_LOGLEVEL_ 3 26 | 27 | // To not display stored SSIDs and PWDs on Config Portal, select false. Default is true 28 | // Even the stored Credentials are not display, just leave them all blank to reconnect and reuse the stored Credentials 29 | //#define DISPLAY_STORED_CREDENTIALS_IN_CP false 30 | 31 | //Ported to ESP32 32 | #ifdef ESP32 33 | #include 34 | #include 35 | #include 36 | 37 | // From v1.1.1 38 | #include 39 | WiFiMulti wifiMulti; 40 | 41 | // LittleFS has higher priority than SPIFFS 42 | #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) 43 | #define USE_LITTLEFS true 44 | #define USE_SPIFFS false 45 | #elif defined(ARDUINO_ESP32C3_DEV) 46 | // For core v1.0.6-, ESP32-C3 only supporting SPIFFS and EEPROM. To use v2.0.0+ for LittleFS 47 | #define USE_LITTLEFS false 48 | #define USE_SPIFFS true 49 | #endif 50 | 51 | #if USE_LITTLEFS 52 | // Use LittleFS 53 | #include "FS.h" 54 | 55 | // Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h 56 | //#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) ) //(ESP_ARDUINO_VERSION_MAJOR >= 2) 57 | #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) 58 | #if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3) 59 | #warning Using ESP32 Core 1.0.6 or 2.0.0+ 60 | #endif 61 | 62 | // The library has been merged into esp32 core from release 1.0.6 63 | #include // https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS 64 | 65 | FS* filesystem = &LittleFS; 66 | #define FileFS LittleFS 67 | #define FS_Name "LittleFS" 68 | #else 69 | #if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3) 70 | #warning Using ESP32 Core 1.0.5-. You must install LITTLEFS library 71 | #endif 72 | 73 | // The library has been merged into esp32 core from release 1.0.6 74 | #include // https://github.com/lorol/LITTLEFS 75 | 76 | FS* filesystem = &LITTLEFS; 77 | #define FileFS LITTLEFS 78 | #define FS_Name "LittleFS" 79 | #endif 80 | 81 | #elif USE_SPIFFS 82 | #include 83 | FS* filesystem = &SPIFFS; 84 | #define FileFS SPIFFS 85 | #define FS_Name "SPIFFS" 86 | #else 87 | // +Use FFat 88 | #include 89 | FS* filesystem = &FFat; 90 | #define FileFS FFat 91 | #define FS_Name "FFat" 92 | #endif 93 | ////// 94 | 95 | #define LED_BUILTIN 2 96 | #define LED_ON HIGH 97 | #define LED_OFF LOW 98 | 99 | #else 100 | 101 | #include //https://github.com/esp8266/Arduino 102 | //needed for library 103 | #include 104 | 105 | // From v1.1.1 106 | #include 107 | ESP8266WiFiMulti wifiMulti; 108 | 109 | #define USE_LITTLEFS true 110 | 111 | #if USE_LITTLEFS 112 | #include 113 | FS* filesystem = &LittleFS; 114 | #define FileFS LittleFS 115 | #define FS_Name "LittleFS" 116 | #else 117 | FS* filesystem = &SPIFFS; 118 | #define FileFS SPIFFS 119 | #define FS_Name "SPIFFS" 120 | #endif 121 | ////// 122 | 123 | #define ESP_getChipId() (ESP.getChipId()) 124 | 125 | #define LED_ON LOW 126 | #define LED_OFF HIGH 127 | #endif 128 | 129 | // SSID and PW for your Router 130 | String Router_SSID; 131 | String Router_Pass; 132 | 133 | // From v1.1.1 134 | // You only need to format the filesystem once 135 | //#define FORMAT_FILESYSTEM true 136 | #define FORMAT_FILESYSTEM false 137 | 138 | #define MIN_AP_PASSWORD_SIZE 8 139 | 140 | #define SSID_MAX_LEN 32 141 | //From v1.0.10, WPA2 passwords can be up to 63 characters long. 142 | #define PASS_MAX_LEN 64 143 | 144 | typedef struct 145 | { 146 | char wifi_ssid[SSID_MAX_LEN]; 147 | char wifi_pw [PASS_MAX_LEN]; 148 | } WiFi_Credentials; 149 | 150 | typedef struct 151 | { 152 | String wifi_ssid; 153 | String wifi_pw; 154 | } WiFi_Credentials_String; 155 | 156 | #define NUM_WIFI_CREDENTIALS 2 157 | 158 | // Assuming max 49 chars 159 | #define TZNAME_MAX_LEN 50 160 | #define TIMEZONE_MAX_LEN 50 161 | 162 | typedef struct 163 | { 164 | WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; 165 | char TZ_Name[TZNAME_MAX_LEN]; // "America/Toronto" 166 | char TZ[TIMEZONE_MAX_LEN]; // "EST5EDT,M3.2.0,M11.1.0" 167 | uint16_t checksum; 168 | } WM_Config; 169 | 170 | WM_Config WM_config; 171 | 172 | #define CONFIG_FILENAME F("/wifi_cred.dat") 173 | ////// 174 | 175 | // Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected 176 | bool initialConfig = false; 177 | 178 | // Use false if you don't like to display Available Pages in Information Page of Config Portal 179 | // Comment out or use true to display Available Pages in Information Page of Config Portal 180 | // Must be placed before #include 181 | #define USE_AVAILABLE_PAGES true 182 | 183 | // From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used. 184 | // You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa 185 | // You have to explicitly specify false to disable the feature. 186 | //#define USE_STATIC_IP_CONFIG_IN_CP false 187 | 188 | // Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal. 189 | // See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23) 190 | #define USE_ESP_WIFIMANAGER_NTP true 191 | 192 | // Just use enough to save memory. On ESP8266, can cause blank ConfigPortal screen 193 | // if using too much memory 194 | #define USING_AFRICA false 195 | #define USING_AMERICA true 196 | #define USING_ANTARCTICA false 197 | #define USING_ASIA false 198 | #define USING_ATLANTIC false 199 | #define USING_AUSTRALIA false 200 | #define USING_EUROPE false 201 | #define USING_INDIAN false 202 | #define USING_PACIFIC false 203 | #define USING_ETC_GMT false 204 | 205 | // Use true to enable CloudFlare NTP service. System can hang if you don't have Internet access while accessing CloudFlare 206 | // See Issue #21: CloudFlare link in the default portal (https://github.com/khoih-prog/ESP_WiFiManager/issues/21) 207 | #define USE_CLOUDFLARE_NTP false 208 | 209 | // New in v1.0.11 210 | #define USING_CORS_FEATURE true 211 | 212 | //////////////////////////////////////////// 213 | 214 | // Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network 215 | #if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP) 216 | // Force DHCP to be true 217 | #if defined(USE_DHCP_IP) 218 | #undef USE_DHCP_IP 219 | #endif 220 | #define USE_DHCP_IP true 221 | #else 222 | // You can select DHCP or Static IP here 223 | #define USE_DHCP_IP true 224 | //#define USE_DHCP_IP false 225 | #endif 226 | 227 | #if ( USE_DHCP_IP ) 228 | // Use DHCP 229 | 230 | #if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3) 231 | #warning Using DHCP IP 232 | #endif 233 | 234 | IPAddress stationIP = IPAddress(0, 0, 0, 0); 235 | IPAddress gatewayIP = IPAddress(192, 168, 2, 1); 236 | IPAddress netMask = IPAddress(255, 255, 255, 0); 237 | 238 | #else 239 | // Use static IP 240 | 241 | #if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3) 242 | #warning Using static IP 243 | #endif 244 | 245 | #ifdef ESP32 246 | IPAddress stationIP = IPAddress(192, 168, 2, 232); 247 | #else 248 | IPAddress stationIP = IPAddress(192, 168, 2, 186); 249 | #endif 250 | 251 | IPAddress gatewayIP = IPAddress(192, 168, 2, 1); 252 | IPAddress netMask = IPAddress(255, 255, 255, 0); 253 | #endif 254 | 255 | //////////////////////////////////////////// 256 | 257 | 258 | #define USE_CONFIGURABLE_DNS true 259 | 260 | IPAddress dns1IP = gatewayIP; 261 | IPAddress dns2IP = IPAddress(8, 8, 8, 8); 262 | 263 | #define USE_CUSTOM_AP_IP false 264 | 265 | IPAddress APStaticIP = IPAddress(192, 168, 100, 1); 266 | IPAddress APStaticGW = IPAddress(192, 168, 100, 1); 267 | IPAddress APStaticSN = IPAddress(255, 255, 255, 0); 268 | 269 | #include //https://github.com/khoih-prog/ESPAsync_WiFiManager 270 | 271 | // Redundant, for v1.10.0 only 272 | //#include //https://github.com/khoih-prog/ESPAsync_WiFiManager 273 | 274 | #define HTTP_PORT 80 275 | 276 | /////////////////////////////////////////// 277 | // New in v1.4.0 278 | /****************************************** 279 | // Defined in ESPAsync_WiFiManager.h 280 | typedef struct 281 | { 282 | IPAddress _ap_static_ip; 283 | IPAddress _ap_static_gw; 284 | IPAddress _ap_static_sn; 285 | 286 | } WiFi_AP_IPConfig; 287 | 288 | typedef struct 289 | { 290 | IPAddress _sta_static_ip; 291 | IPAddress _sta_static_gw; 292 | IPAddress _sta_static_sn; 293 | #if USE_CONFIGURABLE_DNS 294 | IPAddress _sta_static_dns1; 295 | IPAddress _sta_static_dns2; 296 | #endif 297 | } WiFi_STA_IPConfig; 298 | ******************************************/ 299 | 300 | WiFi_AP_IPConfig WM_AP_IPconfig; 301 | WiFi_STA_IPConfig WM_STA_IPconfig; 302 | 303 | void initAPIPConfigStruct(WiFi_AP_IPConfig &in_WM_AP_IPconfig) 304 | { 305 | in_WM_AP_IPconfig._ap_static_ip = APStaticIP; 306 | in_WM_AP_IPconfig._ap_static_gw = APStaticGW; 307 | in_WM_AP_IPconfig._ap_static_sn = APStaticSN; 308 | } 309 | 310 | void initSTAIPConfigStruct(WiFi_STA_IPConfig &in_WM_STA_IPconfig) 311 | { 312 | in_WM_STA_IPconfig._sta_static_ip = stationIP; 313 | in_WM_STA_IPconfig._sta_static_gw = gatewayIP; 314 | in_WM_STA_IPconfig._sta_static_sn = netMask; 315 | #if USE_CONFIGURABLE_DNS 316 | in_WM_STA_IPconfig._sta_static_dns1 = dns1IP; 317 | in_WM_STA_IPconfig._sta_static_dns2 = dns2IP; 318 | #endif 319 | } 320 | 321 | void displayIPConfigStruct(WiFi_STA_IPConfig in_WM_STA_IPconfig) 322 | { 323 | LOGERROR3(F("stationIP ="), in_WM_STA_IPconfig._sta_static_ip, ", gatewayIP =", in_WM_STA_IPconfig._sta_static_gw); 324 | LOGERROR1(F("netMask ="), in_WM_STA_IPconfig._sta_static_sn); 325 | #if USE_CONFIGURABLE_DNS 326 | LOGERROR3(F("dns1IP ="), in_WM_STA_IPconfig._sta_static_dns1, ", dns2IP =", in_WM_STA_IPconfig._sta_static_dns2); 327 | #endif 328 | } 329 | 330 | void configWiFi(WiFi_STA_IPConfig in_WM_STA_IPconfig) 331 | { 332 | #if USE_CONFIGURABLE_DNS 333 | // Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5 334 | WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn, 335 | in_WM_STA_IPconfig._sta_static_dns1, in_WM_STA_IPconfig._sta_static_dns2); 336 | #else 337 | // Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2. 338 | WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn); 339 | #endif 340 | } 341 | 342 | /////////////////////////////////////////// 343 | 344 | uint8_t connectMultiWiFi() 345 | { 346 | #if ESP32 347 | // For ESP32, this better be 0 to shorten the connect time. 348 | // For ESP32-S2/C3, must be > 500 349 | #if ( USING_ESP32_S2 || USING_ESP32_C3 ) 350 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 500L 351 | #else 352 | // For ESP32 core v1.0.6, must be >= 500 353 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 800L 354 | #endif 355 | #else 356 | // For ESP8266, this better be 2200 to enable connect the 1st time 357 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 2200L 358 | #endif 359 | 360 | #define WIFI_MULTI_CONNECT_WAITING_MS 500L 361 | 362 | uint8_t status; 363 | 364 | //WiFi.mode(WIFI_STA); 365 | 366 | LOGERROR(F("ConnectMultiWiFi with :")); 367 | 368 | if ( (Router_SSID != "") && (Router_Pass != "") ) 369 | { 370 | LOGERROR3(F("* Flash-stored Router_SSID = "), Router_SSID, F(", Router_Pass = "), Router_Pass ); 371 | LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass ); 372 | wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str()); 373 | } 374 | 375 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++) 376 | { 377 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8) 378 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") 379 | && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) ) 380 | { 381 | LOGERROR3(F("* Additional SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw ); 382 | } 383 | } 384 | 385 | LOGERROR(F("Connecting MultiWifi...")); 386 | 387 | //WiFi.mode(WIFI_STA); 388 | 389 | #if !USE_DHCP_IP 390 | // New in v1.4.0 391 | configWiFi(WM_STA_IPconfig); 392 | ////// 393 | #endif 394 | 395 | int i = 0; 396 | status = wifiMulti.run(); 397 | delay(WIFI_MULTI_1ST_CONNECT_WAITING_MS); 398 | 399 | while ( ( i++ < 20 ) && ( status != WL_CONNECTED ) ) 400 | { 401 | status = WiFi.status(); 402 | 403 | if ( status == WL_CONNECTED ) 404 | break; 405 | else 406 | delay(WIFI_MULTI_CONNECT_WAITING_MS); 407 | } 408 | 409 | if ( status == WL_CONNECTED ) 410 | { 411 | LOGERROR1(F("WiFi connected after time: "), i); 412 | LOGERROR3(F("SSID:"), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); 413 | LOGERROR3(F("Channel:"), WiFi.channel(), F(",IP address:"), WiFi.localIP() ); 414 | } 415 | else 416 | { 417 | LOGERROR(F("WiFi not connected")); 418 | 419 | #if ESP8266 420 | ESP.reset(); 421 | #else 422 | ESP.restart(); 423 | #endif 424 | } 425 | 426 | return status; 427 | } 428 | 429 | #if USE_ESP_WIFIMANAGER_NTP 430 | 431 | void printLocalTime() 432 | { 433 | #if ESP8266 434 | static time_t now; 435 | 436 | now = time(nullptr); 437 | 438 | if ( now > 1451602800 ) 439 | { 440 | Serial.print("Local Date/Time: "); 441 | Serial.print(ctime(&now)); 442 | } 443 | 444 | #else 445 | struct tm timeinfo; 446 | 447 | getLocalTime( &timeinfo ); 448 | 449 | // Valid only if year > 2000. 450 | // You can get from timeinfo : tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec 451 | if (timeinfo.tm_year > 100 ) 452 | { 453 | Serial.print("Local Date/Time: "); 454 | Serial.print( asctime( &timeinfo ) ); 455 | } 456 | 457 | #endif 458 | } 459 | 460 | #endif 461 | 462 | void heartBeatPrint() 463 | { 464 | #if USE_ESP_WIFIMANAGER_NTP 465 | printLocalTime(); 466 | #else 467 | static int num = 1; 468 | 469 | if (WiFi.status() == WL_CONNECTED) 470 | Serial.print(F("H")); // H means connected to WiFi 471 | else 472 | Serial.print(F("F")); // F means not connected to WiFi 473 | 474 | if (num == 80) 475 | { 476 | Serial.println(); 477 | num = 1; 478 | } 479 | else if (num++ % 10 == 0) 480 | { 481 | Serial.print(F(" ")); 482 | } 483 | 484 | #endif 485 | } 486 | 487 | void check_WiFi() 488 | { 489 | if ( (WiFi.status() != WL_CONNECTED) ) 490 | { 491 | Serial.println(F("\nWiFi lost. Call connectMultiWiFi in loop")); 492 | connectMultiWiFi(); 493 | } 494 | } 495 | 496 | void check_status() 497 | { 498 | static ulong checkstatus_timeout = 0; 499 | static ulong checkwifi_timeout = 0; 500 | 501 | static ulong current_millis; 502 | 503 | #define WIFICHECK_INTERVAL 1000L 504 | 505 | #if USE_ESP_WIFIMANAGER_NTP 506 | #define HEARTBEAT_INTERVAL 60000L 507 | #else 508 | #define HEARTBEAT_INTERVAL 10000L 509 | #endif 510 | 511 | current_millis = millis(); 512 | 513 | // Check WiFi every WIFICHECK_INTERVAL (1) seconds. 514 | if ((current_millis > checkwifi_timeout) || (checkwifi_timeout == 0)) 515 | { 516 | check_WiFi(); 517 | checkwifi_timeout = current_millis + WIFICHECK_INTERVAL; 518 | } 519 | 520 | // Print hearbeat every HEARTBEAT_INTERVAL (10) seconds. 521 | if ((current_millis > checkstatus_timeout) || (checkstatus_timeout == 0)) 522 | { 523 | heartBeatPrint(); 524 | checkstatus_timeout = current_millis + HEARTBEAT_INTERVAL; 525 | } 526 | } 527 | 528 | int calcChecksum(uint8_t* address, uint16_t sizeToCalc) 529 | { 530 | uint16_t checkSum = 0; 531 | 532 | for (uint16_t index = 0; index < sizeToCalc; index++) 533 | { 534 | checkSum += * ( ( (byte*) address ) + index); 535 | } 536 | 537 | return checkSum; 538 | } 539 | 540 | bool loadConfigData() 541 | { 542 | File file = FileFS.open(CONFIG_FILENAME, "r"); 543 | LOGERROR(F("LoadWiFiCfgFile ")); 544 | 545 | memset((void *) &WM_config, 0, sizeof(WM_config)); 546 | 547 | // New in v1.4.0 548 | memset((void *) &WM_STA_IPconfig, 0, sizeof(WM_STA_IPconfig)); 549 | ////// 550 | 551 | if (file) 552 | { 553 | file.readBytes((char *) &WM_config, sizeof(WM_config)); 554 | 555 | // New in v1.4.0 556 | file.readBytes((char *) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig)); 557 | ////// 558 | 559 | file.close(); 560 | LOGERROR(F("OK")); 561 | 562 | if ( WM_config.checksum != calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) ) ) 563 | { 564 | LOGERROR(F("WM_config checksum wrong")); 565 | 566 | return false; 567 | } 568 | 569 | // New in v1.4.0 570 | displayIPConfigStruct(WM_STA_IPconfig); 571 | ////// 572 | 573 | return true; 574 | } 575 | else 576 | { 577 | LOGERROR(F("failed")); 578 | 579 | return false; 580 | } 581 | } 582 | 583 | void saveConfigData() 584 | { 585 | File file = FileFS.open(CONFIG_FILENAME, "w"); 586 | LOGERROR(F("SaveWiFiCfgFile ")); 587 | 588 | if (file) 589 | { 590 | WM_config.checksum = calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) ); 591 | 592 | file.write((uint8_t*) &WM_config, sizeof(WM_config)); 593 | 594 | displayIPConfigStruct(WM_STA_IPconfig); 595 | 596 | // New in v1.4.0 597 | file.write((uint8_t*) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig)); 598 | ////// 599 | 600 | file.close(); 601 | LOGERROR(F("OK")); 602 | } 603 | else 604 | { 605 | LOGERROR(F("failed")); 606 | } 607 | } 608 | 609 | void setup() 610 | { 611 | // put your setup code here, to run once: 612 | Serial.begin(115200); 613 | 614 | while (!Serial); 615 | 616 | delay(200); 617 | 618 | Serial.print("\nStarting Async_AutoConnectAP using " + String(FS_Name)); 619 | Serial.println(" on " + String(ARDUINO_BOARD)); 620 | Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION); 621 | 622 | #if defined(ESP_ASYNC_WIFIMANAGER_VERSION_INT) 623 | 624 | if (ESP_ASYNC_WIFIMANAGER_VERSION_INT < ESP_ASYNC_WIFIMANAGER_VERSION_MIN) 625 | { 626 | Serial.print("Warning. Must use this example on Version later than : "); 627 | Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION_MIN_TARGET); 628 | } 629 | 630 | #endif 631 | 632 | if (FORMAT_FILESYSTEM) 633 | FileFS.format(); 634 | 635 | // Format FileFS if not yet 636 | #ifdef ESP32 637 | 638 | if (!FileFS.begin(true)) 639 | #else 640 | if (!FileFS.begin()) 641 | #endif 642 | { 643 | #ifdef ESP8266 644 | FileFS.format(); 645 | #endif 646 | 647 | Serial.println(F("SPIFFS/LittleFS failed! Already tried formatting.")); 648 | 649 | if (!FileFS.begin()) 650 | { 651 | // prevents debug info from the library to hide err message. 652 | delay(100); 653 | 654 | #if USE_LITTLEFS 655 | Serial.println(F("LittleFS failed!. Please use SPIFFS or EEPROM. Stay forever")); 656 | #else 657 | Serial.println(F("SPIFFS failed!. Please use LittleFS or EEPROM. Stay forever")); 658 | #endif 659 | 660 | while (true) 661 | { 662 | delay(1); 663 | } 664 | } 665 | } 666 | 667 | unsigned long startedAt = millis(); 668 | 669 | // New in v1.4.0 670 | initAPIPConfigStruct(WM_AP_IPconfig); 671 | initSTAIPConfigStruct(WM_STA_IPconfig); 672 | ////// 673 | 674 | //Local intialization. Once its business is done, there is no need to keep it around 675 | // Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX 676 | //ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer); 677 | // Use this to personalize DHCP hostname (RFC952 conformed) 678 | AsyncWebServer webServer(HTTP_PORT); 679 | 680 | #if ( USING_ESP32_S2 || USING_ESP32_C3 ) 681 | ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, NULL, "AutoConnectAP"); 682 | #else 683 | AsyncDNSServer dnsServer; 684 | 685 | ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "AutoConnectAP"); 686 | #endif 687 | 688 | ESPAsync_wifiManager.setDebugOutput(true); 689 | 690 | //reset settings - for testing 691 | //ESPAsync_wifiManager.resetSettings(); 692 | 693 | #if USE_CUSTOM_AP_IP 694 | //set custom ip for portal 695 | // New in v1.4.0 696 | ESPAsync_wifiManager.setAPStaticIPConfig(WM_AP_IPconfig); 697 | ////// 698 | #endif 699 | 700 | ESPAsync_wifiManager.setMinimumSignalQuality(-1); 701 | 702 | // From v1.0.10 only 703 | // Set config portal channel, default = 1. Use 0 => random channel from 1-13 704 | ESPAsync_wifiManager.setConfigPortalChannel(0); 705 | ////// 706 | 707 | #if !USE_DHCP_IP 708 | // Set (static IP, Gateway, Subnetmask, DNS1 and DNS2) or (IP, Gateway, Subnetmask). New in v1.0.5 709 | // New in v1.4.0 710 | ESPAsync_wifiManager.setSTAStaticIPConfig(WM_STA_IPconfig); 711 | ////// 712 | #endif 713 | 714 | // New from v1.1.1 715 | #if USING_CORS_FEATURE 716 | ESPAsync_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin"); 717 | #endif 718 | 719 | // We can't use WiFi.SSID() in ESP32 as it's only valid after connected. 720 | // SSID and Password stored in ESP32 wifi_ap_record_t and wifi_config_t are also cleared in reboot 721 | // Have to create a new function to store in EEPROM/SPIFFS for this purpose 722 | Router_SSID = ESPAsync_wifiManager.WiFi_SSID(); 723 | Router_Pass = ESPAsync_wifiManager.WiFi_Pass(); 724 | 725 | //Remove this line if you do not want to see WiFi password printed 726 | Serial.println("ESP Self-Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass); 727 | 728 | bool configDataLoaded = false; 729 | 730 | // From v1.1.0, Don't permit NULL password 731 | if ( (Router_SSID != "") && (Router_Pass != "") ) 732 | { 733 | LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass); 734 | wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str()); 735 | 736 | ESPAsync_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout. 737 | Serial.println(F("Got ESP Self-Stored Credentials. Timeout 120s for Config Portal")); 738 | } 739 | 740 | if (loadConfigData()) 741 | { 742 | configDataLoaded = true; 743 | 744 | ESPAsync_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout. 745 | Serial.println(F("Got stored Credentials. Timeout 120s for Config Portal")); 746 | 747 | #if USE_ESP_WIFIMANAGER_NTP 748 | 749 | if ( strlen(WM_config.TZ_Name) > 0 ) 750 | { 751 | LOGERROR3(F("Current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ); 752 | 753 | #if ESP8266 754 | configTime(WM_config.TZ, "pool.ntp.org"); 755 | #else 756 | //configTzTime(WM_config.TZ, "pool.ntp.org" ); 757 | configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org"); 758 | #endif 759 | } 760 | else 761 | { 762 | Serial.println(F("Current Timezone is not set. Enter Config Portal to set.")); 763 | } 764 | 765 | #endif 766 | } 767 | else 768 | { 769 | // Enter CP only if no stored SSID on flash and file 770 | Serial.println(F("Open Config Portal without Timeout: No stored Credentials.")); 771 | initialConfig = true; 772 | } 773 | 774 | String chipID = String(ESP_getChipId(), HEX); 775 | chipID.toUpperCase(); 776 | 777 | // SSID and PW for Config Portal 778 | String AP_SSID = "ESP_" + chipID + "_AutoConnectAP"; 779 | String AP_PASS = "MyESP_" + chipID; 780 | 781 | if (initialConfig) 782 | { 783 | Serial.println(F("We haven't got any access point credentials, so get them now")); 784 | 785 | Serial.print(F("Starting configuration portal @ ")); 786 | 787 | #if USE_CUSTOM_AP_IP 788 | Serial.print(APStaticIP); 789 | #else 790 | Serial.print(F("192.168.4.1")); 791 | #endif 792 | 793 | Serial.print(F(", SSID = ")); 794 | Serial.print(AP_SSID); 795 | Serial.print(F(", PWD = ")); 796 | Serial.println(AP_PASS); 797 | 798 | #if DISPLAY_STORED_CREDENTIALS_IN_CP 799 | // New. Update Credentials, got from loadConfigData(), to display on CP 800 | ESPAsync_wifiManager.setCredentials(WM_config.WiFi_Creds[0].wifi_ssid, WM_config.WiFi_Creds[0].wifi_pw, 801 | WM_config.WiFi_Creds[1].wifi_ssid, WM_config.WiFi_Creds[1].wifi_pw); 802 | #endif 803 | 804 | // Starts an access point 805 | //if (!ESPAsync_wifiManager.startConfigPortal((const char *) ssid.c_str(), password)) 806 | if ( !ESPAsync_wifiManager.startConfigPortal(AP_SSID.c_str(), AP_PASS.c_str()) ) 807 | Serial.println(F("Not connected to WiFi but continuing anyway.")); 808 | else 809 | Serial.println(F("WiFi connected...yeey :)")); 810 | 811 | // Stored for later usage, from v1.1.0, but clear first 812 | memset(&WM_config, 0, sizeof(WM_config)); 813 | 814 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++) 815 | { 816 | String tempSSID = ESPAsync_wifiManager.getSSID(i); 817 | String tempPW = ESPAsync_wifiManager.getPW(i); 818 | 819 | if (strlen(tempSSID.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1) 820 | strcpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str()); 821 | else 822 | strncpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1); 823 | 824 | if (strlen(tempPW.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1) 825 | strcpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str()); 826 | else 827 | strncpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1); 828 | 829 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8) 830 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") 831 | && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) ) 832 | { 833 | LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw ); 834 | wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw); 835 | } 836 | } 837 | 838 | #if USE_ESP_WIFIMANAGER_NTP 839 | String tempTZ = ESPAsync_wifiManager.getTimezoneName(); 840 | 841 | if (strlen(tempTZ.c_str()) < sizeof(WM_config.TZ_Name) - 1) 842 | strcpy(WM_config.TZ_Name, tempTZ.c_str()); 843 | else 844 | strncpy(WM_config.TZ_Name, tempTZ.c_str(), sizeof(WM_config.TZ_Name) - 1); 845 | 846 | const char * TZ_Result = ESPAsync_wifiManager.getTZ(WM_config.TZ_Name); 847 | 848 | if (strlen(TZ_Result) < sizeof(WM_config.TZ) - 1) 849 | strcpy(WM_config.TZ, TZ_Result); 850 | else 851 | strncpy(WM_config.TZ, TZ_Result, sizeof(WM_config.TZ_Name) - 1); 852 | 853 | if ( strlen(WM_config.TZ_Name) > 0 ) 854 | { 855 | LOGERROR3(F("Saving current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ); 856 | 857 | #if ESP8266 858 | configTime(WM_config.TZ, "pool.ntp.org"); 859 | #else 860 | //configTzTime(WM_config.TZ, "pool.ntp.org" ); 861 | configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org"); 862 | #endif 863 | } 864 | else 865 | { 866 | LOGERROR(F("Current Timezone Name is not set. Enter Config Portal to set.")); 867 | } 868 | 869 | #endif 870 | 871 | // New in v1.4.0 872 | ESPAsync_wifiManager.getSTAStaticIPConfig(WM_STA_IPconfig); 873 | ////// 874 | 875 | saveConfigData(); 876 | } 877 | else 878 | { 879 | wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str()); 880 | } 881 | 882 | startedAt = millis(); 883 | 884 | if (!initialConfig) 885 | { 886 | // Load stored data, the addAP ready for MultiWiFi reconnection 887 | if (!configDataLoaded) 888 | loadConfigData(); 889 | 890 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++) 891 | { 892 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8) 893 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") 894 | && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) ) 895 | { 896 | LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw ); 897 | wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw); 898 | } 899 | } 900 | 901 | if ( WiFi.status() != WL_CONNECTED ) 902 | { 903 | Serial.println(F("ConnectMultiWiFi in setup")); 904 | 905 | connectMultiWiFi(); 906 | } 907 | } 908 | 909 | Serial.print(F("After waiting ")); 910 | Serial.print((float) (millis() - startedAt) / 1000L); 911 | Serial.print(F(" secs more in setup(), connection result is ")); 912 | 913 | if (WiFi.status() == WL_CONNECTED) 914 | { 915 | Serial.print(F("connected. Local IP: ")); 916 | Serial.println(WiFi.localIP()); 917 | } 918 | else 919 | Serial.println(ESPAsync_wifiManager.getStatus(WiFi.status())); 920 | } 921 | 922 | void loop() 923 | { 924 | // put your main code here, to run repeatedly 925 | check_status(); 926 | } 927 | -------------------------------------------------------------------------------- /examples/Async_ConfigOnDoubleReset_Multi/Async_ConfigOnDoubleReset_Multi.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Async_ConfigOnDoubleReset_Multi.cpp 3 | For ESP8266 / ESP32 boards 4 | 5 | ESPAsync_WiFiManager is a library for the ESP8266/Arduino platform, using (ESP)AsyncWebServer to enable easy 6 | configuration and reconfiguration of WiFi credentials using a Captive Portal. 7 | 8 | Modified from 9 | 1. Tzapu (https://github.com/tzapu/WiFiManager) 10 | 2. Ken Taylor (https://github.com/kentaylor) 11 | 3. Alan Steremberg (https://github.com/alanswx/ESPAsyncWiFiManager) 12 | 4. Khoi Hoang (https://github.com/khoih-prog/ESP_WiFiManager) 13 | 14 | Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager 15 | Licensed under MIT license 16 | *****************************************************************************************************************************/ 17 | /**************************************************************************************************************************** 18 | This example will open a configuration portal when the reset button is pressed twice. 19 | This method works well on Wemos boards which have a single reset button on board. It avoids using a pin for launching the configuration portal. 20 | 21 | How It Works 22 | 1) ESP8266 23 | Save data in RTC memory 24 | 2) ESP32 25 | Save data in EEPROM from address 256, size 512 bytes (both configurable) 26 | 27 | So when the device starts up it checks this region of ram for a flag to see if it has been recently reset. 28 | If so it launches a configuration portal, if not it sets the reset flag. After running for a while this flag is cleared so that 29 | it will only launch the configuration portal in response to closely spaced resets. 30 | 31 | Settings 32 | There are two values to be set in the sketch. 33 | 34 | DRD_TIMEOUT - Number of seconds to wait for the second reset. Set to 10 in the example. 35 | DRD_ADDRESS - The address in ESP8266 RTC RAM to store the flag. This memory must not be used for other purposes in the same sketch. Set to 0 in the example. 36 | 37 | This example, originally relied on the Double Reset Detector library from https://github.com/datacute/DoubleResetDetector 38 | To support ESP32, use ESP_DoubleResetDetector library from //https://github.com/khoih-prog/ESP_DoubleResetDetector 39 | *****************************************************************************************************************************/ 40 | 41 | #if !( defined(ESP8266) || defined(ESP32) ) 42 | #error This code is intended to run on the ESP8266 or ESP32 platform! Please check your Tools->Board setting. 43 | #endif 44 | 45 | #include "Async_ConfigOnDoubleReset_Multi.h" 46 | 47 | //Ported to ESP32 48 | #ifdef ESP32 49 | WiFiMulti wifiMulti; 50 | 51 | #if USE_LITTLEFS 52 | #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) 53 | FS* filesystem = &LittleFS; 54 | #else 55 | FS* filesystem = &LITTLEFS; 56 | #endif 57 | 58 | #elif USE_SPIFFS 59 | FS* filesystem = &SPIFFS; 60 | #else 61 | FS* filesystem = &FFat; 62 | #endif 63 | ////// 64 | 65 | #else 66 | 67 | ESP8266WiFiMulti wifiMulti; 68 | 69 | #if USE_LITTLEFS 70 | FS* filesystem = &LittleFS; 71 | #else 72 | FS* filesystem = &SPIFFS; 73 | #endif 74 | ////// 75 | 76 | #endif 77 | 78 | DoubleResetDetector* drd; 79 | 80 | // Onboard LED I/O pin on NodeMCU board 81 | const int PIN_LED = 2; // D4 on NodeMCU and WeMos. GPIO2/ADC12 of ESP32. Controls the onboard LED. 82 | 83 | // SSID and PW for Config Portal 84 | String ssid = "ESP_" + String(ESP_getChipId(), HEX); 85 | String password; 86 | //extern const char* password; // = "your_password"; 87 | 88 | // SSID and PW for your Router 89 | String Router_SSID; 90 | String Router_Pass; 91 | 92 | WM_Config WM_config; 93 | 94 | // Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected 95 | bool initialConfig; // = false; 96 | 97 | #if ( USE_DHCP_IP ) 98 | // Use DHCP 99 | #if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3) 100 | #warning Using DHCP IP 101 | #endif 102 | 103 | IPAddress stationIP = IPAddress(0, 0, 0, 0); 104 | IPAddress gatewayIP = IPAddress(192, 168, 1, 1); 105 | IPAddress netMask = IPAddress(255, 255, 255, 0); 106 | #else 107 | // Use static IP 108 | #if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3) 109 | #warning Using static IP 110 | #endif 111 | 112 | #ifdef ESP32 113 | IPAddress stationIP = IPAddress(192, 168, 2, 232); 114 | #else 115 | IPAddress stationIP = IPAddress(192, 168, 2, 186); 116 | #endif 117 | 118 | IPAddress gatewayIP = IPAddress(192, 168, 2, 1); 119 | IPAddress netMask = IPAddress(255, 255, 255, 0); 120 | #endif 121 | 122 | IPAddress dns1IP = gatewayIP; 123 | IPAddress dns2IP = IPAddress(8, 8, 8, 8); 124 | 125 | IPAddress APStaticIP = IPAddress(192, 168, 100, 1); 126 | IPAddress APStaticGW = IPAddress(192, 168, 100, 1); 127 | IPAddress APStaticSN = IPAddress(255, 255, 255, 0); 128 | 129 | 130 | WiFi_AP_IPConfig WM_AP_IPconfig; 131 | WiFi_STA_IPConfig WM_STA_IPconfig; 132 | 133 | void initAPIPConfigStruct(WiFi_AP_IPConfig &in_WM_AP_IPconfig) 134 | { 135 | in_WM_AP_IPconfig._ap_static_ip = APStaticIP; 136 | in_WM_AP_IPconfig._ap_static_gw = APStaticGW; 137 | in_WM_AP_IPconfig._ap_static_sn = APStaticSN; 138 | } 139 | 140 | void initSTAIPConfigStruct(WiFi_STA_IPConfig &in_WM_STA_IPconfig) 141 | { 142 | in_WM_STA_IPconfig._sta_static_ip = stationIP; 143 | in_WM_STA_IPconfig._sta_static_gw = gatewayIP; 144 | in_WM_STA_IPconfig._sta_static_sn = netMask; 145 | #if USE_CONFIGURABLE_DNS 146 | in_WM_STA_IPconfig._sta_static_dns1 = dns1IP; 147 | in_WM_STA_IPconfig._sta_static_dns2 = dns2IP; 148 | #endif 149 | } 150 | 151 | void displayIPConfigStruct(WiFi_STA_IPConfig in_WM_STA_IPconfig) 152 | { 153 | LOGERROR3(F("stationIP ="), in_WM_STA_IPconfig._sta_static_ip, ", gatewayIP =", in_WM_STA_IPconfig._sta_static_gw); 154 | LOGERROR1(F("netMask ="), in_WM_STA_IPconfig._sta_static_sn); 155 | #if USE_CONFIGURABLE_DNS 156 | LOGERROR3(F("dns1IP ="), in_WM_STA_IPconfig._sta_static_dns1, ", dns2IP =", in_WM_STA_IPconfig._sta_static_dns2); 157 | #endif 158 | } 159 | 160 | void configWiFi(WiFi_STA_IPConfig in_WM_STA_IPconfig) 161 | { 162 | #if USE_CONFIGURABLE_DNS 163 | // Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5 164 | WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn, 165 | in_WM_STA_IPconfig._sta_static_dns1, in_WM_STA_IPconfig._sta_static_dns2); 166 | #else 167 | // Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2. 168 | WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn); 169 | #endif 170 | } 171 | 172 | /////////////////////////////////////////// 173 | 174 | uint8_t connectMultiWiFi() 175 | { 176 | #if ESP32 177 | // For ESP32, this better be 0 to shorten the connect time. 178 | // For ESP32-S2/C3, must be > 500 179 | #if ( USING_ESP32_S2 || USING_ESP32_C3 ) 180 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 500L 181 | #else 182 | // For ESP32 core v1.0.6, must be >= 500 183 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 800L 184 | #endif 185 | #else 186 | // For ESP8266, this better be 2200 to enable connect the 1st time 187 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 2200L 188 | #endif 189 | 190 | #define WIFI_MULTI_CONNECT_WAITING_MS 500L 191 | 192 | uint8_t status; 193 | 194 | //WiFi.mode(WIFI_STA); 195 | 196 | LOGERROR(F("ConnectMultiWiFi with :")); 197 | 198 | if ( (Router_SSID != "") && (Router_Pass != "") ) 199 | { 200 | LOGERROR3(F("* Flash-stored Router_SSID = "), Router_SSID, F(", Router_Pass = "), Router_Pass ); 201 | LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass ); 202 | wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str()); 203 | } 204 | 205 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++) 206 | { 207 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8) 208 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") 209 | && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) ) 210 | { 211 | LOGERROR3(F("* Additional SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw ); 212 | } 213 | } 214 | 215 | LOGERROR(F("Connecting MultiWifi...")); 216 | 217 | //WiFi.mode(WIFI_STA); 218 | 219 | #if !USE_DHCP_IP 220 | // New in v1.4.0 221 | configWiFi(WM_STA_IPconfig); 222 | ////// 223 | #endif 224 | 225 | int i = 0; 226 | 227 | status = wifiMulti.run(); 228 | delay(WIFI_MULTI_1ST_CONNECT_WAITING_MS); 229 | 230 | while ( ( i++ < 20 ) && ( status != WL_CONNECTED ) ) 231 | { 232 | status = WiFi.status(); 233 | 234 | if ( status == WL_CONNECTED ) 235 | break; 236 | else 237 | delay(WIFI_MULTI_CONNECT_WAITING_MS); 238 | } 239 | 240 | if ( status == WL_CONNECTED ) 241 | { 242 | LOGERROR1(F("WiFi connected after time: "), i); 243 | LOGERROR3(F("SSID:"), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); 244 | LOGERROR3(F("Channel:"), WiFi.channel(), F(",IP address:"), WiFi.localIP() ); 245 | } 246 | else 247 | { 248 | LOGERROR(F("WiFi not connected")); 249 | 250 | // To avoid unnecessary DRD 251 | drd->loop(); 252 | 253 | #if ESP8266 254 | ESP.reset(); 255 | #else 256 | ESP.restart(); 257 | #endif 258 | } 259 | 260 | return status; 261 | } 262 | 263 | #if USE_ESP_WIFIMANAGER_NTP 264 | 265 | void printLocalTime() 266 | { 267 | #if ESP8266 268 | static time_t now; 269 | 270 | now = time(nullptr); 271 | 272 | if ( now > 1451602800 ) 273 | { 274 | Serial.print("Local Date/Time: "); 275 | Serial.print(ctime(&now)); 276 | } 277 | 278 | #else 279 | struct tm timeinfo; 280 | 281 | getLocalTime( &timeinfo ); 282 | 283 | // Valid only if year > 2000. 284 | // You can get from timeinfo : tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec 285 | if (timeinfo.tm_year > 100 ) 286 | { 287 | Serial.print("Local Date/Time: "); 288 | Serial.print( asctime( &timeinfo ) ); 289 | } 290 | 291 | #endif 292 | } 293 | 294 | #endif 295 | 296 | void heartBeatPrint() 297 | { 298 | #if USE_ESP_WIFIMANAGER_NTP 299 | printLocalTime(); 300 | #else 301 | static int num = 1; 302 | 303 | if (WiFi.status() == WL_CONNECTED) 304 | Serial.print(F("H")); // H means connected to WiFi 305 | else 306 | Serial.print(F("F")); // F means not connected to WiFi 307 | 308 | if (num == 80) 309 | { 310 | Serial.println(); 311 | num = 1; 312 | } 313 | else if (num++ % 10 == 0) 314 | { 315 | Serial.print(F(" ")); 316 | } 317 | 318 | #endif 319 | } 320 | 321 | void check_WiFi() 322 | { 323 | if ( (WiFi.status() != WL_CONNECTED) ) 324 | { 325 | Serial.println(F("\nWiFi lost. Call connectMultiWiFi in loop")); 326 | connectMultiWiFi(); 327 | } 328 | } 329 | 330 | void check_status() 331 | { 332 | static ulong checkstatus_timeout = 0; 333 | static ulong checkwifi_timeout = 0; 334 | 335 | static ulong current_millis; 336 | 337 | #define WIFICHECK_INTERVAL 1000L 338 | 339 | #if USE_ESP_WIFIMANAGER_NTP 340 | #define HEARTBEAT_INTERVAL 60000L 341 | #else 342 | #define HEARTBEAT_INTERVAL 10000L 343 | #endif 344 | 345 | current_millis = millis(); 346 | 347 | // Check WiFi every WIFICHECK_INTERVAL (1) seconds. 348 | if ((current_millis > checkwifi_timeout) || (checkwifi_timeout == 0)) 349 | { 350 | check_WiFi(); 351 | checkwifi_timeout = current_millis + WIFICHECK_INTERVAL; 352 | } 353 | 354 | // Print hearbeat every HEARTBEAT_INTERVAL (10) seconds. 355 | if ((current_millis > checkstatus_timeout) || (checkstatus_timeout == 0)) 356 | { 357 | heartBeatPrint(); 358 | checkstatus_timeout = current_millis + HEARTBEAT_INTERVAL; 359 | } 360 | } 361 | 362 | int calcChecksum(uint8_t* address, uint16_t sizeToCalc) 363 | { 364 | uint16_t checkSum = 0; 365 | 366 | for (uint16_t index = 0; index < sizeToCalc; index++) 367 | { 368 | checkSum += * ( ( (byte*) address ) + index); 369 | } 370 | 371 | return checkSum; 372 | } 373 | 374 | bool loadConfigData() 375 | { 376 | File file = FileFS.open(CONFIG_FILENAME, "r"); 377 | LOGERROR(F("LoadWiFiCfgFile ")); 378 | 379 | memset((void *) &WM_config, 0, sizeof(WM_config)); 380 | 381 | // New in v1.4.0 382 | memset((void *) &WM_STA_IPconfig, 0, sizeof(WM_STA_IPconfig)); 383 | ////// 384 | 385 | if (file) 386 | { 387 | file.readBytes((char *) &WM_config, sizeof(WM_config)); 388 | 389 | // New in v1.4.0 390 | file.readBytes((char *) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig)); 391 | ////// 392 | 393 | file.close(); 394 | LOGERROR(F("OK")); 395 | 396 | if ( WM_config.checksum != calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) ) ) 397 | { 398 | LOGERROR(F("WM_config checksum wrong")); 399 | 400 | return false; 401 | } 402 | 403 | // New in v1.4.0 404 | displayIPConfigStruct(WM_STA_IPconfig); 405 | ////// 406 | 407 | return true; 408 | } 409 | else 410 | { 411 | LOGERROR(F("failed")); 412 | 413 | return false; 414 | } 415 | } 416 | 417 | void saveConfigData() 418 | { 419 | File file = FileFS.open(CONFIG_FILENAME, "w"); 420 | LOGERROR(F("SaveWiFiCfgFile ")); 421 | 422 | if (file) 423 | { 424 | WM_config.checksum = calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) ); 425 | 426 | file.write((uint8_t*) &WM_config, sizeof(WM_config)); 427 | 428 | displayIPConfigStruct(WM_STA_IPconfig); 429 | 430 | // New in v1.4.0 431 | file.write((uint8_t*) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig)); 432 | ////// 433 | 434 | file.close(); 435 | LOGERROR(F("OK")); 436 | } 437 | else 438 | { 439 | LOGERROR(F("failed")); 440 | } 441 | } 442 | -------------------------------------------------------------------------------- /examples/Async_ConfigOnDoubleReset_Multi/Async_ConfigOnDoubleReset_Multi.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Async_ConfigOnDoubleReset_Multi.h 3 | For ESP8266 / ESP32 boards 4 | 5 | ESPAsync_WiFiManager is a library for the ESP8266/Arduino platform, using (ESP)AsyncWebServer to enable easy 6 | configuration and reconfiguration of WiFi credentials using a Captive Portal. 7 | 8 | Modified from 9 | 1. Tzapu (https://github.com/tzapu/WiFiManager) 10 | 2. Ken Taylor (https://github.com/kentaylor) 11 | 3. Alan Steremberg (https://github.com/alanswx/ESPAsyncWiFiManager) 12 | 4. Khoi Hoang (https://github.com/khoih-prog/ESP_WiFiManager) 13 | 14 | Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager 15 | Licensed under MIT license 16 | *****************************************************************************************************************************/ 17 | /**************************************************************************************************************************** 18 | This example will open a configuration portal when the reset button is pressed twice. 19 | This method works well on Wemos boards which have a single reset button on board. It avoids using a pin for launching the configuration portal. 20 | 21 | How It Works 22 | 1) ESP8266 23 | Save data in RTC memory 24 | 2) ESP32 25 | Save data in EEPROM from address 256, size 512 bytes (both configurable) 26 | 27 | So when the device starts up it checks this region of ram for a flag to see if it has been recently reset. 28 | If so it launches a configuration portal, if not it sets the reset flag. After running for a while this flag is cleared so that 29 | it will only launch the configuration portal in response to closely spaced resets. 30 | 31 | Settings 32 | There are two values to be set in the sketch. 33 | 34 | DRD_TIMEOUT - Number of seconds to wait for the second reset. Set to 10 in the example. 35 | DRD_ADDRESS - The address in ESP8266 RTC RAM to store the flag. This memory must not be used for other purposes in the same sketch. Set to 0 in the example. 36 | 37 | This example, originally relied on the Double Reset Detector library from https://github.com/datacute/DoubleResetDetector 38 | To support ESP32, use ESP_DoubleResetDetector library from //https://github.com/khoih-prog/ESP_DoubleResetDetector 39 | *****************************************************************************************************************************/ 40 | 41 | #if !( defined(ESP8266) || defined(ESP32) ) 42 | #error This code is intended to run on the ESP8266 or ESP32 platform! Please check your Tools->Board setting. 43 | #endif 44 | 45 | #define ESP_ASYNC_WIFIMANAGER_VERSION_MIN_TARGET "ESPAsync_WiFiManager v1.14.0" 46 | #define ESP_ASYNC_WIFIMANAGER_VERSION_MIN 1014000 47 | 48 | // Use from 0 to 4. Higher number, more debugging messages and memory usage. 49 | #define _ESPASYNC_WIFIMGR_LOGLEVEL_ 1 50 | 51 | #include 52 | 53 | //Ported to ESP32 54 | #ifdef ESP32 55 | #include 56 | #include 57 | #include 58 | 59 | // From v1.1.1 60 | #include 61 | extern WiFiMulti wifiMulti; 62 | 63 | // LittleFS has higher priority than SPIFFS 64 | #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) 65 | #define USE_LITTLEFS true 66 | #define USE_SPIFFS false 67 | #elif defined(ARDUINO_ESP32C3_DEV) 68 | // For core v1.0.6-, ESP32-C3 only supporting SPIFFS and EEPROM. To use v2.0.0+ for LittleFS 69 | #define USE_LITTLEFS false 70 | #define USE_SPIFFS true 71 | #endif 72 | 73 | #if USE_LITTLEFS 74 | // Use LittleFS 75 | #include "FS.h" 76 | 77 | // Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h 78 | //#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) ) //(ESP_ARDUINO_VERSION_MAJOR >= 2) 79 | #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) 80 | #if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3) 81 | #warning Using ESP32 Core 1.0.6 or 2.0.0+ 82 | #endif 83 | 84 | // The library has been merged into esp32 core from release 1.0.6 85 | #include // https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS 86 | 87 | extern FS* filesystem; // = &LittleFS; 88 | #define FileFS LittleFS 89 | #define FS_Name "LittleFS" 90 | #else 91 | #if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3) 92 | #warning Using ESP32 Core 1.0.5-. You must install LITTLEFS library 93 | #endif 94 | 95 | // The library has been merged into esp32 core from release 1.0.6 96 | #include // https://github.com/lorol/LITTLEFS 97 | 98 | extern FS* filesystem; // = &LITTLEFS; 99 | #define FileFS LITTLEFS 100 | #define FS_Name "LittleFS" 101 | #endif 102 | 103 | #elif USE_SPIFFS 104 | #include 105 | extern FS* filesystem; // = &SPIFFS; 106 | #define FileFS SPIFFS 107 | #define FS_Name "SPIFFS" 108 | #else 109 | // +Use FFat 110 | #include 111 | extern FS* filesystem; // = &FFat; 112 | #define FileFS FFat 113 | #define FS_Name "FFat" 114 | #endif 115 | ////// 116 | 117 | #define LED_BUILTIN 2 118 | #define LED_ON HIGH 119 | #define LED_OFF LOW 120 | 121 | #else 122 | 123 | #include //https://github.com/esp8266/Arduino 124 | //needed for library 125 | #include 126 | 127 | // From v1.1.1 128 | #include 129 | extern ESP8266WiFiMulti wifiMulti; 130 | 131 | #define USE_LITTLEFS true 132 | 133 | #if USE_LITTLEFS 134 | #include 135 | extern FS* filesystem; // = &LittleFS; 136 | #define FileFS LittleFS 137 | #define FS_Name "LittleFS" 138 | #else 139 | extern FS* filesystem; // = &SPIFFS; 140 | #define FileFS SPIFFS 141 | #define FS_Name "SPIFFS" 142 | #endif 143 | ////// 144 | 145 | #define ESP_getChipId() (ESP.getChipId()) 146 | 147 | #define LED_ON LOW 148 | #define LED_OFF HIGH 149 | #endif 150 | 151 | // These defines must be put before #include 152 | // to select where to store DoubleResetDetector's variable. 153 | // For ESP32, You must select one to be true (EEPROM or SPIFFS) 154 | // For ESP8266, You must select one to be true (RTC, EEPROM, SPIFFS or LITTLEFS) 155 | // Otherwise, library will use default EEPROM storage 156 | #ifdef ESP32 157 | 158 | // These defines must be put before #include 159 | // to select where to store DoubleResetDetector's variable. 160 | // For ESP32, You must select one to be true (EEPROM or SPIFFS) 161 | // Otherwise, library will use default EEPROM storage 162 | #if USE_LITTLEFS 163 | #define ESP_DRD_USE_LITTLEFS true 164 | #define ESP_DRD_USE_SPIFFS false 165 | #define ESP_DRD_USE_EEPROM false 166 | #elif USE_SPIFFS 167 | #define ESP_DRD_USE_LITTLEFS false 168 | #define ESP_DRD_USE_SPIFFS true 169 | #define ESP_DRD_USE_EEPROM false 170 | #else 171 | #define ESP_DRD_USE_LITTLEFS false 172 | #define ESP_DRD_USE_SPIFFS false 173 | #define ESP_DRD_USE_EEPROM true 174 | #endif 175 | 176 | #else //ESP8266 177 | 178 | // For DRD 179 | // These defines must be put before #include 180 | // to select where to store DoubleResetDetector's variable. 181 | // For ESP8266, You must select one to be true (RTC, EEPROM, SPIFFS or LITTLEFS) 182 | // Otherwise, library will use default EEPROM storage 183 | #if USE_LITTLEFS 184 | #define ESP_DRD_USE_LITTLEFS true 185 | #define ESP_DRD_USE_SPIFFS false 186 | #else 187 | #define ESP_DRD_USE_LITTLEFS false 188 | #define ESP_DRD_USE_SPIFFS true 189 | #endif 190 | 191 | #define ESP_DRD_USE_EEPROM false 192 | #define ESP8266_DRD_USE_RTC false 193 | #endif 194 | 195 | #define DOUBLERESETDETECTOR_DEBUG true //false 196 | 197 | #include //https://github.com/khoih-prog/ESP_DoubleResetDetector 198 | 199 | // Number of seconds after reset during which a 200 | // subseqent reset will be considered a double reset. 201 | #define DRD_TIMEOUT 10 202 | 203 | // RTC Memory Address for the DoubleResetDetector to use 204 | #define DRD_ADDRESS 0 205 | 206 | //DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS); 207 | extern DoubleResetDetector* drd;////// 208 | 209 | // Onboard LED I/O pin on NodeMCU board 210 | extern const int PIN_LED; // = 2; // D4 on NodeMCU and WeMos. GPIO2/ADC12 of ESP32. Controls the onboard LED. 211 | 212 | // SSID and PW for Config Portal 213 | //String ssid = "ESP_" + String(ESP_getChipId(), HEX); 214 | extern String ssid; 215 | extern String password; 216 | //extern const char* password; // = "your_password"; 217 | 218 | // SSID and PW for your Router 219 | extern String Router_SSID; 220 | extern String Router_Pass; 221 | 222 | // From v1.1.1 223 | // You only need to format the filesystem once 224 | //#define FORMAT_FILESYSTEM true 225 | #define FORMAT_FILESYSTEM false 226 | 227 | #define MIN_AP_PASSWORD_SIZE 8 228 | 229 | #define SSID_MAX_LEN 32 230 | //From v1.0.10, WPA2 passwords can be up to 63 characters long. 231 | #define PASS_MAX_LEN 64 232 | 233 | typedef struct 234 | { 235 | char wifi_ssid[SSID_MAX_LEN]; 236 | char wifi_pw [PASS_MAX_LEN]; 237 | } WiFi_Credentials; 238 | 239 | typedef struct 240 | { 241 | String wifi_ssid; 242 | String wifi_pw; 243 | } WiFi_Credentials_String; 244 | 245 | #define NUM_WIFI_CREDENTIALS 2 246 | 247 | // Assuming max 49 chars 248 | #define TZNAME_MAX_LEN 50 249 | #define TIMEZONE_MAX_LEN 50 250 | 251 | typedef struct 252 | { 253 | WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; 254 | char TZ_Name[TZNAME_MAX_LEN]; // "America/Toronto" 255 | char TZ[TIMEZONE_MAX_LEN]; // "EST5EDT,M3.2.0,M11.1.0" 256 | uint16_t checksum; 257 | } WM_Config; 258 | 259 | extern WM_Config WM_config; 260 | 261 | #define CONFIG_FILENAME F("/wifi_cred.dat") 262 | ////// 263 | 264 | // Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected 265 | extern bool initialConfig; // = false; 266 | 267 | // Use false if you don't like to display Available Pages in Information Page of Config Portal 268 | // Comment out or use true to display Available Pages in Information Page of Config Portal 269 | // Must be placed before #include 270 | #define USE_AVAILABLE_PAGES true //false 271 | 272 | // From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used. 273 | // You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa 274 | // You have to explicitly specify false to disable the feature. 275 | //#define USE_STATIC_IP_CONFIG_IN_CP false 276 | 277 | // Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal. 278 | // See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23) 279 | #define USE_ESP_WIFIMANAGER_NTP false 280 | 281 | // Just use enough to save memory. On ESP8266, can cause blank ConfigPortal screen 282 | // if using too much memory 283 | #define USING_AFRICA false 284 | #define USING_AMERICA true 285 | #define USING_ANTARCTICA false 286 | #define USING_ASIA false 287 | #define USING_ATLANTIC false 288 | #define USING_AUSTRALIA false 289 | #define USING_EUROPE false 290 | #define USING_INDIAN false 291 | #define USING_PACIFIC false 292 | #define USING_ETC_GMT false 293 | 294 | // Use true to enable CloudFlare NTP service. System can hang if you don't have Internet access while accessing CloudFlare 295 | // See Issue #21: CloudFlare link in the default portal (https://github.com/khoih-prog/ESP_WiFiManager/issues/21) 296 | #define USE_CLOUDFLARE_NTP false 297 | 298 | // New in v1.0.11 299 | #define USING_CORS_FEATURE true 300 | ////// 301 | 302 | // Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network 303 | #if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP) 304 | // Force DHCP to be true 305 | #if defined(USE_DHCP_IP) 306 | #undef USE_DHCP_IP 307 | #endif 308 | #define USE_DHCP_IP true 309 | #else 310 | // You can select DHCP or Static IP here 311 | //#define USE_DHCP_IP true 312 | #define USE_DHCP_IP false 313 | #endif 314 | 315 | #if ( USE_DHCP_IP ) 316 | // Use DHCP 317 | #if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3) 318 | #warning Using DHCP IP 319 | #endif 320 | 321 | extern IPAddress stationIP; // = IPAddress(0, 0, 0, 0); 322 | extern IPAddress gatewayIP; // = IPAddress(192, 168, 1, 1); 323 | extern IPAddress netMask; // = IPAddress(255, 255, 255, 0); 324 | #else 325 | // Use static IP 326 | #if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3) 327 | #warning Using static IP 328 | #endif 329 | 330 | #ifdef ESP32 331 | extern IPAddress stationIP; // = IPAddress(192, 168, 2, 232); 332 | #else 333 | extern IPAddress stationIP; // = IPAddress(192, 168, 2, 186); 334 | #endif 335 | 336 | extern IPAddress gatewayIP; // = IPAddress(192, 168, 2, 1); 337 | extern IPAddress netMask; // = IPAddress(255, 255, 255, 0); 338 | #endif 339 | 340 | #define USE_CONFIGURABLE_DNS true 341 | 342 | extern IPAddress dns1IP; // = gatewayIP; 343 | extern IPAddress dns2IP; // = IPAddress(8, 8, 8, 8); 344 | 345 | #define USE_CUSTOM_AP_IP false 346 | 347 | extern IPAddress APStaticIP; // = IPAddress(192, 168, 100, 1); 348 | extern IPAddress APStaticGW; // = IPAddress(192, 168, 100, 1); 349 | extern IPAddress APStaticSN; // = IPAddress(255, 255, 255, 0); 350 | 351 | #include //https://github.com/khoih-prog/ESPAsync_WiFiManager 352 | 353 | #define HTTP_PORT 80 354 | 355 | extern WiFi_AP_IPConfig WM_AP_IPconfig; 356 | extern WiFi_STA_IPConfig WM_STA_IPconfig; 357 | 358 | void initAPIPConfigStruct(WiFi_AP_IPConfig &in_WM_AP_IPconfig); 359 | void initSTAIPConfigStruct(WiFi_STA_IPConfig &in_WM_STA_IPconfig); 360 | void displayIPConfigStruct(WiFi_STA_IPConfig in_WM_STA_IPconfig); 361 | void configWiFi(WiFi_STA_IPConfig in_WM_STA_IPconfig); 362 | 363 | uint8_t connectMultiWiFi(); 364 | 365 | 366 | #if USE_ESP_WIFIMANAGER_NTP 367 | void printLocalTime(); 368 | #endif 369 | 370 | void heartBeatPrint(); 371 | 372 | void check_WiFi(); 373 | void check_status(); 374 | int calcChecksum(uint8_t* address, uint16_t sizeToCalc); 375 | bool loadConfigData(); 376 | void saveConfigData(); 377 | -------------------------------------------------------------------------------- /examples/Async_ConfigOnDoubleReset_Multi/Async_ConfigOnDoubleReset_Multi.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Async_ConfigOnDoubleReset_Multi.ino 3 | For ESP8266 / ESP32 boards 4 | 5 | ESPAsync_WiFiManager is a library for the ESP8266/Arduino platform, using (ESP)AsyncWebServer to enable easy 6 | configuration and reconfiguration of WiFi credentials using a Captive Portal. 7 | 8 | Modified from 9 | 1. Tzapu (https://github.com/tzapu/WiFiManager) 10 | 2. Ken Taylor (https://github.com/kentaylor) 11 | 3. Alan Steremberg (https://github.com/alanswx/ESPAsyncWiFiManager) 12 | 4. Khoi Hoang (https://github.com/khoih-prog/ESP_WiFiManager) 13 | 14 | Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager 15 | Licensed under MIT license 16 | *****************************************************************************************************************************/ 17 | /**************************************************************************************************************************** 18 | This example will open a configuration portal when the reset button is pressed twice. 19 | This method works well on Wemos boards which have a single reset button on board. It avoids using a pin for launching the configuration portal. 20 | 21 | How It Works 22 | 1) ESP8266 23 | Save data in RTC memory 24 | 2) ESP32 25 | Save data in EEPROM from address 256, size 512 bytes (both configurable) 26 | 27 | So when the device starts up it checks this region of ram for a flag to see if it has been recently reset. 28 | If so it launches a configuration portal, if not it sets the reset flag. After running for a while this flag is cleared so that 29 | it will only launch the configuration portal in response to closely spaced resets. 30 | 31 | Settings 32 | There are two values to be set in the sketch. 33 | 34 | DRD_TIMEOUT - Number of seconds to wait for the second reset. Set to 10 in the example. 35 | DRD_ADDRESS - The address in ESP8266 RTC RAM to store the flag. This memory must not be used for other purposes in the same sketch. Set to 0 in the example. 36 | 37 | This example, originally relied on the Double Reset Detector library from https://github.com/datacute/DoubleResetDetector 38 | To support ESP32, use ESP_DoubleResetDetector library from //https://github.com/khoih-prog/ESP_DoubleResetDetector 39 | *****************************************************************************************************************************/ 40 | 41 | #if !( defined(ESP8266) || defined(ESP32) ) 42 | #error This code is intended to run on the ESP8266 or ESP32 platform! Please check your Tools->Board setting. 43 | #endif 44 | 45 | // These definitions must be placed before #include 46 | #include "Async_ConfigOnDoubleReset_Multi.h" 47 | 48 | #include //https://github.com/khoih-prog/ESPAsync_WiFiManager 49 | 50 | // Redundant, for v1.10.0 only 51 | //#include //https://github.com/khoih-prog/ESPAsync_WiFiManager 52 | 53 | void setup() 54 | { 55 | // put your setup code here, to run once: 56 | // initialize the LED digital pin as an output. 57 | pinMode(PIN_LED, OUTPUT); 58 | 59 | Serial.begin(115200); 60 | 61 | while (!Serial); 62 | 63 | delay(200); 64 | 65 | Serial.print(F("\nStarting Async_ConfigOnDoubleReset_Multi using ")); 66 | Serial.print(FS_Name); 67 | Serial.print(F(" on ")); 68 | Serial.println(ARDUINO_BOARD); 69 | Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION); 70 | Serial.println(ESP_DOUBLE_RESET_DETECTOR_VERSION); 71 | 72 | #if defined(ESP_ASYNC_WIFIMANAGER_VERSION_INT) 73 | 74 | if (ESP_ASYNC_WIFIMANAGER_VERSION_INT < ESP_ASYNC_WIFIMANAGER_VERSION_MIN) 75 | { 76 | Serial.print("Warning. Must use this example on Version later than : "); 77 | Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION_MIN_TARGET); 78 | } 79 | 80 | #endif 81 | 82 | Serial.setDebugOutput(false); 83 | 84 | if (FORMAT_FILESYSTEM) 85 | FileFS.format(); 86 | 87 | // Format FileFS if not yet 88 | #ifdef ESP32 89 | 90 | if (!FileFS.begin(true)) 91 | #else 92 | if (!FileFS.begin()) 93 | #endif 94 | { 95 | #ifdef ESP8266 96 | FileFS.format(); 97 | #endif 98 | 99 | Serial.println(F("SPIFFS/LittleFS failed! Already tried formatting.")); 100 | 101 | if (!FileFS.begin()) 102 | { 103 | // prevents debug info from the library to hide err message. 104 | delay(100); 105 | 106 | #if USE_LITTLEFS 107 | Serial.println(F("LittleFS failed!. Please use SPIFFS or EEPROM. Stay forever")); 108 | #else 109 | Serial.println(F("SPIFFS failed!. Please use LittleFS or EEPROM. Stay forever")); 110 | #endif 111 | 112 | while (true) 113 | { 114 | delay(1); 115 | } 116 | } 117 | } 118 | 119 | drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS); 120 | 121 | unsigned long startedAt = millis(); 122 | 123 | // New in v1.4.0 124 | initAPIPConfigStruct(WM_AP_IPconfig); 125 | initSTAIPConfigStruct(WM_STA_IPconfig); 126 | ////// 127 | 128 | //Local intialization. Once its business is done, there is no need to keep it around 129 | // Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX 130 | //ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer); 131 | // Use this to personalize DHCP hostname (RFC952 conformed) 132 | AsyncWebServer webServer(HTTP_PORT); 133 | 134 | #if ( USING_ESP32_S2 || USING_ESP32_C3 ) 135 | ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, NULL, "AsyncConfigOnDoubleReset"); 136 | #else 137 | AsyncDNSServer dnsServer; 138 | 139 | ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "AsyncConfigOnDoubleReset"); 140 | #endif 141 | 142 | #if USE_CUSTOM_AP_IP 143 | //set custom ip for portal 144 | // New in v1.4.0 145 | ESPAsync_wifiManager.setAPStaticIPConfig(WM_AP_IPconfig); 146 | ////// 147 | #endif 148 | 149 | ESPAsync_wifiManager.setMinimumSignalQuality(-1); 150 | 151 | // From v1.0.10 only 152 | // Set config portal channel, default = 1. Use 0 => random channel from 1-11 153 | ESPAsync_wifiManager.setConfigPortalChannel(0); 154 | ////// 155 | 156 | #if !USE_DHCP_IP 157 | // Set (static IP, Gateway, Subnetmask, DNS1 and DNS2) or (IP, Gateway, Subnetmask). New in v1.0.5 158 | // New in v1.4.0 159 | ESPAsync_wifiManager.setSTAStaticIPConfig(WM_STA_IPconfig); 160 | ////// 161 | #endif 162 | 163 | // New from v1.1.1 164 | #if USING_CORS_FEATURE 165 | ESPAsync_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin"); 166 | #endif 167 | 168 | // We can't use WiFi.SSID() in ESP32 as it's only valid after connected. 169 | // SSID and Password stored in ESP32 wifi_ap_record_t and wifi_config_t are also cleared in reboot 170 | // Have to create a new function to store in EEPROM/SPIFFS for this purpose 171 | Router_SSID = ESPAsync_wifiManager.WiFi_SSID(); 172 | Router_Pass = ESPAsync_wifiManager.WiFi_Pass(); 173 | 174 | //Remove this line if you do not want to see WiFi password printed 175 | Serial.println("ESP Self-Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass); 176 | 177 | // SSID to uppercase 178 | ssid.toUpperCase(); 179 | password = "My" + ssid; 180 | 181 | bool configDataLoaded = false; 182 | 183 | // From v1.1.0, Don't permit NULL password 184 | if ( (Router_SSID != "") && (Router_Pass != "") ) 185 | { 186 | LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass); 187 | wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str()); 188 | 189 | ESPAsync_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout. 190 | Serial.println(F("Got ESP Self-Stored Credentials. Timeout 120s for Config Portal")); 191 | } 192 | 193 | if (loadConfigData()) 194 | { 195 | configDataLoaded = true; 196 | 197 | ESPAsync_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout. 198 | Serial.println(F("Got stored Credentials. Timeout 120s for Config Portal")); 199 | 200 | #if USE_ESP_WIFIMANAGER_NTP 201 | 202 | if ( strlen(WM_config.TZ_Name) > 0 ) 203 | { 204 | LOGERROR3(F("Current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ); 205 | 206 | #if ESP8266 207 | configTime(WM_config.TZ, "pool.ntp.org"); 208 | #else 209 | //configTzTime(WM_config.TZ, "pool.ntp.org" ); 210 | configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org"); 211 | #endif 212 | } 213 | else 214 | { 215 | Serial.println(F("Current Timezone is not set. Enter Config Portal to set.")); 216 | } 217 | 218 | #endif 219 | } 220 | else 221 | { 222 | // Enter CP only if no stored SSID on flash and file 223 | Serial.println(F("Open Config Portal without Timeout: No stored Credentials.")); 224 | initialConfig = true; 225 | } 226 | 227 | if (drd->detectDoubleReset()) 228 | { 229 | // DRD, disable timeout. 230 | ESPAsync_wifiManager.setConfigPortalTimeout(0); 231 | 232 | Serial.println(F("Open Config Portal without Timeout: Double Reset Detected")); 233 | initialConfig = true; 234 | } 235 | 236 | if (initialConfig) 237 | { 238 | Serial.print(F("Starting configuration portal @ ")); 239 | 240 | #if USE_CUSTOM_AP_IP 241 | Serial.print(APStaticIP); 242 | #else 243 | Serial.print(F("192.168.4.1")); 244 | #endif 245 | 246 | Serial.print(F(", SSID = ")); 247 | Serial.print(ssid); 248 | Serial.print(F(", PWD = ")); 249 | Serial.println(password); 250 | 251 | digitalWrite(PIN_LED, LED_ON); // turn the LED on by making the voltage LOW to tell us we are in configuration mode. 252 | 253 | //sets timeout in seconds until configuration portal gets turned off. 254 | //If not specified device will remain in configuration mode until 255 | //switched off via webserver or device is restarted. 256 | //ESPAsync_wifiManager.setConfigPortalTimeout(600); 257 | 258 | #if DISPLAY_STORED_CREDENTIALS_IN_CP 259 | // New. Update Credentials, got from loadConfigData(), to display on CP 260 | ESPAsync_wifiManager.setCredentials(WM_config.WiFi_Creds[0].wifi_ssid, WM_config.WiFi_Creds[0].wifi_pw, 261 | WM_config.WiFi_Creds[1].wifi_ssid, WM_config.WiFi_Creds[1].wifi_pw); 262 | #endif 263 | 264 | // Starts an access point 265 | if (!ESPAsync_wifiManager.startConfigPortal((const char *) ssid.c_str(), password.c_str())) 266 | Serial.println(F("Not connected to WiFi but continuing anyway.")); 267 | else 268 | { 269 | Serial.println(F("WiFi connected...yeey :)")); 270 | } 271 | 272 | // Stored for later usage, from v1.1.0, but clear first 273 | memset(&WM_config, 0, sizeof(WM_config)); 274 | 275 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++) 276 | { 277 | String tempSSID = ESPAsync_wifiManager.getSSID(i); 278 | String tempPW = ESPAsync_wifiManager.getPW(i); 279 | 280 | if (strlen(tempSSID.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1) 281 | strcpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str()); 282 | else 283 | strncpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1); 284 | 285 | if (strlen(tempPW.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1) 286 | strcpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str()); 287 | else 288 | strncpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1); 289 | 290 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8) 291 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") 292 | && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) ) 293 | { 294 | LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw ); 295 | wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw); 296 | } 297 | } 298 | 299 | #if USE_ESP_WIFIMANAGER_NTP 300 | String tempTZ = ESPAsync_wifiManager.getTimezoneName(); 301 | 302 | if (strlen(tempTZ.c_str()) < sizeof(WM_config.TZ_Name) - 1) 303 | strcpy(WM_config.TZ_Name, tempTZ.c_str()); 304 | else 305 | strncpy(WM_config.TZ_Name, tempTZ.c_str(), sizeof(WM_config.TZ_Name) - 1); 306 | 307 | const char * TZ_Result = ESPAsync_wifiManager.getTZ(WM_config.TZ_Name); 308 | 309 | if (strlen(TZ_Result) < sizeof(WM_config.TZ) - 1) 310 | strcpy(WM_config.TZ, TZ_Result); 311 | else 312 | strncpy(WM_config.TZ, TZ_Result, sizeof(WM_config.TZ_Name) - 1); 313 | 314 | if ( strlen(WM_config.TZ_Name) > 0 ) 315 | { 316 | LOGERROR3(F("Saving current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ); 317 | 318 | #if ESP8266 319 | configTime(WM_config.TZ, "pool.ntp.org"); 320 | #else 321 | //configTzTime(WM_config.TZ, "pool.ntp.org" ); 322 | configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org"); 323 | #endif 324 | } 325 | else 326 | { 327 | LOGERROR(F("Current Timezone Name is not set. Enter Config Portal to set.")); 328 | } 329 | 330 | #endif 331 | 332 | // New in v1.4.0 333 | ESPAsync_wifiManager.getSTAStaticIPConfig(WM_STA_IPconfig); 334 | ////// 335 | 336 | saveConfigData(); 337 | } 338 | 339 | digitalWrite(PIN_LED, LED_OFF); // Turn led off as we are not in configuration mode. 340 | 341 | startedAt = millis(); 342 | 343 | if (!initialConfig) 344 | { 345 | // Load stored data, the addAP ready for MultiWiFi reconnection 346 | if (!configDataLoaded) 347 | loadConfigData(); 348 | 349 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++) 350 | { 351 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8) 352 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") 353 | && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) ) 354 | { 355 | LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw ); 356 | wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw); 357 | } 358 | } 359 | 360 | if ( WiFi.status() != WL_CONNECTED ) 361 | { 362 | Serial.println(F("ConnectMultiWiFi in setup")); 363 | 364 | connectMultiWiFi(); 365 | } 366 | } 367 | 368 | Serial.print(F("After waiting ")); 369 | Serial.print((float) (millis() - startedAt) / 1000); 370 | Serial.print(F(" secs more in setup(), connection result is ")); 371 | 372 | if (WiFi.status() == WL_CONNECTED) 373 | { 374 | Serial.print(F("connected. Local IP: ")); 375 | Serial.println(WiFi.localIP()); 376 | } 377 | else 378 | Serial.println(ESPAsync_wifiManager.getStatus(WiFi.status())); 379 | } 380 | 381 | void loop() 382 | { 383 | // Call the double reset detector loop method every so often, 384 | // so that it can recognise when the timeout expires. 385 | // You can also call drd.stop() when you wish to no longer 386 | // consider the next reset as a double reset. 387 | drd->loop(); 388 | 389 | // put your main code here, to run repeatedly 390 | check_status(); 391 | } 392 | -------------------------------------------------------------------------------- /examples/Async_ConfigOnSwitch/README.md: -------------------------------------------------------------------------------- 1 | # The Config On Switch Example 2 | In this example we initiate the configuration portal to connect an ESP8266 to WiFi by pushing a button. The example requires this version of WiFi Manager. It will not work with the tzapu version. 3 | 4 | ## Why Have A Button To Initiate Configuration? 5 | Once the ESP device contains network credentials it will always try to connect to that network in the background and succeed whenever that network becomes visible. The application continues to function and because WiFi networks tend to be flaky only a human has the knowledge of whether a new network is required or it is better to wait for the network to become visible again. Therefore, providing a configuration portal must be human initiated and requiring a button push is a good way to get human input. 6 | 7 | The alternative of automatically going into configuration mode every time a WiFi network becomes invisible will cause the application to stop and the device will sit in configuration mode forever. This is undesirable when a network is temporarily unavailable. 8 | 9 | ## Issues With Automatically Going Into Configuration Mode 10 | Providing a timeout on configuration mode is one way to get the application running again when a network becomes temporarily unavailable and no one is around to reboot. However, the application will still not function while waiting for the timeout and the device is vulnerable to sabotage when in config mode. With a push button it will also be vulnerable to sabotage whenever the saboteur has physical access but then it is vulnerable in other ways as well. An assumption that saboteurs will not have physical access to the device is sufficient for most applications. 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer/README.md: -------------------------------------------------------------------------------- 1 | # Async_ESP32_FSWebServer Example 2 | 3 | Compare this efficient Async_ESP32_FSWebServer example with the so complicated twin [ESP32_FSWebServer](https://github.com/khoih-prog/ESP_WiFiManager/tree/master/examples/ESP32_FSWebServer) to appreciate the powerful AsynWebServer this [ESPAsync_WiFiManager Library](https://github.com/khoih-prog/ESPAsync_WiFiManager) is relying on. 4 | 5 | ## First, how Config Portal works? 6 | 7 | In `Configuration Portal Mode`, it starts an access point called `ESP_xxxxxx`. Connect to it using the configurable password you can define in the code. For example, `your_password` (see examples): 8 | 9 | ```cpp 10 | // SSID and PW for Config Portal 11 | String ssid = "ESP_" + String(ESP_getChipId(), HEX); 12 | const char* password = "your_password"; 13 | ``` 14 | After you connected, please, go to http://192.168.4.1, you'll see this `Main` page: 15 | 16 |

17 | 18 |

19 | 20 | Select `Information` to enter the Info page where the board info will be shown (long page) 21 | 22 |

23 | 24 |

25 | 26 | or short page (default) 27 | 28 |

29 | 30 |

31 | 32 | Select `Configuration` to enter this page where you can select an AP and specify its WiFi Credentials 33 | 34 |

35 | 36 |

37 | 38 | Enter your credentials, then click `Save`. The WiFi Credentials will be saved and the board reboots to connect to the selected WiFi AP. 39 | 40 | If you're already connected to a listed WiFi AP and don't want to change anything, just select `Exit Portal` from the `Main` page to reboot the board and connect to the previously-stored AP. The WiFi Credentials are still intact. 41 | 42 | --- 43 | 44 | ## How to use this Async_ESP32_FSWebServer example? 45 | 46 | This shows you how to use this example in Ubuntu (but you can use similar commands in other OSes) 47 | 48 | ### Download Data files 49 | 50 | 1. For example, you already downloaded data files from [Async_ESP32_FSWebServer data](https://github.com/khoih-prog/ESPAsync_WiFiManager/tree/master/examples/Async_ESP32_FSWebServer/data) to a local folder, for example: 51 | 52 | ``` 53 | ~/Arduino/libraries/ESPAsync_WiFiManager-master/examples/Async_ESP32_FSWebServer/data 54 | ``` 55 | 56 | ### HOWTO Upload files to ESP32 (SPIFFS or FFat) 57 | 58 | Use one of these methods (preferable first) 59 | 60 | 1. Go to http://async-esp32fs.local/edit, then "Choose file" -> "Upload" 61 | 2. or Upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE) 62 | 3. or upload the contents of a folder by running the following commands: 63 | ``` 64 | Ubuntu$ cd ~/Arduino/libraries/ESPAsync_WiFiManager-master/examples/Async_ESP32_FSWebServer/data 65 | Ubuntu$ for file in \`\ls -A1\`; do curl -F "file=@$PWD/$file" http://async-esp32fs.local/edit; done 66 | ``` 67 | --- 68 | 69 | ### Demonstrating pictures 70 | 71 |

72 | 73 |

74 | 75 | 4. Edit / Delete / Download any file in the the folder by going to http://async-esp32fs.local/edit 76 | 77 |

78 | 79 |

80 | 81 | 82 | -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer/data/CanadaFlag_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer/data/CanadaFlag_1.png -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer/data/CanadaFlag_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer/data/CanadaFlag_2.png -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer/data/CanadaFlag_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer/data/CanadaFlag_3.jpg -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer/data/edit.htm.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer/data/edit.htm.gz -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer/data/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer/data/favicon.ico -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer/data/graphs.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer/data/graphs.js.gz -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer/data/index.htm: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | ESP Monitor 23 | 24 | 85 | 86 | 87 |
88 | 89 | 90 | 91 | 92 |
93 |
94 |
95 |
96 | 97 | -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer/pics/async-esp32fs.local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer/pics/async-esp32fs.local.png -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer/pics/async-esp32fs.local_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer/pics/async-esp32fs.local_edit.png -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer_DRD/README.md: -------------------------------------------------------------------------------- 1 | # Async_ESP32_FSWebServer_DRD Example 2 | 3 | Compare this efficient Async_ESP32_FSWebServer_DRD example with the so complicated twin [ESP32_FSWebServer_DRD](https://github.com/khoih-prog/ESP_WiFiManager/tree/master/examples/ESP32_FSWebServer_DRD) to appreciate the powerful AsynWebServer this [ESPAsync_WiFiManager Library](https://github.com/khoih-prog/ESPAsync_WiFiManager) is relying on. 4 | 5 | ## First, how Config Portal works? 6 | 7 | In `Configuration Portal Mode`, it starts an access point called `ESP_xxxxxx`. Connect to it using the configurable password you can define in the code. For example, `your_password` (see examples): 8 | 9 | ```cpp 10 | // SSID and PW for Config Portal 11 | String ssid = "ESP_" + String(ESP_getChipId(), HEX); 12 | const char* password = "your_password"; 13 | ``` 14 | After you connected, please, go to http://192.168.4.1, you'll see this `Main` page: 15 | 16 |

17 | 18 |

19 | 20 | Select `Information` to enter the Info page where the board info will be shown (long page) 21 | 22 |

23 | 24 |

25 | 26 | or short page (default) 27 | 28 |

29 | 30 |

31 | 32 | Select `Configuration` to enter this page where you can select an AP and specify its WiFi Credentials 33 | 34 |

35 | 36 |

37 | 38 | Enter your credentials, then click `Save`. The WiFi Credentials will be saved and the board reboots to connect to the selected WiFi AP. 39 | 40 | If you're already connected to a listed WiFi AP and don't want to change anything, just select `Exit Portal` from the `Main` page to reboot the board and connect to the previously-stored AP. The WiFi Credentials are still intact. 41 | 42 | --- 43 | 44 | ## How to use this Async_ESP32_FSWebServer_DRD example? 45 | 46 | This shows you how to use this example in Ubuntu (but you can use similar commands in other OSes) 47 | 48 | ### Download Data files 49 | 50 | 1. For example, you already downloaded data files from [Async_ESP32_FSWebServer_DRD data](https://github.com/khoih-prog/ESPAsync_WiFiManager/tree/master/examples/Async_ESP32_FSWebServer_DRD/data) to a local folder, for example: 51 | 52 | ``` 53 | ~/Arduino/libraries/ESPAsync_WiFiManager-master/examples/Async_ESP32_FSWebServer_DRD/data 54 | ``` 55 | 56 | ### HOWTO Upload files to ESP32 (SPIFFS or FFat) 57 | 58 | Use one of these methods (preferable first) 59 | 60 | 1. Go to http://async-esp32fs.local/edit, then "Choose file" -> "Upload" 61 | 2. or Upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE) 62 | 3. or upload the contents of a folder by running the following commands: 63 | ``` 64 | Ubuntu$ cd ~/Arduino/libraries/ESPAsync_WiFiManager-master/examples/Async_ESP32_FSWebServer_DRD/data 65 | Ubuntu$ for file in \`\ls -A1\`; do curl -F "file=@$PWD/$file" http://async-esp32fs.local/edit; done 66 | ``` 67 | 68 | --- 69 | 70 | ### Demonstrating pictures 71 | 72 |

73 | 74 |

75 | 76 | 4. Edit / Delete / Download any file in the the folder by going to http://async-esp32fs.local/edit 77 | 78 |

79 | 80 |

81 | 82 | 83 | -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer_DRD/data/CanadaFlag_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer_DRD/data/CanadaFlag_1.png -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer_DRD/data/CanadaFlag_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer_DRD/data/CanadaFlag_2.png -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer_DRD/data/CanadaFlag_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer_DRD/data/CanadaFlag_3.jpg -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer_DRD/data/edit.htm.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer_DRD/data/edit.htm.gz -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer_DRD/data/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer_DRD/data/favicon.ico -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer_DRD/data/graphs.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer_DRD/data/graphs.js.gz -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer_DRD/data/index.htm: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | ESP Monitor 23 | 24 | 85 | 86 | 87 |
88 | 89 | 90 | 91 | 92 |
93 |
94 |
95 |
96 | 97 | -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer_DRD/pics/async-esp32fs.local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer_DRD/pics/async-esp32fs.local.png -------------------------------------------------------------------------------- /examples/Async_ESP32_FSWebServer_DRD/pics/async-esp32fs.local_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP32_FSWebServer_DRD/pics/async-esp32fs.local_edit.png -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer/README.md: -------------------------------------------------------------------------------- 1 | # Async_ESP_FSWebServer Example 2 | 3 | Compare this efficient Async_ESP_FSWebServer example with the so complicated twin [ESP_FSWebServer](https://github.com/khoih-prog/ESP_WiFiManager/tree/master/examples/ESP_FSWebServer) to appreciate the powerful AsynWebServer this [ESPAsync_WiFiManager Library](https://github.com/khoih-prog/ESPAsync_WiFiManager) is relying on. 4 | 5 | ## First, how Config Portal works? 6 | 7 | In `Configuration Portal Mode`, it starts an access point called `ESP_xxxxxx`. Connect to it using the configurable password you can define in the code. For example, `your_password` (see examples): 8 | 9 | ```cpp 10 | // SSID and PW for Config Portal 11 | String ssid = "ESP_" + String(ESP_getChipId(), HEX); 12 | const char* password = "your_password"; 13 | ``` 14 | After you connected, please, go to http://192.168.4.1, you'll see this `Main` page: 15 | 16 |

17 | 18 |

19 | 20 | Select `Information` to enter the Info page where the board info will be shown (long page) 21 | 22 |

23 | 24 |

25 | 26 | or short page (default) 27 | 28 |

29 | 30 |

31 | 32 | Select `Configuration` to enter this page where you can select an AP and specify its WiFi Credentials 33 | 34 |

35 | 36 |

37 | 38 | Enter your credentials, then click `Save`. The WiFi Credentials will be saved and the board reboots to connect to the selected WiFi AP. 39 | 40 | If you're already connected to a listed WiFi AP and don't want to change anything, just select `Exit Portal` from the `Main` page to reboot the board and connect to the previously-stored AP. The WiFi Credentials are still intact. 41 | 42 | --- 43 | 44 | ## How to use this Async_ESP_FSWebServer example? 45 | 46 | This shows you how to use this example in Ubuntu (but you can use similar commands in other OSes) 47 | 48 | ### Download Data files 49 | 50 | 1. For example, you already downloaded data files from [Async_ESP_FSWebServer data](https://github.com/khoih-prog/ESPAsync_WiFiManager/tree/master/examples/Async_ESP_FSWebServer/data) to a local folder, for example: 51 | 52 | ``` 53 | ~/Arduino/libraries/ESPAsync_WiFiManager-master/examples/Async_ESP_FSWebServer/data 54 | ``` 55 | 56 | ### HOWTO Upload files to ESP8266 (LittleFS or SPIFFS) 57 | 58 | Use one of these methods (preferable first) 59 | 60 | 1. Go to http://async-esp8266fs.local/edit, then "Choose file" -> "Upload" 61 | 2. or Upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE) 62 | 3. or upload the contents of a folder by running the following commands: 63 | ``` 64 | Ubuntu$ cd ~/Arduino/libraries/ESPAsync_WiFiManager-master/examples/Async_ESP_FSWebServer/data 65 | Ubuntu$ for file in \`\ls -A1\`; do curl -F "file=@$PWD/$file" http://async-esp8266fs.local/edit; done 66 | ``` 67 | 68 | --- 69 | 70 | ### Demonstrating pictures 71 | 72 |

73 | 74 |

75 | 76 | 4. Edit / Delete / Download any file in the the folder by going to http://async-esp8266fs.local/edit 77 | 78 |

79 | 80 |

81 | 82 | 83 | -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer/data/CanadaFlag_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer/data/CanadaFlag_1.png -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer/data/CanadaFlag_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer/data/CanadaFlag_2.png -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer/data/CanadaFlag_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer/data/CanadaFlag_3.jpg -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer/data/edit.htm.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer/data/edit.htm.gz -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer/data/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer/data/favicon.ico -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer/data/graphs.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer/data/graphs.js.gz -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer/data/index.htm: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | ESP Monitor 23 | 24 | 85 | 86 | 87 |
88 | 89 | 90 | 91 | 92 |
93 |
94 |
95 |
96 | 97 | -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer/pics/async-esp8266fs.local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer/pics/async-esp8266fs.local.png -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer/pics/async-esp8266fs.local_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer/pics/async-esp8266fs.local_edit.png -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/README.md: -------------------------------------------------------------------------------- 1 | # Async_ESP_FSWebServer_DRD Example 2 | 3 | Compare this efficient Async_ESP_FSWebServer example with the so complicated twin [ESP_FSWebServer_DRD](https://github.com/khoih-prog/ESP_WiFiManager/tree/master/examples/ESP_FSWebServer_DRD) to appreciate the powerful AsynWebServer this [ESPAsync_WiFiManager Library](https://github.com/khoih-prog/ESPAsync_WiFiManager) is relying on. 4 | 5 | ## First, how Config Portal works? 6 | 7 | In `Configuration Portal Mode`, it starts an access point called `ESP_xxxxxx`. Connect to it using the configurable password you can define in the code. For example, `your_password` (see examples): 8 | 9 | ```cpp 10 | // SSID and PW for Config Portal 11 | String ssid = "ESP_" + String(ESP_getChipId(), HEX); 12 | const char* password = "your_password"; 13 | ``` 14 | After you connected, please, go to http://192.168.4.1, you'll see this `Main` page: 15 | 16 |

17 | 18 |

19 | 20 | Select `Information` to enter the Info page where the board info will be shown (long page) 21 | 22 |

23 | 24 |

25 | 26 | or short page (default) 27 | 28 |

29 | 30 |

31 | 32 | Select `Configuration` to enter this page where you can select an AP and specify its WiFi Credentials 33 | 34 |

35 | 36 |

37 | 38 | Enter your credentials, then click `Save`. The WiFi Credentials will be saved and the board reboots to connect to the selected WiFi AP. 39 | 40 | If you're already connected to a listed WiFi AP and don't want to change anything, just select `Exit Portal` from the `Main` page to reboot the board and connect to the previously-stored AP. The WiFi Credentials are still intact. 41 | 42 | --- 43 | 44 | ## How to use this Async_ESP_FSWebServer example? 45 | 46 | This shows you how to use this example in Ubuntu (but you can use similar commands in other OSes) 47 | 48 | ### Download Data files 49 | 50 | 1. For example, you already downloaded data files from [Async_ESP_FSWebServer data](https://github.com/khoih-prog/ESPAsync_WiFiManager/tree/master/examples/Async_ESP_FSWebServer/data) to a local folder, for example: 51 | 52 | ``` 53 | ~/Arduino/libraries/ESPAsync_WiFiManager-master/examples/Async_ESP_FSWebServer_DRD/data 54 | ``` 55 | 56 | ### HOWTO Upload files to ESP8266 (LittleFS or SPIFFS) 57 | 58 | Use one of these methods (preferable first) 59 | 60 | 1. Go to http://async-esp8266fs.local/edit, then "Choose file" -> "Upload" 61 | 2. or Upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE) 62 | 3. or upload the contents of a folder by running the following commands: 63 | ``` 64 | Ubuntu$ cd ~/Arduino/libraries/ESPAsync_WiFiManager-master/examples/Async_ESP_FSWebServer/data 65 | Ubuntu$ for file in \`\ls -A1\`; do curl -F "file=@$PWD/$file" http://async-esp8266fs.local/edit; done 66 | ``` 67 | 68 | --- 69 | 70 | ### Demonstrating pictures 71 | 72 |

73 | 74 |

75 | 76 | 4. Edit / Delete / Download any file in the the folder by going to http://async-esp8266fs.local/edit 77 | 78 |

79 | 80 |

81 | 82 | 83 | -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/data/CanadaFlag_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer_DRD/data/CanadaFlag_1.png -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/data/CanadaFlag_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer_DRD/data/CanadaFlag_2.png -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/data/CanadaFlag_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer_DRD/data/CanadaFlag_3.jpg -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/data/edit.htm.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer_DRD/data/edit.htm.gz -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/data/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer_DRD/data/favicon.ico -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/data/graphs.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer_DRD/data/graphs.js.gz -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/data/index.htm: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | ESP Monitor 23 | 24 | 85 | 86 | 87 |
88 | 89 | 90 | 91 | 92 |
93 |
94 |
95 |
96 | 97 | -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/pics/async-esp8266fs.local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer_DRD/pics/async-esp8266fs.local.png -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/pics/async-esp8266fs.local_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer_DRD/pics/async-esp8266fs.local_edit.png -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/pics/esp8266fs.local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer_DRD/pics/esp8266fs.local.png -------------------------------------------------------------------------------- /examples/Async_ESP_FSWebServer_DRD/pics/esp8266fs.local_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khoih-prog/ESPAsync_WiFiManager/e83343f4c2df14b504d284982152539692ac2078/examples/Async_ESP_FSWebServer_DRD/pics/esp8266fs.local_edit.png -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ########################################## 2 | # Syntax Coloring Map For ESP_WifiManager 3 | ########################################## 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ESPAsync_WiFiManager KEYWORD1 10 | ESPAsync_WMParameter KEYWORD1 11 | 12 | WiFi_AP_IPConfig KEYWORD1 13 | WiFi_STA_IPConfig KEYWORD1 14 | 15 | WiFiResult KEYWORD1 16 | wifi_ssid_count_t KEYWORD1 17 | 18 | ####################################### 19 | # Methods and Functions (KEYWORD2) 20 | ####################################### 21 | 22 | getID KEYWORD2 23 | getValue KEYWORD2 24 | getPlaceholder KEYWORD2 25 | getValueLength KEYWORD2 26 | getLabelPlacement KEYWORD2 27 | getCustomHTML KEYWORD2 28 | autoConnect KEYWORD2 29 | startConfigPortal KEYWORD2 30 | getConfigPortalSSID KEYWORD2 31 | getConfigPortalPW KEYWORD2 32 | resetSettings KEYWORD2 33 | setConfigPortalTimeout KEYWORD2 34 | setTimeout KEYWORD2 35 | setConnectTimeout KEYWORD2 36 | setDebugOutput KEYWORD2 37 | setMinimumSignalQuality KEYWORD2 38 | setConfigPortalChannel KEYWORD2 39 | setAPStaticIPConfig KEYWORD2 40 | getAPStaticIPConfig KEYWORD2 41 | setSTAStaticIPConfig KEYWORD2 42 | getSTAStaticIPConfig KEYWORD2 43 | setAPCallback KEYWORD2 44 | setSaveConfigCallback KEYWORD2 45 | addParameter KEYWORD2 46 | setBreakAfterConfig KEYWORD2 47 | setCustomHeadElement KEYWORD2 48 | setRemoveDuplicateAPs KEYWORD2 49 | setCredentials KEYWORD2 50 | getSSID KEYWORD2 51 | getPW KEYWORD2 52 | getSSID1 KEYWORD2 53 | getPW1 KEYWORD2 54 | setCORSHeader KEYWORD2 55 | getCORSHeader KEYWORD2 56 | getParameters KEYWORD2 57 | getParametersCount KEYWORD2 58 | getStatus KEYWORD2 59 | getStoredWiFiSSID KEYWORD2 60 | getStoredWiFiPass KEYWORD2 61 | WiFi_SSID KEYWORD2 62 | WiFi_Pass KEYWORD2 63 | setHostname KEYWORD2 64 | getTimezoneName KEYWORD2 65 | setTimezoneName KEYWORD2 66 | getTZ KEYWORD2 67 | 68 | ####################################### 69 | 70 | getChipID KEYWORD2 71 | getChipOUI KEYWORD2 72 | 73 | ESP_getChipId KEYWORD2 74 | ESP_getChipOUI KEYWORD2 75 | 76 | ####################################### 77 | # Constants (LITERAL1) 78 | ####################################### 79 | 80 | # LITERAL1 81 | 82 | ESP_ASYNC_WIFIMANAGER_VERSION LITERAL1 83 | ESP_ASYNC_WIFIMANAGER_VERSION_MAJOR LITERAL1 84 | ESP_ASYNC_WIFIMANAGER_VERSION_MINOR LITERAL1 85 | ESP_ASYNC_WIFIMANAGER_VERSION_PATCH LITERAL1 86 | ESP_ASYNC_WIFIMANAGER_VERSION_INT LITERAL1 87 | 88 | WM_HTTP_200 LITERAL1 89 | WM_HTTP_HEAD_START LITERAL1 90 | WM_HTTP_STYLE LITERAL1 91 | WM_HTTP_SCRIPT LITERAL1 92 | WM_HTTP_SCRIPT_NTP_MSG LITERAL1 93 | WM_HTTP_SCRIPT_NTP_HIDDEN LITERAL1 94 | WM_HTTP_SCRIPT_NTP LITERAL1 95 | WM_HTTP_HEAD_END LITERAL1 96 | WM_FLDSET_START LITERAL1 97 | WM_FLDSET_END LITERAL1 98 | WM_HTTP_PORTAL_OPTIONS LITERAL1 99 | WM_HTTP_ITEM LITERAL1 100 | JSON_ITEM LITERAL1 101 | WM_HTTP_FORM_LABEL_BEFORE LITERAL1 102 | WM_HTTP_FORM_LABEL_AFTER LITERAL1 103 | WM_HTTP_FORM_LABEL LITERAL1 104 | WM_HTTP_FORM_PARAM LITERAL1 105 | WM_HTTP_FORM_END LITERAL1 106 | WM_HTTP_SAVED LITERAL1 107 | WM_HTTP_END LITERAL1 108 | WM_HTTP_HEAD_CL LITERAL1 109 | WM_HTTP_HEAD_CT LITERAL1 110 | WM_HTTP_HEAD_CT2 LITERAL1 111 | WM_HTTP_CACHE_CONTROL LITERAL1 112 | WM_HTTP_PRAGMA LITERAL1 113 | WM_HTTP_NO_CACHE LITERAL1 114 | WM_HTTP_EXPIRES LITERAL1 115 | WM_HTTP_CORS LITERAL1 116 | WM_HTTP_CORS_ALLOW_ALL LITERAL1 117 | WM_HTTP_AVAILABLE_PAGES LITERAL1 118 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ESPAsync_WiFiManager", 3 | "version": "1.15.1", 4 | "keywords": "wifi, WiFiManager, esp8266, esp32, esp32-s2, esp32-s3, esp32-c3, AsyncWebServer, Async-WiFiManager, MultiWiFi, Async, Communication, Credentials, Config-Portal, DoubleReset, MultiReset, littlefs, spiffs, dns-server, iot, eeprom", 5 | "description": "ESP32 (including ESP32-S2, ESP32-S3 and ESP32-C3), ESP8266 WiFi Connection Manager using AsyncWebServer, with enhanced GUI and fallback Web ConfigPortal. This Library is used for configuring ESP32 (including ESP32-S2, ESP32-S3 and ESP32-C3), ESP8266 modules WiFi Credentials at runtime. You can also specify static DNS servers, personalized HostName, fixed or random AP channel. Now with MultiWiFi auto(Re)connect, configurable CORS Header and auto-Timezone features. Auto detect ESP32 core and use either built-in LittleFS or external LITTLEFS library. Using AsyncDNSServer instead of DNSServer. Now using correct ESP32 chipIP and optionally display Credentials on Config Portal", 6 | "authors": 7 | { 8 | "name": "Khoi Hoang", 9 | "url": "https://github.com/khoih-prog", 10 | "maintainer": true 11 | }, 12 | "repository": 13 | { 14 | "type": "git", 15 | "url": "https://github.com/khoih-prog/ESPAsync_WiFiManager" 16 | }, 17 | "homepage": "https://github.com/khoih-prog/ESPAsync_WiFiManager", 18 | "export": { 19 | "exclude": [ 20 | "linux", 21 | "extras", 22 | "tests" 23 | ] 24 | }, 25 | "dependencies": [ 26 | { 27 | "name": "AsyncTCP", 28 | "version": "https://github.com/me-no-dev/AsyncTCP", 29 | "platforms": [ "espressif32"] 30 | }, 31 | { 32 | "name": "ESPAsyncTCP", 33 | "version": "https://github.com/khoih-prog/ESPAsyncTCP", 34 | "platforms": [ "espressif8266"] 35 | }, 36 | { 37 | "name": "ESP Async WebServer", 38 | "version": "https://github.com/khoih-prog/ESPAsyncWebServer", 39 | "platforms": ["espressif8266", "espressif32"] 40 | }, 41 | { 42 | "owner": "me-no-dev", 43 | "name": "ESPAsyncUDP", 44 | "version": "0.0.0-alpha+sha.697c75a025", 45 | "platforms": ["espressif8266"] 46 | }, 47 | { 48 | "name": "ESPAsyncDNSServer", 49 | "version": "https://github.com/khoih-prog/ESPAsyncDNSServer", 50 | "platforms": ["espressif8266", "espressif32"] 51 | }, 52 | { 53 | "owner": "khoih-prog", 54 | "name": "ESP_DoubleResetDetector", 55 | "version": ">=1.3.2", 56 | "platforms": ["espressif8266", "espressif32"] 57 | } 58 | ], 59 | "license": "MIT", 60 | "frameworks": "*", 61 | "platforms": ["espressif8266", "espressif32"], 62 | "examples": "examples/*/*/*.ino", 63 | "headers": ["ESPAsync_WiFiManager.h", "ESPAsync_WiFiManager.hpp"] 64 | } 65 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=ESPAsync_WiFiManager 2 | version=1.15.1 3 | author=Khoi Hoang 4 | maintainer=Khoi Hoang 5 | license=MIT 6 | sentence=ESP32 (including ESP32-S2, ESP32-S3 and ESP32-C3), ESP8266 WiFi Connection Manager using AsyncWebServer, with enhanced GUI and fallback Web ConfigPortal. 7 | paragraph=This Library is used for configuring ESP32 (including ESP32-S2, ESP32-S3 and ESP32-C3), ESP8266 modules WiFi Credentials at runtime. You can also specify static DNS servers, personalized HostName, fixed or random AP channel. Now with MultiWiFi auto(Re)connect, configurable CORS Header and auto-Timezone features. Auto detect ESP32 core and use either built-in LittleFS or external LITTLEFS library. Using AsyncDNSServer instead of DNSServer now. Now using correct ESP32 chipIP and optionally display Credentials on Config Portal 8 | category=Communication 9 | url=https://github.com/khoih-prog/ESPAsync_WiFiManager 10 | architectures=esp8266,esp32 11 | depends=ESP_DoubleResetDetector 12 | includes=ESPAsync_WiFiManager.h, ESPAsync_WiFiManager.hpp 13 | -------------------------------------------------------------------------------- /platformio/platformio.ini: -------------------------------------------------------------------------------- 1 | ;PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | ; ============================================================ 13 | ; chose environment: 14 | ; ESP8266 15 | ; ESP32 16 | ; ============================================================ 17 | default_envs = ESP8266 18 | ;default_envs = ESP32 19 | 20 | [env] 21 | ; ============================================================ 22 | ; Serial configuration 23 | ; choose upload speed, serial-monitor speed 24 | ; ============================================================ 25 | upload_speed = 921600 26 | ;upload_port = COM11 27 | ;monitor_speed = 9600 28 | ;monitor_port = COM11 29 | 30 | ; Checks for the compatibility with frameworks and dev/platforms 31 | lib_compat_mode = strict 32 | lib_ldf_mode = chain+ 33 | ;lib_ldf_mode = deep+ 34 | 35 | lib_deps = 36 | ; PlatformIO 4.x 37 | ; ESP Async WebServer@>=1.2.3 38 | ; https://github.com/khoih-prog/ESPAsyncWebServer 39 | ; ESPAsyncTCP@>=1.2.2 40 | ; https://github.com/khoih-prog/ESPAsyncTCP 41 | ; AsyncTCP@>=1.1.1 42 | ; ESP_DoubleResetDetector@>=1.3.2 43 | ; ESPAsyncDNSServer@>=1.0.0 44 | ; https://github.com/khoih-prog/ESPAsyncDNSServer 45 | ; LittleFS_esp32@>=1.0.6 46 | ; PlatformIO 5.x 47 | ; me-no-dev/ESP Async WebServer@>=1.2.3 48 | https://github.com/khoih-prog/ESPAsyncWebServer 49 | ; me-no-dev/ESPAsyncTCP@>=1.2.2 50 | https://github.com/khoih-prog/ESPAsyncTCP 51 | me-no-dev/AsyncTCP@>=1.1.1 52 | khoih-prog/ESP_DoubleResetDetector@>=1.3.2 53 | ; devyte/ESPAsyncDNSServer@>=1.0.0 54 | https://github.com/khoih-prog/ESPAsyncDNSServer 55 | ; lorol/LittleFS_esp32@>=1.0.6 56 | 57 | build_flags = 58 | ; set your debug output (default=Serial) 59 | -D DEBUG_ESP_PORT=Serial 60 | ; comment the folowing line to enable WiFi debugging 61 | -D NDEBUG 62 | 63 | [env:ESP8266] 64 | platform = espressif8266 65 | framework = arduino 66 | ; ============================================================ 67 | ; Board configuration 68 | ; choose your board by uncommenting one of the following lines 69 | ; ============================================================ 70 | ;board = gen4iod 71 | ;board = huzzah 72 | ;board = oak 73 | ;board = esp_wroom_02 74 | ;board = espduino 75 | ;board = espectro 76 | ;board = espino 77 | ;board = espresso_lite_v1 78 | ;board = espresso_lite_v2 79 | ;board = esp12e 80 | ;board = esp01_1m 81 | ;board = esp01 82 | ;board = esp07 83 | ;board = esp8285 84 | ;board = heltec_wifi_kit_8 85 | ;board = inventone 86 | ;board = nodemcu 87 | board = nodemcuv2 88 | ;board = modwifi 89 | ;board = phoenix_v1 90 | ;board = phoenix_v2 91 | ;board = sparkfunBlynk 92 | ;board = thing 93 | ;board = thingdev 94 | ;board = esp210 95 | ;board = espinotee 96 | ;board = d1 97 | ;board = d1_mini 98 | ;board = d1_mini_lite 99 | ;board = d1_mini_pro 100 | ;board = wifi_slot 101 | ;board = wifiduino 102 | ;board = wifinfo 103 | ;board = wio_link 104 | ;board = wio_node 105 | ;board = xinabox_cw01 106 | ;board = esp32doit-devkit-v1 107 | 108 | [env:ESP32] 109 | platform = espressif32 110 | framework = arduino 111 | ; ============================================================ 112 | ; Board configuration 113 | ; choose your board by uncommenting one of the following lines 114 | ; ============================================================ 115 | ;board = esp32cam 116 | ;board = alksesp32 117 | ;board = featheresp32 118 | ;board = espea32 119 | ;board = bpi-bit 120 | ;board = d-duino-32 121 | board = esp32doit-devkit-v1 122 | ;board = pocket_32 123 | ;board = fm-devkit 124 | ;board = pico32 125 | ;board = esp32-evb 126 | ;board = esp32-gateway 127 | ;board = esp32-pro 128 | ;board = esp32-poe 129 | ;board = oroca_edubot 130 | ;board = onehorse32dev 131 | ;board = lopy 132 | ;board = lopy4 133 | ;board = wesp32 134 | ;board = esp32thing 135 | ;board = sparkfun_lora_gateway_1-channel 136 | ;board = ttgo-lora32-v1 137 | ;board = ttgo-t-beam 138 | ;board = turta_iot_node 139 | ;board = lolin_d32 140 | ;board = lolin_d32_pro 141 | ;board = lolin32 142 | ;board = wemosbat 143 | ;board = widora-air 144 | ;board = xinabox_cw02 145 | ;board = iotbusio 146 | ;board = iotbusproteus 147 | ;board = nina_w10 148 | -------------------------------------------------------------------------------- /src/ESPAsync_WiFiManager.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | ESPAsync_WiFiManager.h 3 | For ESP8266 / ESP32 boards 4 | 5 | ESPAsync_WiFiManager is a library for the ESP8266/Arduino platform, using (ESP)AsyncWebServer to enable easy 6 | configuration and reconfiguration of WiFi credentials using a Captive Portal. 7 | 8 | Modified from 9 | 1. Tzapu (https://github.com/tzapu/WiFiManager) 10 | 2. Ken Taylor (https://github.com/kentaylor) 11 | 3. Alan Steremberg (https://github.com/alanswx/ESPAsyncWiFiManager) 12 | 4. Khoi Hoang (https://github.com/khoih-prog/ESP_WiFiManager) 13 | 14 | Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager 15 | Licensed under MIT license 16 | 17 | Version: 1.15.1 18 | 19 | Version Modified By Date Comments 20 | ------- ----------- ---------- ----------- 21 | 1.0.11 K Hoang 21/08/2020 Initial coding to use (ESP)AsyncWebServer instead of (ESP8266)WebServer. Bump up to v1.0.11 22 | to sync with ESP_WiFiManager v1.0.11 23 | ... 24 | 1.10.0 K Hoang 29/12/2021 Fix `multiple-definitions` linker error and weird bug related to src_cpp 25 | 1.11.0 K Hoang 17/01/2022 Enable compatibility with old code to include only ESP_WiFiManager.h 26 | 1.12.0 K Hoang 10/02/2022 Add support to new ESP32-S3 27 | 1.12.1 K Hoang 11/02/2022 Add LittleFS support to ESP32-C3. Use core LittleFS instead of Lorol's LITTLEFS for v2.0.0+ 28 | 1.12.2 K Hoang 13/03/2022 Optimize code by using passing by `reference` instead of by `value` 29 | 1.13.0 K Hoang 18/08/2022 Using AsynsDNSServer instead of DNSServer 30 | 1.14.0 K Hoang 09/09/2022 Fix ESP32 chipID and add ESP_getChipOUI() 31 | 1.14.1 K Hoang 15/09/2022 Remove dependency on ESP_AsyncWebServer, ESPAsyncTCP and AsyncTCP in `library.properties` 32 | 1.15.0 K Hoang 07/10/2022 Optional display Credentials (SSIDs, PWDs) in Config Portal 33 | 1.15.1 K Hoang 25/10/2022 Using random channel for softAP without password. Add astyle using allman style 34 | *****************************************************************************************************************************/ 35 | 36 | #pragma once 37 | 38 | #ifndef ESPAsync_WiFiManager_h 39 | #define ESPAsync_WiFiManager_h 40 | 41 | #include //https://github.com/khoih-prog/ESPAsync_WiFiManager 42 | #include //https://github.com/khoih-prog/ESPAsync_WiFiManager 43 | 44 | #endif // ESPAsync_WiFiManager_h 45 | 46 | -------------------------------------------------------------------------------- /src/ESPAsync_WiFiManager_Debug.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | ESPAsync_WiFiManager_Debug.h 3 | For ESP8266 / ESP32 boards 4 | 5 | ESPAsync_WiFiManager is a library for the ESP8266/Arduino platform, using (ESP)AsyncWebServer to enable easy 6 | configuration and reconfiguration of WiFi credentials using a Captive Portal. 7 | 8 | Modified from 9 | 1. Tzapu (https://github.com/tzapu/WiFiManager) 10 | 2. Ken Taylor (https://github.com/kentaylor) 11 | 3. Alan Steremberg (https://github.com/alanswx/ESPAsyncWiFiManager) 12 | 4. Khoi Hoang (https://github.com/khoih-prog/ESP_WiFiManager) 13 | 14 | Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager 15 | Licensed under MIT license 16 | 17 | Version: 1.15.1 18 | 19 | Version Modified By Date Comments 20 | ------- ----------- ---------- ----------- 21 | 1.0.11 K Hoang 21/08/2020 Initial coding to use (ESP)AsyncWebServer instead of (ESP8266)WebServer. Bump up to v1.0.11 22 | to sync with ESP_WiFiManager v1.0.11 23 | ... 24 | 1.10.0 K Hoang 29/12/2021 Fix `multiple-definitions` linker error and weird bug related to src_cpp 25 | 1.11.0 K Hoang 17/01/2022 Enable compatibility with old code to include only ESP_WiFiManager.h 26 | 1.12.0 K Hoang 10/02/2022 Add support to new ESP32-S3 27 | 1.12.1 K Hoang 11/02/2022 Add LittleFS support to ESP32-C3. Use core LittleFS instead of Lorol's LITTLEFS for v2.0.0+ 28 | 1.12.2 K Hoang 13/03/2022 Optimize code by using passing by `reference` instead of by `value` 29 | 1.13.0 K Hoang 18/08/2022 Using AsynsDNSServer instead of DNSServer 30 | 1.14.0 K Hoang 09/09/2022 Fix ESP32 chipID and add ESP_getChipOUI() 31 | 1.14.1 K Hoang 15/09/2022 Remove dependency on ESP_AsyncWebServer, ESPAsyncTCP and AsyncTCP in `library.properties` 32 | 1.15.0 K Hoang 07/10/2022 Optional display Credentials (SSIDs, PWDs) in Config Portal 33 | 1.15.1 K Hoang 25/10/2022 Using random channel for softAP without password. Add astyle using allman style 34 | *****************************************************************************************************************************/ 35 | 36 | #pragma once 37 | 38 | #ifndef ESPAsync_WiFiManager_Debug_H 39 | #define ESPAsync_WiFiManager_Debug_H 40 | 41 | #ifdef ESPASYNC_WIFIMGR_DEBUG_PORT 42 | #define DBG_PORT_ESP_WM ESPASYNC_WIFIMGR_DEBUG_PORT 43 | #else 44 | #define DBG_PORT_ESP_WM Serial 45 | #endif 46 | 47 | // Change _ESPASYNC_WIFIMGR_LOGLEVEL_ to set tracing and logging verbosity 48 | // 0: DISABLED: no logging 49 | // 1: ERROR: errors 50 | // 2: WARN: errors and warnings 51 | // 3: INFO: errors, warnings and informational (default) 52 | // 4: DEBUG: errors, warnings, informational and debug 53 | 54 | #ifndef _ESPASYNC_WIFIMGR_LOGLEVEL_ 55 | #define _ESPASYNC_WIFIMGR_LOGLEVEL_ 1 56 | #endif 57 | 58 | ///////////////////////////////////////////////////////// 59 | 60 | const char ESP_WM_MARK[] = "[WM] "; 61 | const char ESP_WM_SP[] = " "; 62 | 63 | #define ESP_WM_PRINT DBG_PORT_ESP_WM.print 64 | #define ESP_WM_PRINTLN DBG_PORT_ESP_WM.println 65 | 66 | #define ESP_WM_PRINT_MARK ESP_WM_PRINT(ESP_WM_MARK) 67 | #define ESP_WM_PRINT_SP ESP_WM_PRINT(ESP_WM_SP) 68 | 69 | ///////////////////////////////////////////////////////// 70 | 71 | #define LOGERROR(x) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>0) { ESP_WM_PRINT_MARK; ESP_WM_PRINTLN(x); } 72 | #define LOGERROR0(x) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>0) { ESP_WM_PRINT(x); } 73 | #define LOGERROR1(x,y) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>0) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(y); } 74 | #define LOGERROR2(x,y,z) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>0) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINT(y); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(z); } 75 | #define LOGERROR3(x,y,z,w) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>0) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINT(y); ESP_WM_PRINT_SP; ESP_WM_PRINT(z); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(w); } 76 | 77 | ///////////////////////////////////////////////////////// 78 | 79 | #define LOGWARN(x) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>1) { ESP_WM_PRINT_MARK; ESP_WM_PRINTLN(x); } 80 | #define LOGWARN0(x) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>1) { ESP_WM_PRINT(x); } 81 | #define LOGWARN1(x,y) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>1) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(y); } 82 | #define LOGWARN2(x,y,z) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>1) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINT(y); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(z); } 83 | #define LOGWARN3(x,y,z,w) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>1) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINT(y); ESP_WM_PRINT_SP; ESP_WM_PRINT(z); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(w); } 84 | 85 | ///////////////////////////////////////////////////////// 86 | 87 | #define LOGINFO(x) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>2) { ESP_WM_PRINT_MARK; ESP_WM_PRINTLN(x); } 88 | #define LOGINFO0(x) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>2) { ESP_WM_PRINT(x); } 89 | #define LOGINFO1(x,y) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>2) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(y); } 90 | #define LOGINFO2(x,y,z) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>2) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINT(y); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(z); } 91 | #define LOGINFO3(x,y,z,w) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>2) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINT(y); ESP_WM_PRINT_SP; ESP_WM_PRINT(z); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(w); } 92 | 93 | ///////////////////////////////////////////////////////// 94 | 95 | #define LOGDEBUG(x) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>3) { ESP_WM_PRINT_MARK; ESP_WM_PRINTLN(x); } 96 | #define LOGDEBUG0(x) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>3) { ESP_WM_PRINT(x); } 97 | #define LOGDEBUG1(x,y) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>3) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(y); } 98 | #define LOGDEBUG2(x,y,z) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>3) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINT(y); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(z); } 99 | #define LOGDEBUG3(x,y,z,w) if(_ESPASYNC_WIFIMGR_LOGLEVEL_>3) { ESP_WM_PRINT_MARK; ESP_WM_PRINT(x); ESP_WM_PRINT_SP; ESP_WM_PRINT(y); ESP_WM_PRINT_SP; ESP_WM_PRINT(z); ESP_WM_PRINT_SP; ESP_WM_PRINTLN(w); } 100 | 101 | ///////////////////////////////////////////////////////// 102 | 103 | #endif // ESPAsync_WiFiManager_Debug_H 104 | 105 | -------------------------------------------------------------------------------- /travis/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function build_examples() 4 | { 5 | # track the exit code for this platform 6 | local exit_code=0 7 | # loop through results and add them to the array 8 | examples=($(find $PWD/examples/ -name "*.pde" -o -name "*.ino")) 9 | 10 | # get the last example in the array 11 | local last="${examples[@]:(-1)}" 12 | 13 | # loop through example sketches 14 | for example in "${examples[@]}"; do 15 | 16 | # store the full path to the example's sketch directory 17 | local example_dir=$(dirname $example) 18 | 19 | # store the filename for the example without the path 20 | local example_file=$(basename $example) 21 | 22 | echo "$example_file: " 23 | local sketch="$example_dir/$example_file" 24 | echo "$sketch" 25 | #arduino -v --verbose-build --verify $sketch 26 | 27 | # verify the example, and save stdout & stderr to a variable 28 | # we have to avoid reading the exit code of local: 29 | # "when declaring a local variable in a function, the local acts as a command in its own right" 30 | local build_stdout 31 | build_stdout=$(arduino --verify $sketch 2>&1) 32 | 33 | # echo output if the build failed 34 | if [ $? -ne 0 ]; then 35 | # heavy X 36 | echo -e "\xe2\x9c\x96" 37 | echo -e "----------------------------- DEBUG OUTPUT -----------------------------\n" 38 | echo "$build_stdout" 39 | echo -e "\n------------------------------------------------------------------------\n" 40 | 41 | # mark as fail 42 | exit_code=1 43 | 44 | else 45 | # heavy checkmark 46 | echo -e "\xe2\x9c\x93" 47 | fi 48 | done 49 | 50 | return $exit_code 51 | } 52 | -------------------------------------------------------------------------------- /utils/astyle_library.conf: -------------------------------------------------------------------------------- 1 | # Code formatting rules for Arduino libraries, modified from for KH libraries: 2 | # 3 | # https://github.com/arduino/Arduino/blob/master/build/shared/examples_formatter.conf 4 | # 5 | 6 | # astyle --style=allman -s2 -t2 -C -S -xW -Y -M120 -f -p -xg -H -xb -c --xC120 -xL *.h *.cpp *.ino 7 | 8 | --mode=c 9 | --lineend=linux 10 | --style=allman 11 | 12 | # -r or -R 13 | #--recursive 14 | 15 | # -c => Converts tabs into spaces 16 | convert-tabs 17 | 18 | # -s2 => 2 spaces indentation 19 | --indent=spaces=2 20 | 21 | # -t2 => tab =2 spaces 22 | #--indent=tab=2 23 | 24 | # -C 25 | --indent-classes 26 | 27 | # -S 28 | --indent-switches 29 | 30 | # -xW 31 | --indent-preproc-block 32 | 33 | # -Y => indent classes, switches (and cases), comments starting at column 1 34 | --indent-col1-comments 35 | 36 | # -M120 => maximum of 120 spaces to indent a continuation line 37 | --max-continuation-indent=120 38 | 39 | # -xC120 => max‑code‑length will break a line if the code exceeds # characters 40 | --max-code-length=120 41 | 42 | # -f => 43 | --break-blocks 44 | 45 | # -p => put a space around operators 46 | --pad-oper 47 | 48 | # -xg => Insert space padding after commas 49 | --pad-comma 50 | 51 | # -H => put a space after if/for/while 52 | pad-header 53 | 54 | # -xb => Break one line headers (e.g. if/for/while) 55 | --break-one-line-headers 56 | 57 | # -c => Converts tabs into spaces 58 | #--convert-tabs 59 | 60 | # if you like one-liners, keep them 61 | #keep-one-line-statements 62 | 63 | # -xV 64 | --attach-closing-while 65 | 66 | #unpad-paren 67 | 68 | # -xp 69 | remove-comment-prefix 70 | 71 | -------------------------------------------------------------------------------- /utils/restyle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for dir in . ; do 4 | find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.ino" \) -exec astyle --suffix=none --options=./utils/astyle_library.conf \{\} \; 5 | done 6 | 7 | --------------------------------------------------------------------------------