├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── Makefile
├── README.md
├── build_web_pages.bat
├── build_web_pages.sh
├── components
├── cmd_nvs
│ ├── CMakeLists.txt
│ ├── cmd_nvs.c
│ ├── cmd_nvs.h
│ └── component.mk
├── cmd_router
│ ├── CMakeLists.txt
│ ├── cmd_router.c
│ ├── cmd_router.h
│ ├── component.mk
│ └── router_globals.h
├── cmd_system
│ ├── CMakeLists.txt
│ ├── cmd_system.c
│ ├── cmd_system.h
│ └── component.mk
├── console_handler
│ ├── CMakeLists.txt
│ ├── component.mk
│ ├── console_handler.c
│ ├── file_system.c
│ └── include
│ │ ├── console_handler.h
│ │ └── file_system.h
├── hardware_handler
│ ├── CMakeLists.txt
│ ├── button_handler.c
│ ├── component.mk
│ ├── hardware_handler.c
│ ├── include
│ │ ├── button_handler.h
│ │ ├── hardware_handler.h
│ │ └── led_handler.h
│ └── led_handler.c
├── ota_handler
│ ├── CMakeLists.txt
│ ├── README.md
│ ├── component.mk
│ ├── include
│ │ └── ota_handler.h
│ └── ota_handler.c
├── router_handler
│ ├── CMakeLists.txt
│ ├── component.mk
│ ├── include
│ │ └── router_handler.h
│ └── router_handler.c
├── utils
│ ├── CMakeLists.txt
│ ├── component.mk
│ ├── include
│ │ ├── initialization.h
│ │ ├── mac_filter.h
│ │ ├── mac_generator.h
│ │ ├── nvm.h
│ │ └── utils.h
│ ├── initialization.c
│ ├── mac_filter.c
│ ├── mac_generator.c
│ ├── nvm.c
│ └── utils.c
├── web_server
│ ├── CMakeLists.txt
│ ├── auth_handler.c
│ ├── component.mk
│ ├── get_data_handler.c
│ ├── include
│ │ ├── auth_handler.h
│ │ ├── get_data_handler.h
│ │ ├── request_handler.h
│ │ ├── storage_handler.h
│ │ └── web_server.h
│ ├── request_handler.c
│ ├── response_handler.c
│ ├── storage_handler.c
│ ├── web_server.c
│ └── www
│ │ ├── README.md
│ │ ├── additional
│ │ └── auto_generate.zip
│ │ ├── auto_generate.exe
│ │ ├── html
│ │ ├── 404.html
│ │ ├── APScanResults.json
│ │ ├── ClientScanResults.json
│ │ ├── ClientScanTime.json
│ │ ├── Gemfile
│ │ ├── Gemfile.lock
│ │ ├── _config.yml
│ │ ├── _i18n
│ │ │ └── english.yml
│ │ ├── _includes
│ │ │ ├── footer.html
│ │ │ ├── inline.js
│ │ │ └── nav.html
│ │ ├── _layouts
│ │ │ ├── html.html
│ │ │ └── page.html
│ │ ├── dark.scss
│ │ ├── index.html
│ │ ├── info.html
│ │ ├── js
│ │ │ ├── functions.js
│ │ │ ├── info.js
│ │ │ ├── scan.js
│ │ │ └── settings.js
│ │ ├── main.scss
│ │ ├── reloadSSID.json
│ │ ├── restart.json
│ │ ├── settings.html
│ │ ├── settings.json
│ │ ├── settingsReset.json
│ │ ├── settingsSave.json
│ │ └── sysinfo.json
│ │ └── output
│ │ └── gzip
│ │ ├── dark.css.gz
│ │ ├── error_404.html.gz
│ │ ├── functions.js.gz
│ │ ├── index.html.gz
│ │ ├── info.html.gz
│ │ ├── info.js.gz
│ │ ├── main.css.gz
│ │ ├── scan.js.gz
│ │ ├── settings.html.gz
│ │ └── settings.js.gz
└── wifi_handler
│ ├── CMakeLists.txt
│ ├── component.mk
│ ├── include
│ ├── wifi_event_handler.h
│ ├── wifi_handler.h
│ └── wifi_init.h
│ ├── wifi_event_handler.c
│ ├── wifi_handler.c
│ └── wifi_init.c
├── docs
├── Advanced_topics.md
├── Build_setup.md
└── images
│ ├── auto_generate.png
│ ├── info.png
│ ├── scan.png
│ ├── settings.png
│ ├── win_flash_full_bin.png
│ └── win_flash_multi_bin.png
├── partitions.csv
├── platformio.ini
├── post_extra_script.py
├── pre_extra_script.py
├── sdkconfig.esp32dev
├── sdkconfig.esp32dev.old
├── src
├── CMakeLists.txt
├── Kconfig.projbuild
├── component.mk
├── esp32_nat_router.c
└── include
│ └── cmd_decl.h
├── start_web_server.bat
└── start_web_server.sh
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/*
2 | !build/bootloader
3 | !build/esp32_nat_router.bin
4 | !build/partitions_example.bin
5 | .pio*
6 | .vscode
7 | .vscode/*
8 | !sdkconfig.*
9 | !sdkconfig.defaults
10 | components/web_server/www/output/html/
11 | release/
12 | pytest/
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The following lines of boilerplate have to be in your project's CMakeLists
2 | # in this exact order for cmake to work correctly
3 | cmake_minimum_required(VERSION 3.5)
4 |
5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6 | project(esp32_nat_router+)
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Jaya Satish
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.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a
3 | # project subdirectory.
4 | #
5 |
6 | # PROJECT_NAME := esp32_nat_router
7 |
8 | include $(IDF_PATH)/make/project.mk
9 |
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ESP32-NAT Router +
2 |
3 | This Firmware that helps you use the ESP32 as a WiFi router. You can use it to do a few things, like make your existing WiFi signal stronger, create a new WiFi network for guests or smart devices, or simplify a more complicated network. It can handle data at a speed of more than 15mbps.
4 |
5 | ## Acknowledgments
6 |
7 | This project builds upon the works of *Martin-Ger's* [ESP32 NAT Router](https://github.com/martin-ger/esp32_nat_router) and *Sam Denty's* [Wi-PWN](https://github.com/samdenty/Wi-PWN) for the UI design. However, other sources have also provided inspiration and contributed to the development of this project, including:
8 |
9 | - [@Kevin Wolfe](https://gitlab.com/kevinwolfe) (who provided OTA and other useful resources)
10 | - [@nopnop2002](https://github.com/nopnop2002) (Cjson Doc and Examples)
11 | - [@dchristl](https://github.com/dchristl) (whose work and ideas)
12 |
13 | ## Features
14 |
15 | The features of the project, which includes:
16 |
17 | - Providing a user-friendly UI with mobile support for easy accessibility
18 | - Displaying connected states and quality in the UI for transparency
19 | - Scanning for available APs to enhance network connectivity
20 | - Allowing users to disable or enable the on-board indicator LED
21 | - Incorporating a button menu (accessible via Boot button)
22 | - Custom DNS server for personalized settings
23 | - Incorporating a secure web interface with basic authentication method
24 | - Offering OTA updates for easy maintenance and functionality enhancements
25 | - Randomize MAC address
26 | - Switch Between Dark and Light mode. (through settings)
27 | - Auto reload pages when connected to Router
28 | - MAC Filter for added security
29 | - and many more...........
30 |
31 | ## First Boot
32 |
33 | Upon the first boot of the ESP32 NAT Router, a WiFi network with an open AP and an ssid of "ESP32_NAT_Router +" will be available. Users can configure the device using either a simple web interface or the serial console.
34 |
35 | ## Web Config Interface
36 |
37 | The ESP32 NAT Router has a web interface that allows you to configure all its parameters. To access this interface, connect your PC or smartphone to the WiFi SSID "ESP32_NAT_Router +". Once you're connected, open your web browser and enter
38 |
39 | "[http://192.168.4.1](http://192.168.4.1/)'' into the address bar of your browser. Once you have entered this, you will be prompted for a username and password. The default `username is "admin" `and the default` password is "123456789"`. Please note that it is recommended to change these to a more secure username and password once you have logged in:
40 |
41 |
42 |
43 | To configure the uplink WiFi network, follow these steps:
44 |
45 | 1. Go to "Settings" in the web interface of the ESP32 NAT Router
46 | 2. Enter the appropriate values for the "STA Settings" section. If it is an open network, leave the password field blank
47 | 3. Change the "AP Settings" and other customizations as necessary
48 | 4. Click on the "Save" button to save the configuration
49 | 5. Press the "Reboot" button located at the bottom right corner of the page (Nessory)
50 | 6. Wait for the device to reboot
51 |
52 | Connect to the newly configured WiFi network with the updated settings.
53 | By following these steps, you can reconfigure the ESP32 NAT Router to connect to a new uplink WiFi network with customized settings based on your preferences.
54 |
55 | **Note:** The 5th step is necessary to update certain settings on the device and apply them. Skipping this step may result in the settings not being properly applied, which can lead to issues with the device's functionality. Therefore, it is recommended to always complete the 5th step when making any changes to the device's settings in order to ensure that the device is functioning as expected and that any desired changes have been properly applied.
56 |
57 |
61 |
62 | ## Flashing the prebuild binaries
63 |
64 | - Download [latest release](https://github.com/gjroots/esp32_nat_router_plus/releases/latest)
65 | * Download esp32nat_Router+_vX.X.X.zip for fresh install (multi bin)
66 | * Download esp32nat_Router+_full_vX.X.X_0x0.zip for single bin (merged, 0x0)
67 | - Install [esptool](https://github.com/espressif/esptool)
68 |
69 | ### First install/ Reset (Terminal/CMD)
70 |
71 | Please note that if your device was previously used for other projects, or if you want to reset all settings from a previous version, executing the following steps will result in complete data loss.
72 |
73 | Note: replace X.X.X with respective Version.(eg. ...._v1.0.0.bin)
74 |
75 | Unpack archive first and then execute:
76 |
77 | Single bin method (merged, 0x0):
78 |
79 | ```
80 | esptool.py write_flash 0x0 esp32nat_Router+_full_vX.X.X_0x0.bin
81 | ```
82 |
83 | Multi bin method:
84 |
85 | ```
86 | esptool.py --chip esp32 \
87 | --before default_reset --after hard_reset write_flash \
88 | -z --flash_mode dio --flash_freq 40m --flash_size detect \
89 | 0x1000 bootloader.bin \
90 | 0x8000 partitions.bin \
91 | 0x10000 esp32nat_Router+_vX.X.X.bin
92 | ```
93 |
94 | ### Update from older version
95 |
96 | If this project was already installed. No data loss from previous version.
97 |
98 | ```
99 | esptool.py write_flash 0x10000 esp32nat_Router+_vX.X.X.bin
100 | ```
101 |
102 | If any problem occurs, erase flash manually before flashing:
103 |
104 | ```
105 | esptool.py erase_flash
106 | ```
107 |
108 | ### OTA method :
109 |
110 | To perform an OTA update on the ESP32-NATS Router+, follow these steps:
111 |
112 | 1. Go to the "Info" page in the web interface of the router
113 | 2. Click on the "Update" button
114 | 3. Select the desired bin file for the update
115 |
116 | Please note that the OTA method only supports updating with a single bin file, such as "esp32nat_Router+_vX.X.X.bin". Updating with a full bin (merged to single bin 0x0) is not supported.
117 |
118 | ### Alternative way/ Graphical (Windows only)
119 |
120 | As an alternative you might use [Espressif's Flash Download Tools](https://www.espressif.com/en/support/download/other-tools).
121 | Check the marked parameters and files like below (ckeck the COM-Port for your environment).
122 | Check the addresses like below:
123 |
124 | 
125 |
126 | ### or
127 |
128 | 
129 |
130 | ## Building the Binaries
131 |
132 | To build the binaries, please refer to the following guide: "[How to setup environment and build project](docs/Build_setup.md)" located in the "docs" folder. This guide outlines the necessary steps to set up the environment and build the binaries.
133 |
134 | ## Advanced topics and configuration
135 |
136 | For more advanced configuration and topics, refer to the "[Advanced topics](docs/Advanced_topics.md)" guide located in the "docs" folder. This guide covers topics such as configuring wireless protocols, setting up custom DNS servers working with OTA and other settings.
137 |
138 | ## Misc
139 |
140 | If you experience any issues or have any suggestions for new features, please feel free to ask or raise an issue. Please note that as this project is a spare time project, the creator may not be always available to answer queries promptly. However, if the creator is free, they will respond as soon as possible. Thank you for your understanding and patience.
141 |
142 | If you are happy with the project and would like to support the creator, there are several ways to do so. One way is to contribute to the codebase or documentation. Alternatively, you can support the creator through by spreading the word about the project to others who may find it useful.
143 |
144 | ## License
145 |
146 | The software is released under the **MIT License** , which can be found in the file named "[LICENSE](LICENSE)". Additionally, any third-party source files included in the software will have their own license header.
147 |
148 | ## Screenshots
149 |
150 | [
](docs/images/scan.png)
151 |
152 | [
](docs/images/settings.png)
153 |
154 | [
](docs/images/info.png)
155 |
--------------------------------------------------------------------------------
/build_web_pages.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | cd components\web_server\www\html
3 | echo Current directory: %cd%
4 | echo Site Building Started
5 |
6 | ::this command enables to minified version site files
7 | set JEKYLL_ENV=production
8 |
9 | ::Execute Building Site
10 | bundle exec jekyll build
11 |
12 | echo Site Building completed
--------------------------------------------------------------------------------
/build_web_pages.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | cd components\\web_server\\www\\html
3 | pwd
4 | echo Site Building Started
5 |
6 | # this command enables to minified version site files
7 | JEKYLL_ENV=production # comment out if not require
8 |
9 | # this command execute Building Site
10 | bundle exec jekyll build
11 |
12 | echo Site Building completed
13 |
--------------------------------------------------------------------------------
/components/cmd_nvs/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS "cmd_nvs.c"
2 | INCLUDE_DIRS .
3 | REQUIRES console nvs_flash)
--------------------------------------------------------------------------------
/components/cmd_nvs/cmd_nvs.h:
--------------------------------------------------------------------------------
1 | /* Console example — declarations of command registration functions.
2 |
3 | This example code is in the Public Domain (or CC0 licensed, at your option.)
4 |
5 | Unless required by applicable law or agreed to in writing, this
6 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7 | CONDITIONS OF ANY KIND, either express or implied.
8 | */
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C" {
13 | #endif
14 |
15 | // Register NVS functions
16 | void register_nvs(void);
17 |
18 | #ifdef __cplusplus
19 | }
20 | #endif
21 |
22 |
--------------------------------------------------------------------------------
/components/cmd_nvs/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Component Makefile
3 | #
4 | # This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
5 | # this will take the sources in the src/ directory, compile them and link them into
6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
7 | # please read the SDK documents if you need to do this.
8 | #
9 |
10 | COMPONENT_ADD_INCLUDEDIRS := .
11 |
--------------------------------------------------------------------------------
/components/cmd_router/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS "cmd_router.c"
2 | INCLUDE_DIRS .
3 | REQUIRES console esp_wifi driver nvs_flash)
4 |
--------------------------------------------------------------------------------
/components/cmd_router/cmd_router.h:
--------------------------------------------------------------------------------
1 | /* Console example — various router commands
2 |
3 | This example code is in the Public Domain (or CC0 licensed, at your option.)
4 |
5 | Unless required by applicable law or agreed to in writing, this
6 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7 | CONDITIONS OF ANY KIND, either express or implied.
8 | */
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C" {
13 | #endif
14 |
15 | // Register router functions
16 | void register_router(void);
17 |
18 | #ifdef __cplusplus
19 | }
20 | #endif
21 |
--------------------------------------------------------------------------------
/components/cmd_router/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Component Makefile
3 | #
4 | # This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
5 | # this will take the sources in the src/ directory, compile them and link them into
6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
7 | # please read the SDK documents if you need to do this.
8 | #
9 |
10 | COMPONENT_ADD_INCLUDEDIRS := .
11 |
--------------------------------------------------------------------------------
/components/cmd_router/router_globals.h:
--------------------------------------------------------------------------------
1 | /* Various global declarations for the esp32_nat_router
2 |
3 | Unless required by applicable law or agreed to in writing, this
4 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
5 | CONDITIONS OF ANY KIND, either express or implied.
6 | */
7 | #pragma once
8 |
9 | #ifdef __cplusplus
10 | extern "C"
11 | {
12 | #endif
13 |
14 | #define PARAM_NAMESPACE "esp32_nat"
15 | #include "lwip/ip4_addr.h"
16 | #define PROTO_TCP 6
17 | #define PROTO_UDP 17
18 |
19 | extern char *ssid;
20 | extern char *ent_username;
21 | extern char *ent_identity;
22 | extern char *passwd;
23 | extern char *static_ip;
24 | extern char *subnet_mask;
25 | extern char *gateway_addr;
26 | extern char *ap_ssid;
27 | extern char *ap_passwd;
28 | extern char *ap_ip;
29 |
30 | extern bool scanning_started;
31 |
32 | extern uint16_t connect_count;
33 | extern bool ap_connect;
34 |
35 | extern uint32_t my_ip;
36 | extern uint32_t my_ap_ip;
37 |
38 | void preprocess_string(char *str);
39 | int set_sta(int argc, char **argv);
40 | int set_sta_static(int argc, char **argv);
41 | int set_ap(int argc, char **argv);
42 |
43 | esp_err_t get_config_param_int(char *name, int *param);
44 | esp_err_t get_config_param_str(char *name, char **param);
45 |
46 | void print_portmap_tab();
47 | esp_err_t add_portmap(u8_t proto, u16_t mport, u32_t daddr, u16_t dport);
48 | esp_err_t del_portmap(u8_t proto, u16_t mport);
49 |
50 | #ifdef __cplusplus
51 | }
52 | #endif
53 |
--------------------------------------------------------------------------------
/components/cmd_system/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS "cmd_system.c"
2 | INCLUDE_DIRS .
3 | REQUIRES console driver esp_wifi spi_flash esp_app_format)
--------------------------------------------------------------------------------
/components/cmd_system/cmd_system.h:
--------------------------------------------------------------------------------
1 | /* Console example — various system commands
2 |
3 | This example code is in the Public Domain (or CC0 licensed, at your option.)
4 |
5 | Unless required by applicable law or agreed to in writing, this
6 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7 | CONDITIONS OF ANY KIND, either express or implied.
8 | */
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C" {
13 | #endif
14 |
15 | // Register system functions
16 | void register_system(void);
17 | void determineChipType(char chip_type[30]);
18 |
19 | #ifdef __cplusplus
20 | }
21 | #endif
22 |
--------------------------------------------------------------------------------
/components/cmd_system/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Component Makefile
3 | #
4 | # This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
5 | # this will take the sources in the src/ directory, compile them and link them into
6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
7 | # please read the SDK documents if you need to do this.
8 | #
9 |
10 | COMPONENT_ADD_INCLUDEDIRS := .
11 |
--------------------------------------------------------------------------------
/components/console_handler/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS console_handler.c file_system.c
2 |
3 | INCLUDE_DIRS include
4 | REQUIRES cmd_router cmd_nvs nvs_flash fatfs json vfs esp_driver_uart esp_driver_usb_serial_jtag)
--------------------------------------------------------------------------------
/components/console_handler/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Component Makefile
3 | #
4 | # This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
5 | # this will take the sources in the src/ directory, compile them and link them into
6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
7 | # please read the SDK documents if you need to do this.
8 | #
9 |
10 | COMPONENT_ADD_INCLUDEDIRS := .
11 |
--------------------------------------------------------------------------------
/components/console_handler/console_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include "driver/uart_vfs.h"
17 | #include "driver/usb_serial_jtag_vfs.h"
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include "esp_sleep.h"
23 | #include "esp_vfs_dev.h"
24 | #include "driver/usb_serial_jtag.h"
25 | #include "router_globals.h"
26 | #include "console_handler.h"
27 |
28 | void initialize_console(void)
29 | {
30 | /* Drain stdout before reconfiguring it */
31 | fflush(stdout);
32 | fsync(fileno(stdout));
33 |
34 | /* Disable buffering on stdin */
35 | setvbuf(stdin, NULL, _IONBF, 0);
36 |
37 | /* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
38 | uart_vfs_dev_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR);
39 | /* Move the caret to the beginning of the next line on '\n' */
40 | uart_vfs_dev_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF);
41 |
42 | /* Configure UART. Note that REF_TICK is used so that the baud rate remains
43 | * correct while APB frequency is changing in light sleep mode.
44 | */
45 | const uart_config_t uart_config = {
46 | .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE,
47 | .data_bits = UART_DATA_8_BITS,
48 | .parity = UART_PARITY_DISABLE,
49 | .stop_bits = UART_STOP_BITS_1,
50 | #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
51 | .source_clk = UART_SCLK_REF_TICK,
52 | #else
53 | .source_clk = UART_SCLK_XTAL,
54 | #endif
55 | };
56 | /* Install UART driver for interrupt-driven reads and writes */
57 | ESP_ERROR_CHECK(uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM,
58 | 256, 0, 0, NULL, 0));
59 | ESP_ERROR_CHECK(uart_param_config(CONFIG_ESP_CONSOLE_UART_NUM, &uart_config));
60 |
61 | /* Tell VFS to use UART driver */
62 | uart_vfs_dev_use_driver(CONFIG_ESP_CONSOLE_UART_NUM);
63 |
64 | /* Initialize the console */
65 | esp_console_config_t console_config = {
66 | .max_cmdline_args = 8,
67 | .max_cmdline_length = 256,
68 | #if CONFIG_LOG_COLORS
69 | .hint_color = atoi(LOG_COLOR_CYAN)
70 | #endif
71 | };
72 | ESP_ERROR_CHECK(esp_console_init(&console_config));
73 |
74 | /* Configure linenoise line completion library */
75 | /* Enable multiline editing. If not set, long commands will scroll within
76 | * single line.
77 | */
78 | linenoiseSetMultiLine(1);
79 |
80 | /* Tell linenoise where to get command completions and hints */
81 | linenoiseSetCompletionCallback(&esp_console_get_completion);
82 | linenoiseSetHintsCallback((linenoiseHintsCallback *)&esp_console_get_hint);
83 |
84 | /* Set command history size */
85 | linenoiseHistorySetMaxLen(100);
86 |
87 | #if CONFIG_STORE_HISTORY
88 | /* Load command history from filesystem */
89 | linenoiseHistoryLoad(HISTORY_PATH);
90 | #endif
91 |
92 | /* Register commands */
93 | esp_console_register_help_command();
94 | }
95 |
96 |
97 | void start_console(void)
98 | {
99 | /* Prompt to be printed before each line.
100 | * This can be customized, made dynamic, etc.
101 | */
102 | const char *prompt = LOG_COLOR_I "esp32> " LOG_RESET_COLOR;
103 |
104 | printf("\n"
105 | "ESP32 NAT ROUTER\n"
106 | "Type 'help' to get the list of commands.\n"
107 | "Use UP/DOWN arrows to navigate through command history.\n"
108 | "Press TAB when typing command name to auto-complete.\n");
109 |
110 | if (strlen(ssid) == 0)
111 | {
112 | printf("\n"
113 | "Unconfigured WiFi\n"
114 | "Configure using 'set_sta' and 'set_ap' and restart.\n");
115 | }
116 |
117 | /* Figure out if the terminal supports escape sequences */
118 | int probe_status = linenoiseProbe();
119 | if (probe_status)
120 | { /* zero indicates success */
121 | printf("\n"
122 | "Your terminal application does not support escape sequences.\n"
123 | "Line editing and history features are disabled.\n"
124 | "On Windows, try using Putty instead.\n");
125 | linenoiseSetDumbMode(1);
126 | #if CONFIG_LOG_COLORS
127 | /* Since the terminal doesn't support escape sequences,
128 | * don't use color codes in the prompt.
129 | */
130 | prompt = "esp32> ";
131 | #endif // CONFIG_LOG_COLORS
132 | }
133 |
134 | /* Main loop */
135 | while (true)
136 | {
137 | /* Get a line using linenoise.
138 | * The line is returned when ENTER is pressed.
139 | */
140 | char *line = linenoise(prompt);
141 | if (line == NULL)
142 | { /* Ignore empty lines */
143 | continue;
144 | }
145 | /* Add the command to the history */
146 | linenoiseHistoryAdd(line);
147 | #if CONFIG_STORE_HISTORY
148 | /* Save command history to filesystem */
149 | linenoiseHistorySave(HISTORY_PATH);
150 | #endif
151 |
152 | /* Try to run the command */
153 | int ret;
154 | esp_err_t err = esp_console_run(line, &ret);
155 | if (err == ESP_ERR_NOT_FOUND)
156 | {
157 | printf("Unrecognized command\n");
158 | }
159 | else if (err == ESP_ERR_INVALID_ARG)
160 | {
161 | // command was empty
162 | }
163 | else if (err == ESP_OK && ret != ESP_OK)
164 | {
165 | printf("Command returned non-zero error code: 0x%x (%s)\n", ret, esp_err_to_name(ret));
166 | }
167 | else if (err != ESP_OK)
168 | {
169 | printf("Internal error: %s\n", esp_err_to_name(err));
170 | }
171 | /* linenoise allocates line buffer on the heap, so need to free it */
172 | linenoiseFree(line);
173 | }
174 | }
--------------------------------------------------------------------------------
/components/console_handler/file_system.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #include "router_globals.h"
17 | #include "console_handler.h"
18 |
19 | static const char *TAG = "Console/file_system";
20 |
21 | /* Console command history can be stored to and loaded from a file.
22 | * The easiest way to do this is to use FATFS filesystem on top of
23 | * wear_levelling library.
24 | */
25 | #if CONFIG_STORE_HISTORY
26 |
27 | void initialize_filesystem(void)
28 | {
29 | static wl_handle_t wl_handle;
30 | const esp_vfs_fat_mount_config_t mount_config = {
31 | .max_files = 4,
32 | .format_if_mount_failed = true};
33 | esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(MOUNT_PATH, "storage", &mount_config, &wl_handle);
34 | if (err != ESP_OK)
35 | {
36 | ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
37 | return;
38 | }
39 | }
40 | #endif // CONFIG_STORE_HISTORY
--------------------------------------------------------------------------------
/components/console_handler/include/console_handler.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 |
16 | #define MOUNT_PATH "/data"
17 | #define HISTORY_PATH MOUNT_PATH "/history.txt"
18 |
19 | void initialize_console(void);
20 | void start_console(void);
21 |
22 | #ifdef __cplusplus
23 | }
24 | #endif
25 |
--------------------------------------------------------------------------------
/components/console_handler/include/file_system.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 |
16 | void initialize_filesystem(void);
17 |
18 | #ifdef __cplusplus
19 | }
20 | #endif
21 |
--------------------------------------------------------------------------------
/components/hardware_handler/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS hardware_handler.c led_handler.c
2 | button_handler.c
3 | INCLUDE_DIRS include
4 | REQUIRES cmd_router utils web_server)
--------------------------------------------------------------------------------
/components/hardware_handler/button_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #include "button_handler.h"
10 | #include "hardware_handler.h"
11 | #include "router_globals.h"
12 | #include "led_handler.h"
13 | #include "initialization.h"
14 | #include "utils.h"
15 | #include "nvm.h"
16 | #include "web_server.h"
17 |
18 |
19 | int menu_count = 0;
20 | bool IsMenuEnable = false;
21 |
22 |
23 | //-----------------------------------------------------------------------------
24 | void menu_count_reset(void)
25 | {
26 | menu_count = -1;
27 | }
28 |
29 |
30 | //-----------------------------------------------------------------------------
31 | void selected_menu_item(void)
32 | {
33 | switch (menu_count)
34 | {
35 | case 0:
36 | printf("selected menu mode\n");
37 | IsMenuEnable = true;
38 | break;
39 | case 1:
40 | printf("selected menu: 1\n");
41 | IsLedEnable = false;
42 | item_selected_success();
43 | break;
44 | case 2:
45 | printf("selected menu: 2\n");
46 | toggle_webserver();
47 | item_selected_success();
48 | break;
49 | case 3:
50 | printf("selected menu: 3\n");
51 | if (nvm_erase() == ESP_OK)
52 | {
53 | item_selected_success();
54 | vTaskDelay(2000 / portTICK_PERIOD_MS);
55 | restart();
56 | }
57 | break;
58 | default:
59 | break;
60 | }
61 | }
62 |
63 |
64 | //-----------------------------------------------------------------------------
65 | void button_task(void *pvParameters)
66 | {
67 | static float menu_reset_time_s = 0;
68 | while (1)
69 | {
70 | static float button_down_time_s = 0;
71 | vTaskDelay(100 / portTICK_PERIOD_MS);
72 | bool button_pressed = hardware_user_button_pressed();
73 | if (button_pressed)
74 | {
75 | if (button_down_time_s == 0)
76 | {
77 | printf("Button pressed!\n");
78 | menu_reset_time_s = 0;
79 | button_down_time_s = system_uptime_s();
80 | menu_reset_time_s = system_uptime_s();
81 | }
82 | else if (system_uptime_s() > (button_down_time_s + 3))
83 | {
84 | button_down_time_s += (60 * 60);
85 | selected_menu_item();
86 | menu_count_reset();
87 | }
88 | }
89 | else if ((system_uptime_s() > (menu_reset_time_s + 15)) && (IsMenuEnable))
90 | {
91 | printf("Button menu time out\n");
92 | menu_reset_time_s = 0;
93 | menu_count = 0;
94 | IsMenuEnable = false;
95 | }
96 | else if (button_down_time_s)
97 | {
98 | // printf("Button released!\n");
99 | button_down_time_s = 0;
100 | if (menu_count > 2 || !IsMenuEnable)
101 | {
102 | menu_count = 0;
103 | IsMenuEnable = false;
104 | }
105 | else
106 | {
107 | menu_count++;
108 | }
109 | printf("menu number : %d \n", menu_count);
110 | }
111 | }
112 | }
113 |
114 |
115 | //-----------------------------------------------------------------------------
116 | void start_button_task(void)
117 | {
118 | xTaskCreate(button_task, "Button_task", configMINIMAL_STACK_SIZE * 3, NULL, 1, NULL);
119 | }
120 |
121 | //-----------------------------------------------------------------------------
--------------------------------------------------------------------------------
/components/hardware_handler/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Component Makefile
3 | #
4 | # This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
5 | # this will take the sources in the src/ directory, compile them and link them into
6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
7 | # please read the SDK documents if you need to do this.
8 | #
9 |
10 | COMPONENT_ADD_INCLUDEDIRS := .
11 |
--------------------------------------------------------------------------------
/components/hardware_handler/hardware_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 |
11 | #include "hardware_handler.h"
12 | #include "utils.h"
13 | #include "led_handler.h"
14 | #include "button_handler.h"
15 | #include "router_globals.h"
16 |
17 | #define PIN_BUTTON (0)
18 | #define PIN_LED (2)
19 |
20 | static bool led_on = false;
21 |
22 |
23 | //-----------------------------------------------------------------------------
24 | bool hardware_user_button_pressed(void)
25 | {
26 | return !gpio_get_level(PIN_BUTTON);
27 | }
28 |
29 | //-----------------------------------------------------------------------------
30 | void hardware_turn_on_led(void)
31 | {
32 | gpio_set_level(PIN_LED, 1);
33 | led_on = true;
34 | }
35 |
36 | //-----------------------------------------------------------------------------
37 | void hardware_turn_off_led(void)
38 | {
39 | gpio_set_level(PIN_LED, 0);
40 | led_on = false;
41 | }
42 |
43 | //-----------------------------------------------------------------------------
44 | void hardware_toggle_led(void)
45 | {
46 | led_on = !led_on;
47 | gpio_set_level(PIN_LED, led_on);
48 | }
49 |
50 | //-----------------------------------------------------------------------------
51 | void hardware_init()
52 | {
53 | gpio_config_t io_conf;
54 | io_conf.pin_bit_mask = (1ULL << PIN_BUTTON);
55 | io_conf.mode = GPIO_MODE_INPUT;
56 | io_conf.intr_type = GPIO_INTR_DISABLE;
57 | io_conf.pull_up_en = 1;
58 | io_conf.pull_down_en = 0;
59 | gpio_config(&io_conf);
60 |
61 | io_conf.pin_bit_mask = (1ULL << PIN_LED);
62 | io_conf.mode = GPIO_MODE_OUTPUT;
63 | gpio_set_level(PIN_LED, led_on);
64 | gpio_config(&io_conf);
65 |
66 | start_button_task();
67 | start_led_status_task();
68 | }
69 |
--------------------------------------------------------------------------------
/components/hardware_handler/include/button_handler.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 |
16 | #include
17 | void start_button_task(void);
18 | extern int menu_count;
19 | extern bool IsMenuEnable;
20 |
21 | #ifdef __cplusplus
22 | }
23 | #endif
--------------------------------------------------------------------------------
/components/hardware_handler/include/hardware_handler.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #ifndef HARDWARE_HANDLER_H
9 | #define HARDWARE_HANDLER_H
10 |
11 | #endif
12 |
13 | #pragma once
14 |
15 | #ifdef __cplusplus
16 | extern "C"
17 | {
18 | #endif
19 |
20 | #include
21 | #include
22 |
23 | void hardware_init();
24 | bool hardware_user_button_pressed(void);
25 | void hardware_turn_on_led(void);
26 | void hardware_turn_off_led(void);
27 | void hardware_toggle_led(void);
28 |
29 | #ifdef __cplusplus
30 | }
31 | #endif
32 |
--------------------------------------------------------------------------------
/components/hardware_handler/include/led_handler.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 | #include "stdbool.h"
16 |
17 | extern bool IsLedEnable;
18 | void start_led_status_task(void);
19 | void item_selected_success(void);
20 |
21 | #ifdef __cplusplus
22 | }
23 | #endif
--------------------------------------------------------------------------------
/components/hardware_handler/led_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include "led_handler.h"
9 | #include "hardware_handler.h"
10 | #include "router_globals.h"
11 | #include "button_handler.h"
12 |
13 | //-----------------------------------------------------------------------------
14 | void item_selected_success(void)
15 | {
16 |
17 | for (int i = 0; i < 4; i++)
18 | {
19 | hardware_toggle_led();
20 | vTaskDelay(50 / portTICK_PERIOD_MS);
21 | hardware_toggle_led();
22 | vTaskDelay(50 / portTICK_PERIOD_MS);
23 | }
24 | IsMenuEnable = false;
25 | }
26 |
27 | //-----------------------------------------------------------------------------
28 | void led_status_task(void *pvParameters)
29 | {
30 | while (1)
31 | {
32 | if (IsLedEnable || IsMenuEnable)
33 | {
34 | if (IsMenuEnable)
35 | {
36 | hardware_turn_on_led();
37 |
38 | // Blinking pattern for menu mode
39 | for (int i = 0; i < menu_count; i++)
40 | {
41 | hardware_toggle_led();
42 | vTaskDelay(100 / portTICK_PERIOD_MS);
43 | hardware_toggle_led();
44 | vTaskDelay(200 / portTICK_PERIOD_MS);
45 | }
46 | }
47 | else
48 | {
49 | (ap_connect) ? hardware_turn_on_led() : hardware_turn_off_led();
50 |
51 | // Blinking pattern for client mode
52 | for (int i = 0; i < connect_count; i++)
53 | {
54 | hardware_toggle_led();
55 | vTaskDelay(50 / portTICK_PERIOD_MS);
56 | hardware_toggle_led();
57 | vTaskDelay(50 / portTICK_PERIOD_MS);
58 | }
59 | }
60 |
61 | vTaskDelay(1000 / portTICK_PERIOD_MS);
62 | }
63 | else
64 | {
65 | hardware_turn_off_led();
66 | vTaskDelay(100 / portTICK_PERIOD_MS);
67 | }
68 | }
69 | }
70 |
71 | //-----------------------------------------------------------------------------
72 | void start_led_status_task(void)
73 | {
74 | xTaskCreate(led_status_task, "led_status_task", configMINIMAL_STACK_SIZE * 3, NULL, 1, NULL);
75 | }
76 |
77 | //-----------------------------------------------------------------------------
--------------------------------------------------------------------------------
/components/ota_handler/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS "ota_handler.c"
2 | INCLUDE_DIRS include
3 | REQUIRES esp_http_server app_update cmd_router esp_eth)
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/components/ota_handler/README.md:
--------------------------------------------------------------------------------
1 | # ESP32-NAT Router +
2 |
3 | ## OTA Handler Component
4 |
5 | The OTA Handler is a firmware updater, that allows you to update ESP32 device over the air. It uses the HTTP POST method to upload the new firmware, making it easy to update devices without needing physical access.
6 |
7 | ## Usage
8 |
9 | To use the OTA Handler, you need to include the `ota_update_handler` function in your code. Here's an example of how to use it:
10 |
11 | ```c
12 | #include "ota_handler.h"
13 |
14 | // Run initial in main()
15 | ota_update_init()
16 |
17 | ................
18 | //send Uploding post request to this function
19 | ota_update_handler(req);
20 | ```
21 |
22 | In `CMakeLists.txt` update `REQUIRES ota_handler`
23 |
24 | The `ota_update_handler` function checks if the firmware binary is present in the request body, verifies that it's valid, and updates the firmware if everything is correct. If the update is successful, it sends a response indicating that the firmware update was successful.
25 |
26 | In addition to the `ota_update_task(void *Param)` function, the OTA Handler also provides a task that can be used for continuous checking. If you need to perform continuous checking for firmware updates and also if problem occur it will restore back to old version.
27 |
28 | ## Credit's
29 |
30 | - The OTA update code was inspired by [@Kecin Wolfe](https://gitlab.com/kevinwolfe/esp32_template)'s implementation.
31 |
--------------------------------------------------------------------------------
/components/ota_handler/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Component Makefile
3 | #
4 | # This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
5 | # this will take the sources in the src/ directory, compile them and link them into
6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
7 | # please read the SDK documents if you need to do this.
8 | #
9 |
10 | COMPONENT_ADD_INCLUDEDIRS := .
11 |
--------------------------------------------------------------------------------
/components/ota_handler/include/ota_handler.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #pragma once
9 |
10 | #ifdef __cplusplus
11 | extern "C"
12 | {
13 | #endif
14 | #include
15 | #include
16 | #include "esp_http_server.h"
17 |
18 | void ota_update_init(void);
19 | esp_err_t ota_update_handler(httpd_req_t *req);
20 |
21 | #ifdef __cplusplus
22 | }
23 | #endif
--------------------------------------------------------------------------------
/components/ota_handler/ota_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include "nvs_flash.h"
15 | #include "esp_netif.h"
16 | #include "esp_eth.h"
17 | #include "esp_ota_ops.h"
18 | #include "esp_flash_partitions.h"
19 | #include "esp_partition.h"
20 | #include "router_globals.h"
21 | #include "ota_handler.h"
22 |
23 | static const char *TAG = "OTA handler";
24 |
25 | //-----------------------------------------------------------------------------
26 | esp_err_t ota_update_handler(httpd_req_t *req)
27 | {
28 |
29 | esp_err_t err;
30 | char buf[256];
31 | int remaining = req->content_len;
32 | esp_ota_handle_t update_handle = 0;
33 | const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
34 | const esp_partition_t *running_partition = esp_ota_get_running_partition();
35 |
36 | if (!update_partition)
37 | {
38 | ESP_LOGE(TAG, "Failed to get update partition");
39 | return ESP_FAIL;
40 | }
41 |
42 | ESP_LOGI(TAG, "Writing partition: type %d, subtype %d, offset 0x%08lx\n",
43 | update_partition->type, update_partition->subtype, update_partition->address);
44 | ESP_LOGI(TAG, "Running partition: type %d, subtype %d, offset 0x%08lx\n",
45 | running_partition->type, running_partition->subtype, running_partition->address);
46 |
47 | err = esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle);
48 | if (err != ESP_OK)
49 | {
50 | ESP_LOGE(TAG, "Failed to begin OTA (%s)", esp_err_to_name(err));
51 | return err;
52 | }
53 |
54 | while (remaining > 0)
55 | {
56 | int ret = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)));
57 | if (ret <= 0)
58 | {
59 | if (ret == HTTPD_SOCK_ERR_TIMEOUT)
60 | {
61 | continue;
62 | }
63 | ESP_LOGE(TAG, "Failed to receive OTA data (%s)", esp_err_to_name(ret));
64 | esp_ota_abort(update_handle);
65 | return ESP_FAIL;
66 | }
67 | remaining -= ret;
68 | err = esp_ota_write(update_handle, buf, ret);
69 | if (err != ESP_OK)
70 | {
71 | ESP_LOGE(TAG, "Failed to write OTA data (%s)", esp_err_to_name(err));
72 | esp_ota_abort(update_handle);
73 | return ESP_FAIL;
74 | }
75 | }
76 |
77 | err = esp_ota_end(update_handle);
78 | if (err != ESP_OK)
79 | {
80 | ESP_LOGE(TAG, "Failed to end OTA (%s)", esp_err_to_name(err));
81 | esp_ota_abort(update_handle);
82 | return ESP_FAIL;
83 | }
84 |
85 | err = esp_ota_set_boot_partition(update_partition);
86 | if (err != ESP_OK)
87 | {
88 | ESP_LOGE(TAG, "Failed to set boot partition (%s)", esp_err_to_name(err));
89 | esp_ota_abort(update_handle);
90 | return ESP_FAIL;
91 | }
92 |
93 | ESP_LOGI(TAG, "OTA Success! Rebooting\n");
94 |
95 | httpd_resp_set_status(req, HTTPD_200);
96 | httpd_resp_send(req, NULL, 0);
97 |
98 | vTaskDelay(2000 / portTICK_PERIOD_MS);
99 | esp_restart();
100 |
101 | return ESP_OK;
102 | }
103 |
104 | //-----------------------------------------------------------------------------
105 | /* handling ota update process */
106 | void ota_update_task(void *Param)
107 | {
108 | const esp_partition_t *running = esp_ota_get_running_partition();
109 | esp_ota_img_states_t ota_state;
110 | if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK)
111 | {
112 | if (ota_state == ESP_OTA_IMG_PENDING_VERIFY)
113 | {
114 | // Validate image some how, then call:
115 | esp_ota_mark_app_valid_cancel_rollback();
116 | // If needed: esp_ota_mark_app_invalid_rollback_and_reboot();
117 | }
118 | }
119 |
120 | const uint32_t task_delay_ms = 10;
121 | while (1)
122 | {
123 | vTaskDelay(task_delay_ms / portTICK_PERIOD_MS);
124 | }
125 | }
126 |
127 | void ota_update_init(void)
128 | {
129 | xTaskCreate(ota_update_task, "ota_update_task", configMINIMAL_STACK_SIZE * 3, NULL, 1, NULL);
130 | }
--------------------------------------------------------------------------------
/components/router_handler/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS router_handler.c
2 |
3 | INCLUDE_DIRS include
4 | REQUIRES cmd_router utils)
--------------------------------------------------------------------------------
/components/router_handler/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Component Makefile
3 | #
4 | # This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
5 | # this will take the sources in the src/ directory, compile them and link them into
6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
7 | # please read the SDK documents if you need to do this.
8 | #
9 |
10 | COMPONENT_ADD_INCLUDEDIRS := .
11 |
--------------------------------------------------------------------------------
/components/router_handler/include/router_handler.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 |
16 | #include
17 | esp_err_t get_portmap_tab();
18 | esp_err_t apply_portmap_tab();
19 | esp_err_t delete_portmap_tab();
20 |
21 | #ifdef __cplusplus
22 | }
23 | #endif
24 |
--------------------------------------------------------------------------------
/components/router_handler/router_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "router_globals.h"
26 | #include "initialization.h"
27 | #include "router_handler.h"
28 |
29 |
30 | static const char *TAG = "Router_handler";
31 |
32 | struct portmap_table_entry
33 | {
34 | u32_t daddr;
35 | u16_t mport;
36 | u16_t dport;
37 | u8_t proto;
38 | u8_t valid;
39 | };
40 | struct portmap_table_entry portmap_tab[IP_PORTMAP_MAX];
41 |
42 |
43 | //-----------------------------------------------------------------------------
44 | esp_err_t apply_portmap_tab()
45 | {
46 | for (int i = 0; i < IP_PORTMAP_MAX; i++)
47 | {
48 | if (portmap_tab[i].valid)
49 | {
50 | ip_portmap_add(portmap_tab[i].proto, my_ip, portmap_tab[i].mport, portmap_tab[i].daddr, portmap_tab[i].dport);
51 | }
52 | }
53 | return ESP_OK;
54 | }
55 |
56 |
57 | //-----------------------------------------------------------------------------
58 | esp_err_t delete_portmap_tab()
59 | {
60 | for (int i = 0; i < IP_PORTMAP_MAX; i++)
61 | {
62 | if (portmap_tab[i].valid)
63 | {
64 | ip_portmap_remove(portmap_tab[i].proto, portmap_tab[i].mport);
65 | }
66 | }
67 | return ESP_OK;
68 | }
69 |
70 |
71 | //-----------------------------------------------------------------------------
72 | void print_portmap_tab()
73 | {
74 | for (int i = 0; i < IP_PORTMAP_MAX; i++)
75 | {
76 | if (portmap_tab[i].valid)
77 | {
78 | printf("%s", portmap_tab[i].proto == PROTO_TCP ? "TCP " : "UDP ");
79 | ip4_addr_t addr;
80 | addr.addr = my_ip;
81 | printf(IPSTR ":%d -> ", IP2STR(&addr), portmap_tab[i].mport);
82 | addr.addr = portmap_tab[i].daddr;
83 | printf(IPSTR ":%d\n", IP2STR(&addr), portmap_tab[i].dport);
84 | }
85 | }
86 | }
87 |
88 |
89 | //-----------------------------------------------------------------------------
90 | esp_err_t get_portmap_tab()
91 | {
92 | esp_err_t err;
93 | nvs_handle_t nvs;
94 | size_t len;
95 |
96 | err = nvs_open(PARAM_NAMESPACE, NVS_READWRITE, &nvs);
97 | if (err != ESP_OK)
98 | {
99 | return err;
100 | }
101 | err = nvs_get_blob(nvs, "portmap_tab", NULL, &len);
102 | if (err == ESP_OK)
103 | {
104 | if (len != sizeof(portmap_tab))
105 | {
106 | err = ESP_ERR_NVS_INVALID_LENGTH;
107 | }
108 | else
109 | {
110 | err = nvs_get_blob(nvs, "portmap_tab", portmap_tab, &len);
111 | if (err != ESP_OK)
112 | {
113 | memset(portmap_tab, 0, sizeof(portmap_tab));
114 | }
115 | }
116 | }
117 | nvs_close(nvs);
118 |
119 | return err;
120 | }
121 |
122 |
123 | //-----------------------------------------------------------------------------
124 | esp_err_t add_portmap(u8_t proto, u16_t mport, u32_t daddr, u16_t dport)
125 | {
126 | esp_err_t err;
127 | nvs_handle_t nvs;
128 |
129 | for (int i = 0; i < IP_PORTMAP_MAX; i++)
130 | {
131 | if (!portmap_tab[i].valid)
132 | {
133 | portmap_tab[i].proto = proto;
134 | portmap_tab[i].mport = mport;
135 | portmap_tab[i].daddr = daddr;
136 | portmap_tab[i].dport = dport;
137 | portmap_tab[i].valid = 1;
138 |
139 | err = nvs_open(PARAM_NAMESPACE, NVS_READWRITE, &nvs);
140 | if (err != ESP_OK)
141 | {
142 | return err;
143 | }
144 | err = nvs_set_blob(nvs, "portmap_tab", portmap_tab, sizeof(portmap_tab));
145 | if (err == ESP_OK)
146 | {
147 | err = nvs_commit(nvs);
148 | if (err == ESP_OK)
149 | {
150 | ESP_LOGI(TAG, "New portmap table stored.");
151 | }
152 | }
153 | nvs_close(nvs);
154 |
155 | ip_portmap_add(proto, my_ip, mport, daddr, dport);
156 |
157 | return ESP_OK;
158 | }
159 | }
160 | return ESP_ERR_NO_MEM;
161 | }
162 |
163 |
164 | //-----------------------------------------------------------------------------
165 | esp_err_t del_portmap(u8_t proto, u16_t mport)
166 | {
167 | esp_err_t err;
168 | nvs_handle_t nvs;
169 |
170 | for (int i = 0; i < IP_PORTMAP_MAX; i++)
171 | {
172 | if (portmap_tab[i].valid && portmap_tab[i].mport == mport && portmap_tab[i].proto == proto)
173 | {
174 | portmap_tab[i].valid = 0;
175 |
176 | err = nvs_open(PARAM_NAMESPACE, NVS_READWRITE, &nvs);
177 | if (err != ESP_OK)
178 | {
179 | return err;
180 | }
181 | err = nvs_set_blob(nvs, "portmap_tab", portmap_tab, sizeof(portmap_tab));
182 | if (err == ESP_OK)
183 | {
184 | err = nvs_commit(nvs);
185 | if (err == ESP_OK)
186 | {
187 | ESP_LOGI(TAG, "New portmap table stored.");
188 | }
189 | }
190 | nvs_close(nvs);
191 |
192 | ip_portmap_remove(proto, mport);
193 | return ESP_OK;
194 | }
195 | }
196 | return ESP_OK;
197 | }
198 |
199 | //-----------------------------------------------------------------------------
--------------------------------------------------------------------------------
/components/utils/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS utils.c initialization.c nvm.c mac_generator.c mac_filter.c
2 |
3 | INCLUDE_DIRS include
4 | REQUIRES cmd_router cmd_nvs nvs_flash json esp_http_server
5 | driver esp_hw_support esp_timer efuse)
--------------------------------------------------------------------------------
/components/utils/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Component Makefile
3 | #
4 | # This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
5 | # this will take the sources in the src/ directory, compile them and link them into
6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
7 | # please read the SDK documents if you need to do this.
8 | #
9 |
10 | COMPONENT_ADD_INCLUDEDIRS := .
11 |
--------------------------------------------------------------------------------
/components/utils/include/initialization.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 |
16 | #include
17 | #include
18 | #include "esp_err.h"
19 | #define MAX_LOGIN_ATTEMPTS (5)
20 | #define LOCK_OUT_TIME_MINUTES (1) // MINUTES
21 | #define DEFAULT_AP_IP "192.168.4.1"
22 | #define DEFAULT_DNS1 "1.1.1.1"
23 | #define DEFAULT_ADMIN_USERNAME "admin"
24 | #define DEFAULT_ADMIN_PASSWORD "123456789"
25 | #define DEFAULT_SSID "ESP32_NAT_Router +"
26 |
27 | extern bool IsLedEnable, IsWebServerEnable, IsCustomDnsEnable,
28 | IsRandomizeMacEnable, IsDarkModeEnable, IsWifiAuthFail, IsMacFilterEnable, IsAllowList;
29 |
30 | extern char *customDNSip, *authUsername,
31 | *authPass, *macAp, *dnsIP, *cache;
32 | extern char currentMAC[18];
33 | extern int max_login_attempts, lock_out_time_minutes;
34 | esp_err_t parms_init();
35 |
36 | typedef struct
37 | {
38 | char *username;
39 | char *password;
40 | } basic_auth_info_t;
41 |
42 | extern basic_auth_info_t auth_info;
43 |
44 | #ifdef __cplusplus
45 | }
46 | #endif
47 |
--------------------------------------------------------------------------------
/components/utils/include/mac_filter.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 | #include
16 | #include
17 | #include
18 |
19 | #define MAX_MAC_ADDRESSES 10
20 | #define NVS_KEY "stored_macs"
21 |
22 |
23 | esp_err_t store_mac_address_in_nvs(const char *macAddress);
24 | esp_err_t remove_mac_address_from_nvs(const char *macAddress);
25 | bool check_mac_address_in_nvs(const char *macAddress);
26 | cJSON *retrieve_mac_addresses_as_json();
27 | void mac_filter(const uint8_t mac[6],uint8_t aid);
28 | void refresh_mac_filter();
29 |
30 | #ifdef __cplusplus
31 | }
32 | #endif
33 |
--------------------------------------------------------------------------------
/components/utils/include/mac_generator.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 |
16 | void custom_mac_generator(void);
17 |
18 | #ifdef __cplusplus
19 | }
20 | #endif
21 |
--------------------------------------------------------------------------------
/components/utils/include/nvm.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 |
16 | #include "esp_err.h"
17 |
18 | esp_err_t nvm_erase(void);
19 | esp_err_t nvm_set_bool(const char *key, bool value);
20 | void initialize_nvs(void);
21 |
22 | #ifdef __cplusplus
23 | }
24 | #endif
25 |
--------------------------------------------------------------------------------
/components/utils/include/utils.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 |
16 | #include
17 | #include
18 | #include
19 |
20 | #ifdef ICACHE_FLASH
21 | #define ICACHE_FLASH_ATTR __attribute__((section(".irom0.text")))
22 | #define ICACHE_RODATA_ATTR __attribute__((section(".irom.text")))
23 | #else
24 | #define ICACHE_FLASH_ATTR
25 | #define ICACHE_RODATA_ATTR
26 | #endif /* ICACHE_FLASH */
27 |
28 | float system_uptime_s(void);
29 | void restart(void);
30 |
31 | bool is_valid_ip(const char *ip_str);
32 | bool str_to_bool(const char *key);
33 | int bool_to_int(bool value);
34 | bool word_check(const char *str, const char *word);
35 | char *html_escape(const char *src);
36 |
37 | #ifdef __cplusplus
38 | }
39 | #endif
40 |
--------------------------------------------------------------------------------
/components/utils/initialization.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include "initialization.h"
12 | #include "router_globals.h"
13 | #include "mac_generator.h"
14 |
15 | static const char *TAG = "utils/initialization";
16 |
17 | bool IsLedEnable = true, IsWebServerEnable = true,
18 | IsCustomDnsEnable = false, IsRandomizeMacEnable = false,
19 | IsDarkModeEnable = false, IsWifiAuthFail = false,
20 | IsMacFilterEnable = false, IsAllowList = false;
21 |
22 | char *ssid, *ent_username, *ent_identity,
23 | *passwd, *static_ip, *subnet_mask, *gateway_addr,
24 | *ap_ssid, *ap_passwd, *ap_ip, *customDNSip, *authUsername,
25 | *authPass, *macAp, *dnsIP = "";
26 |
27 | char currentMAC[18];
28 |
29 | //-----------------------------------------------------------------------------
30 | esp_err_t IRAM_ATTR parms_init()
31 | {
32 | int webServer = 1, ledEnable = 1, customDnsEnable = 0,
33 | darkModeEnable = 0, randomizeMac = 0, isMacFilterEnable = 0, isAllowList = 0;
34 |
35 | // ESP_LOGW(TAG, "initialization Started");
36 | get_config_param_str("ssid", &ssid);
37 | get_config_param_str("passwd", &passwd);
38 | get_config_param_str("ent_username", &ent_username);
39 | get_config_param_str("ent_identity", &ent_identity);
40 | get_config_param_str("ap_ssid", &ap_ssid);
41 | get_config_param_str("ap_passwd", &ap_passwd);
42 | get_config_param_str("static_ip", &static_ip);
43 | get_config_param_str("subnet_mask", &subnet_mask);
44 | get_config_param_str("gateway_addr", &gateway_addr);
45 | get_config_param_str("custom_dns_ip", &customDNSip);
46 | get_config_param_str("ap_ip", &ap_ip);
47 | get_config_param_str("auth_username", &authUsername);
48 | // get_config_param_str("mac_ap", &macAp);
49 | get_config_param_str("auth_password", &authPass);
50 |
51 | get_config_param_int("web_server", &webServer);
52 | get_config_param_int("led_enable", &ledEnable);
53 | get_config_param_int("custom_dns", &customDnsEnable);
54 | get_config_param_int("dark_mode", &darkModeEnable);
55 | get_config_param_int("randomize_mac", &randomizeMac);
56 | get_config_param_int("max_login_attempts", &max_login_attempts);
57 | get_config_param_int("lock_out_time_minutes", &lock_out_time_minutes);
58 | get_config_param_int("mac_Filter", &isMacFilterEnable);
59 | get_config_param_int("Is_allow_list", &isAllowList);
60 |
61 | ap_ssid = (ap_ssid != NULL) ? ap_ssid : DEFAULT_SSID;
62 | ap_passwd = (ap_passwd != NULL) ? ap_passwd : "";
63 | ssid = (ssid != NULL) ? ssid : "";
64 | passwd = (passwd != NULL) ? passwd : "";
65 | ent_username = (ent_username != NULL) ? ent_username : "";
66 | ent_identity = (ent_identity != NULL) ? ent_identity : "";
67 |
68 | static_ip = (static_ip != NULL) ? static_ip : "";
69 | subnet_mask = (subnet_mask != NULL) ? subnet_mask : "";
70 | gateway_addr = (gateway_addr != NULL) ? gateway_addr : "";
71 |
72 | ap_ip = (ap_ip != NULL) ? ap_ip : DEFAULT_AP_IP;
73 | customDNSip = (customDNSip != NULL) ? customDNSip : DEFAULT_DNS1;
74 |
75 | authUsername = (authUsername != NULL) ? authUsername : DEFAULT_ADMIN_USERNAME;
76 | authPass = (authPass != NULL) ? authPass : DEFAULT_ADMIN_PASSWORD;
77 | max_login_attempts = (max_login_attempts <= 0) ? MAX_LOGIN_ATTEMPTS : max_login_attempts;
78 | lock_out_time_minutes = (lock_out_time_minutes <= 0) ? LOCK_OUT_TIME_MINUTES : lock_out_time_minutes;
79 |
80 | IsWebServerEnable = (webServer != 0);
81 | IsLedEnable = (ledEnable != 0);
82 | IsCustomDnsEnable = (customDnsEnable != 0);
83 | IsDarkModeEnable = (darkModeEnable != 0);
84 | IsRandomizeMacEnable = (randomizeMac != 0);
85 | IsMacFilterEnable = (isMacFilterEnable != 0);
86 | IsAllowList = (isAllowList != 0);
87 | auth_info.username = authUsername;
88 | auth_info.password = authPass;
89 |
90 | // if (IsCustomDnsEnable)
91 | // {
92 | // if (strcmp(customDNSip, "default") == 0)
93 | // {
94 | // customDNSip = DEFAULT_DNS1;
95 | // }
96 | // }
97 |
98 | macAp = currentMAC; //(macAp != NULL) ? macAp : currentMAC;
99 |
100 | ESP_LOGI(TAG, "Initialization complected");
101 | return ESP_OK;
102 | }
103 |
--------------------------------------------------------------------------------
/components/utils/mac_filter.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | * @license
4 | * this software licensed under MIT
5 | *
6 | *
7 | */
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include "utils.h"
18 | #include "esp_efuse.h"
19 | #include "esp_system.h"
20 | #include "esp_mac.h"
21 | #include "esp_netif.h"
22 | #include "esp_wifi.h"
23 |
24 | #include "mac_filter.h"
25 | #include "initialization.h"
26 |
27 |
28 | bool check_mac_address_in_nvs(const char *macAddress) {
29 | cJSON *json = retrieve_mac_addresses_as_json();
30 | if (json == NULL) return false;
31 |
32 | int numMacs = cJSON_GetArraySize(json);
33 | for (int i = 0; i < numMacs; i++) {
34 | if (strcmp(cJSON_GetArrayItem(json, i)->valuestring, macAddress) == 0) {
35 | cJSON_Delete(json);
36 | return true;
37 | }
38 | }
39 |
40 | cJSON_Delete(json);
41 | return false;
42 | }
43 |
44 | //-----------------------------------------------------------------------------
45 | void mac_filter(const uint8_t mac[6], uint8_t aid) {
46 | char mac_address[18];
47 | sprintf(mac_address, MACSTR, MAC2STR(mac));
48 | if (IsMacFilterEnable) {
49 | if ((IsAllowList && !check_mac_address_in_nvs(mac_address)) ||
50 | (!IsAllowList && check_mac_address_in_nvs(mac_address))) {
51 | ESP_LOGI("MAC Filter","MAC Address %s not allowed, disconnecting...\n", IsAllowList ? "NOT found in Allow List" : "found in Deny List");
52 | esp_wifi_deauth_sta(aid);
53 | }
54 | }
55 | }
56 |
57 | //-----------------------------------------------------------------------------
58 | esp_err_t check_in_filter_list(const uint8_t mac[6]) {
59 | uint16_t aid;
60 | esp_err_t err = esp_wifi_ap_get_sta_aid(mac, &aid);
61 | if (err == ESP_OK) {
62 | mac_filter(mac, aid);
63 | } else {
64 | printf("Failed to get AID for MAC address\n");
65 | }
66 | return err;
67 | }
68 |
69 | //-----------------------------------------------------------------------------
70 | void refresh_mac_filter() {
71 | wifi_sta_list_t wifi_sta_list;
72 | // Get the list of connected stations
73 | ESP_ERROR_CHECK(esp_wifi_ap_get_sta_list(&wifi_sta_list));
74 |
75 | for (int i = 0; i < wifi_sta_list.num; i++) {
76 | wifi_sta_info_t station = wifi_sta_list.sta[i];
77 | esp_err_t result = check_in_filter_list(station.mac);
78 | if (result != ESP_OK) {
79 | ESP_LOGE("MAC_FILTER", "Error processing MAC address at index %d", i);
80 | }
81 | }
82 | }
83 |
84 | //-----------------------------------------------------------------------------
--------------------------------------------------------------------------------
/components/utils/mac_generator.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include "utils.h"
16 | #include "esp_efuse.h"
17 | #include "esp_system.h"
18 | #include "esp_mac.h"
19 | #include "esp_netif.h"
20 | #include "esp_wifi.h"
21 |
22 | #include "router_globals.h"
23 | #include "initialization.h"
24 | #include "mac_generator.h"
25 |
26 | static const char *TAG = "utils/MAC Generator";
27 |
28 | bool esp_base_mac_addr_check(uint8_t *mac)
29 | {
30 | // Check if MAC address is all zeros or all ones
31 | for (int i = 0; i < 6; i++)
32 | {
33 | if (mac[i] != 0x00 && mac[i] != 0xff)
34 | {
35 | return false;
36 | }
37 | }
38 | return true;
39 | }
40 |
41 | void custom_mac_generator(void)
42 | {
43 | uint8_t default_mac_addr[6] = {0};
44 | esp_err_t err = esp_efuse_mac_get_default(default_mac_addr);
45 | if (err != ESP_OK)
46 | {
47 | ESP_LOGE(TAG, "Failed to read default MAC address");
48 | return;
49 | }
50 | if (IsRandomizeMacEnable)
51 | {
52 | uint8_t random_mac_addr[6];
53 | bool is_valid_mac = false;
54 | memcpy(random_mac_addr, default_mac_addr, sizeof(default_mac_addr));
55 | while (!is_valid_mac)
56 | {
57 | for (int i = 1; i < 6; i++)
58 | {
59 | random_mac_addr[i] = esp_random() % 256;
60 | }
61 | // Check if the random MAC address is already in use
62 | if (!esp_base_mac_addr_check(random_mac_addr))
63 | {
64 | is_valid_mac = true;
65 | }
66 | }
67 | // Set the new MAC address with the first byte unchanged
68 | err = esp_base_mac_addr_set(random_mac_addr);
69 | if (err != ESP_OK)
70 | {
71 | ESP_LOGE(TAG, "Failed to set random MAC address");
72 | return;
73 | }
74 | uint8_t read_mac_addr[6] = {0};
75 | err = esp_base_mac_addr_get(read_mac_addr);
76 | if (err != ESP_OK)
77 | {
78 | ESP_LOGE(TAG, "Failed to read MAC address");
79 | return;
80 | }
81 | if (memcmp(read_mac_addr, random_mac_addr, 6) == 0)
82 | {
83 | sprintf(currentMAC, MACSTR, MAC2STR(random_mac_addr));
84 | }
85 | }
86 | else
87 | {
88 | sprintf(currentMAC, MACSTR, MAC2STR(default_mac_addr));
89 | }
90 | ESP_LOGI(TAG, "Setting random MAC address: %s", currentMAC);
91 | }
92 |
--------------------------------------------------------------------------------
/components/utils/nvm.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include "esp_err.h"
14 | #include
15 |
16 | #include "nvm.h"
17 | #include "router_globals.h"
18 | #include "utils.h"
19 | #include "mac_filter.h"
20 |
21 | static const char *TAG = "utils/nvm";
22 |
23 | void initialize_nvs(void)
24 | {
25 | esp_err_t err = nvs_flash_init();
26 | if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
27 | {
28 | ESP_ERROR_CHECK(nvs_flash_erase());
29 | err = nvs_flash_init();
30 | }
31 | ESP_ERROR_CHECK(err);
32 | }
33 |
34 | //-----------------------------------------------------------------------------
35 | esp_err_t nvm_set_bool(const char *key, bool value)
36 | {
37 |
38 | nvs_handle handle;
39 | error_t err = nvs_open(PARAM_NAMESPACE, NVS_READWRITE, &handle);
40 | if (err != ESP_OK)
41 | {
42 | ESP_LOGI(TAG, "NVS open error");
43 | return ESP_FAIL;
44 | }
45 | return nvs_set_i32(handle, key, bool_to_int(value));
46 | }
47 |
48 | //-----------------------------------------------------------------------------
49 | esp_err_t nvm_erase(void)
50 | {
51 | nvs_handle_t nvs_handle;
52 | esp_err_t err = nvs_open(PARAM_NAMESPACE, NVS_READWRITE, &nvs_handle);
53 | if (err != ESP_OK)
54 | {
55 | ESP_LOGI(TAG, "NVS open error");
56 | return ESP_FAIL;
57 | }
58 | err = nvs_erase_all(nvs_handle);
59 | if (err != ESP_OK)
60 | {
61 | ESP_LOGI(TAG, "NVS Erase all error");
62 | return ESP_FAIL;
63 | }
64 | err = nvs_commit(nvs_handle);
65 | if (err != ESP_OK)
66 | {
67 | return ESP_FAIL;
68 | }
69 | nvs_close(nvs_handle);
70 | return ESP_OK;
71 | }
72 |
73 | //-----------------------------------------------------------------------------
74 | cJSON *retrieve_mac_addresses_as_json() {
75 | nvs_handle_t handle;
76 | esp_err_t err = nvs_open(PARAM_NAMESPACE, NVS_READONLY, &handle);
77 | if (err != ESP_OK) {
78 | return NULL;
79 | }
80 |
81 | size_t required_size;
82 | err = nvs_get_str(handle, NVS_KEY, NULL, &required_size);
83 | if (err != ESP_OK || required_size == 0) {
84 | nvs_close(handle);
85 | return NULL;
86 | }
87 |
88 | char *buffer = malloc(required_size);
89 | if (buffer == NULL) {
90 | nvs_close(handle);
91 | return NULL;
92 | }
93 |
94 | err = nvs_get_str(handle, NVS_KEY, buffer, &required_size);
95 | if (err != ESP_OK) {
96 | free(buffer);
97 | nvs_close(handle);
98 | return NULL;
99 | }
100 |
101 | cJSON *json = cJSON_Parse(buffer);
102 | free(buffer);
103 | nvs_close(handle);
104 | return json;
105 | }
106 |
107 | //-----------------------------------------------------------------------------
108 | esp_err_t save_mac_addresses_as_json(cJSON *json) {
109 | nvs_handle_t handle;
110 | esp_err_t err = nvs_open(PARAM_NAMESPACE, NVS_READWRITE, &handle);
111 | if (err != ESP_OK) {
112 | cJSON_Delete(json);
113 | return err;
114 | }
115 |
116 | char *serialized = cJSON_Print(json);
117 | if (serialized == NULL) {
118 | cJSON_Delete(json);
119 | nvs_close(handle);
120 | return ESP_ERR_NO_MEM;
121 | }
122 |
123 | err = nvs_set_str(handle, NVS_KEY, serialized);
124 |
125 | ESP_LOGI("MACS ARE","%s",serialized);
126 | free(serialized);
127 | nvs_close(handle);
128 | return err;
129 | }
130 |
131 | //-----------------------------------------------------------------------------
132 | esp_err_t store_mac_address_in_nvs(const char *macAddress) {
133 | cJSON *json = retrieve_mac_addresses_as_json();
134 | if (json == NULL) {
135 | json = cJSON_CreateArray();
136 | }
137 |
138 | int numMacs = cJSON_GetArraySize(json);
139 | if (numMacs >= MAX_MAC_ADDRESSES) {
140 | cJSON_Delete(json);
141 | return ESP_ERR_NO_MEM;
142 | }
143 |
144 | for (int i = 0; i < numMacs; i++) {
145 | const char *storedMac = cJSON_GetArrayItem(json, i)->valuestring;
146 | if (strcmp(storedMac, macAddress) == 0) {
147 | cJSON_Delete(json);
148 | return ESP_OK;
149 | }
150 | }
151 |
152 | cJSON_AddItemToArray(json, cJSON_CreateString(macAddress));
153 |
154 | esp_err_t err = save_mac_addresses_as_json(json);
155 | cJSON_Delete(json);
156 | return err;
157 | }
158 |
159 | //-----------------------------------------------------------------------------
160 | esp_err_t remove_mac_address_from_nvs(const char *macAddress) {
161 | cJSON *json = retrieve_mac_addresses_as_json();
162 | if (json == NULL) {
163 | return ESP_ERR_NVS_NOT_FOUND;
164 | }
165 |
166 | int numMacs = cJSON_GetArraySize(json);
167 | for (int i = 0; i < numMacs; i++) {
168 | const char *storedMac = cJSON_GetArrayItem(json, i)->valuestring;
169 | if (strcmp(storedMac, macAddress) == 0) {
170 | cJSON_DeleteItemFromArray(json, i);
171 |
172 | esp_err_t err = save_mac_addresses_as_json(json);
173 | cJSON_Delete(json);
174 | return err;
175 | }
176 | }
177 | cJSON_Delete(json);
178 | return ESP_ERR_NOT_FOUND;
179 | }
180 |
181 | //-----------------------------------------------------------------------------
--------------------------------------------------------------------------------
/components/utils/utils.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "esp_timer.h"
13 | #include
14 | #include
15 | #include "initialization.h"
16 | #include "router_globals.h"
17 | #include "utils.h"
18 | #include "esp_efuse.h"
19 | #include "esp_system.h"
20 | #include "esp_mac.h"
21 | #include "esp_netif.h"
22 | #include "esp_wifi.h"
23 |
24 | // static const char *TAG = "components/utils";
25 |
26 | //-----------------------------------------------------------------------------
27 | bool word_check(const char *str, const char *word)
28 | {
29 | return (strstr(str, word) != NULL);
30 | }
31 |
32 | //-----------------------------------------------------------------------------
33 | int bool_to_int(bool value)
34 | {
35 | return value ? 1 : 0;
36 | }
37 |
38 | //-----------------------------------------------------------------------------
39 | bool str_to_bool(const char *key)
40 | {
41 | return strcmp(key, "true") == 0;
42 | }
43 |
44 | //-----------------------------------------------------------------------------
45 | bool is_valid_ip(const char *ip_str)
46 | {
47 | struct in_addr addr;
48 | int result = inet_pton(AF_INET, ip_str, &addr);
49 | return result != 0;
50 | }
51 |
52 | //-----------------------------------------------------------------------------
53 | uint64_t system_uptime_usec(void)
54 | {
55 | return esp_timer_get_time();
56 | }
57 |
58 | //-----------------------------------------------------------------------------
59 | float system_uptime_s(void)
60 | {
61 | return (float)(system_uptime_usec() / 1000000.0);
62 | }
63 |
64 | //-----------------------------------------------------------------------------
65 | void restart(void)
66 | {
67 | esp_restart();
68 | }
69 |
70 | //-----------------------------------------------------------------------------
71 | char *param_set_default(const char *def_val)
72 | {
73 | char *retval = malloc(strlen(def_val) + 1);
74 | strcpy(retval, def_val);
75 | return retval;
76 | }
77 |
78 |
79 | char* url_decode(const char* src) {
80 | if (src == NULL) {
81 | return NULL;
82 | }
83 |
84 | char* dest = malloc(strlen(src) + 1);
85 | if (dest == NULL) {
86 | return NULL;
87 | }
88 |
89 | char* p = dest;
90 | while (*src != '\0') {
91 | if (*src == '%' && *(src + 1) != '\0' && *(src + 2) != '\0') {
92 | char hex[3] = { *(src + 1), *(src + 2), '\0' };
93 | int i = strtol(hex, NULL, 16);
94 | *p++ = (char)i;
95 | src += 3;
96 | }
97 | else {
98 | *p++ = *src++;
99 | }
100 | }
101 | *p = '\0';
102 | return dest;
103 | }
104 |
105 | //-----------------------------------------------------------------------------
106 | char *html_escape(const char *src)
107 | {
108 | if (src == NULL)
109 | {
110 | return NULL;
111 | }
112 | // Decode the input string using url_decode
113 | char* decoded = url_decode(src);
114 | int len = strlen(decoded);
115 | int esc_len = len + 1;
116 | for (int i = 0; i < len; i++)
117 | {
118 | if (decoded[i] == '\\' || decoded[i] == '\'' || decoded[i] == '\"' || decoded[i] == '&' || decoded[i] == '#' || decoded[i] == ';')
119 | {
120 | esc_len += 5;
121 | }
122 | }
123 | char *res = malloc(sizeof(char) * (esc_len + 1));
124 | if (res == NULL)
125 | {
126 | return NULL;
127 | }
128 | int j = 0;
129 | for (int i = 0; i < len; i++)
130 | {
131 | if (decoded[i] == '\\' || decoded[i] == '\'' || decoded[i] == '\"' || decoded[i] == '&' || decoded[i] == '#' || decoded[i] == ';')
132 | {
133 | res[j++] = '&';
134 | res[j++] = 'a';
135 | res[j++] = 'm';
136 | res[j++] = 'p';
137 | res[j++] = ';';
138 | }
139 | else
140 | {
141 | res[j++] = decoded[i];
142 | }
143 | }
144 | res[j] = '\0';
145 | free(decoded);
146 | return res;
147 | }
--------------------------------------------------------------------------------
/components/web_server/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS request_handler.c response_handler.c get_data_handler.c
2 | storage_handler.c auth_handler.c web_server.c
3 |
4 | INCLUDE_DIRS include
5 | REQUIRES esp_http_server esp-tls json esp_http_client utils
6 | cmd_router cmd_nvs ota_handler wifi_handler)
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/components/web_server/auth_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include "stdio.h"
12 | #include "string.h"
13 | #include "request_handler.h"
14 | #include "auth_handler.h"
15 | #include "nvs.h"
16 | #include "cmd_nvs.h"
17 | #include "router_globals.h"
18 | #include "ota_handler.h"
19 | #include "esp_http_server.h"
20 | #include "utils.h"
21 |
22 | char auth_buffer[512];
23 | #define HTTPD_401 "401 Unauthorized"
24 | #define HTTPD_403 "403 Forbidden"
25 |
26 | int max_login_attempts;
27 | int lock_out_time_minutes;
28 |
29 | int failed_attempts_count = 0;
30 | float block_start_time = 0;
31 |
32 | #define BLOCKING_TIME_SEC (lock_out_time_minutes * 60) // convert minutes to seconds
33 |
34 | basic_auth_info_t auth_info = {
35 |
36 | };
37 |
38 | //-----------------------------------------------------------------------------
39 | // block's the user for some time to avoid brute force attacks
40 | static bool block_request(void)
41 | {
42 | float current_time = system_uptime_s();
43 | // Reset block_start_time if blocking period has passed
44 | if ((block_start_time > 0) && ((block_start_time + BLOCKING_TIME_SEC) < current_time))
45 | {
46 | block_start_time = 0;
47 | failed_attempts_count = 0;
48 | }
49 | // printf("current time : %f, blocked time: %f\n", current_time, block_start_time);
50 | return (failed_attempts_count >= max_login_attempts && (block_start_time + BLOCKING_TIME_SEC) > current_time);
51 | }
52 |
53 | //-----------------------------------------------------------------------------
54 | static char *http_auth_basic(char *username, char *password)
55 | {
56 | int out;
57 | char user_info[128];
58 | static char digest[512];
59 | size_t n = 0;
60 | sprintf(user_info, "%s:%s", username, password);
61 |
62 | esp_crypto_base64_encode(NULL, 0, &n, (const unsigned char *)user_info, strlen(user_info));
63 |
64 | // 6: The length of the "Basic " string
65 | // n: Number of bytes for a base64 encode format
66 | // 1: Number of bytes for a reserved which be used to fill zero
67 | if (sizeof(digest) > (6 + n + 1))
68 | {
69 | strcpy(digest, "Basic ");
70 | esp_crypto_base64_encode((unsigned char *)digest + 6, n, (size_t *)&out, (const unsigned char *)user_info, strlen(user_info));
71 | }
72 |
73 | return digest;
74 | }
75 |
76 | //-----------------------------------------------------------------------------
77 | esp_err_t authentication_handler(httpd_req_t *req, int req_id)
78 | {
79 |
80 | if (block_request())
81 | {
82 | httpd_resp_set_status(req, HTTPD_403);
83 | httpd_resp_set_hdr(req, "Connection", "close");
84 | httpd_resp_send(req, NULL, 0);
85 | return ESP_OK;
86 | }
87 |
88 | size_t buf_len = httpd_req_get_hdr_value_len(req, "Authorization") + 1;
89 | if ((buf_len > 1) && (buf_len <= sizeof(auth_buffer)))
90 | {
91 | char auth_buffer[buf_len];
92 | if (httpd_req_get_hdr_value_str(req, "Authorization", auth_buffer, buf_len) == ESP_OK)
93 | {
94 | char *auth_credentials = http_auth_basic(auth_info.username, auth_info.password);
95 | if (!strncmp(auth_credentials, auth_buffer, buf_len))
96 | {
97 | failed_attempts_count = 0;
98 | httpd_resp_set_status(req, HTTPD_200);
99 |
100 | switch (req_id)
101 | {
102 | case POST_OTA_UPDATE_ID:
103 | return ota_update_handler(req);
104 | case COMMON_JS_ID:
105 | return common_js_response(req);
106 | case COMMON_DATA_ID:
107 | return common_data_request(req);
108 | default:
109 | return common_page_response_handler(req, req_id);
110 | }
111 | }
112 | }
113 | }
114 | printf("Not authenticated\n");
115 | failed_attempts_count++;
116 | if (failed_attempts_count >= max_login_attempts && block_start_time == 0)
117 | {
118 | block_start_time = system_uptime_s();
119 | }
120 |
121 | httpd_resp_set_status(req, HTTPD_401);
122 | httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"Hello authenticate first\"");
123 | httpd_resp_send(req, NULL, 0);
124 |
125 | return ESP_OK;
126 | }
127 |
--------------------------------------------------------------------------------
/components/web_server/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Component Makefile
3 | #
4 | # This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
5 | # this will take the sources in the src/ directory, compile them and link them into
6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
7 | # please read the SDK documents if you need to do this.
8 | #
9 |
10 | COMPONENT_ADD_INCLUDEDIRS := .
11 |
--------------------------------------------------------------------------------
/components/web_server/get_data_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include "get_data_handler.h"
14 | #include "router_globals.h"
15 | #include "request_handler.h"
16 | #include "auth_handler.h"
17 | #include "initialization.h"
18 | #include "wifi_handler.h"
19 |
20 | #define MAX_CLIENTS 10
21 |
22 | static const char *TAG = "Web server/get_data_handler";
23 |
24 | //-----------------------------------------------------------------------------
25 | esp_err_t get_settings_data_handler(httpd_req_t *req)
26 | {
27 | parms_init();
28 |
29 | cJSON *root;
30 | root = cJSON_CreateObject();
31 |
32 | cJSON_AddStringToObject(root, "ssid", ssid);
33 | cJSON_AddStringToObject(root, "password", passwd);
34 | cJSON_AddStringToObject(root, "entUsername", ent_username);
35 | cJSON_AddStringToObject(root, "entIdentity", ent_identity);
36 | cJSON_AddStringToObject(root, "apSsid", ap_ssid);
37 | cJSON_AddStringToObject(root, "apPassword", ap_passwd);
38 |
39 | cJSON_AddStringToObject(root, "apIP", ap_ip);
40 |
41 | cJSON_AddStringToObject(root, "staticIP", static_ip);
42 | cJSON_AddStringToObject(root, "subnetMask", subnet_mask);
43 | cJSON_AddStringToObject(root, "gateWay", gateway_addr);
44 |
45 | cJSON_AddStringToObject(root, "macAp", currentMAC);
46 | cJSON_AddStringToObject(root, "dnsIP", customDNSip);
47 |
48 | cJSON_AddBoolToObject(root, "randMacAp", IsRandomizeMacEnable);
49 | cJSON_AddBoolToObject(root, "CustomDns", IsCustomDnsEnable);
50 | cJSON_AddBoolToObject(root, "ledEnable", IsLedEnable);
51 | cJSON_AddBoolToObject(root, "darkMode", IsDarkModeEnable);
52 | cJSON_AddBoolToObject(root, "webServer", IsWebServerEnable);
53 | cJSON_AddBoolToObject(root, "macFilterEnabled", IsMacFilterEnable);
54 | cJSON_AddStringToObject(root, "authUsername", authUsername);
55 | cJSON_AddStringToObject(root, "authPassword", authPass);
56 | cJSON_AddNumberToObject(root, "maxLoginAttempts", max_login_attempts);
57 | cJSON_AddNumberToObject(root, "blockingTimeMin", lock_out_time_minutes);
58 | char *my_json_string = cJSON_Print(root);
59 |
60 | httpd_resp_set_type(req, "application/json");
61 | httpd_resp_send(req, my_json_string, HTTPD_RESP_USE_STRLEN);
62 | // ESP_LOGI(TAG, "Requesting settings Data");
63 |
64 | cJSON_Delete(root);
65 | return ESP_OK;
66 | }
67 |
68 | //-----------------------------------------------------------------------------
69 | esp_err_t get_scan_data_handler(httpd_req_t *req)
70 | {
71 |
72 | char *scan_result = wifi_scan_handler();
73 |
74 | httpd_resp_set_type(req, "application/json");
75 |
76 | httpd_resp_send(req, scan_result, HTTPD_RESP_USE_STRLEN);
77 | ESP_LOGI(TAG, "Requesting scan aps Data");
78 | free(scan_result);
79 |
80 | return ESP_OK;
81 | }
82 |
83 | //-----------------------------------------------------------------------------
84 | esp_err_t get_info_data_handler(httpd_req_t *req)
85 | {
86 | char *info_result = wifi_info_handler();
87 |
88 | httpd_resp_set_type(req, "application/json");
89 | httpd_resp_send(req, info_result, HTTPD_RESP_USE_STRLEN);
90 | // ESP_LOGI(TAG, "Requesting Info Data");
91 | free(info_result);
92 | return ESP_OK;
93 | }
94 |
--------------------------------------------------------------------------------
/components/web_server/include/auth_handler.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 |
16 | #include
17 | #include "initialization.h"
18 |
19 | esp_err_t authentication_handler(httpd_req_t *req, int url_id_number);
20 | extern int max_login_attempts;
21 | extern int lock_out_time_minutes;
22 |
23 | #ifdef __cplusplus
24 | }
25 | #endif
26 |
--------------------------------------------------------------------------------
/components/web_server/include/get_data_handler.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #pragma once
9 |
10 | #ifdef __cplusplus
11 | extern "C"
12 | {
13 | #endif
14 |
15 | #ifdef __cplusplus
16 | }
17 | #endif
18 |
--------------------------------------------------------------------------------
/components/web_server/include/request_handler.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #ifndef URL_REQUEST_HANDLER
10 | #define URL_REQUEST_HANDLER
11 |
12 | #endif
13 |
14 | #pragma once
15 |
16 | #ifdef __cplusplus
17 | extern "C"
18 | {
19 | #endif
20 |
21 | #include "esp_http_server.h"
22 |
23 | #define SCAN_PAGE_ID 1
24 | #define SETTINGS_PAGE_ID 2
25 | #define INFO_PAGE_ID 3
26 | #define MAIN_CSS_ID 4
27 | #define DARK_CSS_ID 5
28 |
29 | #define COMMON_JS_ID 6
30 | #define COMMON_DATA_ID 7
31 |
32 | #define POST_OTA_UPDATE_ID 8
33 | #define ERR_404_PAGE_ID 404
34 |
35 | // Register NVS functions
36 | esp_err_t get_scan_handler(httpd_req_t *req);
37 | esp_err_t get_settings_handler(httpd_req_t *req);
38 |
39 | esp_err_t get_info_handler(httpd_req_t *req);
40 | esp_err_t get_main_css_handler(httpd_req_t *req);
41 | esp_err_t get_dark_css_handler(httpd_req_t *req);
42 | esp_err_t get_error_404_handler(httpd_req_t *req);
43 |
44 | esp_err_t common_page_response_handler(httpd_req_t *req, int req_id);
45 | esp_err_t common_js_path_handler(httpd_req_t *req);
46 | esp_err_t common_js_response(httpd_req_t *req);
47 |
48 | esp_err_t common_data_handler(httpd_req_t *req);
49 | esp_err_t common_data_request(httpd_req_t *req);
50 |
51 | esp_err_t http_404_error_handler(httpd_req_t *req);
52 |
53 | esp_err_t get_settings_data_handler(httpd_req_t *req);
54 | esp_err_t save_settings_data_handler(httpd_req_t *req);
55 |
56 | esp_err_t get_scan_data_handler(httpd_req_t *req);
57 | esp_err_t get_info_data_handler(httpd_req_t *req);
58 |
59 | // esp_err_t ssids_post_handler(httpd_req_t *req);
60 | esp_err_t post_ota_update_handler(httpd_req_t *req);
61 |
62 | #ifdef __cplusplus
63 | }
64 | #endif
65 |
--------------------------------------------------------------------------------
/components/web_server/include/storage_handler.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 |
16 | #include "esp_err.h"
17 | #include
18 |
19 | esp_err_t save_settings_data_handler(httpd_req_t *req);
20 |
21 | #ifdef __cplusplus
22 | }
23 | #endif
24 |
--------------------------------------------------------------------------------
/components/web_server/include/web_server.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 |
9 | #pragma once
10 |
11 | #ifdef __cplusplus
12 | extern "C"
13 | {
14 | #endif
15 | #include
16 |
17 | void stop_web_server(void);
18 | void toggle_webserver(void);
19 | extern httpd_handle_t server;
20 | httpd_handle_t start_webserver(void);
21 |
22 | #ifdef __cplusplus
23 | }
24 | #endif
25 |
--------------------------------------------------------------------------------
/components/web_server/request_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include "esp_http_server.h"
11 | #include "auth_handler.h"
12 | #include "request_handler.h"
13 | // static const char *TAG = "components/uurl_request_handler";
14 | #include
15 |
16 | /* ******** Request Handlers ************ */
17 |
18 | //-----------------------------------------------------------------------------
19 | esp_err_t get_scan_handler(httpd_req_t *req)
20 | {
21 | return authentication_handler(req, SCAN_PAGE_ID);
22 | }
23 |
24 |
25 | esp_err_t get_settings_handler(httpd_req_t *req)
26 | {
27 | return authentication_handler(req, SETTINGS_PAGE_ID);
28 | }
29 |
30 |
31 | esp_err_t get_info_handler(httpd_req_t *req)
32 | {
33 | return authentication_handler(req, INFO_PAGE_ID);
34 | }
35 |
36 |
37 | //-----------------------------------------------------------------------------
38 | esp_err_t get_main_css_handler(httpd_req_t *req)
39 | {
40 | return common_page_response_handler(req, MAIN_CSS_ID);
41 | }
42 | esp_err_t get_dark_css_handler(httpd_req_t *req)
43 | {
44 | return common_page_response_handler(req, DARK_CSS_ID);
45 | }
46 |
47 |
48 | //-----------------------------------------------------------------------------
49 | esp_err_t common_js_path_handler(httpd_req_t *req)
50 | {
51 | if (strcmp(req->uri, "/js/functions.js") == 0)
52 | {
53 | return common_js_response(req);
54 | }
55 | return authentication_handler(req, COMMON_JS_ID);
56 | }
57 |
58 |
59 | //-----------------------------------------------------------------------------
60 | esp_err_t common_data_handler(httpd_req_t *req)
61 | {
62 | return authentication_handler(req, COMMON_DATA_ID);
63 | }
64 |
65 |
66 | //-----------------------------------------------------------------------------
67 | esp_err_t post_ota_update_handler(httpd_req_t *req)
68 | {
69 | return authentication_handler(req, POST_OTA_UPDATE_ID);
70 | }
71 |
72 |
73 | //-----------------------------------------------------------------------------
74 | esp_err_t get_error_404_handler(httpd_req_t *req)
75 | {
76 | return common_page_response_handler(req, ERR_404_PAGE_ID);
77 | }
--------------------------------------------------------------------------------
/components/web_server/response_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include "esp_http_server.h"
11 | #include
12 | #include "router_globals.h"
13 | #include "request_handler.h"
14 | #include "initialization.h"
15 | #include "storage_handler.h"
16 | #include "utils.h"
17 | #include "nvm.h"
18 | static const char *TAG = "components/url_requesr_handler";
19 |
20 | // it is possible to simplify the code by using a macro that specifies the symbol name.
21 |
22 | // <<<--- it is equivalent to --->>>
23 | // extern const char name_start[] asm("_binary_name_start");
24 | // extern const char name_end[] asm("_binary_name_end");
25 | // #define HTTPD_404 404_html_gz_start
26 |
27 | #define BINARY_SYMBOL(name) \
28 | extern const char name##_start[] asm("_binary_" #name "_start"); \
29 | extern const char name##_end[] asm("_binary_" #name "_end");
30 |
31 | BINARY_SYMBOL(index_html_gz);
32 | BINARY_SYMBOL(settings_html_gz);
33 | BINARY_SYMBOL(info_html_gz);
34 | BINARY_SYMBOL(error_404_html_gz);
35 |
36 | BINARY_SYMBOL(main_css_gz);
37 | BINARY_SYMBOL(dark_css_gz);
38 |
39 | // javaScript
40 | BINARY_SYMBOL(scan_js_gz);
41 | BINARY_SYMBOL(info_js_gz);
42 | BINARY_SYMBOL(settings_js_gz);
43 | BINARY_SYMBOL(functions_js_gz);
44 | BINARY_SYMBOL(info_js_gz);
45 |
46 | /************* returns subsequent Response pages***************/
47 | typedef struct
48 | {
49 | const int id;
50 | const char *type;
51 | const uint8_t *start;
52 | const uint8_t *end;
53 | } url_handler_t;
54 |
55 | url_handler_t handlers[] = {
56 | {SCAN_PAGE_ID, "text/html", (const uint8_t *)index_html_gz_start, (const uint8_t *)index_html_gz_end},
57 | {SETTINGS_PAGE_ID, "text/html", (const uint8_t *)settings_html_gz_start, (const uint8_t *)settings_html_gz_end},
58 | {INFO_PAGE_ID, "text/html", (const uint8_t *)info_html_gz_start, (const uint8_t *)info_html_gz_end},
59 | {ERR_404_PAGE_ID, "text/html", (const uint8_t *)error_404_html_gz_start, (const uint8_t *)error_404_html_gz_end},
60 | {MAIN_CSS_ID, "text/css", (const uint8_t *)main_css_gz_start, (const uint8_t *)main_css_gz_end},
61 | {DARK_CSS_ID, "text/css", (const uint8_t *)dark_css_gz_start, (const uint8_t *)dark_css_gz_end},
62 | };
63 |
64 |
65 | //-----------------------------------------------------------------------------
66 | esp_err_t ICACHE_FLASH_ATTR common_page_response_handler(httpd_req_t *req, int req_id)
67 | {
68 | for (int i = 0; i < sizeof(handlers) / sizeof(handlers[0]); i++)
69 | {
70 | if (handlers[i].id == req_id)
71 | {
72 | if (!IsDarkModeEnable && req_id == DARK_CSS_ID)
73 | {
74 | httpd_resp_set_type(req, handlers[i].type);
75 | return httpd_resp_send(req, "/* Dark mode disabled */", HTTPD_RESP_USE_STRLEN);
76 | }
77 | if (req_id == ERR_404_PAGE_ID)
78 | {
79 | httpd_resp_set_status(req, HTTPD_404);
80 | }
81 |
82 | const size_t handler_size = handlers[i].end - handlers[i].start;
83 | httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
84 | return httpd_resp_send(req, (const char *)handlers[i].start, handler_size);
85 | }
86 | }
87 | httpd_resp_send_404(req);
88 | return ESP_OK;
89 | }
90 |
91 | /////////////////////////////////////////**************JAVA_SCRIPT*********///////////////////////////////////////////////////////
92 |
93 | typedef struct
94 | {
95 | const char *uri;
96 | const uint8_t *start;
97 | const uint8_t *end;
98 | } js_file_t;
99 |
100 | js_file_t js_files[] = {
101 | {"/js/scan.js", (const uint8_t *)scan_js_gz_start, (const uint8_t *)scan_js_gz_end},
102 | {"/js/info.js", (const uint8_t *)info_js_gz_start, (const uint8_t *)info_js_gz_end},
103 | {"/js/settings.js", (const uint8_t *)settings_js_gz_start, (const uint8_t *)settings_js_gz_end},
104 | {"/js/functions.js", (const uint8_t *)functions_js_gz_start, (const uint8_t *)functions_js_gz_end},
105 | };
106 | const size_t num_js_files = sizeof(js_files) / sizeof(js_files[0]);
107 |
108 |
109 | //-----------------------------------------------------------------------------
110 | esp_err_t ICACHE_FLASH_ATTR common_js_response(httpd_req_t *req)
111 | {
112 | for (int i = 0; i < num_js_files; i++)
113 | {
114 | if (strcmp(req->uri, js_files[i].uri) == 0)
115 | {
116 | const size_t js_size = (js_files[i].end - js_files[i].start);
117 | httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
118 | httpd_resp_set_type(req, "application/javascript");
119 |
120 | return httpd_resp_send(req, (const char *)js_files[i].start, js_size);
121 | }
122 | }
123 | return http_404_error_handler(req);
124 | }
125 |
126 | //-----------------------------------------------------------------------------
127 | esp_err_t common_data_request(httpd_req_t *req)
128 | {
129 |
130 | if (strcmp(req->uri, "/data/settings.json") == 0)
131 | {
132 | return get_settings_data_handler(req);
133 | }
134 | else if (word_check(req->uri, "/data/settingsSave.json"))
135 | {
136 | return save_settings_data_handler(req);
137 | }
138 |
139 | else if (strcmp(req->uri, "/data/APScanResults.json") == 0)
140 | {
141 | return get_scan_data_handler(req);
142 | }
143 | else if (strcmp(req->uri, "/data/sysinfo.json") == 0)
144 | {
145 | return get_info_data_handler(req);
146 | }
147 | else if (strcmp(req->uri, "/data/ClientScanTime.json") == 0)
148 | {
149 | httpd_resp_set_type(req, "application/json");
150 | return httpd_resp_send(req, "true", HTTPD_RESP_USE_STRLEN);
151 | }
152 | else if (strcmp(req->uri, "/data/restart.json") == 0)
153 | {
154 | ESP_LOGW(TAG, "Restarting now...");
155 | httpd_resp_set_type(req, "application/json");
156 | if (httpd_resp_send(req, "true", HTTPD_RESP_USE_STRLEN) == ESP_OK)
157 | {
158 | vTaskDelay(pdMS_TO_TICKS(2000));
159 | restart();
160 | }
161 | return ESP_OK;
162 | }
163 | else if (strcmp(req->uri, "/data/settingsReset.json") == 0)
164 | {
165 |
166 | if (nvm_erase() == ESP_OK)
167 | httpd_resp_send(req, "true", HTTPD_RESP_USE_STRLEN);
168 |
169 | else
170 | return httpd_resp_send(req, "false", HTTPD_RESP_USE_STRLEN);
171 | }
172 |
173 | return http_404_error_handler(req);
174 | }
175 |
--------------------------------------------------------------------------------
/components/web_server/storage_handler.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "cmd_nvs.h"
13 | #include "auth_handler.h"
14 | #include "router_globals.h"
15 | #include "request_handler.h"
16 | #include "initialization.h"
17 | #include "utils.h"
18 | #include "mac_filter.h"
19 |
20 | static const char *TAG = "url_handler/get_data_handler";
21 |
22 | bool error = false;
23 |
24 | //-----------------------------------------------------------------------------
25 | esp_err_t save_settings_data_handler(httpd_req_t *req)
26 | {
27 |
28 | char *query_buf;
29 | size_t query_buf_len;
30 | char param_buf[64];
31 | esp_err_t err;
32 | bool valid_query = false;
33 |
34 | // get the query string
35 | query_buf_len = httpd_req_get_url_query_len(req) + 1;
36 | query_buf = malloc(query_buf_len);
37 | if (query_buf == NULL)
38 | {
39 | return ESP_ERR_NO_MEM;
40 | }
41 | err = httpd_req_get_url_query_str(req, query_buf, query_buf_len);
42 | if (err != ESP_OK)
43 | {
44 | free(query_buf);
45 | return err;
46 | }
47 |
48 | nvs_handle handle;
49 | err = nvs_open(PARAM_NAMESPACE, NVS_READWRITE, &handle);
50 | if (err != ESP_OK)
51 | {
52 | ESP_LOGI(TAG, "NVS error");
53 | valid_query = false;
54 | }
55 |
56 | if (httpd_query_key_value(query_buf, "ssid", param_buf, sizeof(param_buf)) == ESP_OK)
57 | {
58 | ssid = html_escape(strdup(param_buf));
59 | err = nvs_set_str(handle, "ssid", ssid);
60 | }
61 | if (httpd_query_key_value(query_buf, "password", param_buf, sizeof(param_buf)) == ESP_OK)
62 | {
63 | passwd = html_escape(strdup(param_buf));
64 | err = nvs_set_str(handle, "passwd", passwd);
65 | }
66 | if (httpd_query_key_value(query_buf, "ent_username", param_buf, sizeof(param_buf)) == ESP_OK)
67 | {
68 | ent_username = html_escape(strdup(param_buf));
69 | err = nvs_set_str(handle, "ent_username", ent_username);
70 | }
71 | if (httpd_query_key_value(query_buf, "ent_identity", param_buf, sizeof(param_buf)) == ESP_OK)
72 | {
73 | ent_identity = html_escape(strdup(param_buf));
74 | err = nvs_set_str(handle, "ent_identity", ent_identity);
75 | }
76 | if (httpd_query_key_value(query_buf, "apSsid", param_buf, sizeof(param_buf)) == ESP_OK)
77 | {
78 | ap_ssid = html_escape(strdup(param_buf));
79 | err = nvs_set_str(handle, "ap_ssid", ap_ssid);
80 | }
81 |
82 | if (httpd_query_key_value(query_buf, "apPassword", param_buf, sizeof(param_buf)) == ESP_OK)
83 | {
84 | ap_passwd = html_escape(strdup(param_buf));
85 | err = nvs_set_str(handle, "ap_passwd", ap_passwd);
86 | }
87 | // if (httpd_query_key_value(query_buf, "macAp", param_buf, sizeof(param_buf)) == ESP_OK)
88 | // {
89 | // macAp = html_escape(strdup(param_buf));
90 | // err = nvs_set_str(handle, "macAp", macAp);
91 | // }
92 | if (httpd_query_key_value(query_buf, "staticIP", param_buf, sizeof(param_buf)) == ESP_OK)
93 | {
94 | static_ip = html_escape(strdup(param_buf));
95 | if (is_valid_ip(static_ip))
96 | err = nvs_set_str(handle, "static_ip", static_ip);
97 | else
98 | ESP_LOGE(TAG, "Invalid Static IP Address");
99 | }
100 | if (httpd_query_key_value(query_buf, "subnetMask", param_buf, sizeof(param_buf)) == ESP_OK)
101 | {
102 | subnet_mask = html_escape(strdup(param_buf));
103 | if (is_valid_ip(subnet_mask))
104 | err = nvs_set_str(handle, "subnet_mask", subnet_mask);
105 | else
106 | ESP_LOGE(TAG, "Invalid Subnet Mask Address");
107 | }
108 | if (httpd_query_key_value(query_buf, "gateWay", param_buf, sizeof(param_buf)) == ESP_OK)
109 | {
110 | gateway_addr = html_escape(strdup(param_buf));
111 | if (is_valid_ip(gateway_addr))
112 | err = nvs_set_str(handle, "gateway_addr", gateway_addr);
113 | else
114 | ESP_LOGE(TAG, "Invalid Gateway Addr Address");
115 | }
116 | if (httpd_query_key_value(query_buf, "apIP", param_buf, sizeof(param_buf)) == ESP_OK)
117 | {
118 | ap_ip = html_escape(strdup(param_buf));
119 | if (is_valid_ip(ap_ip))
120 | err = nvs_set_str(handle, "ap_ip", ap_ip);
121 | else
122 | ESP_LOGE(TAG, "Invalid AP IP Address");
123 | }
124 |
125 | if (httpd_query_key_value(query_buf, "dnsIP", param_buf, sizeof(param_buf)) == ESP_OK)
126 | {
127 | customDNSip = html_escape(strdup(param_buf));
128 | if (strcmp(customDNSip, "default") != 0)
129 | {
130 | if (is_valid_ip(customDNSip))
131 | err = nvs_set_str(handle, "custom_dns_ip", customDNSip);
132 | else
133 | ESP_LOGE(TAG, "Invalid DNS IP Address");
134 | }
135 | }
136 |
137 | if (httpd_query_key_value(query_buf, "adminUsername", param_buf, sizeof(param_buf)) == ESP_OK)
138 | {
139 | authUsername = html_escape(strdup(param_buf));
140 | err = nvs_set_str(handle, "auth_username", authUsername);
141 | }
142 | if (httpd_query_key_value(query_buf, "adminPassword", param_buf, sizeof(param_buf)) == ESP_OK)
143 | {
144 | authPass = html_escape(strdup(param_buf));
145 | err = nvs_set_str(handle, "auth_password", authPass);
146 | }
147 |
148 | if (httpd_query_key_value(query_buf, "maxLoginAttempts", param_buf, sizeof(param_buf)) == ESP_OK)
149 | {
150 | max_login_attempts = atoi(html_escape(strdup(param_buf)));
151 | err = nvs_set_i32(handle, "max_login_attempts", max_login_attempts);
152 | }
153 |
154 | if (httpd_query_key_value(query_buf, "blockingTimeMin", param_buf, sizeof(param_buf)) == ESP_OK)
155 | {
156 | lock_out_time_minutes = atoi(html_escape(strdup(param_buf)));
157 | err = nvs_set_i32(handle, "lock_out_time_minutes", lock_out_time_minutes);
158 | }
159 |
160 | if (httpd_query_key_value(query_buf, "randMacAp", param_buf, sizeof(param_buf)) == ESP_OK)
161 | {
162 | IsRandomizeMacEnable = str_to_bool(html_escape(strdup(param_buf)));
163 | err = nvs_set_i32(handle, "randomize_mac", bool_to_int(IsRandomizeMacEnable));
164 | }
165 |
166 | if (httpd_query_key_value(query_buf, "CustomDns", param_buf, sizeof(param_buf)) == ESP_OK)
167 | {
168 |
169 | IsCustomDnsEnable = str_to_bool(html_escape(strdup(param_buf)));
170 | err = nvs_set_i32(handle, "custom_dns", bool_to_int(IsCustomDnsEnable));
171 | }
172 |
173 | if (httpd_query_key_value(query_buf, "ledEnable", param_buf, sizeof(param_buf)) == ESP_OK)
174 | {
175 | IsLedEnable = str_to_bool(html_escape(strdup(param_buf)));
176 | err = nvs_set_i32(handle, "led_enable", bool_to_int(IsLedEnable));
177 | }
178 |
179 | if (httpd_query_key_value(query_buf, "webServer", param_buf, sizeof(param_buf)) == ESP_OK)
180 | {
181 | IsWebServerEnable = str_to_bool(html_escape(strdup(param_buf)));
182 | err = nvs_set_i32(handle, "web_server", bool_to_int(IsWebServerEnable));
183 | }
184 | if (httpd_query_key_value(query_buf, "darkMode", param_buf, sizeof(param_buf)) == ESP_OK)
185 | {
186 | IsDarkModeEnable = str_to_bool(html_escape(strdup(param_buf)));
187 | err = nvs_set_i32(handle, "dark_mode", bool_to_int(IsDarkModeEnable));
188 | }
189 | if (httpd_query_key_value(query_buf, "macFilterEnable", param_buf, sizeof(param_buf)) == ESP_OK)
190 | {
191 | IsMacFilterEnable = str_to_bool(html_escape(strdup(param_buf)));
192 | err = nvs_set_i32(handle, "mac_Filter", bool_to_int(IsMacFilterEnable));
193 | printf("Commit failed! (%s)\n", esp_err_to_name(err));
194 |
195 | }
196 | ///////////////////
197 | if (httpd_query_key_value(query_buf, "add_mac_address", param_buf, sizeof(param_buf)) == ESP_OK)
198 | {
199 | store_mac_address_in_nvs(html_escape(strdup(param_buf)));
200 | refresh_mac_filter();
201 |
202 | }
203 |
204 | if (httpd_query_key_value(query_buf, "remove_mac_address", param_buf, sizeof(param_buf)) == ESP_OK)
205 | {
206 | remove_mac_address_from_nvs(html_escape(strdup(param_buf)));
207 | refresh_mac_filter();
208 | }
209 |
210 | if (httpd_query_key_value(query_buf, "filter_list_type", param_buf, sizeof(param_buf)) == ESP_OK)
211 | {
212 | IsAllowList = word_check(html_escape(strdup(param_buf)),"Allow");
213 | err = nvs_set_i32(handle, "Is_allow_list", bool_to_int(IsAllowList));
214 | refresh_mac_filter();
215 | }
216 |
217 |
218 | /////////////////
219 |
220 | valid_query = (err == ESP_OK);
221 |
222 | if (valid_query)
223 | {
224 | err = nvs_commit(handle);
225 | if (err != ESP_OK)
226 | {
227 | free(query_buf);
228 | nvs_close(handle);
229 | return err;
230 | }
231 | nvs_close(handle);
232 | free(query_buf);
233 | return httpd_resp_send(req, "true", HTTPD_RESP_USE_STRLEN);
234 | }
235 | else
236 | {
237 | nvs_close(handle);
238 | free(query_buf);
239 | return httpd_resp_send(req, "false", HTTPD_RESP_USE_STRLEN);
240 | }
241 | }
242 |
243 | //-----------------------------------------------------------------------------
--------------------------------------------------------------------------------
/components/web_server/web_server.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Jaya Satish
3 | *
4 | *@copyright Copyright (c) 2023
5 | *Licensed under MIT
6 | *
7 | */
8 | /* Simple HTTP Server Example
9 |
10 | This example code is in the Public Domain (or CC0 licensed, at your option.)
11 |
12 | Unless required by applicable law or agreed to in writing, this
13 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 | CONDITIONS OF ANY KIND, either express or implied.
15 | */
16 |
17 | #include
18 | #include
19 | #include "web_server.h"
20 | #include "router_globals.h"
21 | #include "request_handler.h"
22 | #include "auth_handler.h"
23 |
24 | static const char *TAG = "HTTPServer";
25 |
26 | // declare global variable to store server handle
27 | httpd_handle_t server = NULL;
28 |
29 | static httpd_uri_t get_scan = {
30 | .uri = "/",
31 | .method = HTTP_GET,
32 | .handler = get_scan_handler,
33 | .user_ctx = &auth_info};
34 |
35 | static httpd_uri_t get_settings = {
36 | .uri = "/settings",
37 | .method = HTTP_GET,
38 | .handler = get_settings_handler,
39 | .user_ctx = &auth_info};
40 |
41 | static httpd_uri_t get_info = {
42 | .uri = "/info",
43 | .method = HTTP_GET,
44 | .handler = get_info_handler,
45 | .user_ctx = &auth_info};
46 |
47 | static httpd_uri_t get_main_css = {
48 | .uri = "/main.css",
49 | .method = HTTP_GET,
50 | .handler = get_main_css_handler,
51 | .user_ctx = &auth_info};
52 |
53 | static httpd_uri_t get_dark_css = {
54 | .uri = "/dark.css",
55 | .method = HTTP_GET,
56 | .handler = get_dark_css_handler,
57 | .user_ctx = &auth_info};
58 |
59 | static httpd_uri_t get_error_404 = {
60 | .uri = "/404",
61 | .method = HTTP_GET,
62 | .handler = get_error_404_handler,
63 | .user_ctx = &auth_info};
64 |
65 | // javascript
66 | static httpd_uri_t common_js_path = {
67 | .uri = "/js/*",
68 | .method = HTTP_GET,
69 | .handler = common_js_path_handler,
70 | .user_ctx = &auth_info};
71 |
72 | static httpd_uri_t common_data_path = {
73 | .uri = "/data/*",
74 | .method = HTTP_GET,
75 | .handler = common_data_handler,
76 | .user_ctx = &auth_info};
77 |
78 | static httpd_uri_t settings_post_path = {
79 | .uri = "/data/settingsSave.json",
80 | .method = HTTP_POST,
81 | .handler = common_data_handler,
82 | .user_ctx = &auth_info};
83 |
84 | static httpd_uri_t post_ota_update = {
85 | .uri = "/ota",
86 | .method = HTTP_POST,
87 | .handler = post_ota_update_handler,
88 | .user_ctx = &auth_info};
89 |
90 | //-----------------------------------------------------------------------------
91 | esp_err_t http_404_error_handler(httpd_req_t *req)
92 | {
93 | httpd_resp_set_status(req, "302 Temporary Redirect");
94 | httpd_resp_set_hdr(req, "Location", "/404");
95 | httpd_resp_send(req, "Redirect to 404 page", HTTPD_RESP_USE_STRLEN);
96 | return ESP_OK;
97 | }
98 |
99 | static httpd_uri_t error_404_handler = {
100 | .uri = "/*",
101 | .method = HTTP_GET,
102 | .handler = http_404_error_handler,
103 | .user_ctx = NULL};
104 |
105 | //-----------------------------------------------------------------------------
106 | httpd_handle_t start_webserver(void)
107 | {
108 | httpd_config_t config = HTTPD_DEFAULT_CONFIG();
109 | // config.task_priority = 6,
110 | // config.max_resp_headers = 1024;
111 | config.max_uri_handlers = 15;
112 | config.uri_match_fn = httpd_uri_match_wildcard;
113 | config.lru_purge_enable = true;
114 |
115 | // config.stack_size = 10000;
116 |
117 | if (httpd_start(&server, &config) != ESP_OK)
118 | {
119 | ESP_LOGE(TAG, "Error starting server!");
120 | return NULL;
121 | }
122 | ESP_LOGI(TAG, "Registering URI handlers");
123 | httpd_register_uri_handler(server, &get_scan);
124 | httpd_register_uri_handler(server, &get_info);
125 | httpd_register_uri_handler(server, &get_settings);
126 | httpd_register_uri_handler(server, &get_main_css);
127 | httpd_register_uri_handler(server, &get_dark_css);
128 | httpd_register_uri_handler(server, &common_js_path);
129 | httpd_register_uri_handler(server, &common_data_path);
130 | httpd_register_uri_handler(server, &settings_post_path);
131 | httpd_register_uri_handler(server, &post_ota_update);
132 | httpd_register_uri_handler(server, &get_error_404);
133 | httpd_register_uri_handler(server, &error_404_handler);
134 | return server;
135 | }
136 |
137 | //-----------------------------------------------------------------------------
138 | void stop_web_server(void)
139 | {
140 | if (server != NULL)
141 | {
142 | httpd_stop(server);
143 | server = NULL;
144 | ESP_LOGI(TAG, "Http server stoped");
145 | }
146 | }
147 |
148 | //-----------------------------------------------------------------------------
149 | void toggle_webserver(void)
150 | {
151 | IsWebServerEnable = !IsWebServerEnable;
152 | if (IsWebServerEnable)
153 | {
154 | server = start_webserver();
155 | }
156 | else
157 | {
158 | stop_web_server();
159 | }
160 | }
161 |
162 | //-----------------------------------------------------------------------------
--------------------------------------------------------------------------------
/components/web_server/www/README.md:
--------------------------------------------------------------------------------
1 | # ESP32-NAT Router +
2 |
3 | ## What is Jekyll?
4 |
5 | [Jekyll](https://jekyllrb.com/) is a pre-compiler for static content generation that simplifies website maintenance. It uses Ruby to generate static HTML pages, which means that the outputted HTML is the same as if it were written by hand.
6 |
7 | To start using Jekyll, you need to follow these steps:
8 |
9 | - Install Ruby, Gem package manager & Jekyll ( check [here](https://www.ruby-lang.org/ ) )
10 | - Run `bundle install` in the `/html` folder to install dependencies
11 |
12 | Note :
13 |
14 | Jekyll is a static site generator that uses a specific format to separate the metadata of a web page from its content. At the top of each web file, it's important to include a specific syntax in the form of three hyphens
15 |
16 | ```
17 | ---
18 | ---
19 | ```
20 |
21 | This is known as the front matter and it specifies the metadata of the web page, such as the author and the layout styles etc.
22 |
23 | It's important to include these three hyphen lines at the top of each file in order for Jekyll to properly parse the content and avoid errors while running and building the site. Therefore, always make sure to position these lines in the correct place in your web files to ensure a smooth development and build process.
24 |
25 | ## How to run a local server
26 |
27 | Once Jekyll is installed, you can start a local server by following these steps:
28 |
29 | - Run `bundle exec jekyll serve --watch` in the `/html` folder
30 | - Navigate to `http://127.0.0.1:4000` to see the website
31 | - Changes made to files will be reflected in real-time, so you can test and make adjustments to your site's appearance and functionality. (make sure to refresh the page though)
32 | - Alternatively, You can run the server, navigate to the root folder of the project and use `./start_web_server.sh` for Linux terminal or `start_web_server.bat` for Windows.
33 |
34 | ## How to update web-server files?
35 |
36 | ### Build
37 |
38 | - Building is a mandatory step after making changes. you can run the command `JEKYLL_ENV=production bundle exec jekyll build` for Linux Terminal OR
39 |
40 | `set JEKYLL_ENV=production bundle exec jekyll build` for Windows CMD in the `/html` folder to generate and return to production mode minified files.
41 |
42 | - Alternatively, navigate to the root folder of the project and use `./build_web_pages.sh` in Linux terminal or `build_web_pages.bat` in Windows CMD.
43 |
44 | ### Auto Mode (Windows only)
45 |
46 | - Make sure you have Jekyll & Gems installed (see above)
47 |
48 | - Launch `auto_generate.exe`
49 |
50 | - Wait for it to finish
51 |
52 | - That's it **¯\_(ツ)_/¯**
53 |
54 | ### How to Build auto_generate.exe
55 |
56 | The `auto_generate.exe` code is written in JavaScript and converted into an executable file using the `pkg` package for Node.js.
57 |
58 | To build the `auto_generate.exe` file, which automatically generates the website, follow these simple steps:
59 | 1. Install [Node.js](https://nodejs.org)
60 | 2. Open a terminal and run `npm i -g pkg` .
61 | 3. Extract the ZIP file provided in the **additional** folder
62 | 4. Click on `build_auto_generate.bat` or simply run `pkg --compress GZip index.js -o auto_generate.exe`
63 | 5. Wait for some time to download the required files.
64 | 6. That's it! You have successfully built the `auto_generate.exe` file which automatically generates the website.
--------------------------------------------------------------------------------
/components/web_server/www/additional/auto_generate.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gjroots/esp32_nat_router_plus/c3f18851b961019fb6bf7a0154d9b646a2a40cb4/components/web_server/www/additional/auto_generate.zip
--------------------------------------------------------------------------------
/components/web_server/www/auto_generate.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gjroots/esp32_nat_router_plus/c3f18851b961019fb6bf7a0154d9b646a2a40cb4/components/web_server/www/auto_generate.exe
--------------------------------------------------------------------------------
/components/web_server/www/html/404.html:
--------------------------------------------------------------------------------
1 | ---
2 | title: error.title
3 | after-js: fadeIn()
4 | layout: page
5 | ---
6 |
14 |
17 |
--------------------------------------------------------------------------------
/components/web_server/www/html/APScanResults.json:
--------------------------------------------------------------------------------
1 | {
2 | "aps": [
3 | {
4 | "c": 10,
5 | "m": "EXAMPLE MAC",
6 | "ss": "Example network 1",
7 | "r": -90,
8 | "e": 0,
9 | "h": 1
10 | },
11 | {
12 | "c": 9,
13 | "m": "EXAMPLE MAC",
14 | "ss": "Example network 2",
15 | "r": -79,
16 | "e": 2,
17 | "h": 1
18 | },
19 | {
20 | "c": 10,
21 | "m": "EXAMPLE MAC",
22 | "ss": "Example network 3",
23 | "r": -20,
24 | "e": 3,
25 | "h": 0
26 | },
27 | {
28 | "c": 10,
29 | "m": "EXAMPLE MAC",
30 | "ss": "Example network 4",
31 | "r": -70,
32 | "e": 4,
33 | "h": 0
34 | },
35 | {
36 | "c": 10,
37 | "m": "EXAMPLE MAC",
38 | "ss": "Example network 5",
39 | "r": -5,
40 | "e": 1,
41 | "h": 0
42 | },
43 | {
44 | "c": 10,
45 | "m": "EXAMPLE MAC",
46 | "ss": "Example network 6",
47 | "r": -80,
48 | "e": 0,
49 | "h": 0
50 | },
51 | {
52 | "c": 10,
53 | "m": "EXAMPLE MAC",
54 | "ss": "Example network 7",
55 | "r": -5,
56 | "e": 1,
57 | "h": 0
58 | },
59 | {
60 | "c": 6,
61 | "m": "EXAMPLE MAC",
62 | "ss": "....",
63 | "r": -42,
64 | "e": 0,
65 | "h": 0
66 | },
67 | {
68 | "c": 6,
69 | "m": "EXAMPLE MAC",
70 | "ss": "....",
71 | "r": -42,
72 | "e": 0,
73 | "h": 0
74 | }
75 | ]
76 | }
77 |
--------------------------------------------------------------------------------
/components/web_server/www/html/ClientScanResults.json:
--------------------------------------------------------------------------------
1 | {
2 | "clients":[
3 | {
4 | "i":0,
5 | "p":96,
6 | "m":"11:22:33:44:55:66",
7 | "n":"Name 1",
8 | "l":"0",
9 | "v":"IntelCor",
10 | "s":0,
11 | "a":"EXAMPLE-COMPUTER"
12 | },
13 | {
14 | "i":1,
15 | "p":12,
16 | "m":"22:33:44:55:66:77",
17 | "n":"",
18 | "l":"-1",
19 | "v":"Samsung",
20 | "s":0,
21 | "a":"EXAMPLE-ANDROID"
22 | },
23 | {
24 | "i":2,
25 | "p":339,
26 | "m":"33:44:55:66:77:88",
27 | "n":"",
28 | "l":"-1",
29 | "v":"Apple",
30 | "s":0,
31 | "a":"EXAMPLE-PHONE"
32 | },
33 | {
34 | "i":3,
35 | "p":339,
36 | "m":"00:00:00:00:00:11",
37 | "n":"",
38 | "l":"-1",
39 | "v":"Microsoft",
40 | "s":0,
41 | "a":"EXAMPLE-SAVED"
42 | }
43 | ],
44 | "nameList":[
45 | {
46 | "n":"SAVED-DEVICE",
47 | "m":"00:00:00:00:00:11"
48 | },
49 | {
50 | "n":"SAVED-DEVICE2",
51 | "m":"11:00:00:00:00:11"
52 | }
53 | ]
54 | }
--------------------------------------------------------------------------------
/components/web_server/www/html/ClientScanTime.json:
--------------------------------------------------------------------------------
1 | 15
--------------------------------------------------------------------------------
/components/web_server/www/html/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | # If you have any plugins, put them here!
4 | group :jekyll_plugins do
5 | gem 'jekyll-tidy'
6 | gem 'jekyll-multiple-languages-plugin'
7 | # gem 'jekyll-gzip'
8 | gem 'jekyll-minifier'
9 |
10 | end
11 |
12 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
13 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
14 |
15 |
--------------------------------------------------------------------------------
/components/web_server/www/html/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | addressable (2.8.1)
5 | public_suffix (>= 2.0.2, < 6.0)
6 | colorator (1.1.0)
7 | concurrent-ruby (1.2.0)
8 | cssminify2 (2.0.1)
9 | em-websocket (0.5.3)
10 | eventmachine (>= 0.12.9)
11 | http_parser.rb (~> 0)
12 | eventmachine (1.2.7)
13 | execjs (2.8.1)
14 | ffi (1.15.5)
15 | forwardable-extended (2.6.0)
16 | google-protobuf (3.24.2-x64-mingw-ucrt)
17 | htmlbeautifier (1.4.2)
18 | htmlcompressor (0.4.0)
19 | http_parser.rb (0.8.0)
20 | i18n (1.12.0)
21 | concurrent-ruby (~> 1.0)
22 | jekyll (4.3.2)
23 | addressable (~> 2.4)
24 | colorator (~> 1.0)
25 | em-websocket (~> 0.5)
26 | i18n (~> 1.0)
27 | jekyll-sass-converter (>= 2.0, < 4.0)
28 | jekyll-watch (~> 2.0)
29 | kramdown (~> 2.3, >= 2.3.1)
30 | kramdown-parser-gfm (~> 1.0)
31 | liquid (~> 4.0)
32 | mercenary (>= 0.3.6, < 0.5)
33 | pathutil (~> 0.9)
34 | rouge (>= 3.0, < 5.0)
35 | safe_yaml (~> 1.0)
36 | terminal-table (>= 1.8, < 4.0)
37 | webrick (~> 1.7)
38 | jekyll-minifier (0.1.10)
39 | cssminify2 (~> 2.0)
40 | htmlcompressor (~> 0.4)
41 | jekyll (>= 3.5)
42 | json-minify (~> 0.0.3)
43 | uglifier (~> 4.1)
44 | jekyll-multiple-languages-plugin (1.8.0)
45 | jekyll (>= 2.0, < 5.0)
46 | jekyll-sass-converter (3.0.0)
47 | sass-embedded (~> 1.54)
48 | jekyll-tidy (0.2.2)
49 | htmlbeautifier
50 | htmlcompressor
51 | jekyll
52 | jekyll-watch (2.2.1)
53 | listen (~> 3.0)
54 | json (2.6.1)
55 | json-minify (0.0.3)
56 | json (> 0)
57 | kramdown (2.4.0)
58 | rexml
59 | kramdown-parser-gfm (1.1.0)
60 | kramdown (~> 2.0)
61 | liquid (4.0.4)
62 | listen (3.8.0)
63 | rb-fsevent (~> 0.10, >= 0.10.3)
64 | rb-inotify (~> 0.9, >= 0.9.10)
65 | mercenary (0.4.0)
66 | pathutil (0.16.2)
67 | forwardable-extended (~> 2.6)
68 | public_suffix (5.0.1)
69 | rb-fsevent (0.11.2)
70 | rb-inotify (0.10.1)
71 | ffi (~> 1.0)
72 | rexml (3.2.5)
73 | rouge (4.0.1)
74 | safe_yaml (1.0.5)
75 | sass-embedded (1.57.1-x64-mingw-ucrt)
76 | google-protobuf (~> 3.21)
77 | terminal-table (3.0.2)
78 | unicode-display_width (>= 1.1.1, < 3)
79 | tzinfo (2.0.5)
80 | concurrent-ruby (~> 1.0)
81 | tzinfo-data (1.2022.7)
82 | tzinfo (>= 1.0.0)
83 | uglifier (4.2.0)
84 | execjs (>= 0.3.0, < 3)
85 | unicode-display_width (2.4.2)
86 | webrick (1.7.0)
87 |
88 | PLATFORMS
89 | x64-mingw-ucrt
90 |
91 | DEPENDENCIES
92 | jekyll-minifier
93 | jekyll-multiple-languages-plugin
94 | jekyll-tidy
95 | tzinfo-data
96 |
97 | BUNDLED WITH
98 | 2.4.4
99 |
--------------------------------------------------------------------------------
/components/web_server/www/html/_config.yml:
--------------------------------------------------------------------------------
1 | # Exclude some folders & files
2 | baseurl: ""
3 | exclude: ["_*", "package.json", "node_modules", "Gemfile*"]
4 | destination: ../output/html
5 |
6 | # Language plugin
7 | languages: ["english"]
8 | # "german", "russian", "italian", "dutch", "chinese", "portuguese", "slovak", "polish", "estonian", "hebrew", "czech", "turkish", "indonesia"]
9 |
10 |
11 | # Jekyll tidy HTML plugin
12 | jekyll_tidy:
13 | exclude: ["*.js"]
14 |
15 |
16 | # Gem plugin(s)
17 | plugins: [jekyll-tidy, jekyll-multiple-languages-plugin, jekyll-minifier]
18 |
19 | # Compress outputted sass
20 | sass:
21 | style: compressed
22 |
23 |
24 | jekyll-minifier:
25 | compress_javascript: false
26 | exclude: "*.json"
27 | uglifier_args:
28 | harmony: true
29 |
30 |
31 | # Set port
32 | port: 4000
33 | # Enable access from local network ~ not just localhost
34 | #host: 0.0.0.0
35 |
--------------------------------------------------------------------------------
/components/web_server/www/html/_i18n/english.yml:
--------------------------------------------------------------------------------
1 | ##################################
2 | # #
3 | # TRANSLATION FILE #
4 | # #
5 | ##################################
6 | #
7 | # Format:
8 | # What is '$$'?
9 | # '$$' is a variable thats replaced with HTML
10 | # For example:
11 | # `$$click here$$` => `click here`
12 | # `translated by $$` => `translated by sam`
13 | #
14 | # DO NOT REMOVE THE INDENTATION!
15 | # The indentation is critical to YAML, so please don't change it
16 | #
17 | # Try and retain the case, for example:
18 | # If it is capitalized keep it capitalized
19 | #
20 | #
21 | # What encoding should I use?
22 | # UTF-8 ~ jekyll doesn't support any other encodings
23 | #
24 |
25 |
26 | nav:
27 | scan: "Scan"
28 | settings: "Settings"
29 | info: "Info"
30 |
31 | global:
32 | save: "Save"
33 | reset: "Reset"
34 | ssid: "SSID"
35 | password: "Password"
36 | reboot: "Reboot"
37 | guide: "Guide"
38 | footer: "Designed by Jaya Satish - @gjroots"
39 | connect: "Connect"
40 |
41 | scan:
42 | title: "Scan"
43 | selectssid: "Select SSID"
44 | card-1:
45 | header: "Scan for networks ($$)"
46 | table:
47 | signal: "Signal"
48 | security: "Security"
49 | channel: "Ch." # Try and abbreviate, column is small
50 | card-2:
51 | header: "To connect, click on the SSID, If password is less than 8, it is open."
52 | strings:
53 | A: "Open"
54 | B: "INFO: No Wi-Fi network selected!"
55 | messages:
56 | E0: "Failed to parse scan results!"
57 | E1: "ERROR: Failed to scan for networks!"
58 | E2: "Reconnect to Wi-Fi network"
59 | E3: "Failed to save settings!"
60 | E4: "ERROR: Failed to save settings!"
61 |
62 |
63 | settings:
64 | title: "Settings"
65 | card-1:
66 | header: "Customization"
67 | toggle-1: "Enable dark mode"
68 | toggle-2: "Enable LED indicator"
69 | toggle-3: "Enable Web server"
70 | toggle-4: "Enable MAC filter"
71 | card-2:
72 | header: "Admin Settings"
73 | field-1: "Username"
74 | field-2: "Password"
75 | field-3: "Login failed attempts"
76 | field-4: "Lock-out period (minutes)"
77 | card-3:
78 | header: "AP Settings"
79 | card-4:
80 | header: "STA Settings
(WPA2 Enterprise: Leave it blank for regular)"
81 | field-1: "Enterprise Username"
82 | field-2: "Enterprise Identity"
83 | card-5:
84 | header: "Static Settings"
85 | field-1: "Static IP"
86 | field-2: "Subnet Mask"
87 | field-3: "Gateway"
88 | card-6:
89 | header: "Advance Settings"
90 | field-1: "AP IP"
91 | field-2: "DNS IP"
92 | field-3: "MAC address"
93 | toggle-1: "Enable custom DNS"
94 | toggle-2: "Random MAC address"
95 |
96 |
97 | strings:
98 | A: "Are you sure reset to default settings?"
99 | B: "All changes will be lost!"
100 | messages:
101 | E0: "Failed to save settings!"
102 | E1: "Failed to reset settings!"
103 | E2: "ERROR: Failed to load settings.json"
104 | E3: "ERROR: Failed to save settings!"
105 | E4: "ERROR: Reset the settings"
106 | info:
107 | title: "Info"
108 | card-1:
109 | header: "ESP32-NAT Router +"
110 | table:
111 | A: "version"
112 | B: "Update"
113 | C: "IP / DNS"
114 | card-2:
115 | header: "Connected Users ($$)"
116 | table:
117 | A: "IP Address"
118 | B: "MAC Address"
119 | C: "Add"
120 | card-3:
121 | header: "Acknowledgements"
122 | card-4:
123 | header: "MAC Filter($$)"
124 | table:
125 | A: "ID"
126 | B: "MAC Address"
127 | C: "Remove"
128 | strings:
129 | B: "OTA update"
130 | C: "upload"
131 | D: "Other projects"
132 | E: "Report bug"
133 | F: "Other projects"
134 | messages:
135 | message-1: "file uploading Status: $$"
136 | message-2: "OTA Update Success - Restarting"
137 | message-3: "Settings have been saved."
138 | E0: "ERROR: Failed to load sysinfo.json"
139 | E1: "ERROR: OTA update ERROR"
140 | E2: "Failed to save settings!"
141 | E3: "ERROR: Failed to save settings!"
142 |
143 | error:
144 | title: "404"
145 | page-header: "Page not found"
146 |
147 | errors:
148 | bad-response: "ERROR: Bad response"
149 | E11: "Reconnect and reload this page"
150 | E12: "Reconnect to Wi-Fi network"
151 | E13: "Failed to restart Router!"
152 | E14: "Didn't receive a response!"
153 | E15: "Reconnect and reload this page"
154 | S1: "Are you sure you want to reboot?"
155 | S2: "Wi-Fi network Connected"
156 | S3: "Wi-Fi network Connected Reloading...."
157 |
--------------------------------------------------------------------------------
/components/web_server/www/html/_includes/footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {% if page.js %}{% endif %}
5 | {% if page.after-js %}{% endif %}
--------------------------------------------------------------------------------
/components/web_server/www/html/_includes/inline.js:
--------------------------------------------------------------------------------
1 | {% if page.inline-js %}{{ page.inline-js }}{% endif %}
2 | /(^|;)\s*minimal=/.test(document.cookie) && (document.body.id = "minimal");
--------------------------------------------------------------------------------
/components/web_server/www/html/_includes/nav.html:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/components/web_server/www/html/_layouts/html.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% t page.title %} - ESP32-NAT Router +
4 |
5 |
6 | {% if page.url != "/setup.html" %}{% endif %}
7 |
8 |
9 |
10 |
11 |
12 | {{ content }}
13 |
14 |