├── .codespellrc
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── dependabot.yml
├── stale.yml
└── workflows
│ ├── auto-github-actions.yml
│ ├── report-size-deltas.yml
│ └── spell-check.yml
├── .gitignore
├── CONTRIBUTING.md
├── Images
├── Configuration.png
├── Configuration_1-0-11.png
├── Configuration_1-0-8.png
├── Configuration_1-0-9.png
├── Configuration_Simple.png
├── Configuration_Standard.png
├── Info.png
├── Info_Short.png
├── Info_Short_1-0-5.png
├── Main.png
├── Main_1-0-5.png
└── Saved.png
├── LICENSE
├── README.md
├── changelog.md
├── esp32s2_WebServer_Patch
├── WebServer.cpp
└── WebServer.h
├── examples
├── AutoConnect
│ └── AutoConnect.ino
├── AutoConnectWithFSParameters
│ └── AutoConnectWithFSParameters.ino
├── AutoConnectWithFeedback
│ └── AutoConnectWithFeedback.ino
├── AutoConnectWithFeedbackLED
│ └── AutoConnectWithFeedbackLED.ino
├── ConfigOnDRD_FS_MQTT_Ptr
│ └── ConfigOnDRD_FS_MQTT_Ptr.ino
├── ConfigOnDRD_FS_MQTT_Ptr_Complex
│ └── ConfigOnDRD_FS_MQTT_Ptr_Complex.ino
├── ConfigOnDRD_FS_MQTT_Ptr_Medium
│ └── ConfigOnDRD_FS_MQTT_Ptr_Medium.ino
├── ConfigOnDoubleReset
│ └── ConfigOnDoubleReset.ino
├── ConfigOnDoubleReset_Multi
│ ├── ConfigOnDoubleReset_Multi.cpp
│ ├── ConfigOnDoubleReset_Multi.h
│ └── ConfigOnDoubleReset_Multi.ino
├── ConfigOnStartup
│ └── ConfigOnStartup.ino
├── ConfigOnSwitch
│ ├── ConfigOnSwitch.ino
│ └── README.md
├── ConfigOnSwitchFS
│ └── ConfigOnSwitchFS.ino
├── ConfigOnSwitchFS_MQTT_Ptr
│ └── ConfigOnSwitchFS_MQTT_Ptr.ino
├── ConfigPortalParamsOnSwitch
│ └── ConfigPortalParamsOnSwitch.ino
├── ESP32_FSWebServer
│ ├── 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
│ │ ├── esp8266fs.local.png
│ │ └── esp8266fs.local_edit.png
├── ESP32_FSWebServer_DRD
│ ├── 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
│ │ ├── esp8266fs.local.png
│ │ └── esp8266fs.local_edit.png
├── ESP_FSWebServer
│ ├── 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
│ │ ├── esp8266fs.local.png
│ │ └── esp8266fs.local_edit.png
└── ESP_FSWebServer_DRD
│ ├── 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
│ ├── esp8266fs.local.png
│ └── esp8266fs.local_edit.png
├── keywords.txt
├── library.json
├── library.properties
├── platformio
└── platformio.ini
├── src
├── ESP_WiFiManager-Impl.h
├── ESP_WiFiManager.h
├── ESP_WiFiManager.hpp
├── ESP_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, or your post will be ignored and deleted:
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.5)
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-52-generic #58~20.04.1-Ubuntu SMP Thu Oct 13 13:09:46 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
54 |
55 | Context:
56 | I encountered a crash when using this library
57 |
58 | Steps to reproduce:
59 | 1. ...
60 | 2. ...
61 | 3. ...
62 | 4. ...
63 | ```
64 | ---
65 |
66 | ### Sending Feature Requests
67 |
68 | Feel free to post feature requests. It's helpful if you can explain exactly why the feature would be useful.
69 |
70 | 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.
71 |
72 | ---
73 |
74 | ### Sending Pull Requests
75 |
76 | Pull Requests with changes and fixes are also welcome!
77 |
78 | Please use the `astyle` to reformat the updated library code as follows (demo for Ubuntu Linux)
79 |
80 | 1. Change directory to the library GitHub
81 |
82 | ```
83 | xy@xy-Inspiron-3593:~$ cd Arduino/xy/ESP_WifiManager_GitHub/
84 | xy@xy-Inspiron-3593:~/Arduino/xy/ESP_WifiManager_GitHub$
85 | ```
86 |
87 | 2. Issue astyle command
88 |
89 | ```
90 | xy@xy-Inspiron-3593:~/Arduino/xy/ESP_WifiManager_GitHub$ bash utils/restyle.sh
91 | ```
92 |
93 |
94 |
--------------------------------------------------------------------------------
/.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 | A clear and concise description of any alternative solutions or features you've considered.
20 |
21 | ### Additional context
22 |
23 | Add any other context or screenshots about the feature request here.
24 |
--------------------------------------------------------------------------------
/.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/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 ESP_WiFiManager
2 |
3 | ### Reporting Bugs
4 |
5 | Please report bugs in ESP_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/ESP_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/ESP_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-52-generic #58~20.04.1-Ubuntu SMP Thu Oct 13 13:09:46 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/ESP_WifiManager_GitHub/
63 | xy@xy-Inspiron-3593:~/Arduino/xy/ESP_WifiManager_GitHub$
64 | ```
65 |
66 | 2. Issue astyle command
67 |
68 | ```
69 | xy@xy-Inspiron-3593:~/Arduino/xy/ESP_WifiManager_GitHub$ bash utils/restyle.sh
70 | ```
71 |
72 |
73 |
--------------------------------------------------------------------------------
/Images/Configuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Configuration.png
--------------------------------------------------------------------------------
/Images/Configuration_1-0-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Configuration_1-0-11.png
--------------------------------------------------------------------------------
/Images/Configuration_1-0-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Configuration_1-0-8.png
--------------------------------------------------------------------------------
/Images/Configuration_1-0-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Configuration_1-0-9.png
--------------------------------------------------------------------------------
/Images/Configuration_Simple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Configuration_Simple.png
--------------------------------------------------------------------------------
/Images/Configuration_Standard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Configuration_Standard.png
--------------------------------------------------------------------------------
/Images/Info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Info.png
--------------------------------------------------------------------------------
/Images/Info_Short.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Info_Short.png
--------------------------------------------------------------------------------
/Images/Info_Short_1-0-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Info_Short_1-0-5.png
--------------------------------------------------------------------------------
/Images/Main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Main.png
--------------------------------------------------------------------------------
/Images/Main_1-0-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Main_1-0-5.png
--------------------------------------------------------------------------------
/Images/Saved.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/Images/Saved.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 | # ESP_WiFiManager
2 |
3 | [](https://www.ardu-badge.com/ESP_WiFiManager)
4 | [](https://github.com/khoih-prog/ESP_WiFiManager/releases)
5 | [](https://github.com/khoih-prog/ESP_WiFiManager/blob/master/LICENSE)
6 | [](#Contributing)
7 | [](http://github.com/khoih-prog/ESP_WiFiManager/issues)
8 | [](https://github.com/khoih-prog/ESP_WiFiManager)
9 |
10 |
11 |
12 |
13 | ---
14 | ---
15 |
16 | ## Table of Contents
17 |
18 | * [Changelog](#changelog)
19 | * [Releases v1.12.1](#releases-v1121)
20 | * [Releases v1.12.0](#releases-v1120)
21 | * [Releases v1.11.0](#releases-v1110)
22 | * [Releases v1.10.2](#releases-v1102)
23 | * [Releases v1.10.1](#releases-v1101)
24 | * [Releases v1.10.0](#releases-v1100)
25 | * [Releases v1.9.0](#releases-v190)
26 | * [Releases v1.8.0](#releases-v180)
27 | * [Releases v1.7.8](#releases-v178)
28 | * [Releases v1.7.7](#releases-v177)
29 | * [Releases v1.7.6](#releases-v176)
30 | * [Releases v1.7.5](#releases-v175)
31 | * [Releases v1.7.4](#releases-v174)
32 | * [Releases v1.7.3](#releases-v173)
33 | * [Releases v1.7.2](#releases-v172)
34 | * [Releases v1.7.1](#releases-v171)
35 | * [Major Releases v1.7.0](#major-releases-v170)
36 | * [Releases v1.6.1](#releases-v161)
37 | * [Releases v1.6.0](#releases-v160)
38 | * [Releases v1.5.3](#releases-v153)
39 | * [Releases v1.5.2](#releases-v152)
40 | * [Releases v1.5.1](#releases-v151)
41 | * [Releases v1.5.0](#releases-v150)
42 | * [Releases v1.4.3](#releases-v143)
43 | * [Releases v1.4.2](#releases-v142)
44 | * [Major Releases v1.4.1](#major-releases-v141)
45 | * [Releases v1.3.0](#releases-v130)
46 | * [Releases v1.2.0](#releases-v120)
47 | * [Releases v1.1.2](#releases-v112)
48 | * [Releases v1.1.1](#releases-v111)
49 | * [Major Releases v1.1.0](#major-releases-v110)
50 | * [Releases v1.0.11](#releases-v1011)
51 | * [Releases v1.0.10](#releases-v1010)
52 | * [Releases v1.0.9](#releases-v109)
53 | * [Releases v1.0.8](#releases-v108)
54 | * [Releases v1.0.7](#releases-v107)
55 | * [Releases v1.0.6](#releases-v106)
56 |
57 | ---
58 | ---
59 |
60 |
61 | ## Changelog
62 |
63 | ### Releases v1.12.1
64 |
65 | 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)
66 | 2. Add astyle using `allman` style. Restyle the library
67 |
68 | ### Releases v1.12.0
69 |
70 | 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)
71 | 2. Display `Credentials` Hint on Config Portal
72 | 3. Periodic code clean-up
73 |
74 | ### Releases v1.11.0
75 |
76 | 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)
77 | 2. Add ESP32 ESP_getChipOUI() function
78 | 3. Display new info on Config Portal for ESP32
79 | 4. Remove dependency on `LittleFS_esp32` library to prevent PIO error when using new ESP32 core v1.0.6+
80 |
81 | ### Releases v1.10.2
82 |
83 | 1. Send CORS header in handleWifiSave() function. Check [Cors header not sent when saving wifi details, even when cors is enabled #80](https://github.com/khoih-prog/ESP_WiFiManager/issues/80)
84 | 2. Optimize code by using passing by `reference` instead of by `value`
85 | 3. Delete all confusing, function-lacking `minimal` examples
86 | 4. Display informational warnings only when `_WIFIMGR_LOGLEVEL_ > 3`
87 |
88 | ### Releases v1.10.1
89 |
90 | 1. Add LittleFS support to `ESP32-C3`.
91 | 2. Use ESP32-core's LittleFS library instead of Lorol's LITTLEFS library for v2.0.0+
92 |
93 | ### Releases v1.10.0
94 |
95 | 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)
96 |
97 | ### Releases v1.9.0
98 |
99 | 1. Reduce the breaking effect of v1.8.0 by enabling compatibility with old code to include only `ESP_WiFiManager.h`. Check [Important Breaking Change from v1.8.0](https://github.com/khoih-prog/ESP_WiFiManager#Important-Breaking-Change-from-v180)
100 |
101 |
102 | ### Releases v1.8.0
103 |
104 | 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)
105 | 2. Optimize library code by using `reference-passing` instead of `value-passing`
106 |
107 | ### Releases v1.7.8
108 |
109 | 1. 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)
110 | 2. Fix bug returning IP `255.255.255.255` in core v2.0.0+ when using `hostname`
111 |
112 |
113 | ### Releases v1.7.7
114 |
115 | 1. Fix compile error for ESP32 core v1.0.5-
116 |
117 | ### Releases v1.7.6
118 |
119 | 1. Auto detect ESP32 core and use either built-in LittleFS or [LITTLEFS](https://github.com/lorol/LITTLEFS) library
120 | 2. Update `library.json` to use new `headers` for PIO
121 |
122 | ### Releases v1.7.5
123 |
124 | 1. Update `platform.ini` and `library.json` to use original `khoih-prog` instead of `khoih.prog` after PIO fix
125 |
126 | ### Releases v1.7.4
127 |
128 | 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)
129 |
130 | ### Releases v1.7.3
131 |
132 | 1. Fix MultiWiFi connection issue with ESP32 core v2.0.0-rc1+
133 | 2. Verify compatibility with new ESP32 core v2.0.0-rc1+
134 | 3. Verify compatibility with new ESP8266 core v3.0.2
135 |
136 | ### Releases v1.7.2
137 |
138 | 1. Fix warnings and Verify compatibility with new ESP8266 core v3.0.0
139 |
140 | ### Releases v1.7.1
141 |
142 | 1. Fix Json bug in /scan. Check [Invalid Json generated #60](https://github.com/khoih-prog/ESP_WiFiManager/issues/60)
143 | 2. Fix timezoneName not displayed in Info page.
144 |
145 | ### Major Releases v1.7.0
146 |
147 | 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) for more info.
148 | 2. Store those `_timezoneName` and `TZ` in LittleFS or SPIFFS config file.
149 | 3. Using these new timezone feature is optional.
150 | 4. Add checksum in config file to validate data read from LittleFS or SPIFFS config file.
151 | 5. Update examples to show how to use the new TZ feature.
152 |
153 | ### Releases v1.6.1
154 |
155 | 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)
156 | 2. Fix MultiWiFi bug.
157 |
158 | ### Releases v1.6.0
159 |
160 | 1. 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).
161 |
162 |
163 | ### Releases v1.5.3
164 |
165 | 1. Add `dnsServer can't allocate` and `dnsServer can't start` error messages
166 |
167 | ### Releases v1.5.2
168 |
169 | 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)
170 | 2. Tested with [**ESP32 Core 1.0.6**](https://github.com/espressif/arduino-esp32) and [**LittleFS_esp32 v1.0.6**](https://github.com/lorol/LITTLEFS)
171 |
172 | ### Releases v1.5.1
173 |
174 | 1. Fix compiler error if setting `Compiler Warnings` to `All`.
175 | 2. Modify multiWiFi-related timings to work with latest esp32 core v1.0.6
176 |
177 | ### Releases v1.5.0
178 |
179 | 1. Add support to **ESP32-S2 (ESP32-S2 Saola, AI-Thinker ESP-12K, ESP32S2 Dev Module, UM FeatherS2, UM ProS2, microS2, etc.)**
180 | 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)
181 |
182 | ### Releases v1.4.3
183 |
184 | 1. Fix examples' bug not saving Static IP in certain cases.
185 | 2. Add feature to warn if using examples with old library versions
186 |
187 | ### Releases v1.4.2
188 |
189 | 1. Fix examples' bug not using saved WiFi Credentials after losing all WiFi connections.
190 | 2. Fix compiler warnings.
191 |
192 | ### Major Releases v1.4.1
193 |
194 | 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)
195 | 2. Add structures and functions to handle AP and STA IPs.
196 | 3. Add complex examples
197 | * [ConfigOnDRD_FS_MQTT_Ptr_Complex](examples/ConfigOnDRD_FS_MQTT_Ptr_Complex) to demo usage of std::map
198 | * [ConfigOnDRD_FS_MQTT_Ptr_Medium](examples/ConfigOnDRD_FS_MQTT_Ptr_Medium).
199 | 4. Add simple minimal examples
200 | * [ConfigOnDRD_ESP32_minimal](examples/ConfigOnDRD_ESP32_minimal)
201 | * [ConfigOnDRD_ESP8266_minimal](examples/ConfigOnDRD_ESP8266_minimal)
202 | * [AutoConnect_ESP32_minimal](examples/AutoConnect_ESP32_minimal)
203 | * [AutoConnect_ESP8266_minimal](examples/AutoConnect_ESP8266_minimal)
204 | 5. Fix bug.
205 | 6. Fix compiler warnings.
206 | 7. Modify Version String
207 | 8. Add Table of Contents
208 |
209 |
210 | ### Releases v1.3.0
211 |
212 | 1. Add LittleFS support to ESP32-related examples to use [LittleFS_esp32 Library](https://github.com/lorol/LITTLEFS)
213 | 2. Add Version String
214 |
215 | ### Releases v1.2.0
216 |
217 | 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/ESP_WiFiManager#HOWTO-Fix-Multiple-Definitions-Linker-Error)
218 | 2. Fix bug [/close does not close the config portal](https://github.com/khoih-prog/ESPAsync_WiFiManager/issues/16).
219 |
220 | ### Releases v1.1.2
221 |
222 | 1. Fix bug in examples.
223 | 2. Add example.
224 |
225 | ### Releases v1.1.1
226 |
227 | 1. Add setCORSHeader function to allow **configurable CORS Header**. See [Using CORS feature](https://github.com/khoih-prog/ESP_WiFiManager#15-using-cors-cross-origin-resource-sharing-feature)
228 | 2. Fix typo and minor improvement.
229 | 3. Shorten MultiWiFi connection time.
230 |
231 | ### Major Releases v1.1.0
232 |
233 | 1. Add **MultiWiFi feature to auto(Re)connect to the best WiFi at runtime**
234 | 2. Fix bug.
235 | 3. Completely enhanced examples to use new MultiWiFi feature.
236 |
237 | #### Releases v1.0.11
238 |
239 | 1. Add optional **CORS (Cross-Origin Resource Sharing)** feature. Thanks to [AlesSt](https://github.com/AlesSt). See more in [Issue #27: CORS protection fires up with AJAX](https://github.com/khoih-prog/ESP_WiFiManager/issues/27) and [Cross Origin Resource Sharing](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing). To use, you must explicitly use `#define USING_CORS_FEATURE true`
240 | 2. Solve issue softAP with custom IP sometimes not working. Thanks to [AlesSt](https://github.com/AlesSt). See [Issue #26: softAP with custom IP not working](https://github.com/khoih-prog/ESP_WiFiManager/issues/26) and [Wifi.softAPConfig() sometimes set the wrong IP address](https://github.com/espressif/arduino-esp32/issues/985).
241 | 3. Temporary fix for issue of not clearing WiFi SSID/PW from flash of ESP32. Thanks to [AlesSt](https://github.com/AlesSt). See more in [Issue #25: API call /r doesn't clear credentials](https://github.com/khoih-prog/ESP_WiFiManager/issues/25) and [WiFi.disconnect(true) problem](https://github.com/espressif/arduino-esp32/issues/400).
242 | 4. Fix autoConnect() feature to permit autoConnect() to use STA static IP or DHCP IP. Remove from deprecated function list.
243 | 5. Enhance README.md with more instructions and illustrations.
244 |
245 |
246 | #### Releases v1.0.10
247 |
248 | 1. Don't need to reinput already working SSID in Config Port to update other parameters, such as StaticIP.
249 | 2. Disable/Enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
250 | 3. Change HTTP_XYZ constants to WM_HTTP_XYZ to avoid conflicts with future releases of ESP32 and ESP8266 cores.
251 | 4. Add feature to change WiFi AP channel (fixed or random) to avoid conflict in AP-overcrowded environments.
252 | 5. Enhance Config Portal GUI and get the item out of the bucket list.
253 | 6. Enhance README.md with more instructions and illustrations.
254 |
255 | #### Releases v1.0.9
256 |
257 | 1. Fix ESP32 STAstaticIP bug.
258 | 2. Enable changing from DHCP <-> static IP using Config Portal.
259 | 3. Enable NTP configuration from sketch (USE_ESP_WIFIMANAGER_NTP, USE_CLOUDFLARE_NTP). See Issue #21: [CloudFlare link in the default portal](https://github.com/khoih-prog/ESP_WiFiManager/issues/21).
260 | 4. Add, enhance examples (fix MDNS for ESP32 examples, add DRD feature).
261 |
262 | #### Releases v1.0.8
263 |
264 | 1. Fix setSTAStaticIPConfig issue. See [Static Station IP doesn't work](https://github.com/khoih-prog/ESP_WiFiManager/issues/17)
265 | 2. Add LittleFS support for ESP8266 core 2.7.1+ in examples to replace deprecated SPIFFS.
266 | 3. Restructure code.
267 |
268 | #### Releases v1.0.7
269 |
270 | 1. Use `just-in-time` scanWiFiNetworks() to reduce connection time necessary for battery-operated DeepSleep application. Thanks to [CrispinP](https://github.com/CrispinP) for identifying, requesting and testing. See [Starting WiFIManger is very slow (2000ms)](https://github.com/khoih-prog/ESP_WiFiManager/issues/6)
271 | 2. Fix bug relating SPIFFS in examples :
272 | - [ConfigOnSwitchFS](examples/ConfigOnSwitchFS)
273 | - [ConfigPortalParamsOnSwitch](examples/ConfigPortalParamsOnSwitch) (now support ArduinoJson 6.0.0+ as well as 5.13.5-)
274 | - [AutoConnectWithFSParameters](examples/AutoConnectWithFSParameters)
275 | See [Having issue to read the SPIFF file](https://github.com/khoih-prog/ESP_WiFiManager/issues/14), Thanks to [OttoKlaasen](https://github.com/OttoKlaasen) to report.
276 | 3. Fix [README](README.md). See [Accessing manager after connection](https://github.com/khoih-prog/ESP_WiFiManager/issues/15)
277 |
278 | #### Releases v1.0.6
279 |
280 | 1. Add function getConfigPortalPW()
281 | 2. Add 4 new complicated examples compatible with ArduinoJson 6.0.0+ :[AutoConnect](examples/AutoConnect), [AutoConnectWithFeedback](examples/AutoConnectWithFeedback), [AutoConnectWithFeedbackLED](examples/AutoConnectWithFeedbackLED) and [AutoConnectWithFSParameters](examples/AutoConnectWithFSParameters)
282 |
283 |
284 |
285 |
286 |
--------------------------------------------------------------------------------
/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/AutoConnect/AutoConnect.ino:
--------------------------------------------------------------------------------
1 | /****************************************************************************************************************************
2 | AutoConnect.ino
3 | For ESP8266 / ESP32 boards
4 |
5 | ESP_WiFiManager is a library for the ESP8266/ESP32 platform (https://github.com/esp8266/Arduino) to enable easy
6 | configuration and reconfiguration of WiFi credentials using a Captive Portal.
7 |
8 | Modified from Tzapu https://github.com/tzapu/WiFiManager
9 | and from Ken Taylor https://github.com/kentaylor
10 |
11 | Built by Khoi Hoang https://github.com/khoih-prog/ESP_WiFiManager
12 | Licensed under MIT license
13 | *****************************************************************************************************************************/
14 | #if !( defined(ESP8266) || defined(ESP32) )
15 | #error This code is intended to run on the ESP8266 or ESP32 platform! Please check your Tools->Board setting.
16 | #endif
17 |
18 | #define ESP_WIFIMANAGER_VERSION_MIN_TARGET "ESP_WiFiManager v1.12.0"
19 | #define ESP_WIFIMANAGER_VERSION_MIN 1012000
20 |
21 | // Use from 0 to 4. Higher number, more debugging messages and memory usage.
22 | #define _WIFIMGR_LOGLEVEL_ 1
23 |
24 | // To not display stored SSIDs and PWDs on Config Portal, select false. Default is true
25 | // Even the stored Credentials are not display, just leave them all blank to reconnect and reuse the stored Credentials
26 | //#define DISPLAY_STORED_CREDENTIALS_IN_CP false
27 |
28 | //Ported to ESP32
29 | #ifdef ESP32
30 | #include
31 | #include
32 | #include
33 |
34 | // From v1.1.0
35 | #include
36 | WiFiMulti wifiMulti;
37 |
38 | // LittleFS has higher priority than SPIFFS
39 | #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
40 | #define USE_LITTLEFS true
41 | #define USE_SPIFFS false
42 | #elif defined(ARDUINO_ESP32C3_DEV)
43 | // For core v1.0.6-, ESP32-C3 only supporting SPIFFS and EEPROM. To use v2.0.0+ for LittleFS
44 | #define USE_LITTLEFS false
45 | #define USE_SPIFFS true
46 | #endif
47 |
48 | #if USE_LITTLEFS
49 | // Use LittleFS
50 | #include "FS.h"
51 |
52 | // Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h
53 | //#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) ) //(ESP_ARDUINO_VERSION_MAJOR >= 2)
54 | #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
55 | #if (_WIFIMGR_LOGLEVEL_ > 3)
56 | #warning Using ESP32 Core 1.0.6 or 2.0.0+
57 | #endif
58 |
59 | // The library has been merged into esp32 core from release 1.0.6
60 | #include // https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS
61 |
62 | FS* filesystem = &LittleFS;
63 | #define FileFS LittleFS
64 | #define FS_Name "LittleFS"
65 | #else
66 | #if (_WIFIMGR_LOGLEVEL_ > 3)
67 | #warning Using ESP32 Core 1.0.5-. You must install LITTLEFS library
68 | #endif
69 |
70 | // The library has been merged into esp32 core from release 1.0.6
71 | #include // https://github.com/lorol/LITTLEFS
72 |
73 | FS* filesystem = &LITTLEFS;
74 | #define FileFS LITTLEFS
75 | #define FS_Name "LittleFS"
76 | #endif
77 |
78 | #elif USE_SPIFFS
79 | #include
80 | FS* filesystem = &SPIFFS;
81 | #define FileFS SPIFFS
82 | #define FS_Name "SPIFFS"
83 | #else
84 | // Use FFat
85 | #include
86 | FS* filesystem = &FFat;
87 | #define FileFS FFat
88 | #define FS_Name "FFat"
89 | #endif
90 | //////
91 |
92 | #define LED_BUILTIN 2
93 | #define LED_ON HIGH
94 | #define LED_OFF LOW
95 |
96 | #else
97 |
98 | #include //https://github.com/esp8266/Arduino
99 | //needed for library
100 | #include
101 | #include
102 |
103 | // From v1.1.0
104 | #include
105 | ESP8266WiFiMulti wifiMulti;
106 |
107 | #include
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 | // You only need to format the filesystem once
130 | //#define FORMAT_FILESYSTEM true
131 | #define FORMAT_FILESYSTEM false
132 |
133 | // SSID and PW for your Router
134 | String Router_SSID;
135 | String Router_Pass;
136 |
137 | // From v1.1.0
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 491 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 | // Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected
175 | bool initialConfig = false;
176 | //////
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 false
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 (_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 (_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 | #define USE_CONFIGURABLE_DNS true
258 |
259 | IPAddress dns1IP = gatewayIP;
260 | IPAddress dns2IP = IPAddress(8, 8, 8, 8);
261 |
262 | #define USE_CUSTOM_AP_IP false
263 |
264 | // New in v1.4.0
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 |
270 | // Must be placed before #include , or default port 80 will be used
271 | //#define HTTP_PORT 8080
272 |
273 | #include //https://github.com/khoih-prog/ESP_WiFiManager
274 |
275 | // Redundant, for v1.8.0 only
276 | //#include //https://github.com/khoih-prog/ESP_WiFiManager
277 |
278 | // Function Prototypes
279 | uint8_t connectMultiWiFi();
280 |
281 | ///////////////////////////////////////////
282 | // New in v1.4.0
283 | /******************************************
284 | * // Defined in ESPAsync_WiFiManager.h
285 | typedef struct
286 | {
287 | IPAddress _ap_static_ip;
288 | IPAddress _ap_static_gw;
289 | IPAddress _ap_static_sn;
290 |
291 | } WiFi_AP_IPConfig;
292 |
293 | typedef struct
294 | {
295 | IPAddress _sta_static_ip;
296 | IPAddress _sta_static_gw;
297 | IPAddress _sta_static_sn;
298 | #if USE_CONFIGURABLE_DNS
299 | IPAddress _sta_static_dns1;
300 | IPAddress _sta_static_dns2;
301 | #endif
302 | } WiFi_STA_IPConfig;
303 | ******************************************/
304 |
305 | WiFi_AP_IPConfig WM_AP_IPconfig;
306 | WiFi_STA_IPConfig WM_STA_IPconfig;
307 |
308 | void initAPIPConfigStruct(WiFi_AP_IPConfig &in_WM_AP_IPconfig)
309 | {
310 | in_WM_AP_IPconfig._ap_static_ip = APStaticIP;
311 | in_WM_AP_IPconfig._ap_static_gw = APStaticGW;
312 | in_WM_AP_IPconfig._ap_static_sn = APStaticSN;
313 | }
314 |
315 | void initSTAIPConfigStruct(WiFi_STA_IPConfig &in_WM_STA_IPconfig)
316 | {
317 | in_WM_STA_IPconfig._sta_static_ip = stationIP;
318 | in_WM_STA_IPconfig._sta_static_gw = gatewayIP;
319 | in_WM_STA_IPconfig._sta_static_sn = netMask;
320 | #if USE_CONFIGURABLE_DNS
321 | in_WM_STA_IPconfig._sta_static_dns1 = dns1IP;
322 | in_WM_STA_IPconfig._sta_static_dns2 = dns2IP;
323 | #endif
324 | }
325 |
326 | void displayIPConfigStruct(WiFi_STA_IPConfig in_WM_STA_IPconfig)
327 | {
328 | LOGERROR3(F("stationIP ="), in_WM_STA_IPconfig._sta_static_ip, ", gatewayIP =", in_WM_STA_IPconfig._sta_static_gw);
329 | LOGERROR1(F("netMask ="), in_WM_STA_IPconfig._sta_static_sn);
330 | #if USE_CONFIGURABLE_DNS
331 | LOGERROR3(F("dns1IP ="), in_WM_STA_IPconfig._sta_static_dns1, ", dns2IP =", in_WM_STA_IPconfig._sta_static_dns2);
332 | #endif
333 | }
334 |
335 | void configWiFi(WiFi_STA_IPConfig in_WM_STA_IPconfig)
336 | {
337 | #if USE_CONFIGURABLE_DNS
338 | // Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5
339 | WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn, in_WM_STA_IPconfig._sta_static_dns1, in_WM_STA_IPconfig._sta_static_dns2);
340 | #else
341 | // Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2.
342 | WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn);
343 | #endif
344 | }
345 |
346 | ///////////////////////////////////////////
347 |
348 | uint8_t connectMultiWiFi()
349 | {
350 | #if ESP32
351 | // For ESP32, this better be 0 to shorten the connect time.
352 | // For ESP32-S2/C3, must be > 500
353 | #if ( USING_ESP32_S2 || USING_ESP32_C3 )
354 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 500L
355 | #else
356 | // For ESP32 core v1.0.6, must be >= 500
357 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 800L
358 | #endif
359 | #else
360 | // For ESP8266, this better be 2200 to enable connect the 1st time
361 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 2200L
362 | #endif
363 |
364 | #define WIFI_MULTI_CONNECT_WAITING_MS 500L
365 |
366 | uint8_t status;
367 |
368 | //WiFi.mode(WIFI_STA);
369 |
370 | LOGERROR(F("ConnectMultiWiFi with :"));
371 |
372 | if ( (Router_SSID != "") && (Router_Pass != "") )
373 | {
374 | LOGERROR3(F("* Flash-stored Router_SSID = "), Router_SSID, F(", Router_Pass = "), Router_Pass );
375 | LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass );
376 | wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
377 | }
378 |
379 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
380 | {
381 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
382 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
383 | {
384 | LOGERROR3(F("* Additional SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
385 | }
386 | }
387 |
388 | LOGERROR(F("Connecting MultiWifi..."));
389 |
390 | //WiFi.mode(WIFI_STA);
391 |
392 | #if !USE_DHCP_IP
393 | // New in v1.4.0
394 | configWiFi(WM_STA_IPconfig);
395 | //////
396 | #endif
397 |
398 | int i = 0;
399 |
400 | status = wifiMulti.run();
401 | delay(WIFI_MULTI_1ST_CONNECT_WAITING_MS);
402 |
403 | while ( ( i++ < 20 ) && ( status != WL_CONNECTED ) )
404 | {
405 | status = WiFi.status();
406 |
407 | if ( status == WL_CONNECTED )
408 | break;
409 | else
410 | delay(WIFI_MULTI_CONNECT_WAITING_MS);
411 | }
412 |
413 | if ( status == WL_CONNECTED )
414 | {
415 | LOGERROR1(F("WiFi connected after time: "), i);
416 | LOGERROR3(F("SSID:"), WiFi.SSID(), F(",RSSI="), WiFi.RSSI());
417 | LOGERROR3(F("Channel:"), WiFi.channel(), F(",IP address:"), WiFi.localIP() );
418 | }
419 | else
420 | {
421 | LOGERROR(F("WiFi not connected"));
422 |
423 | #if ESP8266
424 | ESP.reset();
425 | #else
426 | ESP.restart();
427 | #endif
428 | }
429 |
430 | return status;
431 | }
432 |
433 | #if USE_ESP_WIFIMANAGER_NTP
434 |
435 | void printLocalTime()
436 | {
437 | #if ESP8266
438 | static time_t now;
439 |
440 | now = time(nullptr);
441 |
442 | if ( now > 1451602800 )
443 | {
444 | Serial.print("Local Date/Time: ");
445 | Serial.print(ctime(&now));
446 | }
447 | #else
448 | struct tm timeinfo;
449 |
450 | getLocalTime( &timeinfo );
451 |
452 | // Valid only if year > 2000.
453 | // You can get from timeinfo : tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec
454 | if (timeinfo.tm_year > 100 )
455 | {
456 | Serial.print("Local Date/Time: ");
457 | Serial.print( asctime( &timeinfo ) );
458 | }
459 | #endif
460 | }
461 |
462 | #endif
463 |
464 | void heartBeatPrint()
465 | {
466 | #if USE_ESP_WIFIMANAGER_NTP
467 | printLocalTime();
468 | #else
469 | static int num = 1;
470 |
471 | if (WiFi.status() == WL_CONNECTED)
472 | Serial.print(F("H")); // H means connected to WiFi
473 | else
474 | Serial.print(F("F")); // F means not connected to WiFi
475 |
476 | if (num == 80)
477 | {
478 | Serial.println();
479 | num = 1;
480 | }
481 | else if (num++ % 10 == 0)
482 | {
483 | Serial.print(F(" "));
484 | }
485 | #endif
486 | }
487 |
488 | void check_WiFi()
489 | {
490 | if ( (WiFi.status() != WL_CONNECTED) )
491 | {
492 | Serial.println(F("\nWiFi lost. Call connectMultiWiFi in loop"));
493 | connectMultiWiFi();
494 | }
495 | }
496 |
497 | void check_status()
498 | {
499 | static ulong checkstatus_timeout = 0;
500 | static ulong checkwifi_timeout = 0;
501 |
502 | static ulong current_millis;
503 |
504 | #define WIFICHECK_INTERVAL 1000L
505 |
506 | #if USE_ESP_WIFIMANAGER_NTP
507 | #define HEARTBEAT_INTERVAL 60000L
508 | #else
509 | #define HEARTBEAT_INTERVAL 10000L
510 | #endif
511 |
512 | current_millis = millis();
513 |
514 | // Check WiFi every WIFICHECK_INTERVAL (1) seconds.
515 | if ((current_millis > checkwifi_timeout) || (checkwifi_timeout == 0))
516 | {
517 | check_WiFi();
518 | checkwifi_timeout = current_millis + WIFICHECK_INTERVAL;
519 | }
520 |
521 | // Print hearbeat every HEARTBEAT_INTERVAL (10) seconds.
522 | if ((current_millis > checkstatus_timeout) || (checkstatus_timeout == 0))
523 | {
524 | heartBeatPrint();
525 | checkstatus_timeout = current_millis + HEARTBEAT_INTERVAL;
526 | }
527 | }
528 |
529 | int calcChecksum(uint8_t* address, uint16_t sizeToCalc)
530 | {
531 | uint16_t checkSum = 0;
532 |
533 | for (uint16_t index = 0; index < sizeToCalc; index++)
534 | {
535 | checkSum += * ( ( (byte*) address ) + index);
536 | }
537 |
538 | return checkSum;
539 | }
540 |
541 | bool loadConfigData()
542 | {
543 | File file = FileFS.open(CONFIG_FILENAME, "r");
544 | LOGERROR(F("LoadWiFiCfgFile "));
545 |
546 | memset((void *) &WM_config, 0, sizeof(WM_config));
547 |
548 | // New in v1.4.0
549 | memset((void *) &WM_STA_IPconfig, 0, sizeof(WM_STA_IPconfig));
550 | //////
551 |
552 | if (file)
553 | {
554 | file.readBytes((char *) &WM_config, sizeof(WM_config));
555 |
556 | // New in v1.4.0
557 | file.readBytes((char *) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig));
558 | //////
559 |
560 | file.close();
561 | LOGERROR(F("OK"));
562 |
563 | if ( WM_config.checksum != calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) ) )
564 | {
565 | LOGERROR(F("WM_config checksum wrong"));
566 |
567 | return false;
568 | }
569 |
570 | // New in v1.4.0
571 | displayIPConfigStruct(WM_STA_IPconfig);
572 | //////
573 |
574 | return true;
575 | }
576 | else
577 | {
578 | LOGERROR(F("failed"));
579 |
580 | return false;
581 | }
582 | }
583 |
584 | void saveConfigData()
585 | {
586 | File file = FileFS.open(CONFIG_FILENAME, "w");
587 | LOGERROR(F("SaveWiFiCfgFile "));
588 |
589 | if (file)
590 | {
591 | WM_config.checksum = calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) );
592 |
593 | file.write((uint8_t*) &WM_config, sizeof(WM_config));
594 |
595 | displayIPConfigStruct(WM_STA_IPconfig);
596 |
597 | // New in v1.4.0
598 | file.write((uint8_t*) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig));
599 | //////
600 |
601 | file.close();
602 | LOGERROR(F("OK"));
603 | }
604 | else
605 | {
606 | LOGERROR(F("failed"));
607 | }
608 | }
609 |
610 | void setup()
611 | {
612 | // put your setup code here, to run once:
613 | Serial.begin(115200);
614 | while (!Serial);
615 |
616 | delay(200);
617 |
618 | Serial.print(F("\nStarting AutoConnectAP using ")); Serial.print(FS_Name);
619 | Serial.print(F(" on ")); Serial.println(ARDUINO_BOARD);
620 | Serial.println(ESP_WIFIMANAGER_VERSION);
621 |
622 | #if defined(ESP_WIFIMANAGER_VERSION_MIN)
623 | if (ESP_WIFIMANAGER_VERSION_INT < ESP_WIFIMANAGER_VERSION_MIN)
624 | {
625 | Serial.print("Warning. Must use this example on Version later than : ");
626 | Serial.println(ESP_WIFIMANAGER_VERSION_MIN_TARGET);
627 | }
628 | #endif
629 |
630 | if (FORMAT_FILESYSTEM)
631 | FileFS.format();
632 |
633 | // Format FileFS if not yet
634 | #ifdef ESP32
635 | if (!FileFS.begin(true))
636 | #else
637 | if (!FileFS.begin())
638 | #endif
639 | {
640 | #ifdef ESP8266
641 | FileFS.format();
642 | #endif
643 |
644 | Serial.println(F("SPIFFS/LittleFS failed! Already tried formatting."));
645 |
646 | if (!FileFS.begin())
647 | {
648 | // prevents debug info from the library to hide err message.
649 | delay(100);
650 |
651 | #if USE_LITTLEFS
652 | Serial.println(F("LittleFS failed!. Please use SPIFFS or EEPROM. Stay forever"));
653 | #else
654 | Serial.println(F("SPIFFS failed!. Please use LittleFS or EEPROM. Stay forever"));
655 | #endif
656 |
657 | while (true)
658 | {
659 | delay(1);
660 | }
661 | }
662 | }
663 |
664 | unsigned long startedAt = millis();
665 |
666 | // New in v1.4.0
667 | initAPIPConfigStruct(WM_AP_IPconfig);
668 | initSTAIPConfigStruct(WM_STA_IPconfig);
669 | //////
670 |
671 | // Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
672 | //ESP_WiFiManager ESP_wifiManager;
673 | // Use this to personalize DHCP hostname (RFC952 conformed)
674 | ESP_WiFiManager ESP_wifiManager("AutoConnectAP");
675 |
676 | ESP_wifiManager.setDebugOutput(true);
677 |
678 | //reset settings - for testing
679 | //ESP_wifiManager.resetSettings();
680 |
681 | #if USE_CUSTOM_AP_IP
682 | //set custom ip for portal
683 | // New in v1.4.0
684 | ESP_wifiManager.setAPStaticIPConfig(WM_AP_IPconfig);
685 | //////
686 | #endif
687 |
688 | ESP_wifiManager.setMinimumSignalQuality(-1);
689 |
690 | // From v1.0.10 only
691 | // Set config portal channel, default = 1. Use 0 => random channel from 1-13
692 | ESP_wifiManager.setConfigPortalChannel(0);
693 | //////
694 |
695 | #if !USE_DHCP_IP
696 | // Set (static IP, Gateway, Subnetmask, DNS1 and DNS2) or (IP, Gateway, Subnetmask). New in v1.0.5
697 | // New in v1.4.0
698 | ESP_wifiManager.setSTAStaticIPConfig(WM_STA_IPconfig);
699 | //////
700 | #endif
701 |
702 | // New from v1.1.1
703 | #if USING_CORS_FEATURE
704 | ESP_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin");
705 | #endif
706 |
707 | // We can't use WiFi.SSID() in ESP32 as it's only valid after connected.
708 | // SSID and Password stored in ESP32 wifi_ap_record_t and wifi_config_t are also cleared in reboot
709 | // Have to create a new function to store in EEPROM/SPIFFS for this purpose
710 | Router_SSID = ESP_wifiManager.WiFi_SSID();
711 | Router_Pass = ESP_wifiManager.WiFi_Pass();
712 |
713 | //Remove this line if you do not want to see WiFi password printed
714 | Serial.println("ESP Self-Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass);
715 |
716 | bool configDataLoaded = false;
717 |
718 | // From v1.1.0, Don't permit NULL password
719 | if ( (Router_SSID != "") && (Router_Pass != "") )
720 | {
721 | LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass);
722 | wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
723 |
724 | ESP_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
725 | Serial.println(F("Got ESP Self-Stored Credentials. Timeout 120s for Config Portal"));
726 | }
727 |
728 | if (loadConfigData())
729 | {
730 | configDataLoaded = true;
731 |
732 | ESP_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
733 | Serial.println(F("Got stored Credentials. Timeout 120s for Config Portal"));
734 |
735 | #if USE_ESP_WIFIMANAGER_NTP
736 | if ( strlen(WM_config.TZ_Name) > 0 )
737 | {
738 | LOGERROR3(F("Current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ);
739 |
740 | #if ESP8266
741 | configTime(WM_config.TZ, "pool.ntp.org");
742 | #else
743 | //configTzTime(WM_config.TZ, "pool.ntp.org" );
744 | configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
745 | #endif
746 | }
747 | else
748 | {
749 | Serial.println(F("Current Timezone is not set. Enter Config Portal to set."));
750 | }
751 | #endif
752 | }
753 | else
754 | {
755 | // Enter CP only if no stored SSID on flash and file
756 | Serial.println(F("Open Config Portal without Timeout: No stored Credentials."));
757 | initialConfig = true;
758 | }
759 |
760 | String chipID = String(ESP_getChipId(), HEX);
761 | chipID.toUpperCase();
762 |
763 | // SSID and PW for Config Portal
764 | String AP_SSID = "ESP_" + chipID + "_AutoConnectAP";
765 | String AP_PASS = "MyESP_" + chipID;
766 |
767 | if (initialConfig)
768 | {
769 | Serial.print(F("Starting configuration portal @ "));
770 |
771 | #if USE_CUSTOM_AP_IP
772 | Serial.print(APStaticIP);
773 | #else
774 | Serial.print(F("192.168.4.1"));
775 | #endif
776 |
777 | #if defined(HTTP_PORT_TO_USE)
778 | Serial.print(F(":")); Serial.print(HTTP_PORT_TO_USE);
779 | #endif
780 |
781 | Serial.print(F(", SSID = "));
782 | Serial.print(AP_SSID);
783 | Serial.print(F(", PWD = "));
784 | Serial.println(AP_PASS);
785 |
786 | initialConfig = true;
787 |
788 | #if DISPLAY_STORED_CREDENTIALS_IN_CP
789 | // New. Update Credentials, got from loadConfigData(), to display on CP
790 | ESP_wifiManager.setCredentials(WM_config.WiFi_Creds[0].wifi_ssid, WM_config.WiFi_Creds[0].wifi_pw,
791 | WM_config.WiFi_Creds[1].wifi_ssid, WM_config.WiFi_Creds[1].wifi_pw);
792 | #endif
793 |
794 | // Starts an access point
795 | //if (!ESP_wifiManager.startConfigPortal((const char *) ssid.c_str(), password))
796 | if ( !ESP_wifiManager.startConfigPortal(AP_SSID.c_str(), AP_PASS.c_str()) )
797 | Serial.println(F("Not connected to WiFi but continuing anyway."));
798 | else
799 | Serial.println(F("WiFi connected...yeey :)"));
800 |
801 | // Stored for later usage, from v1.1.0, but clear first
802 | memset(&WM_config, 0, sizeof(WM_config));
803 |
804 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
805 | {
806 | String tempSSID = ESP_wifiManager.getSSID(i);
807 | String tempPW = ESP_wifiManager.getPW(i);
808 |
809 | if (strlen(tempSSID.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1)
810 | strcpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str());
811 | else
812 | strncpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1);
813 |
814 | if (strlen(tempPW.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1)
815 | strcpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str());
816 | else
817 | strncpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1);
818 |
819 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
820 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
821 | {
822 | LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
823 | wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
824 | }
825 | }
826 |
827 | #if USE_ESP_WIFIMANAGER_NTP
828 | String tempTZ = ESP_wifiManager.getTimezoneName();
829 |
830 | if (strlen(tempTZ.c_str()) < sizeof(WM_config.TZ_Name) - 1)
831 | strcpy(WM_config.TZ_Name, tempTZ.c_str());
832 | else
833 | strncpy(WM_config.TZ_Name, tempTZ.c_str(), sizeof(WM_config.TZ_Name) - 1);
834 |
835 | const char * TZ_Result = ESP_wifiManager.getTZ(WM_config.TZ_Name);
836 |
837 | if (strlen(TZ_Result) < sizeof(WM_config.TZ) - 1)
838 | strcpy(WM_config.TZ, TZ_Result);
839 | else
840 | strncpy(WM_config.TZ, TZ_Result, sizeof(WM_config.TZ_Name) - 1);
841 |
842 | if ( strlen(WM_config.TZ_Name) > 0 )
843 | {
844 | LOGERROR3(F("Saving current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ);
845 |
846 | #if ESP8266
847 | configTime(WM_config.TZ, "pool.ntp.org");
848 | #else
849 | //configTzTime(WM_config.TZ, "pool.ntp.org" );
850 | configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
851 | #endif
852 | }
853 | else
854 | {
855 | LOGERROR(F("Current Timezone Name is not set. Enter Config Portal to set."));
856 | }
857 | #endif
858 |
859 | // New in v1.4.0
860 | ESP_wifiManager.getSTAStaticIPConfig(WM_STA_IPconfig);
861 | //////
862 |
863 | saveConfigData();
864 | }
865 | else
866 | {
867 | wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
868 | }
869 |
870 | startedAt = millis();
871 |
872 | if (!initialConfig)
873 | {
874 | // Load stored data, the addAP ready for MultiWiFi reconnection
875 | if (!configDataLoaded)
876 | loadConfigData();
877 |
878 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
879 | {
880 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
881 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
882 | {
883 | LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
884 | wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
885 | }
886 | }
887 |
888 | if ( WiFi.status() != WL_CONNECTED )
889 | {
890 | Serial.println(F("ConnectMultiWiFi in setup"));
891 |
892 | connectMultiWiFi();
893 | }
894 | }
895 |
896 | Serial.print(F("After waiting "));
897 | Serial.print((float) (millis() - startedAt) / 1000L);
898 | Serial.print(F(" secs more in setup(), connection result is "));
899 |
900 | if (WiFi.status() == WL_CONNECTED)
901 | {
902 | Serial.print(F("connected. Local IP: "));
903 | Serial.println(WiFi.localIP());
904 | }
905 | else
906 | Serial.println(ESP_wifiManager.getStatus(WiFi.status()));
907 | }
908 |
909 | void loop()
910 | {
911 | // put your main code here, to run repeatedly
912 | check_status();
913 | }
914 |
--------------------------------------------------------------------------------
/examples/ConfigOnDoubleReset_Multi/ConfigOnDoubleReset_Multi.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************************************************************
2 | ConfigOnDoubleReset_Multi.cpp
3 | For ESP8266 / ESP32 boards
4 |
5 | ESP_WiFiManager is a library for the ESP8266/ESP32 platform (https://github.com/esp8266/Arduino) to enable easy
6 | configuration and reconfiguration of WiFi credentials using a Captive Portal. Inspired by:
7 | http://www.esp8266.com/viewtopic.php?f=29&t=2520
8 | https://github.com/chriscook8/esp-arduino-apboot
9 | https://github.com/esp8266/Arduino/blob/master/libraries/DNSServer/examples/CaptivePortalAdvanced/
10 |
11 | Modified from Tzapu https://github.com/tzapu/WiFiManager
12 | and from Ken Taylor https://github.com/kentaylor
13 |
14 | Built by Khoi Hoang https://github.com/khoih-prog/ESP_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 "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 |
87 | // SSID and PW for your Router
88 | String Router_SSID;
89 | String Router_Pass;
90 |
91 | WM_Config WM_config;
92 |
93 | // Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected
94 | bool initialConfig = false;
95 |
96 | #if ( USE_DHCP_IP )
97 | // Use DHCP
98 |
99 | #if (_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 |
109 | #if (_WIFIMGR_LOGLEVEL_ > 3)
110 | #warning Using static IP
111 | #endif
112 |
113 | #ifdef ESP32
114 | IPAddress stationIP = IPAddress(192, 168, 2, 232);
115 | #else
116 | IPAddress stationIP = IPAddress(192, 168, 2, 186);
117 | #endif
118 |
119 | IPAddress gatewayIP = IPAddress(192, 168, 2, 1);
120 | IPAddress netMask = IPAddress(255, 255, 255, 0);
121 | #endif
122 |
123 | IPAddress dns1IP = gatewayIP;
124 | IPAddress dns2IP = IPAddress(8, 8, 8, 8);
125 |
126 | IPAddress APStaticIP = IPAddress(192, 168, 100, 1);
127 | IPAddress APStaticGW = IPAddress(192, 168, 100, 1);
128 | IPAddress APStaticSN = IPAddress(255, 255, 255, 0);
129 |
130 | ///////////////////////////////////////////
131 | // New in v1.4.0
132 | /******************************************
133 | * // Defined in ESP_WiFiManager.h
134 | typedef struct
135 | {
136 | IPAddress _ap_static_ip;
137 | IPAddress _ap_static_gw;
138 | IPAddress _ap_static_sn;
139 |
140 | } WiFi_AP_IPConfig;
141 |
142 | typedef struct
143 | {
144 | IPAddress _sta_static_ip;
145 | IPAddress _sta_static_gw;
146 | IPAddress _sta_static_sn;
147 | #if USE_CONFIGURABLE_DNS
148 | IPAddress _sta_static_dns1;
149 | IPAddress _sta_static_dns2;
150 | #endif
151 | } WiFi_STA_IPConfig;
152 | ******************************************/
153 |
154 | WiFi_AP_IPConfig WM_AP_IPconfig;
155 | WiFi_STA_IPConfig WM_STA_IPconfig;
156 |
157 | void initAPIPConfigStruct(WiFi_AP_IPConfig &in_WM_AP_IPconfig)
158 | {
159 | in_WM_AP_IPconfig._ap_static_ip = APStaticIP;
160 | in_WM_AP_IPconfig._ap_static_gw = APStaticGW;
161 | in_WM_AP_IPconfig._ap_static_sn = APStaticSN;
162 | }
163 |
164 | void initSTAIPConfigStruct(WiFi_STA_IPConfig &in_WM_STA_IPconfig)
165 | {
166 | in_WM_STA_IPconfig._sta_static_ip = stationIP;
167 | in_WM_STA_IPconfig._sta_static_gw = gatewayIP;
168 | in_WM_STA_IPconfig._sta_static_sn = netMask;
169 | #if USE_CONFIGURABLE_DNS
170 | in_WM_STA_IPconfig._sta_static_dns1 = dns1IP;
171 | in_WM_STA_IPconfig._sta_static_dns2 = dns2IP;
172 | #endif
173 | }
174 |
175 | void displayIPConfigStruct(WiFi_STA_IPConfig in_WM_STA_IPconfig)
176 | {
177 | LOGERROR3(F("stationIP ="), in_WM_STA_IPconfig._sta_static_ip, ", gatewayIP =", in_WM_STA_IPconfig._sta_static_gw);
178 | LOGERROR1(F("netMask ="), in_WM_STA_IPconfig._sta_static_sn);
179 | #if USE_CONFIGURABLE_DNS
180 | LOGERROR3(F("dns1IP ="), in_WM_STA_IPconfig._sta_static_dns1, ", dns2IP =", in_WM_STA_IPconfig._sta_static_dns2);
181 | #endif
182 | }
183 |
184 | void configWiFi(WiFi_STA_IPConfig in_WM_STA_IPconfig)
185 | {
186 | #if USE_CONFIGURABLE_DNS
187 | // Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5
188 | WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn, in_WM_STA_IPconfig._sta_static_dns1, in_WM_STA_IPconfig._sta_static_dns2);
189 | #else
190 | // Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2.
191 | WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn);
192 | #endif
193 | }
194 |
195 | ///////////////////////////////////////////
196 |
197 | uint8_t connectMultiWiFi()
198 | {
199 | #if ESP32
200 | // For ESP32, this better be 0 to shorten the connect time.
201 | // For ESP32-S2/C3, must be > 500
202 | #if ( USING_ESP32_S2 || USING_ESP32_C3 )
203 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 500L
204 | #else
205 | // For ESP32 core v1.0.6, must be >= 500
206 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 800L
207 | #endif
208 | #else
209 | // For ESP8266, this better be 2200 to enable connect the 1st time
210 | #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 2200L
211 | #endif
212 |
213 | #define WIFI_MULTI_CONNECT_WAITING_MS 500L
214 |
215 | uint8_t status;
216 |
217 | //WiFi.mode(WIFI_STA);
218 |
219 | LOGERROR(F("ConnectMultiWiFi with :"));
220 |
221 | if ( (Router_SSID != "") && (Router_Pass != "") )
222 | {
223 | LOGERROR3(F("* Flash-stored Router_SSID = "), Router_SSID, F(", Router_Pass = "), Router_Pass );
224 | LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass );
225 | wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
226 | }
227 |
228 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
229 | {
230 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
231 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
232 | {
233 | LOGERROR3(F("* Additional SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
234 | }
235 | }
236 |
237 | LOGERROR(F("Connecting MultiWifi..."));
238 |
239 | //WiFi.mode(WIFI_STA);
240 |
241 | #if !USE_DHCP_IP
242 | // New in v1.4.0
243 | configWiFi(WM_STA_IPconfig);
244 | //////
245 | #endif
246 |
247 | int i = 0;
248 |
249 | status = wifiMulti.run();
250 | delay(WIFI_MULTI_1ST_CONNECT_WAITING_MS);
251 |
252 | while ( ( i++ < 20 ) && ( status != WL_CONNECTED ) )
253 | {
254 | status = WiFi.status();
255 |
256 | if ( status == WL_CONNECTED )
257 | break;
258 | else
259 | delay(WIFI_MULTI_CONNECT_WAITING_MS);
260 | }
261 |
262 | if ( status == WL_CONNECTED )
263 | {
264 | LOGERROR1(F("WiFi connected after time: "), i);
265 | LOGERROR3(F("SSID:"), WiFi.SSID(), F(",RSSI="), WiFi.RSSI());
266 | LOGERROR3(F("Channel:"), WiFi.channel(), F(",IP address:"), WiFi.localIP() );
267 | }
268 | else
269 | {
270 | LOGERROR(F("WiFi not connected"));
271 |
272 | // To avoid unnecessary DRD
273 | drd->loop();
274 |
275 | #if ESP8266
276 | ESP.reset();
277 | #else
278 | ESP.restart();
279 | #endif
280 | }
281 |
282 | return status;
283 | }
284 |
285 | #if USE_ESP_WIFIMANAGER_NTP
286 |
287 | void printLocalTime()
288 | {
289 | #if ESP8266
290 | static time_t now;
291 |
292 | now = time(nullptr);
293 |
294 | if ( now > 1451602800 )
295 | {
296 | Serial.print("Local Date/Time: ");
297 | Serial.print(ctime(&now));
298 | }
299 | #else
300 | struct tm timeinfo;
301 |
302 | getLocalTime( &timeinfo );
303 |
304 | // Valid only if year > 2000.
305 | // You can get from timeinfo : tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec
306 | if (timeinfo.tm_year > 100 )
307 | {
308 | Serial.print("Local Date/Time: ");
309 | Serial.print( asctime( &timeinfo ) );
310 | }
311 | #endif
312 | }
313 |
314 | #endif
315 |
316 | void heartBeatPrint()
317 | {
318 | #if USE_ESP_WIFIMANAGER_NTP
319 | printLocalTime();
320 | #else
321 | static int num = 1;
322 |
323 | if (WiFi.status() == WL_CONNECTED)
324 | Serial.print(F("H")); // H means connected to WiFi
325 | else
326 | Serial.print(F("F")); // F means not connected to WiFi
327 |
328 | if (num == 80)
329 | {
330 | Serial.println();
331 | num = 1;
332 | }
333 | else if (num++ % 10 == 0)
334 | {
335 | Serial.print(F(" "));
336 | }
337 | #endif
338 | }
339 |
340 | void check_WiFi()
341 | {
342 | if ( (WiFi.status() != WL_CONNECTED) )
343 | {
344 | Serial.println(F("\nWiFi lost. Call connectMultiWiFi in loop"));
345 | connectMultiWiFi();
346 | }
347 | }
348 |
349 | void check_status()
350 | {
351 | static ulong checkstatus_timeout = 0;
352 | static ulong checkwifi_timeout = 0;
353 |
354 | static ulong current_millis;
355 |
356 | #define WIFICHECK_INTERVAL 1000L
357 |
358 | #if USE_ESP_WIFIMANAGER_NTP
359 | #define HEARTBEAT_INTERVAL 60000L
360 | #else
361 | #define HEARTBEAT_INTERVAL 10000L
362 | #endif
363 |
364 | current_millis = millis();
365 |
366 | // Check WiFi every WIFICHECK_INTERVAL (1) seconds.
367 | if ((current_millis > checkwifi_timeout) || (checkwifi_timeout == 0))
368 | {
369 | check_WiFi();
370 | checkwifi_timeout = current_millis + WIFICHECK_INTERVAL;
371 | }
372 |
373 | // Print hearbeat every HEARTBEAT_INTERVAL (10) seconds.
374 | if ((current_millis > checkstatus_timeout) || (checkstatus_timeout == 0))
375 | {
376 | heartBeatPrint();
377 | checkstatus_timeout = current_millis + HEARTBEAT_INTERVAL;
378 | }
379 | }
380 |
381 | int calcChecksum(uint8_t* address, uint16_t sizeToCalc)
382 | {
383 | uint16_t checkSum = 0;
384 |
385 | for (uint16_t index = 0; index < sizeToCalc; index++)
386 | {
387 | checkSum += * ( ( (byte*) address ) + index);
388 | }
389 |
390 | return checkSum;
391 | }
392 |
393 | bool loadConfigData()
394 | {
395 | File file = FileFS.open(CONFIG_FILENAME, "r");
396 | LOGERROR(F("LoadWiFiCfgFile "));
397 |
398 | memset((void*) &WM_config, 0, sizeof(WM_config));
399 |
400 | // New in v1.4.0
401 | memset((void*) &WM_STA_IPconfig, 0, sizeof(WM_STA_IPconfig));
402 | //////
403 |
404 | if (file)
405 | {
406 | file.readBytes((char *) &WM_config, sizeof(WM_config));
407 |
408 | // New in v1.4.0
409 | file.readBytes((char *) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig));
410 | //////
411 |
412 | file.close();
413 | LOGERROR(F("OK"));
414 |
415 | if ( WM_config.checksum != calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) ) )
416 | {
417 | LOGERROR(F("WM_config checksum wrong"));
418 |
419 | return false;
420 | }
421 |
422 | // New in v1.4.0
423 | displayIPConfigStruct(WM_STA_IPconfig);
424 | //////
425 |
426 | return true;
427 | }
428 | else
429 | {
430 | LOGERROR(F("failed"));
431 |
432 | return false;
433 | }
434 | }
435 |
436 | void saveConfigData()
437 | {
438 | File file = FileFS.open(CONFIG_FILENAME, "w");
439 | LOGERROR(F("SaveWiFiCfgFile "));
440 |
441 | if (file)
442 | {
443 | WM_config.checksum = calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) );
444 |
445 | file.write((uint8_t*) &WM_config, sizeof(WM_config));
446 |
447 | displayIPConfigStruct(WM_STA_IPconfig);
448 |
449 | // New in v1.4.0
450 | file.write((uint8_t*) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig));
451 | //////
452 |
453 | file.close();
454 | LOGERROR(F("OK"));
455 | }
456 | else
457 | {
458 | LOGERROR(F("failed"));
459 | }
460 | }
461 |
--------------------------------------------------------------------------------
/examples/ConfigOnDoubleReset_Multi/ConfigOnDoubleReset_Multi.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************************************************************
2 | ConfigOnDoubleReset_Multi.h
3 | For ESP8266 / ESP32 boards
4 |
5 | ESP_WiFiManager is a library for the ESP8266/ESP32 platform (https://github.com/esp8266/Arduino) to enable easy
6 | configuration and reconfiguration of WiFi credentials using a Captive Portal. Inspired by:
7 | http://www.esp8266.com/viewtopic.php?f=29&t=2520
8 | https://github.com/chriscook8/esp-arduino-apboot
9 | https://github.com/esp8266/Arduino/blob/master/libraries/DNSServer/examples/CaptivePortalAdvanced/
10 |
11 | Modified from Tzapu https://github.com/tzapu/WiFiManager
12 | and from Ken Taylor https://github.com/kentaylor
13 |
14 | Built by Khoi Hoang https://github.com/khoih-prog/ESP_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 | // Use from 0 to 4. Higher number, more debugging messages and memory usage.
46 | #define _WIFIMGR_LOGLEVEL_ 3
47 |
48 | #include
49 |
50 | //Ported to ESP32
51 | #ifdef ESP32
52 | #include
53 | #include
54 | #include
55 |
56 | // From v1.1.0
57 | #include
58 | extern WiFiMulti wifiMulti;
59 |
60 | // LittleFS has higher priority than SPIFFS
61 | #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
62 | #define USE_LITTLEFS true
63 | #define USE_SPIFFS false
64 | #elif defined(ARDUINO_ESP32C3_DEV)
65 | // For core v1.0.6-, ESP32-C3 only supporting SPIFFS and EEPROM. To use v2.0.0+ for LittleFS
66 | #define USE_LITTLEFS false
67 | #define USE_SPIFFS true
68 | #endif
69 |
70 | #if USE_LITTLEFS
71 | // Use LittleFS
72 | #include "FS.h"
73 |
74 | // Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h
75 | //#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) ) //(ESP_ARDUINO_VERSION_MAJOR >= 2)
76 | #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
77 | #if (_WIFIMGR_LOGLEVEL_ > 3)
78 | #warning Using ESP32 Core 1.0.6 or 2.0.0+
79 | #endif
80 |
81 | // The library has been merged into esp32 core from release 1.0.6
82 | #include // https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS
83 |
84 | extern FS* filesystem; // = &LittleFS;
85 | #define FileFS LittleFS
86 | #define FS_Name "LittleFS"
87 | #else
88 | #if (_WIFIMGR_LOGLEVEL_ > 3)
89 | #warning Using ESP32 Core 1.0.5-. You must install LITTLEFS library
90 | #endif
91 |
92 | // The library has been merged into esp32 core from release 1.0.6
93 | #include // https://github.com/lorol/LITTLEFS
94 |
95 | extern FS* filesystem; // = &LITTLEFS;
96 | #define FileFS LITTLEFS
97 | #define FS_Name "LittleFS"
98 | #endif
99 |
100 | #elif USE_SPIFFS
101 | #include
102 | extern FS* filesystem; // = &SPIFFS;
103 | #define FileFS SPIFFS
104 | #define FS_Name "SPIFFS"
105 | #else
106 | // +Use FFat
107 | #include
108 | extern FS* filesystem; // = &FFat;
109 | #define FileFS FFat
110 | #define FS_Name "FFat"
111 | #endif
112 | //////
113 |
114 | #define LED_BUILTIN 2
115 | #define LED_ON HIGH
116 | #define LED_OFF LOW
117 |
118 | #else
119 | #include //https://github.com/esp8266/Arduino
120 | //needed for library
121 | #include
122 | #include
123 |
124 | // From v1.1.0
125 | #include
126 | extern ESP8266WiFiMulti wifiMulti;
127 |
128 | #define USE_LITTLEFS true
129 |
130 | #if USE_LITTLEFS
131 | #include
132 | extern FS* filesystem; // = &LittleFS;
133 | #define FileFS LittleFS
134 | #define FS_Name "LittleFS"
135 | #else
136 | extern FS* filesystem; // = &SPIFFS;
137 | #define FileFS SPIFFS
138 | #define FS_Name "SPIFFS"
139 | #endif
140 | //////
141 |
142 | #define ESP_getChipId() (ESP.getChipId())
143 |
144 | #define LED_ON LOW
145 | #define LED_OFF HIGH
146 | #endif
147 |
148 | // These defines must be put before #include
149 | // to select where to store DoubleResetDetector's variable.
150 | // For ESP32, You must select one to be true (EEPROM or SPIFFS)
151 | // For ESP8266, You must select one to be true (RTC, EEPROM, SPIFFS or LITTLEFS)
152 | // Otherwise, library will use default EEPROM storage
153 | #ifdef ESP32
154 |
155 | // These defines must be put before #include
156 | // to select where to store DoubleResetDetector's variable.
157 | // For ESP32, You must select one to be true (EEPROM or SPIFFS)
158 | // Otherwise, library will use default EEPROM storage
159 | #if USE_LITTLEFS
160 | #define ESP_DRD_USE_LITTLEFS true
161 | #define ESP_DRD_USE_SPIFFS false
162 | #define ESP_DRD_USE_EEPROM false
163 | #elif USE_SPIFFS
164 | #define ESP_DRD_USE_LITTLEFS false
165 | #define ESP_DRD_USE_SPIFFS true
166 | #define ESP_DRD_USE_EEPROM false
167 | #else
168 | #define ESP_DRD_USE_LITTLEFS false
169 | #define ESP_DRD_USE_SPIFFS false
170 | #define ESP_DRD_USE_EEPROM true
171 | #endif
172 |
173 | #else //ESP8266
174 |
175 | // For DRD
176 | // These defines must be put before #include
177 | // to select where to store DoubleResetDetector's variable.
178 | // For ESP8266, You must select one to be true (RTC, EEPROM, SPIFFS or LITTLEFS)
179 | // Otherwise, library will use default EEPROM storage
180 | #if USE_LITTLEFS
181 | #define ESP_DRD_USE_LITTLEFS true
182 | #define ESP_DRD_USE_SPIFFS false
183 | #else
184 | #define ESP_DRD_USE_LITTLEFS false
185 | #define ESP_DRD_USE_SPIFFS true
186 | #endif
187 |
188 | #define ESP_DRD_USE_EEPROM false
189 | #define ESP8266_DRD_USE_RTC false
190 | #endif
191 |
192 | #define DOUBLERESETDETECTOR_DEBUG true //false
193 |
194 | #include //https://github.com/khoih-prog/ESP_DoubleResetDetector
195 |
196 | // Number of seconds after reset during which a
197 | // subseqent reset will be considered a double reset.
198 | #define DRD_TIMEOUT 10
199 |
200 | // RTC Memory Address for the DoubleResetDetector to use
201 | #define DRD_ADDRESS 0
202 |
203 | //DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS);
204 | extern DoubleResetDetector* drd;//////
205 |
206 | // Onboard LED I/O pin on NodeMCU board
207 | extern const int PIN_LED; // = 2; // D4 on NodeMCU and WeMos. GPIO2/ADC12 of ESP32. Controls the onboard LED.
208 |
209 | // SSID and PW for Config Portal
210 | //String ssid = "ESP_" + String(ESP_getChipId(), HEX);
211 | extern String ssid;
212 | extern String password;
213 | //extern const char* password; // = "your_password";
214 |
215 | // SSID and PW for your Router
216 | extern String Router_SSID;
217 | extern String Router_Pass;
218 |
219 | // From v1.1.0
220 | // You only need to format the filesystem once
221 | //#define FORMAT_FILESYSTEM true
222 | #define FORMAT_FILESYSTEM false
223 |
224 | #define MIN_AP_PASSWORD_SIZE 8
225 |
226 | #define SSID_MAX_LEN 32
227 | //From v1.0.10, WPA2 passwords can be up to 63 characters long.
228 | #define PASS_MAX_LEN 64
229 |
230 | typedef struct
231 | {
232 | char wifi_ssid[SSID_MAX_LEN];
233 | char wifi_pw [PASS_MAX_LEN];
234 | } WiFi_Credentials;
235 |
236 | typedef struct
237 | {
238 | String wifi_ssid;
239 | String wifi_pw;
240 | } WiFi_Credentials_String;
241 |
242 | #define NUM_WIFI_CREDENTIALS 2
243 |
244 | // Assuming max 491 chars
245 | #define TZNAME_MAX_LEN 50
246 | #define TIMEZONE_MAX_LEN 50
247 |
248 | typedef struct
249 | {
250 | WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS];
251 | char TZ_Name[TZNAME_MAX_LEN]; // "America/Toronto"
252 | char TZ[TIMEZONE_MAX_LEN]; // "EST5EDT,M3.2.0,M11.1.0"
253 | uint16_t checksum;
254 | } WM_Config;
255 |
256 | extern WM_Config WM_config;
257 |
258 | #define CONFIG_FILENAME F("/wifi_cred.dat")
259 | //////
260 |
261 | // Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected
262 | extern bool initialConfig; // = false;
263 |
264 | // Use false if you don't like to display Available Pages in Information Page of Config Portal
265 | // Comment out or use true to display Available Pages in Information Page of Config Portal
266 | // Must be placed before #include
267 | #define USE_AVAILABLE_PAGES true //false
268 |
269 | // From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
270 | // You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa
271 | // You have to explicitly specify false to disable the feature.
272 | //#define USE_STATIC_IP_CONFIG_IN_CP false
273 |
274 | // Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal.
275 | // See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23)
276 | #define USE_ESP_WIFIMANAGER_NTP true
277 |
278 | // Just use enough to save memory. On ESP8266, can cause blank ConfigPortal screen
279 | // if using too much memory
280 | #define USING_AFRICA false
281 | #define USING_AMERICA true
282 | #define USING_ANTARCTICA false
283 | #define USING_ASIA false
284 | #define USING_ATLANTIC false
285 | #define USING_AUSTRALIA false
286 | #define USING_EUROPE false
287 | #define USING_INDIAN false
288 | #define USING_PACIFIC false
289 | #define USING_ETC_GMT false
290 |
291 | // Use true to enable CloudFlare NTP service. System can hang if you don't have Internet access while accessing CloudFlare
292 | // See Issue #21: CloudFlare link in the default portal (https://github.com/khoih-prog/ESP_WiFiManager/issues/21)
293 | #define USE_CLOUDFLARE_NTP false
294 |
295 | // New in v1.0.11
296 | #define USING_CORS_FEATURE true
297 |
298 | //////
299 |
300 | // Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network
301 | #if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP)
302 | // Force DHCP to be true
303 | #if defined(USE_DHCP_IP)
304 | #undef USE_DHCP_IP
305 | #endif
306 | #define USE_DHCP_IP true
307 | #else
308 | // You can select DHCP or Static IP here
309 | #define USE_DHCP_IP true
310 | //#define USE_DHCP_IP false
311 | #endif
312 |
313 | #if ( USE_DHCP_IP )
314 | // Use DHCP
315 |
316 | #if (_WIFIMGR_LOGLEVEL_ > 3)
317 | #warning Using DHCP IP
318 | #endif
319 |
320 | extern IPAddress stationIP; // = IPAddress(0, 0, 0, 0);
321 | extern IPAddress gatewayIP; // = IPAddress(192, 168, 1, 1);
322 | extern IPAddress netMask; // = IPAddress(255, 255, 255, 0);
323 | #else
324 | // Use static IP
325 |
326 | #if (_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 | // Must be placed before #include , or default port 80 will be used
352 | //#define HTTP_PORT 8080
353 |
354 | #include //https://github.com/khoih-prog/ESP_WiFiManager
355 |
356 | // Function Prototypes
357 | uint8_t connectMultiWiFi();
358 |
359 | ///////////////////////////////////////////
360 | // New in v1.4.0
361 | /******************************************
362 | * // Defined in ESP_WiFiManager.h
363 | typedef struct
364 | {
365 | IPAddress _ap_static_ip;
366 | IPAddress _ap_static_gw;
367 | IPAddress _ap_static_sn;
368 |
369 | } WiFi_AP_IPConfig;
370 |
371 | typedef struct
372 | {
373 | IPAddress _sta_static_ip;
374 | IPAddress _sta_static_gw;
375 | IPAddress _sta_static_sn;
376 | #if USE_CONFIGURABLE_DNS
377 | IPAddress _sta_static_dns1;
378 | IPAddress _sta_static_dns2;
379 | #endif
380 | } WiFi_STA_IPConfig;
381 | ******************************************/
382 |
383 | extern WiFi_AP_IPConfig WM_AP_IPconfig;
384 | extern WiFi_STA_IPConfig WM_STA_IPconfig;
385 |
386 | void initAPIPConfigStruct(WiFi_AP_IPConfig &in_WM_AP_IPconfig);
387 | void initSTAIPConfigStruct(WiFi_STA_IPConfig &in_WM_STA_IPconfig);
388 | void displayIPConfigStruct(WiFi_STA_IPConfig in_WM_STA_IPconfig);
389 | void configWiFi(WiFi_STA_IPConfig in_WM_STA_IPconfig);
390 |
391 | uint8_t connectMultiWiFi();
392 |
393 |
394 | #if USE_ESP_WIFIMANAGER_NTP
395 | void printLocalTime();
396 | #endif
397 |
398 | void heartBeatPrint();
399 |
400 | void check_WiFi();
401 | void check_status();
402 | int calcChecksum(uint8_t* address, uint16_t sizeToCalc);
403 | bool loadConfigData();
404 | void saveConfigData();
405 |
406 | ///////////////////////////////////////////
407 |
--------------------------------------------------------------------------------
/examples/ConfigOnDoubleReset_Multi/ConfigOnDoubleReset_Multi.ino:
--------------------------------------------------------------------------------
1 | /****************************************************************************************************************************
2 | ConfigOnDoubleReset_Multi.ino
3 | For ESP8266 / ESP32 boards
4 |
5 | ESP_WiFiManager is a library for the ESP8266/ESP32 platform (https://github.com/esp8266/Arduino) to enable easy
6 | configuration and reconfiguration of WiFi credentials using a Captive Portal. Inspired by:
7 | http://www.esp8266.com/viewtopic.php?f=29&t=2520
8 | https://github.com/chriscook8/esp-arduino-apboot
9 | https://github.com/esp8266/Arduino/blob/master/libraries/DNSServer/examples/CaptivePortalAdvanced/
10 |
11 | Modified from Tzapu https://github.com/tzapu/WiFiManager
12 | and from Ken Taylor https://github.com/kentaylor
13 |
14 | Built by Khoi Hoang https://github.com/khoih-prog/ESP_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_WIFIMANAGER_VERSION_MIN_TARGET "ESP_WiFiManager v1.12.0"
46 | #define ESP_WIFIMANAGER_VERSION_MIN 1012000
47 |
48 | // Use from 0 to 4. Higher number, more debugging messages and memory usage.
49 | #define _WIFIMGR_LOGLEVEL_ 1
50 |
51 | // To not display stored SSIDs and PWDs on Config Portal, select false. Default is true
52 | // Even the stored Credentials are not display, just leave them all blank to reconnect and reuse the stored Credentials
53 | //#define DISPLAY_STORED_CREDENTIALS_IN_CP false
54 |
55 | // These definitions must be placed before #include
56 | #include "ConfigOnDoubleReset_Multi.h"
57 |
58 | #include //https://github.com/khoih-prog/ESP_WiFiManager
59 |
60 | // Redundant, for v1.8.0 only
61 | //#include //https://github.com/khoih-prog/ESP_WiFiManager
62 |
63 | void setup()
64 | {
65 | // put your setup code here, to run once:
66 | // initialize the LED digital pin as an output.
67 | pinMode(PIN_LED, OUTPUT);
68 |
69 | Serial.begin(115200);
70 | while (!Serial);
71 |
72 | delay(200);
73 |
74 | Serial.print(F("\nStarting ConfigOnDoubleReset_Multi with DoubleResetDetect using ")); Serial.print(FS_Name);
75 | Serial.print(F(" on ")); Serial.println(ARDUINO_BOARD);
76 | Serial.println(ESP_WIFIMANAGER_VERSION);
77 | Serial.println(ESP_DOUBLE_RESET_DETECTOR_VERSION);
78 |
79 | #if defined(ESP_WIFIMANAGER_VERSION_MIN)
80 | if (ESP_WIFIMANAGER_VERSION_INT < ESP_WIFIMANAGER_VERSION_MIN)
81 | {
82 | Serial.print("Warning. Must use this example on Version equal or later than : ");
83 | Serial.println(ESP_WIFIMANAGER_VERSION_MIN_TARGET);
84 | }
85 | #endif
86 |
87 | Serial.setDebugOutput(false);
88 |
89 | if (FORMAT_FILESYSTEM)
90 | FileFS.format();
91 |
92 | // Format FileFS if not yet
93 | #ifdef ESP32
94 | if (!FileFS.begin(true))
95 | #else
96 | if (!FileFS.begin())
97 | #endif
98 | {
99 | #ifdef ESP8266
100 | FileFS.format();
101 | #endif
102 |
103 | Serial.println(F("SPIFFS/LittleFS failed! Already tried formatting."));
104 |
105 | if (!FileFS.begin())
106 | {
107 | // prevents debug info from the library to hide err message.
108 | delay(100);
109 |
110 | #if USE_LITTLEFS
111 | Serial.println(F("LittleFS failed!. Please use SPIFFS or EEPROM. Stay forever"));
112 | #else
113 | Serial.println(F("SPIFFS failed!. Please use LittleFS or EEPROM. Stay forever"));
114 | #endif
115 |
116 | while (true)
117 | {
118 | delay(1);
119 | }
120 | }
121 | }
122 |
123 | drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS);
124 |
125 | unsigned long startedAt = millis();
126 |
127 | // New in v1.4.0
128 | initAPIPConfigStruct(WM_AP_IPconfig);
129 | initSTAIPConfigStruct(WM_STA_IPconfig);
130 | //////
131 |
132 | //Local intialization. Once its business is done, there is no need to keep it around
133 | // Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
134 | //ESP_WiFiManager ESP_wifiManager;
135 | // Use this to personalize DHCP hostname (RFC952 conformed)
136 | ESP_WiFiManager ESP_wifiManager("ConfigOnDoubleReset");
137 |
138 | #if USE_CUSTOM_AP_IP
139 | //set custom ip for portal
140 | // New in v1.4.0
141 | ESP_wifiManager.setAPStaticIPConfig(WM_AP_IPconfig);
142 | //////
143 | #endif
144 |
145 | ESP_wifiManager.setMinimumSignalQuality(-1);
146 |
147 | // From v1.0.10 only
148 | // Set config portal channel, default = 1. Use 0 => random channel from 1-13
149 | ESP_wifiManager.setConfigPortalChannel(0);
150 | //////
151 |
152 | #if !USE_DHCP_IP
153 | // Set (static IP, Gateway, Subnetmask, DNS1 and DNS2) or (IP, Gateway, Subnetmask). New in v1.0.5
154 | // New in v1.4.0
155 | ESP_wifiManager.setSTAStaticIPConfig(WM_STA_IPconfig);
156 | //////
157 | #endif
158 |
159 | // New from v1.1.1
160 | #if USING_CORS_FEATURE
161 | ESP_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin");
162 | #endif
163 |
164 | // We can't use WiFi.SSID() in ESP32 as it's only valid after connected.
165 | // SSID and Password stored in ESP32 wifi_ap_record_t and wifi_config_t are also cleared in reboot
166 | // Have to create a new function to store in EEPROM/SPIFFS for this purpose
167 | Router_SSID = ESP_wifiManager.WiFi_SSID();
168 | Router_Pass = ESP_wifiManager.WiFi_Pass();
169 |
170 | //Remove this line if you do not want to see WiFi password printed
171 | Serial.println("ESP Self-Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass);
172 |
173 | // SSID/PWD to uppercase
174 | ssid.toUpperCase();
175 | password = "My" + ssid;
176 |
177 | bool configDataLoaded = false;
178 |
179 | // From v1.1.0, Don't permit NULL password
180 | if ( (Router_SSID != "") && (Router_Pass != "") )
181 | {
182 | LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass);
183 | wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
184 |
185 | ESP_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
186 | Serial.println(F("Got ESP Self-Stored Credentials. Timeout 120s for Config Portal"));
187 | }
188 |
189 | if (loadConfigData())
190 | {
191 | configDataLoaded = true;
192 |
193 | ESP_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
194 | Serial.println(F("Got stored Credentials. Timeout 120s for Config Portal"));
195 |
196 | #if USE_ESP_WIFIMANAGER_NTP
197 | if ( strlen(WM_config.TZ_Name) > 0 )
198 | {
199 | LOGERROR3(F("Current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ);
200 |
201 | #if ESP8266
202 | configTime(WM_config.TZ, "pool.ntp.org");
203 | #else
204 | //configTzTime(WM_config.TZ, "pool.ntp.org" );
205 | configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
206 | #endif
207 | }
208 | else
209 | {
210 | Serial.println(F("Current Timezone is not set. Enter Config Portal to set."));
211 | }
212 | #endif
213 | }
214 | else
215 | {
216 | // Enter CP only if no stored SSID on flash and file
217 | Serial.println(F("Open Config Portal without Timeout: No stored Credentials."));
218 | initialConfig = true;
219 | }
220 |
221 | if (drd->detectDoubleReset())
222 | {
223 | // DRD, disable timeout.
224 | ESP_wifiManager.setConfigPortalTimeout(0);
225 |
226 | Serial.println(F("Open Config Portal without Timeout: Double Reset Detected"));
227 | initialConfig = true;
228 | }
229 |
230 | if (initialConfig)
231 | {
232 | Serial.print(F("Starting configuration portal @ "));
233 |
234 | #if USE_CUSTOM_AP_IP
235 | Serial.print(APStaticIP);
236 | #else
237 | Serial.print(F("192.168.4.1"));
238 | #endif
239 |
240 | #if defined(HTTP_PORT_TO_USE)
241 | Serial.print(F(":")); Serial.print(HTTP_PORT_TO_USE);
242 | #endif
243 |
244 | Serial.print(F(", SSID = "));
245 | Serial.print(ssid);
246 | Serial.print(F(", PWD = "));
247 | Serial.println(password);
248 |
249 | digitalWrite(PIN_LED, LED_ON); // turn the LED on by making the voltage LOW to tell us we are in configuration mode.
250 |
251 | //sets timeout in seconds until configuration portal gets turned off.
252 | //If not specified device will remain in configuration mode until
253 | //switched off via webserver or device is restarted.
254 | //ESP_wifiManager.setConfigPortalTimeout(600);
255 |
256 | #if DISPLAY_STORED_CREDENTIALS_IN_CP
257 | // New. Update Credentials, got from loadConfigData(), to display on CP
258 | ESP_wifiManager.setCredentials(WM_config.WiFi_Creds[0].wifi_ssid, WM_config.WiFi_Creds[0].wifi_pw,
259 | WM_config.WiFi_Creds[1].wifi_ssid, WM_config.WiFi_Creds[1].wifi_pw);
260 | #endif
261 |
262 | // Starts an access point
263 | if (!ESP_wifiManager.startConfigPortal((const char *) ssid.c_str(), (const char *) password.c_str()))
264 | Serial.println(F("Not connected to WiFi but continuing anyway."));
265 | else
266 | {
267 | Serial.println(F("WiFi connected...yeey :)"));
268 | }
269 |
270 | // Stored for later usage, from v1.1.0, but clear first
271 | memset(&WM_config, 0, sizeof(WM_config));
272 |
273 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
274 | {
275 | String tempSSID = ESP_wifiManager.getSSID(i);
276 | String tempPW = ESP_wifiManager.getPW(i);
277 |
278 | if (strlen(tempSSID.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1)
279 | strcpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str());
280 | else
281 | strncpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1);
282 |
283 | if (strlen(tempPW.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1)
284 | strcpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str());
285 | else
286 | strncpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1);
287 |
288 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
289 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
290 | {
291 | LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
292 | wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
293 | }
294 | }
295 |
296 | #if USE_ESP_WIFIMANAGER_NTP
297 | String tempTZ = ESP_wifiManager.getTimezoneName();
298 |
299 | if (strlen(tempTZ.c_str()) < sizeof(WM_config.TZ_Name) - 1)
300 | strcpy(WM_config.TZ_Name, tempTZ.c_str());
301 | else
302 | strncpy(WM_config.TZ_Name, tempTZ.c_str(), sizeof(WM_config.TZ_Name) - 1);
303 |
304 | const char * TZ_Result = ESP_wifiManager.getTZ(WM_config.TZ_Name);
305 |
306 | if (strlen(TZ_Result) < sizeof(WM_config.TZ) - 1)
307 | strcpy(WM_config.TZ, TZ_Result);
308 | else
309 | strncpy(WM_config.TZ, TZ_Result, sizeof(WM_config.TZ_Name) - 1);
310 |
311 | if ( strlen(WM_config.TZ_Name) > 0 )
312 | {
313 | LOGERROR3(F("Saving current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ);
314 |
315 | #if ESP8266
316 | configTime(WM_config.TZ, "pool.ntp.org");
317 | #else
318 | //configTzTime(WM_config.TZ, "pool.ntp.org" );
319 | configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
320 | #endif
321 | }
322 | else
323 | {
324 | LOGERROR(F("Current Timezone Name is not set. Enter Config Portal to set."));
325 | }
326 | #endif
327 |
328 | // New in v1.4.0
329 | ESP_wifiManager.getSTAStaticIPConfig(WM_STA_IPconfig);
330 | //////
331 |
332 | saveConfigData();
333 | }
334 |
335 | digitalWrite(PIN_LED, LED_OFF); // Turn led off as we are not in configuration mode.
336 |
337 | startedAt = millis();
338 |
339 | if (!initialConfig)
340 | {
341 | // Load stored data, the addAP ready for MultiWiFi reconnection
342 | if (!configDataLoaded)
343 | loadConfigData();
344 |
345 | for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
346 | {
347 | // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
348 | if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
349 | {
350 | LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
351 | wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
352 | }
353 | }
354 |
355 | if ( WiFi.status() != WL_CONNECTED )
356 | {
357 | Serial.println(F("ConnectMultiWiFi in setup"));
358 |
359 | connectMultiWiFi();
360 | }
361 | }
362 |
363 | Serial.print(F("After waiting "));
364 | Serial.print((float) (millis() - startedAt) / 1000);
365 | Serial.print(F(" secs more in setup(), connection result is "));
366 |
367 | if (WiFi.status() == WL_CONNECTED)
368 | {
369 | Serial.print(F("connected. Local IP: "));
370 | Serial.println(WiFi.localIP());
371 | }
372 | else
373 | Serial.println(ESP_wifiManager.getStatus(WiFi.status()));
374 | }
375 |
376 | void loop()
377 | {
378 | // Call the double reset detector loop method every so often,
379 | // so that it can recognise when the timeout expires.
380 | // You can also call drd.stop() when you wish to no longer
381 | // consider the next reset as a double reset.
382 | drd->loop();
383 |
384 | // put your main code here, to run repeatedly
385 | check_status();
386 |
387 | }
388 |
--------------------------------------------------------------------------------
/examples/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/ESP32_FSWebServer/README.md:
--------------------------------------------------------------------------------
1 | # ESP_FSWebServer Example
2 |
3 | ## First, how Config Portal works?
4 | 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):
5 |
6 | ```cpp
7 | // SSID and PW for Config Portal
8 | String ssid = "ESP_" + String(ESP_getChipId(), HEX);
9 | const char* password = "your_password";
10 | ```
11 | After you connected, please, go to http://192.168.4.1, you'll see this `Main` page:
12 |
13 |
14 |
15 |
16 |
17 | Select `Information` to enter the Info page where the board info will be shown (long page)
18 |
19 |
20 |
21 |
22 |
23 | or short page (default)
24 |
25 |
26 |
27 |
28 |
29 | Select `Configuration` to enter this page where you can select an AP and specify its WiFi Credentials
30 |
31 |
32 |
33 |
34 |
35 | Enter your credentials, then click `Save`. The WiFi Credentials will be saved and the board reboots to connect to the selected WiFi AP.
36 |
37 | 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.
38 |
39 |
40 | ## How to use this ESP_FSWebServer example?
41 |
42 | This shows you how to use this example in Ubuntu (but you can use similar commands in other OSes)
43 |
44 | 1. For example, you already downloaded from (https://github.com/khoih-prog/ESP_WiFiManager/tree/master/examples/ESP_FSWebServer/data) to a local folder, e.g.,
45 |
46 | ~/Arduino/libraries/ESP_WiFiManager-master/examples/ESP_FSWebServer/data
47 |
48 | 1. Upload the contents of that `data folder` with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
49 | 2. or upload the contents of a folder by running the following commands:
50 | - Ubuntu$ cd ~/Arduino/libraries/ESP_WiFiManager-master/examples/ESP_FSWebServer/data
51 | - Ubuntu$ for file in \`\ls -A1\`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done
52 | 3. Access the sample web page at http://esp8266fs.local
53 |
54 |
55 |
56 |
57 |
58 | 4. Edit / Delete / Download any file in the the folder by going to http://esp8266fs.local/edit
59 |
60 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/examples/ESP32_FSWebServer/pics/esp8266fs.local.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/examples/ESP32_FSWebServer/pics/esp8266fs.local.png
--------------------------------------------------------------------------------
/examples/ESP32_FSWebServer/pics/esp8266fs.local_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/examples/ESP32_FSWebServer/pics/esp8266fs.local_edit.png
--------------------------------------------------------------------------------
/examples/ESP32_FSWebServer_DRD/README.md:
--------------------------------------------------------------------------------
1 | # ESP_FSWebServer Example
2 |
3 | ## First, how Config Portal works?
4 | 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):
5 |
6 | ```cpp
7 | // SSID and PW for Config Portal
8 | String ssid = "ESP_" + String(ESP_getChipId(), HEX);
9 | const char* password = "your_password";
10 | ```
11 | After you connected, please, go to http://192.168.4.1, you'll see this `Main` page:
12 |
13 |
14 |
15 |
16 |
17 | Select `Information` to enter the Info page where the board info will be shown (long page)
18 |
19 |
20 |
21 |
22 |
23 | or short page (default)
24 |
25 |
26 |
27 |
28 |
29 | Select `Configuration` to enter this page where you can select an AP and specify its WiFi Credentials
30 |
31 |
32 |
33 |
34 |
35 | Enter your credentials, then click `Save`. The WiFi Credentials will be saved and the board reboots to connect to the selected WiFi AP.
36 |
37 | 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.
38 |
39 |
40 | ## How to use this ESP_FSWebServer example?
41 |
42 | This shows you how to use this example in Ubuntu (but you can use similar commands in other OSes)
43 |
44 | 1. For example, you already downloaded from (https://github.com/khoih-prog/ESP_WiFiManager/tree/master/examples/ESP_FSWebServer/data) to a local folder, e.g.,
45 |
46 | ~/Arduino/libraries/ESP_WiFiManager-master/examples/ESP_FSWebServer/data
47 |
48 | 1. Upload the contents of that `data folder` with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
49 | 2. or upload the contents of a folder by running the following commands:
50 | - Ubuntu$ cd ~/Arduino/libraries/ESP_WiFiManager-master/examples/ESP_FSWebServer/data
51 | - Ubuntu$ for file in \`\ls -A1\`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done
52 | 3. Access the sample web page at http://esp8266fs.local
53 |
54 |
55 |
56 |
57 |
58 | 4. Edit / Delete / Download any file in the the folder by going to http://esp8266fs.local/edit
59 |
60 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/examples/ESP32_FSWebServer_DRD/pics/esp8266fs.local.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/examples/ESP32_FSWebServer_DRD/pics/esp8266fs.local.png
--------------------------------------------------------------------------------
/examples/ESP32_FSWebServer_DRD/pics/esp8266fs.local_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/examples/ESP32_FSWebServer_DRD/pics/esp8266fs.local_edit.png
--------------------------------------------------------------------------------
/examples/ESP_FSWebServer/README.md:
--------------------------------------------------------------------------------
1 | # ESP_FSWebServer Example
2 |
3 | ## First, how Config Portal works?
4 | 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):
5 |
6 | ```cpp
7 | // SSID and PW for Config Portal
8 | String ssid = "ESP_" + String(ESP_getChipId(), HEX);
9 | const char* password = "your_password";
10 | ```
11 | After you connected, please, go to http://192.168.4.1, you'll see this `Main` page:
12 |
13 |
14 |
15 |
16 |
17 | Select `Information` to enter the Info page where the board info will be shown (long page)
18 |
19 |
20 |
21 |
22 |
23 | or short page (default)
24 |
25 |
26 |
27 |
28 |
29 | Select `Configuration` to enter this page where you can select an AP and specify its WiFi Credentials
30 |
31 |
32 |
33 |
34 |
35 | Enter your credentials, then click `Save`. The WiFi Credentials will be saved and the board reboots to connect to the selected WiFi AP.
36 |
37 | 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.
38 |
39 |
40 | ## How to use this ESP_FSWebServer example?
41 |
42 | This shows you how to use this example in Ubuntu (but you can use similar commands in other OSes)
43 |
44 | 1. For example, you already downloaded from (https://github.com/khoih-prog/ESP_WiFiManager/tree/master/examples/ESP_FSWebServer/data) to a local folder, e.g.,
45 |
46 | ~/Arduino/libraries/ESP_WiFiManager-master/examples/ESP_FSWebServer/data
47 |
48 | 1. Upload the contents of that `data folder` with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
49 | 2. or upload the contents of a folder by running the following commands:
50 | - Ubuntu$ cd ~/Arduino/libraries/ESP_WiFiManager-master/examples/ESP_FSWebServer/data
51 | - Ubuntu$ for file in \`\ls -A1\`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done
52 | 3. Access the sample web page at http://esp8266fs.local
53 |
54 |
55 |
56 |
57 |
58 | 4. Edit / Delete / Download any file in the the folder by going to http://esp8266fs.local/edit
59 |
60 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/examples/ESP_FSWebServer/pics/esp8266fs.local.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/examples/ESP_FSWebServer/pics/esp8266fs.local.png
--------------------------------------------------------------------------------
/examples/ESP_FSWebServer/pics/esp8266fs.local_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/khoih-prog/ESP_WiFiManager/aeee669702f13058a47f34ddfd5a5937ff1df250/examples/ESP_FSWebServer/pics/esp8266fs.local_edit.png
--------------------------------------------------------------------------------
/examples/ESP_FSWebServer_DRD/README.md:
--------------------------------------------------------------------------------
1 | # ESP_FSWebServer Example
2 |
3 | ## First, how Config Portal works?
4 | 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):
5 |
6 | ```cpp
7 | // SSID and PW for Config Portal
8 | String ssid = "ESP_" + String(ESP_getChipId(), HEX);
9 | const char* password = "your_password";
10 | ```
11 | After you connected, please, go to http://192.168.4.1, you'll see this `Main` page:
12 |
13 |
14 |
15 |
16 |
17 | Select `Information` to enter the Info page where the board info will be shown (long page)
18 |
19 |
20 |
21 |
22 |
23 | or short page (default)
24 |
25 |
26 |
27 |
28 |
29 | Select `Configuration` to enter this page where you can select an AP and specify its WiFi Credentials
30 |
31 |
32 |
33 |
34 |
35 | Enter your credentials, then click `Save`. The WiFi Credentials will be saved and the board reboots to connect to the selected WiFi AP.
36 |
37 | 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.
38 |
39 |
40 | ## How to use this ESP_FSWebServer example?
41 |
42 | This shows you how to use this example in Ubuntu (but you can use similar commands in other OSes)
43 |
44 | 1. For example, you already downloaded from (https://github.com/khoih-prog/ESP_WiFiManager/tree/master/examples/ESP_FSWebServer/data) to a local folder, e.g.,
45 |
46 | ~/Arduino/libraries/ESP_WiFiManager-master/examples/ESP_FSWebServer/data
47 |
48 | 1. Upload the contents of that `data folder` with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
49 | 2. or upload the contents of a folder by running the following commands:
50 | - Ubuntu$ cd ~/Arduino/libraries/ESP_WiFiManager-master/examples/ESP_FSWebServer/data
51 | - Ubuntu$ for file in \`\ls -A1\`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done
52 | 3. Access the sample web page at http://esp8266fs.local
53 |
54 |
55 |
56 |
57 |
58 | 4. Edit / Delete / Download any file in the the folder by going to http://esp8266fs.local/edit
59 |
60 |