diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4e2e6d97..a7aa8881 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,7 +15,7 @@ If you don't find anything, please [open a new issue](https://github.com/khoih-p Please ensure to specify the following: * Arduino IDE version (e.g. 1.8.13) or Platform.io version -* `SAMD` Core Version (e.g. Arduino SAMD core v1.8.9, Adafruit SAMD core v1.6.4, Seeed Studio SAMD v1.8.1) +* `SAMD` Core Version (e.g. Arduino SAMD core v1.8.11, Adafruit SAMD core v1.6.5, Seeed Studio SAMD v1.8.1) * Contextual information (e.g. what you were trying to achieve) * Simplest possible steps to reproduce * Anything that might be relevant in your opinion, such as: @@ -27,9 +27,9 @@ Please ensure to specify the following: ``` Arduino IDE version: 1.8.13 -Arduino SAMD Core Version 1.8.9 +Arduino SAMD Core Version 1.8.11 OS: Ubuntu 20.04 LTS -Linux xy-Inspiron-3593 5.4.0-51-generic #56-Ubuntu SMP Mon Oct 5 14:28:49 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux +Linux xy-Inspiron-3593 5.4.0-65-generic #73-Ubuntu SMP Mon Jan 18 17:25:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux Context: The board couldn't autoreconnect to Local Blynk Server after router power recycling. diff --git a/README.md b/README.md index 6bcb70d9..d7883013 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,17 @@ ## Table of Contents * [Why do we need this WiFiManager_NINA_Lite library](#why-do-we-need-this-wifimanager_nina_lite-library) + * [Features](#features) + * [Currently supported Boards](#currently-supported-boards) + * [Currently supported WiFi shields/modules](#currently-supported-wifi-shieldsmodules) * [Changelog](#changelog) + * [Major Release v1.1.0](#major-release-v110) + * [Release v1.0.5](#release-v105) + * [Major Release v1.0.4](#major-release-v104) + * [Major Release v1.0.3](#major-release-v103) + * [Release v1.0.2](#release-v102) + * [Release v1.0.1](#release-v101) + * [Release v1.0.0](#release-v100) * [Prerequisites](#prerequisites) * [Installation](#installation) * [Use Arduino Library Manager](#use-arduino-library-manager) @@ -30,7 +40,28 @@ * [7. For STM32 boards](#7-for-stm32-boards) * [How It Works](#how-it-works) * [How to use](#how-to-use) + * [1. Basic usage](#1-basic-usage) + * [2. Add custom parameters](#2-add-custom-parameters) + * [3. Not using custom parameters](#3-not-using-custom-parameters) + * [4. To open Config Portal](#4-to-open-config-portal) + * [5. To use different AP WiFi Channel](#5-to-use-different-ap-wifi-channel) + * [6. To use different static AP IP from default](#6-to-use-different-static-ap-ip-from-default) + * [7. To use custom DHCP HostName](#7-to-use-custom-dhcp-hostname) + * [8. To use custom HTML Style](#8-to-use-custom-html-style) + * [9. To use custom Head Elements](#9-to-use-custom-head-elements) + * [10. To use CORS Header](#10-to-use-cors-header) * [Examples](#examples) + * [ 1. SAMD_WiFiNINA](examples/SAMD_WiFiNINA) + * [ 2. SAMD_WiFiNINA_MQTT](examples/SAMD_WiFiNINA_MQTT) + * [ 3. nRF52_WiFiNINA](examples/nRF52_WiFiNINA) + * [ 4. nRF52_WiFiNINA_MQTT](examples/nRF52_WiFiNINA_MQTT) + * [ 5. Teensy_WiFiNINA](examples/Teensy_WiFiNINA) + * [ 6. Teensy_WiFiNINA_MQTT](examples/Teensy_WiFiNINA_MQTT) + * [ 7. STM32_WiFiNINA](examples/STM32_WiFiNINA) + * [ 8. STM32_WiFiNINA_MQTT](examples/STM32_WiFiNINA_MQTT) + * [ 9. SAM_DUE_WiFiNINA](examples/SAM_DUE_WiFiNINA) + * [10. SAM_DUE_WiFiNINA_MQTT](examples/SAM_DUE_WiFiNINA_MQTT) + * [11. Mega_WiFiNINA](examples/Mega_WiFiNINA) * [So, how it works?](#so-how-it-works) * [Important Notes](#important-notes) * [How to use default Credentials and have them pre-loaded onto Config Portal](#how-to-use-default-credentials-and-have-them-pre-loaded-onto-config-portal) @@ -51,19 +82,13 @@ * [4. Lost a WiFi and autoconnect to another WiFi AP](#4-lost-a-wifi-and-autoconnect-to-another-wifi-ap) * [5. Reopen Config Portal if can't connect to any of the 2 WiFi APs](#5-reopen-config-portal-if-cant-connect-to-any-of-the-2-wifi-aps) * [6. DRD Not Detected](#6-drd-not-detected) - * [7. DRD detected and Config Portal is forcefully opened](#7drd-detected-and-config-portal-is-forcefully-opened) + * [7. DRD detected and Config Portal is forcefully opened](#7-drd-detected-and-config-portal-is-forcefully-opened) * [Debug](#debug) * [Troubleshooting](#troubleshooting) -* [TO DO](#to-do) -* [DONE](#done) * [Releases](#releases) - * [New Release v1.0.5](#new-release-v105-1) - * [Major Release v1.0.4](#major-release-v104-1) - * [Major Release v1.0.3](#major-release-v103-1) - * [New in v1.0.2](#new-in-v102-1) - * [New in v1.0.1](#new-in-v101-1) - * [New in v1.0.0](#new-in-v100-1) * [Issues](#issues) +* [TO DO](#to-do) +* [DONE](#done) * [Contributions and Thanks](#contributions-and-thanks) * [Contributing](#contributing) * [License](#license) @@ -74,15 +99,17 @@ ### Why do we need this [WiFiManager_NINA_Lite library](https://github.com/khoih-prog/WiFiManager_NINA_Lite) +#### Features + If you have used the full-fledge WiFiManager such as : 1. [`Tzapu WiFiManager`](https://github.com/tzapu/WiFiManager) 2. [`Ken Taylor WiFiManager`](https://github.com/kentaylor/WiFiManager) 3. [`Khoi Hoang ESP_WiFiManager`](https://github.com/khoih-prog/ESP_WiFiManager) -and have to write complicated callback functions to save custom parameters in SPIFFS, you'd appreciate the simplicity of this Light-Weight Credentials / WiFiManager. +and have to write **complicated callback functions** to save custom parameters in SPIFFS/LittleFS/EEPROM, you'd appreciate the simplicity of this Light-Weight Credentials / WiFiManager. -This library is a Light Weight Credentials / WiFi Manager for WiFiNINA modules/shields, specially designed to support **Teensy, SAM DUE, SAMD21 (Nano-33 IoT, Itsy-Bitsy M0, etc), SAMD51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.), STM32F (F1, F2, F3, F4, F7, Nucleo-144, etc.), nRF52 (Adafruit NRF52840_FEATHER, NRF52832_FEATHER, NRF52840_FEATHER_SENSE, NRF52840_ITSYBITSY, NRF52840_CIRCUITPLAY, NRF52840_CLUE, NRF52840_METRO, NRF52840_PCA10056, PARTICLE_XENON, NINA_B302_ublox, NINA_B112_ublox, etc.), etc. boards running WiFiNINA modules/shields.** with smaller memory (64+K bytes) +This library is a Light Weight Credentials / WiFi Manager for WiFiNINA (WiFiNINA, WINC1500/WiFi101, etc.) modules/shields, specially designed to support **Teensy, SAM DUE, SAMD21 (Nano-33 IoT, Itsy-Bitsy M0, etc), SAMD51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.), STM32F (F1, F2, F3, F4, F7, Nucleo-144, etc.), nRF52 (Adafruit NRF52840_FEATHER, NRF52832_FEATHER, NRF52840_FEATHER_SENSE, NRF52840_ITSYBITSY, NRF52840_CIRCUITPLAY, NRF52840_CLUE, NRF52840_METRO, NRF52840_PCA10056, PARTICLE_XENON, NINA_B302_ublox, NINA_B112_ublox, etc.), etc. boards running WiFiNINA modules/shields.** with smaller memory (64+K bytes) The AVR-family boards (UNO, Nano, etc.) are **not supported** as they don't have enough memory to run Config Portal WebServer. @@ -94,17 +121,68 @@ The web configuration portal, served from the `WiFiNINA modules/shields` is oper New recent features: -- **MultiWiFi** feature for configuring/auto(re)connecting **WiFiNINA** shields to the available MultiWiFi APs at runtime. +- **MultiWiFi** feature for configuring/auto(re)connecting **WiFiNINA (WiFiNINA, WINC1500/WiFi101, etc.)** shields to the available MultiWiFi APs at runtime. - **DoubleDetectDetector** feature to force Config Portal when double reset is detected within predetermined time, default 10s. +- **Powerful-yet-simple-to-use feature to enable adding dynamic custom parameters** from sketch and input using the same Config Portal. Config Portal will be auto-adjusted to match the number of dynamic parameters. +- Optional default **Credentials as well as Dynamic parameters to be optionally autoloaded into Config Portal** to use or change instead of manually input. +- Dynamic custom parameters to be saved **automatically in non-volatile memory, such as Teensy EEPROM, SAMD EEPROM-emulated FlashStorage_SAMD, STM32F/L/H/G/WB/MP1 EEPROM-emulated FlashStorage_STM32 or SAM DUE DueFlashStorage**. - Configurable **Config Portal Title** to be either BoardName or default undistinguishable names. - Examples are redesigned to separate Credentials / Defines / Dynamic Params / Code so that you can change Credentials / Dynamic Params quickly for each device. +- Configurable **Customs HTML Headers**, including Customs Style, Customs Gead Elements, CORS Header. + +This [**WiFiManager_NINA_Lite** library](https://github.com/khoih-prog/WiFiManager_NINA_Lite) currently supports these following boards: + + 1. **nRF52 boards**, such as **AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B302_ublox, NINA_B112_ublox, etc.** + + 2. **SAMD21** + - Arduino SAMD21: ZERO, MKRs, NANO_33_IOT, etc. + - Adafruit SAMD21 (M0): ItsyBitsy M0, Feather M0, Feather M0 Express, Metro M0 Express, Circuit Playground Express, Trinket M0, PIRkey, Hallowing M0, Crickit M0, etc. + - Seeeduino: LoRaWAN, Zero, Femto M0, XIAO M0, Wio GPS Board, etc. + + 3. **SAMD51** + - Adafruit SAMD51 (M4): Metro M4, Grand Central M4, ItsyBitsy M4, Feather M4 Express, Trellis M4, Metro M4 AirLift Lite, MONSTER M4SK Express, Hallowing M4, etc. + - Seeeduino: Wio Terminal, Grove UI Wireless + + 4. **SAM DUE** + 5. **Teensy (4.1, 4.0, 3.6, 3.5, 3,2, 3.1, 3.0)** + 6. **STM32F/L/H/G/WB/MP1 boards (with 32+K Flash)** + - Nucleo-144 + - Nucleo-64 + - Discovery + - Generic STM32F0, STM32F1, STM32F2, STM32F3, STM32F4, STM32F7 (with 64+K Flash): x8 and up + - STM32L0, STM32L1, STM32L4 + - STM32G0, STM32G4 + - STM32H7 + - STM32WB + - STM32MP1 + - LoRa boards + - 3-D printer boards + - Generic Flight Controllers + - Midatronics boards + + +#### Currently supported WiFi shields/modules + +1. WiFiNINA using [`WiFiNINA_Generic library`](https://github.com/khoih-prog/WiFiNINA_Generic) +2. WiFi101 using [`WiFi101 library v0.16.1+`](https://github.com/arduino-libraries/WiFi101) +3. U-Blox W101, W102 using [`WiFiNINA_Generic library`](https://github.com/khoih-prog/WiFiNINA_Generic) --- --- ## Changelog -### New Release v1.0.5 +#### Major Release v1.1.0 + +1. Configurable **Customs HTML Headers**, including Customs Style, Customs Gead Elements, CORS Header. +2. Add support to boards using WiFi101 library such as MKR1000 +3. Fix Config Portal Bug. +4. Add functions to control Config Portal from software or Virtual Switches. Check [How to trigger a Config Portal from code #25](https://github.com/khoih-prog/Blynk_WM/issues/25) +5. Use more efficient [FlashStorage_SAMD v1.1.0](https://github.com/khoih-prog/FlashStorage_SAMD) and [FlashStorage_STM32 v1.00](https://github.com/khoih-prog/FlashStorage_STM32) +6. Optimize code +7. Add Version String + +### Release v1.0.5 1. Modify LOAD_DEFAULT_CONFIG_DATA logic. 4. Enhance MultiWiFi connection logic. @@ -129,17 +207,17 @@ Thanks to [Thor Johnson](https://github.com/thorathome) to test, suggest and enc 5. Add option to have built-in, yet configurable RFC-952-conformed DHCP hostname. 6. Fix bug -#### New in v1.0.2 +#### Release v1.0.2 1. Fix bug 2. Add support to **SAM51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.)**. -#### New in v1.0.1 +#### Release v1.0.1 1. Use new [**WiFiNINA_Generic library**](https://github.com/khoih-prog/WiFiNINA_Generic) to provide support to many more boards (Teensy, AVR Mega, SAM DUE, SAMD51, STM32, etc.) running WiFiNINA. The original WiFiNINA library only supports Nano-33 IoT, Arduino MKR WiFi 1010, Arduino MKR VIDOR 4000 and Arduino UNO WiFi Rev.2. 2. Use new [**FlashStorage_SAMD library**](https://github.com/khoih-prog/FlashStorage_SAMD) to provide EEPROM/FlashStorage support to SAMD51 boards (Itsy-Bitsy M4, etc). -#### New in v1.0.0 +#### Release v1.0.0 1. New **powerful-yet-simple-to-use feature to enable adding dynamic custom parameters** from sketch and input using the same Config Portal. Config Portal will be auto-adjusted to match the number of dynamic parameters. 2. Dynamic custom parameters to be saved **automatically in EEPROM, SAMD EEPROM-emulated FlashStorage or SAM DUE DueFlashStorage**. @@ -150,20 +228,22 @@ Thanks to [Thor Johnson](https://github.com/thorathome) to test, suggest and enc ## Prerequisites 1. [`Arduino IDE 1.8.13+` for Arduino](https://www.arduino.cc/en/Main/Software) - 2. [`Arduino Core for STM32 v1.9.0+`](https://github.com/khoih-prog/Arduino_Core_STM32) for STM32 boards - 3. [`Teensy core 1.53+`](https://www.pjrc.com/teensy/td_download.html) for Teensy (4.1, 4.0, 3.6, 3.5, 3,2, 3.1, 3.0, LC) boards - 4. [`Arduino SAM DUE core 1.6.12+`](https://www.arduino.cc/en/Guide/ArduinoDue) for SAM DUE ARM Cortex-M3 boards - 5. [`Arduino SAMD core 1.8.10+`](https://www.arduino.cc/en/Guide/ArduinoM0) for SAMD ARM Cortex-M0+ boards - 6. [`Adafruit SAMD core 1.6.4+`](https://www.adafruit.com/) for SAMD ARM Cortex-M0+ and M4 boards (Nano 33 IoT, etc.) - 7. [`Seeeduino SAMD core 1.8.1+`](https://www.seeedstudio.com/) for SAMD21/SAMD51 boards (XIAO M0, Wio Terminal, etc.) - 8. [`Adafruit nRF52 v0.21.0+`](www.adafruit.com) for nRF52 boards such as Adafruit NRF52840_FEATHER, NRF52832_FEATHER, NRF52840_FEATHER_SENSE, NRF52840_ITSYBITSY, NRF52840_CIRCUITPLAY, NRF52840_CLUE, NRF52840_METRO, NRF52840_PCA10056, PARTICLE_XENON, **NINA_B302_ublox**, etc. + 2. [`Arduino Core for STM32 v1.9.0+`](https://github.com/stm32duino/Arduino_Core_STM32) for STM32 boards. [![GitHub release](https://img.shields.io/github/release/stm32duino/Arduino_Core_STM32.svg)](https://github.com/stm32duino/Arduino_Core_STM32/releases/latest) + 3. [`Teensy core 1.51`](https://www.pjrc.com/teensy/td_download.html) for Teensy (4.1, 4.0, 3.6, 3.5, 3,2, 3.1, 3.0, LC) boards + 4. [`Arduino SAM DUE core 1.6.12+`](https://github.com/arduino/ArduinoCore-sam) for SAM DUE ARM Cortex-M3 boards + 5. [`Arduino SAMD core 1.8.11+`](https://www.arduino.cc/en/Guide/ArduinoM0) for SAMD ARM Cortex-M0+ boards. [![GitHub release](https://img.shields.io/github/release/arduino/ArduinoCore-samd.svg)](https://github.com/arduino/ArduinoCore-samd/releases/latest) + 6. [`Adafruit SAMD core 1.6.5+`](https://www.adafruit.com/) for SAMD ARM Cortex-M0+ and M4 boards (Nano 33 IoT, etc.). [![GitHub release](https://img.shields.io/github/release/adafruit/ArduinoCore-samd.svg)](https://github.com/adafruit/ArduinoCore-samd/releases/latest) + 7. [`Seeeduino SAMD core 1.8.1+`](https://github.com/Seeed-Studio/ArduinoCore-samd) for SAMD21/SAMD51 boards (XIAO M0, Wio Terminal, etc.). [![Latest release](https://img.shields.io/github/release/Seeed-Studio/ArduinoCore-samd.svg)](https://github.com/Seeed-Studio/ArduinoCore-samd/releases/latest/) + 8. [`Adafruit nRF52 v0.21.0+`](https://www.adafruit.com) for nRF52 boards such as Adafruit NRF52840_FEATHER, NRF52832_FEATHER, NRF52840_FEATHER_SENSE, NRF52840_ITSYBITSY, NRF52840_CIRCUITPLAY, NRF52840_CLUE, NRF52840_METRO, NRF52840_PCA10056, PARTICLE_XENON, **NINA_B302_ublox**, etc. [![GitHub release](https://img.shields.io/github/release/adafruit/Adafruit_nRF52_Arduino.svg)](https://github.com/adafruit/Adafruit_nRF52_Arduino/releases/latest) 9. [`Functional-VLPP library v1.0.1+`](https://github.com/khoih-prog/functional-vlpp) to use server's lambda function. To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/Functional-Vlpp.svg?)](https://www.ardu-badge.com/Functional-Vlpp) -10. [`WiFiNINA_Generic library v1.8.0+`](https://github.com/khoih-prog/WiFiNINA_Generic). To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/WiFiNINA_Generic.svg?)](https://www.ardu-badge.com/WiFiNINA_Generic) -11. [`WiFiWebServer library v1.1.0+`](https://github.com/khoih-prog/WiFiWebServer). To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/WiFiWebServer.svg?)](https://www.ardu-badge.com/WiFiWebServer) -12. [`FlashStorage_SAMD library v1.0.0+`](https://github.com/khoih-prog/FlashStorage_SAMD) for SAMD21 and SAMD51 boards (ZERO, MKR, NANO_33_IOT, M0, M0 Pro, AdaFruit Itsy-Bitsy M4, etc.) -13. [`DueFlashStorage library v1.0.0+`](https://github.com/sebnil/DueFlashStorage) for SAM DUE -14. [`Adafruit's LittleFS/InternalFS`](www.adafruit.com) for nRF52 -15. [`DoubleResetDetector_Generic v1.0.2+`](https://github.com/khoih-prog/DoubleResetDetector_Generic). To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/DoubleResetDetector_Generic.svg?)](https://www.ardu-badge.com/DoubleResetDetector_Generic) +10. [`WiFiNINA_Generic library v1.8.2+`](https://github.com/khoih-prog/WiFiNINA_Generic). To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/WiFiNINA_Generic.svg?)](https://www.ardu-badge.com/WiFiNINA_Generic) +11. [`WiFi101 library v0.16.1+`](https://github.com/arduino-libraries/WiFi101) if using WINC1500/WiFi101 shields (MKR1000, etc.). To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/WiFi101.svg?)](https://www.ardu-badge.com/WiFi101) +12. [`WiFiWebServer library v1.1.1+`](https://github.com/khoih-prog/WiFiWebServer). To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/WiFiWebServer.svg?)](https://www.ardu-badge.com/WiFiWebServer) +13. [`FlashStorage_SAMD library v1.1.0+`](https://github.com/khoih-prog/FlashStorage_SAMD) for SAMD21 and SAMD51 boards (ZERO, MKR, NANO_33_IOT, M0, M0 Pro, AdaFruit Itsy-Bitsy M4, etc.). [![GitHub release](https://img.shields.io/github/release/khoih-prog/FlashStorage_SAMD.svg)](https://github.com/khoih-prog/FlashStorage_SAMD/releases/latest) +14. [`FlashStorage_STM32 library v1.0.0+`](https://github.com/khoih-prog/FlashStorage_STM32) for STM32F/L/H/G/WB/MP1 boards. To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/FlashStorage_STM32.svg?)](https://www.ardu-badge.com/FlashStorage_STM32) +15. [`DueFlashStorage library v1.0+`](https://github.com/sebnil/DueFlashStorage) for SAM DUE. To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/DueFlashStorage.svg?)](https://www.ardu-badge.com/DueFlashStorage) +16. [`Adafruit's LittleFS/InternalFS`](www.adafruit.com) for nRF52 +17. [`DoubleResetDetector_Generic v1.0.3+`](https://github.com/khoih-prog/DoubleResetDetector_Generic). To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/DoubleResetDetector_Generic.svg?)](https://www.ardu-badge.com/DoubleResetDetector_Generic) --- @@ -219,16 +299,22 @@ These files must be copied into the directory: #### 2. For Teensy boards - **To be able to compile and run on Teensy boards**, you have to copy the file [Teensy boards.txt](Packages_Patches/hardware/teensy/avr/boards.txt) into Teensy hardware directory (./arduino-1.8.12/hardware/teensy/avr/boards.txt). + **To be able to compile and run on Teensy boards**, you have to copy the files in [**Packages_Patches for Teensy directory**](Packages_Patches/hardware/teensy/avr) into Teensy hardware directory (./arduino-1.8.13/hardware/teensy/avr/boards.txt). -Supposing the Arduino version is 1.8.12. This file must be copied into the directory: +Supposing the Arduino version is 1.8.13. These files must be copied into the directory: -- `./arduino-1.8.12/hardware/teensy/avr/boards.txt` +- `./arduino-1.8.13/hardware/teensy/avr/boards.txt` +- `./arduino-1.8.13/hardware/teensy/avr/cores/teensy/Stream.h` +- `./arduino-1.8.13/hardware/teensy/avr/cores/teensy3/Stream.h` +- `./arduino-1.8.13/hardware/teensy/avr/cores/teensy4/Stream.h` Whenever a new version is installed, remember to copy this file into the new version directory. For example, new version is x.yy.zz -This file must be copied into the directory: +These files must be copied into the directory: - `./arduino-x.yy.zz/hardware/teensy/avr/boards.txt` +- `./arduino-x.yy.zz/hardware/teensy/avr/cores/teensy/Stream.h` +- `./arduino-x.yy.zz/hardware/teensy/avr/cores/teensy3/Stream.h` +- `./arduino-x.yy.zz/hardware/teensy/avr/cores/teensy4/Stream.h` #### 3. For Arduino SAM DUE boards @@ -249,9 +335,9 @@ This file must be copied into the directory: #### For core version v1.8.10+ -Supposing the Arduino SAMD version is 1.8.10. Now only one file must be copied into the directory: +Supposing the Arduino SAMD version is 1.8.11. Now only one file must be copied into the directory: -- `~/.arduino15/packages/arduino/hardware/samd/1.8.10/platform.txt` +- `~/.arduino15/packages/arduino/hardware/samd/1.8.11/platform.txt` Whenever a new version is installed, remember to copy this files into the new version directory. For example, new version is x.yy.zz @@ -345,12 +431,14 @@ theses files must be copied into the corresponding directory: ### How to use +#### 1. Basic usage + - Include in your sketch ```cpp // Must be before #include // Start location in EEPROM to store config data. Default 0 -// Config data Siz, not including your custom data, currently is 84 bytes) +// Config data Size, not including your custom data, currently is 84 bytes) #define EEPROM_START 0 #include @@ -358,6 +446,8 @@ theses files must be copied into the corresponding directory: WiFiManager_NINA_Lite* WiFiManager_NINA; ``` +#### 2. Add custom parameters + - To add custom parameters, just add ``` @@ -402,8 +492,8 @@ MenuItem myMenuItems [] = { "tk1", "Token1", Blynk_Token1, MAX_BLYNK_TOKEN_LEN }, { "sv2", "Blynk Server2", Blynk_Server2, MAX_BLYNK_SERVER_LEN }, { "tk2", "Token2", Blynk_Token2, MAX_BLYNK_TOKEN_LEN }, - { "pt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, - { "mq", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "prt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, + { "mqt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, }; uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; @@ -418,12 +508,16 @@ uint16_t NUM_MENU_ITEMS = 0; ``` +#### 3. Not using custom parameters + - If you don't need to add dynamic parameters, use the following in sketch ``` #define USE_DYNAMIC_PARAMETERS false ``` +#### 4. To open Config Portal + - When you want to open a config portal, just add ```cpp @@ -431,19 +525,31 @@ WiFiManager_NINA = new WiFiManager_NINA_Lite(); WiFiManager_NINA->begin(); ``` -- To not use default AP WiFi Channel 10 to avoid conflict with other WiFi APs, call +#### 5. To use different AP WiFi Channel + +- To not use default AP WiFi Channel 10 to avoid conflict with other WiFi APs : ```cpp WiFiManager_NINA->setConfigPortalChannel(newChannel); ``` +- To use random AP WiFi Channel to avoid conflict with other WiFi APs : + +```cpp +WiFiManager_NINA->setConfigPortalChannel(0); +``` + +#### 6. To use different static AP IP from default + - To use different static AP IP (not use default `192.168.4.1`), call ```cpp WiFiManager_NINA->setConfigPortalIP(IPAddress(xxx,xxx,xxx,xxx)); ``` -- To set custom DHCP HostName, cal +#### 7. To use custom DHCP HostName + +- To set custom DHCP HostName : ``` // Set customized DHCP HostName @@ -457,6 +563,30 @@ or just use the default Hostname, for example "SAMD-WiFiNINA-XXXXXX" for SAMD //WiFiManager_NINA->begin(); ``` +#### 8. To use custom HTML Style + +``` +const char NewCustomsStyle[] /*PROGMEM*/ = ""; + +... + +WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +``` + +#### 9. To use custom Head Elements + + +``` +WiFiManager_NINA->setCustomsHeadElement(""); +``` + +#### 10. To use CORS Header + +``` +WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +``` + While in AP mode, connect to it using its `SSID` (WIFININA_XXXXXX) / `Password` ("MyWIFININA_XXXXXX"), then open a browser to the Portal AP IP, default `192.168.4.1`, configure wifi then click **Save**. The Credentials / WiFi connection information will be saved in non-volatile memory. It will then autoconnect. @@ -620,7 +750,12 @@ Example of [Default dynamicParams](examples/SAMD_WiFiNINA/dynamicParams.h) - To add custom parameters, just modify the example below ``` -#define USE_DYNAMIC_PARAMETERS true +#ifndef dynamicParams_h +#define dynamicParams_h + +#include "defines.h" + +// USE_DYNAMIC_PARAMETERS defined in defined.h /////////////// Start dynamic Credentials /////////////// @@ -661,8 +796,8 @@ MenuItem myMenuItems [] = { "tk1", "Token1", Blynk_Token1, MAX_BLYNK_TOKEN_LEN }, { "sv2", "Blynk Server2", Blynk_Server2, MAX_BLYNK_SERVER_LEN }, { "tk2", "Token2", Blynk_Token2, MAX_BLYNK_TOKEN_LEN }, - { "pt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, - { "mq", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "prt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, + { "mqt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, }; uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; @@ -675,6 +810,9 @@ uint16_t NUM_MENU_ITEMS = 0; #endif //USE_DYNAMIC_PARAMETERS + +#endif //dynamicParams_h + ``` - If you don't need to add dynamic parameters, use the following in sketch @@ -758,20 +896,39 @@ void check_status() WiFiManager_NINA_Lite* WiFiManager_NINA; +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + void setup() { // Debug console Serial.begin(115200); while (!Serial); - Serial.println("\nStart SAMD_WiFiNINA on " + String(BOARD_TYPE)); + delay(200); + Serial.print(F("\nStarting SAMD_WiFiNINA on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); WiFiManager_NINA = new WiFiManager_NINA_Lite(); // Optional to change default AP IP(192.168.4.1) and channel(10) //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); - //WiFiManager_NINA->setConfigPortalChannel(1); + WiFiManager_NINA->setConfigPortalChannel(0); + +#if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif // Set customized DHCP HostName WiFiManager_NINA->begin(HOST_NAME); @@ -781,23 +938,20 @@ void setup() } #if USE_DYNAMIC_PARAMETERS -void displayCredentials(void) +void displayCredentials() { - Serial.println("\nYour stored Credentials :"); + Serial.println(F("\nYour stored Credentials :")); - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); } } -#endif -void loop() +void displayCredentialsInLoop() { - WiFiManager_NINA->run(); - check_status(); - -#if USE_DYNAMIC_PARAMETERS static bool displayedCredentials = false; if (!displayedCredentials) @@ -816,7 +970,18 @@ void loop() } } } +} + #endif + +void loop() +{ + WiFiManager_NINA->run(); + check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif } ``` --- @@ -828,71 +993,71 @@ void loop() #define defines_h /* Comment this out to disable prints and save space */ -#define DEBUG_WIFI_WEBSERVER_PORT Serial -#define WIFININA_DEBUG_OUTPUT Serial +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial -#define WIFININA_DEBUG true +#define _WIFININA_LOGLEVEL_ 2 -#define DRD_GENERIC_DEBUG true +#define DRD_GENERIC_DEBUG true #if ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ || defined(__SAMD51G19A__) || defined(__SAMD21G18A__) ) -#if defined(WIFININA_USE_SAMD) -#undef WIFININA_USE_SAMD -#undef WIFI_USE_SAMD -#endif -#define WIFININA_USE_SAMD true -#define WIFI_USE_SAMD true + #if defined(WIFININA_USE_SAMD) + #undef WIFININA_USE_SAMD + #undef WIFI_USE_SAMD + #endif + #define WIFININA_USE_SAMD true + #define WIFI_USE_SAMD true #else -#error This code is intended to run only on the SAMD boards ! Please check your Tools->Board setting. + #error This code is intended to run only on the SAMD boards ! Please check your Tools->Board setting. #endif #if defined(WIFININA_USE_SAMD) -#if defined(ARDUINO_SAMD_ZERO) -#define BOARD_TYPE "SAMD Zero" -#elif defined(ARDUINO_SAMD_MKR1000) -#define BOARD_TYPE "SAMD MKR1000" -#elif defined(ARDUINO_SAMD_MKRWIFI1010) -#define BOARD_TYPE "SAMD MKRWIFI1010" -#elif defined(ARDUINO_SAMD_NANO_33_IOT) -#define BOARD_TYPE "SAMD NANO_33_IOT" -#elif defined(ARDUINO_SAMD_MKRFox1200) -#define BOARD_TYPE "SAMD MKRFox1200" -#elif ( defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) ) -#define BOARD_TYPE "SAMD MKRWAN13X0" -#elif defined(ARDUINO_SAMD_MKRGSM1400) -#define BOARD_TYPE "SAMD MKRGSM1400" -#elif defined(ARDUINO_SAMD_MKRNB1500) -#define BOARD_TYPE "SAMD MKRNB1500" -#elif defined(ARDUINO_SAMD_MKRVIDOR4000) -#define BOARD_TYPE "SAMD MKRVIDOR4000" -#elif defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) -#define BOARD_TYPE "SAMD ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS" -#elif defined(ADAFRUIT_ITSYBITSY_M4_EXPRESS) -#define BOARD_TYPE "SAMD ADAFRUIT_ITSYBITSY_M4_EXPRESS" -#elif defined(__SAMD21E18A__) -#define BOARD_TYPE "SAMD21E18A" -#elif defined(__SAMD21G18A__) -#define BOARD_TYPE "SAMD21G18A" -#elif defined(__SAMD51G19A__) -#define BOARD_TYPE "SAMD51G19A" -#elif defined(__SAMD51J19A__) -#define BOARD_TYPE "SAMD51J19A" -#elif defined(__SAMD51J20A__) -#define BOARD_TYPE "SAMD51J20A" -#elif defined(__SAM3X8E__) -#define BOARD_TYPE "SAM3X8E" -#elif defined(__CPU_ARC__) -#define BOARD_TYPE "CPU_ARC" -#elif defined(__SAMD51__) -#define BOARD_TYPE "SAMD51" -#else -#define BOARD_TYPE "SAMD Unknown" -#endif + #if defined(ARDUINO_SAMD_ZERO) + #define BOARD_TYPE "SAMD Zero" + #elif defined(ARDUINO_SAMD_MKR1000) + #define BOARD_TYPE "SAMD MKR1000" + #elif defined(ARDUINO_SAMD_MKRWIFI1010) + #define BOARD_TYPE "SAMD MKRWIFI1010" + #elif defined(ARDUINO_SAMD_NANO_33_IOT) + #define BOARD_TYPE "SAMD NANO_33_IOT" + #elif defined(ARDUINO_SAMD_MKRFox1200) + #define BOARD_TYPE "SAMD MKRFox1200" + #elif ( defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) ) + #define BOARD_TYPE "SAMD MKRWAN13X0" + #elif defined(ARDUINO_SAMD_MKRGSM1400) + #define BOARD_TYPE "SAMD MKRGSM1400" + #elif defined(ARDUINO_SAMD_MKRNB1500) + #define BOARD_TYPE "SAMD MKRNB1500" + #elif defined(ARDUINO_SAMD_MKRVIDOR4000) + #define BOARD_TYPE "SAMD MKRVIDOR4000" + #elif defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) + #define BOARD_TYPE "SAMD ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS" + #elif defined(ADAFRUIT_ITSYBITSY_M4_EXPRESS) + #define BOARD_TYPE "SAMD ADAFRUIT_ITSYBITSY_M4_EXPRESS" + #elif defined(__SAMD21E18A__) + #define BOARD_TYPE "SAMD21E18A" + #elif defined(__SAMD21G18A__) + #define BOARD_TYPE "SAMD21G18A" + #elif defined(__SAMD51G19A__) + #define BOARD_TYPE "SAMD51G19A" + #elif defined(__SAMD51J19A__) + #define BOARD_TYPE "SAMD51J19A" + #elif defined(__SAMD51J20A__) + #define BOARD_TYPE "SAMD51J20A" + #elif defined(__SAM3X8E__) + #define BOARD_TYPE "SAM3X8E" + #elif defined(__CPU_ARC__) + #define BOARD_TYPE "CPU_ARC" + #elif defined(__SAMD51__) + #define BOARD_TYPE "SAMD51" + #else + #define BOARD_TYPE "SAMD Unknown" + #endif #endif @@ -901,7 +1066,74 @@ void loop() #define EEPROM_START 0 #define EEPROM_SIZE (2 * 1024) -#include "WiFiNINA_Pinout_Generic.h" +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// #include @@ -947,7 +1179,7 @@ typedef struct Configuration } WiFiNINA_Configuration; */ -#define TO_LOAD_DEFAULT_CONFIG_DATA true +#define TO_LOAD_DEFAULT_CONFIG_DATA false #if TO_LOAD_DEFAULT_CONFIG_DATA @@ -962,6 +1194,7 @@ typedef struct Configuration // Config Portal data input will be override DEFAULT_CONFIG_DATA bool LOAD_DEFAULT_CONFIG_DATA = false; + WiFiNINA_Configuration defaultConfig = { //char header[16], dummy, not used @@ -1001,7 +1234,7 @@ WiFiNINA_Configuration defaultConfig; #include "defines.h" -#define USE_DYNAMIC_PARAMETERS true +// USE_DYNAMIC_PARAMETERS defined in defined.h /////////////// Start dynamic Credentials /////////////// @@ -1042,8 +1275,8 @@ MenuItem myMenuItems [] = { "tk1", "Token1", Blynk_Token1, MAX_BLYNK_TOKEN_LEN }, { "sv2", "Blynk Server2", Blynk_Server2, MAX_BLYNK_SERVER_LEN }, { "tk2", "Token2", Blynk_Token2, MAX_BLYNK_TOKEN_LEN }, - { "pt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, - { "mq", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "prt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, + { "mqt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, }; uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; @@ -1059,6 +1292,7 @@ uint16_t NUM_MENU_ITEMS = 0; #endif //dynamicParams_h ``` + --- --- @@ -1070,39 +1304,40 @@ This is the terminal output when running [**SAMD_WiFiNINA**](examples/SAMD_WiFiN #### 1. Open Config Portal ``` -Start SAMD_WiFiNINA on SAMD NANO_33_IOT -*NN: Hostname=SAMD-Master-Controller +Starting SAMD_WiFiNINA on SAMD NANO_33_IOT +WiFiManager_NINA_Lite v1.1.0 +[WN] Hostname=SAMD-Master-Controller Flag read = 0xffffffff No doubleResetDetected SetFlag write = 0xd0d01234 -*NN: ======= Start Default Config Data ======= -*NN: Hdr=WIFININA,SSID=SSID1,PW=password1 -*NN: SSID1=SSID2,PW1=password2 -*NN: BName=SAMD-Control -*NN: i=0,id=sv1,data=account.duckdns.org -*NN: i=1,id=tk1,data=token1 -*NN: i=2,id=sv2,data=account.ddns.net -*NN: i=3,id=tk2,data=token2 -*NN: i=4,id=pt,data=8080 -*NN: i=5,id=mq,data=mqtt.duckdns.org -*NN: ChkCrR:CrCCsum=0xaf50,CrRCsum=0xffffffff -*NN: CCSum=0x1360,RCSum=0x0 -*NN: Invalid Stored Dynamic Data. Load default from Sketch -*NN: SaveEEPROM,sz=1024,Datasz=0,CSum=0x109a -*NN: CrCCSum=0x1981 -*NN: ======= Start Loaded Config Data ======= -*NN: Hdr=WIFININA,SSID=SSID1,PW=password1 -*NN: SSID1=SSID2,PW1=password2 -*NN: BName=SAMD-Control -*NN: i=0,id=sv1,data=account.duckdns.org -*NN: i=1,id=tk1,data=token1 -*NN: i=2,id=sv2,data=account.ddns.net -*NN: i=3,id=tk2,data=token2 -*NN: i=4,id=pt,data=8080 -*NN: i=5,id=mq,data=mqtt.duckdns.org -*NN: b:StayInCfgPortal:NoCfgDat -*NN: SSID=WIFININA_51F485,PW=MyWIFININA_51F485 -*NN: IP=192.168.4.1,CH=10 +[WN] ======= Start Default Config Data ======= +[WN] Hdr=WIFININA,SSID=SSID1,PW=password1 +[WN] SSID1=SSID2,PW1=password2 +[WN] BName=SAMD-Control +[WN] i=0,id=sv1,data=account.duckdns.org +[WN] i=1,id=tk1,data=token1 +[WN] i=2,id=sv2,data=account.ddns.net +[WN] i=3,id=tk2,data=token2 +[WN] i=4,id=pt,data=8080 +[WN] i=5,id=mq,data=mqtt.duckdns.org +[WN] ChkCrR:CrCCsum=0xaf50,CrRCsum=0xffffffff +[WN] CCSum=0x1360,RCSum=0x0 +[WN] Invalid Stored Dynamic Data. Load default from Sketch +[WN] SaveEEPROM,sz=1024,Datasz=0,CSum=0x109a +[WN] CrCCSum=0x1981 +[WN] ======= Start Loaded Config Data ======= +[WN] Hdr=WIFININA,SSID=SSID1,PW=password1 +[WN] SSID1=SSID2,PW1=password2 +[WN] BName=SAMD-Control +[WN] i=0,id=sv1,data=account.duckdns.org +[WN] i=1,id=tk1,data=token1 +[WN] i=2,id=sv2,data=account.ddns.net +[WN] i=3,id=tk2,data=token2 +[WN] i=4,id=pt,data=8080 +[WN] i=5,id=mq,data=mqtt.duckdns.org +[WN] b:StayInCfgPortal:NoCfgDat +[WN] SSID=WIFININA_51F485,PW=MyWIFININA_51F485 +[WN] IP=192.168.4.1,CH=10 WiFi-beginAP3: return1 = 7 WiFi-beginAP3: return2 = 7 F @@ -1122,20 +1357,21 @@ FFFFFFFFF ``` Start SAMD_WiFiNINA on SAMD NANO_33_IOT -*NN: Hostname=SAMD-WIFININA51F485 -*NN: CrCCSum=44880,CrRCSum=-1 -*NN: CCSum=53040,RCSum=-1 -*NN: InitEEPROM,sz=1024,Datasz=392 -*NN: pdata=blank,len=34 -*NN: pdata=blank,len=34 -*NN: pdata=blank,len=34 -*NN: pdata=blank,len=34 -*NN: pdata=blank,len=6 -*NN: pdata=blank,len=34 -*NN: CrCCSum=3120 -*NN: b:OpenPortal -*NN: SSID=WIFININA_B18D0F,PW=MyWIFININA_B18D0F -*NN: IP=192.168.4.1,CH=10 +WiFiManager_NINA_Lite v1.1.0 +[WN] Hostname=SAMD-WIFININA51F485 +[WN] CrCCSum=44880,CrRCSum=-1 +[WN] CCSum=53040,RCSum=-1 +[WN] InitEEPROM,sz=1024,Datasz=392 +[WN] pdata=blank,len=34 +[WN] pdata=blank,len=34 +[WN] pdata=blank,len=34 +[WN] pdata=blank,len=34 +[WN] pdata=blank,len=6 +[WN] pdata=blank,len=34 +[WN] CrCCSum=3120 +[WN] b:OpenPortal +[WN] SSID=WIFININA_B18D0F,PW=MyWIFININA_B18D0F +[WN] IP=192.168.4.1,CH=10 WiFi-beginAP3: return1 = 7 WiFi-beginAP3: return2 = 7 FYour stored Credentials : @@ -1146,66 +1382,67 @@ Token2 = blank Port = blank MQTT Server = blank FFFFFFFFF -*NN: h:sv1=BlynkServer1 -*NN: h:tk1=Token1 -*NN: h:sv2=BlynkServer2 -*NN: h:tk2=Token2 -*NN: h:pt=8080 -*NN: h:mq=mqtt-server -*NN: h:UpdEEPROM -*NN: SaveEEPROM,sz=1024,Datasz=392,CSum=3612 -*NN: pdata=BlynkServer1,len=34 -*NN: pdata=Token1,len=34 -*NN: pdata=BlynkServer2,len=34 -*NN: pdata=Token2,len=34 -*NN: pdata=8080,len=6 -*NN: pdata=mqtt-server,len=34 -*NN: CrCCSum=4880 -*NN: h:Rst +[WN] h:sv1=BlynkServer1 +[WN] h:tk1=Token1 +[WN] h:sv2=BlynkServer2 +[WN] h:tk2=Token2 +[WN] h:pt=8080 +[WN] h:mq=mqtt-server +[WN] h:UpdEEPROM +[WN] SaveEEPROM,sz=1024,Datasz=392,CSum=3612 +[WN] pdata=BlynkServer1,len=34 +[WN] pdata=Token1,len=34 +[WN] pdata=BlynkServer2,len=34 +[WN] pdata=Token2,len=34 +[WN] pdata=8080,len=6 +[WN] pdata=mqtt-server,len=34 +[WN] CrCCSum=4880 +[WN] h:Rst ``` #### 3. Got valid Credential from Config Portal, then connected to WiFi ``` Start SAMD_WiFiNINA on SAMD NANO_33_IOT -*NN: Hostname=SAMD-Master-Controller +WiFiManager_NINA_Lite v1.1.0 +[WN] Hostname=SAMD-Master-Controller Flag read = 0xd0d04321 No doubleResetDetected SetFlag write = 0xd0d01234 -*NN: ======= Start Default Config Data ======= -*NN: Hdr=WIFININA,SSID=SSID1,PW=password1 -*NN: SSID1=SSID2,PW1=password2 -*NN: BName=SAMD-Control -*NN: i=0,id=sv1,data=account.duckdns.org -*NN: i=1,id=tk1,data=token1 -*NN: i=2,id=sv2,data=account.ddns.net -*NN: i=3,id=tk2,data=token2 -*NN: i=4,id=pt,data=8080 -*NN: i=5,id=mq,data=mqtt.duckdns.org -*NN: ChkCrR:CrCCsum=0x21ce,CrRCsum=0x21ce -*NN: CCSum=0x1246,RCSum=0x1246 -*NN: CrCCsum=0x21ce,CrRCsum=0x21ce -*NN: Valid Stored Dynamic Data -*NN: ======= Start Stored Config Data ======= -*NN: Hdr=WIFININA,SSID=HueNet1,PW=**** -*NN: SSID1=HueNet2,PW1=**** -*NN: BName=Air-Control -*NN: i=0,id=sv1,data=new_account.duckdns.org -*NN: i=1,id=tk1,data=new_token1 -*NN: i=2,id=sv2,data=new_account.ddns.net -*NN: i=3,id=tk2,data=new_token2 -*NN: i=4,id=pt,data=8080 -*NN: i=5,id=mq,data=new_mqtt.duckdns.org -*NN: ConMultiWifi -*NN: con2WF:SSID=HueNet1,PW=**** -*NN: Remaining retry_time=3 +[WN] ======= Start Default Config Data ======= +[WN] Hdr=WIFININA,SSID=SSID1,PW=password1 +[WN] SSID1=SSID2,PW1=password2 +[WN] BName=SAMD-Control +[WN] i=0,id=sv1,data=account.duckdns.org +[WN] i=1,id=tk1,data=token1 +[WN] i=2,id=sv2,data=account.ddns.net +[WN] i=3,id=tk2,data=token2 +[WN] i=4,id=pt,data=8080 +[WN] i=5,id=mq,data=mqtt.duckdns.org +[WN] ChkCrR:CrCCsum=0x21ce,CrRCsum=0x21ce +[WN] CCSum=0x1246,RCSum=0x1246 +[WN] CrCCsum=0x21ce,CrRCsum=0x21ce +[WN] Valid Stored Dynamic Data +[WN] ======= Start Stored Config Data ======= +[WN] Hdr=WIFININA,SSID=HueNet1,PW=**** +[WN] SSID1=HueNet2,PW1=**** +[WN] BName=Air-Control +[WN] i=0,id=sv1,data=new_account.duckdns.org +[WN] i=1,id=tk1,data=new_token1 +[WN] i=2,id=sv2,data=new_account.ddns.net +[WN] i=3,id=tk2,data=new_token2 +[WN] i=4,id=pt,data=8080 +[WN] i=5,id=mq,data=new_mqtt.duckdns.org +[WN] ConMultiWifi +[WN] con2WF:SSID=HueNet1,PW=**** +[WN] Remaining retry_time=3 WiFi-begin: return1 = 3 WiFi-begin: return2 = 3 -*NN: WOK, lastConnectedIndex=0 -*NN: con2WF:OK -*NN: SSID=HueNet1,RSSI=-21 -*NN: IP=192.168.2.105 -*NN: b:WOK +[WN] WOK, lastConnectedIndex=0 +[WN] con2WF:OK +[WN] SSID=HueNet1,RSSI=-21 +[WN] IP=192.168.2.105 +[WN] b:WOK Stop doubleResetDetecting ClearFlag write = 0xd0d04321 H @@ -1224,19 +1461,19 @@ HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHH #### 4. Lost a WiFi and autoconnect to another WiFi AP ``` -*NN: r:Check&WLost <=== Lost primary WiFi -*NN: r:WLost.ReconW -*NN: ConMultiWifi -*NN: Using index=1, lastConnectedIndex=0 -*NN: con2WF:SSID=HueNet2,PW=**** <=== Connect secondary WiFi -*NN: Remaining retry_time=2 +[WN] r:Check&WLost <=== Lost primary WiFi +[WN] r:WLost.ReconW +[WN] ConMultiWifi +[WN] Using index=1, lastConnectedIndex=0 +[WN] con2WF:SSID=HueNet2,PW=**** <=== Connect secondary WiFi +[WN] Remaining retry_time=2 WiFi-begin: return1 = 3 WiFi-begin: return2 = 3 -*NN: WOK, lastConnectedIndex=1 -*NN: con2WF:OK <=== Success -*NN: SSID=HueNet2,RSSI=-48 -*NN: IP=192.168.2.105 -*NN: r:WOK +[WN] WOK, lastConnectedIndex=1 +[WN] con2WF:OK <=== Success +[WN] SSID=HueNet2,RSSI=-48 +[WN] IP=192.168.2.105 +[WN] r:WOK HHHHHHHHHH HHHHHHHHHH ``` @@ -1244,50 +1481,51 @@ HHHHHHHHHH HHHHHHHHHH ``` Start SAMD_WiFiNINA on SAMD NANO_33_IOT -*NN: Hostname=SAMD-Master-Controller +WiFiManager_NINA_Lite v1.1.0 +[WN] Hostname=SAMD-Master-Controller Flag read = 0xd0d04321 No doubleResetDetected SetFlag write = 0xd0d01234 -*NN: ======= Start Default Config Data ======= -*NN: Hdr=WIFININA,SSID=SSID1,PW=password1 -*NN: SSID1=SSID2,PW1=password2 -*NN: BName=SAMD-Control -*NN: i=0,id=sv1,data=account.duckdns.org -*NN: i=1,id=tk1,data=token1 -*NN: i=2,id=sv2,data=account.ddns.net -*NN: i=3,id=tk2,data=token2 -*NN: i=4,id=pt,data=8080 -*NN: i=5,id=mq,data=mqtt.duckdns.org -*NN: ChkCrR:CrCCsum=0x21ce,CrRCsum=0x21ce -*NN: CCSum=0x1246,RCSum=0x1246 -*NN: CrCCsum=0x21ce,CrRCsum=0x21ce -*NN: Valid Stored Dynamic Data -*NN: ======= Start Stored Config Data ======= -*NN: Hdr=WIFININA,SSID=HueNet1,PW=**** -*NN: SSID1=HueNet2,PW1=**** -*NN: BName=Air-Control -*NN: i=0,id=sv1,data=new_account.duckdns.org -*NN: i=1,id=tk1,data=new_token1 -*NN: i=2,id=sv2,data=new_account.ddns.net -*NN: i=3,id=tk2,data=new_token2 -*NN: i=4,id=pt,data=8080 -*NN: i=5,id=mq,data=new_mqtt.duckdns.org -*NN: ConMultiWifi -*NN: con2WF:SSID=SSID,PW=password -*NN: Remaining retry_time=3 +[WN] ======= Start Default Config Data ======= +[WN] Hdr=WIFININA,SSID=SSID1,PW=password1 +[WN] SSID1=SSID2,PW1=password2 +[WN] BName=SAMD-Control +[WN] i=0,id=sv1,data=account.duckdns.org +[WN] i=1,id=tk1,data=token1 +[WN] i=2,id=sv2,data=account.ddns.net +[WN] i=3,id=tk2,data=token2 +[WN] i=4,id=pt,data=8080 +[WN] i=5,id=mq,data=mqtt.duckdns.org +[WN] ChkCrR:CrCCsum=0x21ce,CrRCsum=0x21ce +[WN] CCSum=0x1246,RCSum=0x1246 +[WN] CrCCsum=0x21ce,CrRCsum=0x21ce +[WN] Valid Stored Dynamic Data +[WN] ======= Start Stored Config Data ======= +[WN] Hdr=WIFININA,SSID=HueNet1,PW=**** +[WN] SSID1=HueNet2,PW1=**** +[WN] BName=Air-Control +[WN] i=0,id=sv1,data=new_account.duckdns.org +[WN] i=1,id=tk1,data=new_token1 +[WN] i=2,id=sv2,data=new_account.ddns.net +[WN] i=3,id=tk2,data=new_token2 +[WN] i=4,id=pt,data=8080 +[WN] i=5,id=mq,data=new_mqtt.duckdns.org +[WN] ConMultiWifi +[WN] con2WF:SSID=SSID,PW=password +[WN] Remaining retry_time=3 WiFi-begin: return1 = 4 WiFi-begin: return2 = 4 -*NN: Remaining retry_time=2 +[WN] Remaining retry_time=2 WiFi-begin: return1 = 4 WiFi-begin: return2 = 4 -*NN: Remaining retry_time=1 +[WN] Remaining retry_time=1 WiFi-begin: return1 = 4 WiFi-begin: return2 = 4 -*NN: Failed using index=0, retry_time=0 -*NN: con2WF:failed -*NN: b:NoW -*NN: SSID=WIFININA_51F485,PW=MyWIFININA_51F485 -*NN: IP=192.168.4.1,CH=10 +[WN] Failed using index=0, retry_time=0 +[WN] con2WF:failed +[WN] b:NoW +[WN] SSID=WIFININA_51F485,PW=MyWIFININA_51F485 +[WN] IP=192.168.4.1,CH=10 WiFi-beginAP3: return1 = 7 WiFi-beginAP3: return2 = 7 Stop doubleResetDetecting @@ -1307,44 +1545,45 @@ FF ``` Start SAMD_WiFiNINA on SAMD NANO_33_IOT -*NN: Hostname=SAMD-Master-Controller +WiFiManager_NINA_Lite v1.1.0 +[WN] Hostname=SAMD-Master-Controller Flag read = 0xd0d04321 No doubleResetDetected SetFlag write = 0xd0d01234 -*NN: ======= Start Default Config Data ======= -*NN: Hdr=WIFININA,SSID=SSID1,PW=password1 -*NN: SSID1=SSID2,PW1=password2 -*NN: BName=SAMD-Control -*NN: i=0,id=sv1,data=account.duckdns.org -*NN: i=1,id=tk1,data=token1 -*NN: i=2,id=sv2,data=account.ddns.net -*NN: i=3,id=tk2,data=token2 -*NN: i=4,id=pt,data=8080 -*NN: i=5,id=mq,data=mqtt.duckdns.org -*NN: ChkCrR:CrCCsum=0x21ce,CrRCsum=0x21ce -*NN: CCSum=0x1246,RCSum=0x1246 -*NN: CrCCsum=0x21ce,CrRCsum=0x21ce -*NN: Valid Stored Dynamic Data -*NN: ======= Start Stored Config Data ======= -*NN: Hdr=WIFININA,SSID=HueNet1,PW=**** -*NN: SSID1=HueNet2,PW1=**** -*NN: BName=Air-Control -*NN: i=0,id=sv1,data=new_account.duckdns.org -*NN: i=1,id=tk1,data=new_token1 -*NN: i=2,id=sv2,data=new_account.ddns.net -*NN: i=3,id=tk2,data=new_token2 -*NN: i=4,id=pt,data=8080 -*NN: i=5,id=mq,data=new_mqtt.duckdns.org -*NN: ConMultiWifi -*NN: con2WF:SSID=HueNet1,PW=**** -*NN: Remaining retry_time=3 +[WN] ======= Start Default Config Data ======= +[WN] Hdr=WIFININA,SSID=SSID1,PW=password1 +[WN] SSID1=SSID2,PW1=password2 +[WN] BName=SAMD-Control +[WN] i=0,id=sv1,data=account.duckdns.org +[WN] i=1,id=tk1,data=token1 +[WN] i=2,id=sv2,data=account.ddns.net +[WN] i=3,id=tk2,data=token2 +[WN] i=4,id=pt,data=8080 +[WN] i=5,id=mq,data=mqtt.duckdns.org +[WN] ChkCrR:CrCCsum=0x21ce,CrRCsum=0x21ce +[WN] CCSum=0x1246,RCSum=0x1246 +[WN] CrCCsum=0x21ce,CrRCsum=0x21ce +[WN] Valid Stored Dynamic Data +[WN] ======= Start Stored Config Data ======= +[WN] Hdr=WIFININA,SSID=HueNet1,PW=**** +[WN] SSID1=HueNet2,PW1=**** +[WN] BName=Air-Control +[WN] i=0,id=sv1,data=new_account.duckdns.org +[WN] i=1,id=tk1,data=new_token1 +[WN] i=2,id=sv2,data=new_account.ddns.net +[WN] i=3,id=tk2,data=new_token2 +[WN] i=4,id=pt,data=8080 +[WN] i=5,id=mq,data=new_mqtt.duckdns.org +[WN] ConMultiWifi +[WN] con2WF:SSID=HueNet1,PW=**** +[WN] Remaining retry_time=3 WiFi-begin: return1 = 3 WiFi-begin: return2 = 3 -*NN: WOK, lastConnectedIndex=0 -*NN: con2WF:OK -*NN: SSID=HueNet1,RSSI=-21 -*NN: IP=192.168.2.105 -*NN: b:WOK +[WN] WOK, lastConnectedIndex=0 +[WN] con2WF:OK +[WN] SSID=HueNet1,RSSI=-21 +[WN] IP=192.168.2.105 +[WN] b:WOK Stop doubleResetDetecting ClearFlag write = 0xd0d04321 H @@ -1358,42 +1597,43 @@ MQTT Server = new_mqtt.duckdns.org HHHHHHHHH HHHHHHHHHH ``` -#### 7.DRD detected and Config Portal is forcefully opened +#### 7. DRD detected and Config Portal is forcefully opened ``` Start SAMD_WiFiNINA on SAMD NANO_33_IOT -*NN: Hostname=SAMD-Master-Controller +WiFiManager_NINA_Lite v1.1.0 +[WN] Hostname=SAMD-Master-Controller Flag read = 0xd0d01234 doubleResetDetected ClearFlag write = 0xd0d04321 -*NN: Double Reset Detected -*NN: ======= Start Default Config Data ======= -*NN: Hdr=WIFININA,SSID=SSID1,PW=password1 -*NN: SSID1=SSID2,PW1=password2 -*NN: BName=SAMD-Control -*NN: i=0,id=sv1,data=account.duckdns.org -*NN: i=1,id=tk1,data=token1 -*NN: i=2,id=sv2,data=account.ddns.net -*NN: i=3,id=tk2,data=token2 -*NN: i=4,id=pt,data=8080 -*NN: i=5,id=mq,data=mqtt.duckdns.org -*NN: ChkCrR:CrCCsum=0x21ce,CrRCsum=0x21ce -*NN: CCSum=0x1246,RCSum=0x1246 -*NN: CrCCsum=0x21ce,CrRCsum=0x21ce -*NN: Valid Stored Dynamic Data -*NN: ======= Start Stored Config Data ======= -*NN: Hdr=WIFININA,SSID=HueNet1,PW=**** -*NN: SSID1=HueNet2,PW1=**** -*NN: BName=Air-Control -*NN: i=0,id=sv1,data=new_account.duckdns.org -*NN: i=1,id=tk1,data=new_token1 -*NN: i=2,id=sv2,data=new_account.ddns.net -*NN: i=3,id=tk2,data=new_token2 -*NN: i=4,id=pt,data=8080 -*NN: i=5,id=mq,data=new_mqtt.duckdns.org -*NN: b:StayInCfgPortal:DRD -*NN: SSID=WIFININA_51F485,PW=MyWIFININA_51F485 -*NN: IP=192.168.4.1,CH=10 +[WN] Double Reset Detected +[WN] ======= Start Default Config Data ======= +[WN] Hdr=WIFININA,SSID=SSID1,PW=password1 +[WN] SSID1=SSID2,PW1=password2 +[WN] BName=SAMD-Control +[WN] i=0,id=sv1,data=account.duckdns.org +[WN] i=1,id=tk1,data=token1 +[WN] i=2,id=sv2,data=account.ddns.net +[WN] i=3,id=tk2,data=token2 +[WN] i=4,id=pt,data=8080 +[WN] i=5,id=mq,data=mqtt.duckdns.org +[WN] ChkCrR:CrCCsum=0x21ce,CrRCsum=0x21ce +[WN] CCSum=0x1246,RCSum=0x1246 +[WN] CrCCsum=0x21ce,CrRCsum=0x21ce +[WN] Valid Stored Dynamic Data +[WN] ======= Start Stored Config Data ======= +[WN] Hdr=WIFININA,SSID=HueNet1,PW=**** +[WN] SSID1=HueNet2,PW1=**** +[WN] BName=Air-Control +[WN] i=0,id=sv1,data=new_account.duckdns.org +[WN] i=1,id=tk1,data=new_token1 +[WN] i=2,id=sv2,data=new_account.ddns.net +[WN] i=3,id=tk2,data=new_token2 +[WN] i=4,id=pt,data=8080 +[WN] i=5,id=mq,data=new_mqtt.duckdns.org +[WN] b:StayInCfgPortal:DRD +[WN] SSID=WIFININA_51F485,PW=MyWIFININA_51F485 +[WN] IP=192.168.4.1,CH=10 WiFi-beginAP3: return1 = 7 WiFi-beginAP3: return2 = 7 F @@ -1415,45 +1655,38 @@ Debug is enabled by default on Serial. To disable, add at the beginning of sketc ```cpp /* Comment this out to disable prints and save space */ -#define DEBUG_WIFI_WEBSERVER_PORT Serial - -#define WIFININA_DEBUG_OUTPUT Serial +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial -#define WIFININA_DEBUG true +#define _WIFININA_LOGLEVEL_ 2 -#define DRD_GENERIC_DEBUG true +#define DRD_GENERIC_DEBUG true ``` +--- + ## Troubleshooting If you get compilation errors, more often than not, you may need to install a newer version of the board's core, `WiFiNINA module/shield` or this library version. Sometimes, the library will only work if you update the `WiFiNINA module/shield` core to the newer or older version because some function compatibility. ---- - -### TO DO - -1. Support more boards - -### DONE - - 1. Adding dynamic custom parameters - 2. Add MultiWiFi and Auto(Re)Connect feature - 3. Add support to SAMD21, SAMD51, nRF52, etc. - 4. Many more to list ( DHCP Hostname, WPA2 password length, special chars, etc.) - 5. Add DRD - 6. Add default Credentials - 7. Add Dynamic parameters - 8. Add Configurable Config Portal Title - 9. Spilt each example into several manageable files. - --- --- ## Releases - -### New Release v1.0.5 + +#### Major Release v1.1.0 + +1. Configurable **Customs HTML Headers**, including Customs Style, Customs Gead Elements, CORS Header. +2. Add support to boards using WiFi101 library such as MKR1000 +3. Fix Config Portal Bug. +4. Add functions to control Config Portal from software or Virtual Switches. Check [How to trigger a Config Portal from code #25](https://github.com/khoih-prog/Blynk_WM/issues/25) +5. Use more efficient [FlashStorage_SAMD v1.1.0](https://github.com/khoih-prog/FlashStorage_SAMD) and [FlashStorage_STM32 v1.00](https://github.com/khoih-prog/FlashStorage_STM32) +6. Optimize code +7. Add Version String + +### Release v1.0.5 1. Modify LOAD_DEFAULT_CONFIG_DATA logic. 4. Enhance MultiWiFi connection logic. @@ -1467,7 +1700,7 @@ Sometimes, the library will only work if you update the `WiFiNINA module/shield` 4. Examples are redesigned to separate Credentials / Defines / Dynamic Params / Code so that you can change Credentials / Dynamic Params quickly for each device. 5. Add Board Name -Thanks to [Thor Johnson](https://github.com/thorathome) to test, suggest and encourage to add those new features in [Blynk_WM](https://github.com/khoih-prog/Blynk_WM), such as Default Credentials/Dynamic Params, Configurable Config Portal Title, DRD. Now those features are speading fast into libraries having similar functionalities. +Thanks to [Thor Johnson](https://github.com/thorathome) to test, suggest and encourage to add those new features in [**Blynk_WM Library**](https://github.com/khoih-prog/Blynk_WM), such as Default Credentials/Dynamic Params, Configurable Config Portal Title, DRD. Now those features are speading fast into libraries having similar functionalities. #### Major Release v1.0.3 @@ -1478,17 +1711,17 @@ Thanks to [Thor Johnson](https://github.com/thorathome) to test, suggest and enc 5. Add option to have built-in, yet configurable RFC-952-conformed DHCP hostname. 6. Fix bug -#### New in v1.0.2 +#### Release v1.0.2 1. Fix bug 2. Add support to **SAM51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.)**. -#### New in v1.0.1 +#### Release v1.0.1 -1. Use new [**WiFiNINA_Generic library**](https://github.com/khoih-prog/WiFiNINA_Generic) to provide support to many more boards (Teensy, AVR Mega, SAM DUE, SAMD51, STM32, etc.) running WiFiNINA. The original WiFiNINA library only supports Nano-33 IoT, Arduino MKR WiFi 1010, Arduino MKR VIDOR 4000 and Arduino UNO WiFi Rev.2. +1. Use new [**WiFiNINA_Generic library**](https://github.com/khoih-prog/WiFiNINA_Generic) to provide support to many more boards (Teensy, AVR Mega, SAM DUE, SAMD51, STM32, etc.) running WiFiNINA. The original WiFiNINA library only supports Nano-33 IoT, Arduino MKR WiFi 1010, Arduino MKR VIDOR 4000 and Arduino UNO WiFi Rev.2. 2. Use new [**FlashStorage_SAMD library**](https://github.com/khoih-prog/FlashStorage_SAMD) to provide EEPROM/FlashStorage support to SAMD51 boards (Itsy-Bitsy M4, etc). -#### New in v1.0.0 +#### Release v1.0.0 1. New **powerful-yet-simple-to-use feature to enable adding dynamic custom parameters** from sketch and input using the same Config Portal. Config Portal will be auto-adjusted to match the number of dynamic parameters. 2. Dynamic custom parameters to be saved **automatically in EEPROM, SAMD EEPROM-emulated FlashStorage or SAM DUE DueFlashStorage**. @@ -1496,6 +1729,31 @@ Thanks to [Thor Johnson](https://github.com/thorathome) to test, suggest and enc 4. Config Portal AP SSID and Password will use 4 bytes of hardware unique macAddress, only for Teensy. --- +--- + +### TO DO + +1. Support more boards + +### DONE + + 1. Adding dynamic custom parameters + 2. Add MultiWiFi and Auto(Re)Connect feature + 3. Add support to SAMD21, SAMD51, nRF52, etc. + 4. Many more to list ( DHCP Hostname, WPA2 password length, special chars, etc.) + 5. Add DRD + 6. Add default Credentials + 7. Add Dynamic parameters + 8. Add Configurable Config Portal Title + 9. Split each example into several manageable files. +10. Configurable **Customs HTML Headers**, including Customs Style, Customs Gead Elements, CORS Header +11. Add functions to control Config Portal from software or Virtual Switches. +12. Use more efficient [FlashStorage_SAMD v1.1.0](https://github.com/khoih-prog/FlashStorage_SAMD) and [FlashStorage_STM32 v1.00](https://github.com/khoih-prog/FlashStorage_STM32) +13. Add Version String + + +--- +--- ### Issues ### @@ -1509,12 +1767,15 @@ Submit issues to: [WiFiManager_NINA_Lite issues](https://github.com/khoih-prog/W 1. Thanks to [Darvesh7](https://github.com/Darvesh7) to report [When Saved Network is unavailable or credential changed bug](https://github.com/khoih-prog/WiFiManager_NINA_Lite/issues/1) leading to the major release v1.0.3 2. Thanks to [Thor Johnson](https://github.com/thorathome) to test, suggest and encourage to add those new features in [Blynk_WM](https://github.com/khoih-prog/Blynk_WM), such as Default Credentials/Dynamic Params, Configurable Config Portal Title, DRD. Now those features are speading fast into libraries having similar functionalities. 3. Thanks to great work of [Miguel Alexandre Wisintainer](https://github.com/tcpipchip) for initiating, inspriring, working with, developing, debugging and testing. Without that, support to nRF52, especially **U-Blox B302, B112 running as nRF52840/nRF52832**, has never been started and finished. See [u-blox nina b](https://github.com/khoih-prog/WiFiNINA_Generic/issues/1) +4. Thanks to [Pierluigi Colangeli](https://github.com/piecol) to make enhancement request in [Custom html header #4](https://github.com/khoih-prog/WiFiManager_NINA_Lite/issues/4) leading to v1.1.0. + +
thorathome
⭐️ Thor Johnson

tcpipchip
⭐️ Miguel Wisintainer

Darvesh7
Darvesh7

piecol
Pierluigi Colangeli

diff --git a/examples/Mega_WiFiNINA/Credentials.h b/examples/Mega_WiFiNINA/Credentials.h index dd744c14..b214826c 100644 --- a/examples/Mega_WiFiNINA/Credentials.h +++ b/examples/Mega_WiFiNINA/Credentials.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - Credentials.h for Mega_WiFiNINA.ino - For AVR or Generic boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + Credentials.h for Mega_WiFiNINA.ino + For AVR or Generic boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef Credentials_h @@ -54,7 +43,7 @@ typedef struct Configuration } WiFiNINA_Configuration; */ -#define TO_LOAD_DEFAULT_CONFIG_DATA true +#define TO_LOAD_DEFAULT_CONFIG_DATA false #if TO_LOAD_DEFAULT_CONFIG_DATA diff --git a/examples/Mega_WiFiNINA/Mega_WiFiNINA.ino b/examples/Mega_WiFiNINA/Mega_WiFiNINA.ino index 051b52fb..a4bf78d8 100644 --- a/examples/Mega_WiFiNINA/Mega_WiFiNINA.ino +++ b/examples/Mega_WiFiNINA/Mega_WiFiNINA.ino @@ -1,25 +1,28 @@ /**************************************************************************************************************************** - Mega_WiFiNINA.ino - For AVR or Generic boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - + Mega_WiFiNINA.ino + For AVR or Generic boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ + #include "defines.h" #include "Credentials.h" #include "dynamicParams.h" @@ -59,20 +62,27 @@ void check_status() WiFiManager_NINA_Lite* WiFiManager_NINA; +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + void setup() { // Debug console Serial.begin(115200); while (!Serial); - Serial.print(F("\nStart Mega_WiFiNINA on ")); - Serial.println(BOARD_TYPE); + delay(200); + + Serial.print(F("\nStarting Mega_WiFiNINA on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); WiFiManager_NINA = new WiFiManager_NINA_Lite(); // Optional to change default AP IP(192.168.4.1) and channel(10) //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); - //WiFiManager_NINA->setConfigPortalChannel(1); + WiFiManager_NINA->setConfigPortalChannel(0); // Set customized DHCP HostName WiFiManager_NINA->begin(HOST_NAME); diff --git a/examples/Mega_WiFiNINA/defines.h b/examples/Mega_WiFiNINA/defines.h index 781a90fc..aa67db6e 100644 --- a/examples/Mega_WiFiNINA/defines.h +++ b/examples/Mega_WiFiNINA/defines.h @@ -1,39 +1,28 @@ /**************************************************************************************************************************** - defines.h for Mega_WiFiNINA.ino - For AVR or Generic boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + defines.h for Mega_WiFiNINA.ino + For AVR or Generic boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef defines_h #define defines_h /* Comment this out to disable prints and save space */ -#define DEBUG_WIFI_WEBSERVER_PORT Serial -#define WIFININA_DEBUG_OUTPUT Serial +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial -#define WIFININA_DEBUG false //true +#define _WIFININA_LOGLEVEL_ 2 -#define DRD_GENERIC_DEBUG false //true +#define DRD_GENERIC_DEBUG true -#if !( defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) ) -#error This code is intended to run only on the Arduino Mega 1280/2560 boards ! Please check your Tools->Board setting. +#if !( defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_ADK) ) + #error This code is intended to run on the AVR Mega, Mega2560, Mega ADK platform! Please check your Tools->Board setting. #endif #if defined(ARDUINO_AVR_MEGA2560) @@ -46,6 +35,75 @@ // Config data Size currently is 128 bytes) #define EEPROM_START 0 +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE false +#define USING_CUSTOMS_HEAD_ELEMENT false +#define USING_CORS_FEATURE false + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS false + +///////////////////////////////////////////// + #include #define HOST_NAME "AVR-Master-Controller" diff --git a/examples/Mega_WiFiNINA/dynamicParams.h b/examples/Mega_WiFiNINA/dynamicParams.h index ace569cd..9695930a 100644 --- a/examples/Mega_WiFiNINA/dynamicParams.h +++ b/examples/Mega_WiFiNINA/dynamicParams.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - dynamicParams.h for Mega_WiFiNINA.ino - For AVR or Generic boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + dynamicParams.h for Mega_WiFiNINA.ino + For AVR or Generic boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef dynamicParams_h @@ -26,7 +15,7 @@ #include "defines.h" -#define USE_DYNAMIC_PARAMETERS true +// USE_DYNAMIC_PARAMETERS defined in defined.h /////////////// Start dynamic Credentials /////////////// @@ -67,8 +56,8 @@ MenuItem myMenuItems [] = { "tk1", "Token1", Blynk_Token1, MAX_BLYNK_TOKEN_LEN }, { "sv2", "Blynk Server2", Blynk_Server2, MAX_BLYNK_SERVER_LEN }, { "tk2", "Token2", Blynk_Token2, MAX_BLYNK_TOKEN_LEN }, - { "pt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, - { "mq", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "prt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, + { "mqt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, }; uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; diff --git a/examples/SAMD_WiFiNINA/Credentials.h b/examples/SAMD_WiFiNINA/Credentials.h index b4975d54..698e2e6b 100644 --- a/examples/SAMD_WiFiNINA/Credentials.h +++ b/examples/SAMD_WiFiNINA/Credentials.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - Credentials.h for SAMD_WiFiNINA.ino - For SAMD boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + Credentials.h for SAMD_WiFiNINA.ino + For SAMD boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef Credentials_h @@ -54,7 +43,7 @@ typedef struct Configuration } WiFiNINA_Configuration; */ -#define TO_LOAD_DEFAULT_CONFIG_DATA true +#define TO_LOAD_DEFAULT_CONFIG_DATA false #if TO_LOAD_DEFAULT_CONFIG_DATA diff --git a/examples/SAMD_WiFiNINA/SAMD_WiFiNINA.ino b/examples/SAMD_WiFiNINA/SAMD_WiFiNINA.ino index e50159ee..c21f5588 100644 --- a/examples/SAMD_WiFiNINA/SAMD_WiFiNINA.ino +++ b/examples/SAMD_WiFiNINA/SAMD_WiFiNINA.ino @@ -1,25 +1,28 @@ -/**************************************************************************************************************************** - SAMD_WiFiNINA.ino - For SAMD boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + SAMD_WiFiNINA.ino + For SAMD boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ + #include "defines.h" #include "Credentials.h" #include "dynamicParams.h" @@ -60,20 +63,39 @@ void check_status() WiFiManager_NINA_Lite* WiFiManager_NINA; +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + void setup() { // Debug console Serial.begin(115200); while (!Serial); - Serial.println("\nStart SAMD_WiFiNINA on " + String(BOARD_TYPE)); + delay(200); + Serial.print(F("\nStarting SAMD_WiFiNINA on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); WiFiManager_NINA = new WiFiManager_NINA_Lite(); // Optional to change default AP IP(192.168.4.1) and channel(10) //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); - //WiFiManager_NINA->setConfigPortalChannel(1); + WiFiManager_NINA->setConfigPortalChannel(0); + +#if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif // Set customized DHCP HostName WiFiManager_NINA->begin(HOST_NAME); @@ -83,23 +105,20 @@ void setup() } #if USE_DYNAMIC_PARAMETERS -void displayCredentials(void) +void displayCredentials() { - Serial.println("\nYour stored Credentials :"); + Serial.println(F("\nYour stored Credentials :")); - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); } } -#endif -void loop() +void displayCredentialsInLoop() { - WiFiManager_NINA->run(); - check_status(); - -#if USE_DYNAMIC_PARAMETERS static bool displayedCredentials = false; if (!displayedCredentials) @@ -118,5 +137,16 @@ void loop() } } } +} + #endif + +void loop() +{ + WiFiManager_NINA->run(); + check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif } diff --git a/examples/SAMD_WiFiNINA/defines.h b/examples/SAMD_WiFiNINA/defines.h index 63c3e3e4..21490f6e 100644 --- a/examples/SAMD_WiFiNINA/defines.h +++ b/examples/SAMD_WiFiNINA/defines.h @@ -1,95 +1,84 @@ /**************************************************************************************************************************** - defines.h for SAMD_WiFiNINA.ino - For SAMD boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + defines.h for SAMD_WiFiNINA.ino + For SAMD boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef defines_h #define defines_h /* Comment this out to disable prints and save space */ -#define DEBUG_WIFI_WEBSERVER_PORT Serial -#define WIFININA_DEBUG_OUTPUT Serial +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial -#define WIFININA_DEBUG true +#define _WIFININA_LOGLEVEL_ 2 -#define DRD_GENERIC_DEBUG true +#define DRD_GENERIC_DEBUG true #if ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ || defined(__SAMD51G19A__) || defined(__SAMD21G18A__) ) -#if defined(WIFININA_USE_SAMD) -#undef WIFININA_USE_SAMD -#undef WIFI_USE_SAMD -#endif -#define WIFININA_USE_SAMD true -#define WIFI_USE_SAMD true + #if defined(WIFININA_USE_SAMD) + #undef WIFININA_USE_SAMD + #undef WIFI_USE_SAMD + #endif + #define WIFININA_USE_SAMD true + #define WIFI_USE_SAMD true #else -#error This code is intended to run only on the SAMD boards ! Please check your Tools->Board setting. + #error This code is intended to run only on the SAMD boards ! Please check your Tools->Board setting. #endif #if defined(WIFININA_USE_SAMD) -#if defined(ARDUINO_SAMD_ZERO) -#define BOARD_TYPE "SAMD Zero" -#elif defined(ARDUINO_SAMD_MKR1000) -#define BOARD_TYPE "SAMD MKR1000" -#elif defined(ARDUINO_SAMD_MKRWIFI1010) -#define BOARD_TYPE "SAMD MKRWIFI1010" -#elif defined(ARDUINO_SAMD_NANO_33_IOT) -#define BOARD_TYPE "SAMD NANO_33_IOT" -#elif defined(ARDUINO_SAMD_MKRFox1200) -#define BOARD_TYPE "SAMD MKRFox1200" -#elif ( defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) ) -#define BOARD_TYPE "SAMD MKRWAN13X0" -#elif defined(ARDUINO_SAMD_MKRGSM1400) -#define BOARD_TYPE "SAMD MKRGSM1400" -#elif defined(ARDUINO_SAMD_MKRNB1500) -#define BOARD_TYPE "SAMD MKRNB1500" -#elif defined(ARDUINO_SAMD_MKRVIDOR4000) -#define BOARD_TYPE "SAMD MKRVIDOR4000" -#elif defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) -#define BOARD_TYPE "SAMD ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS" -#elif defined(ADAFRUIT_ITSYBITSY_M4_EXPRESS) -#define BOARD_TYPE "SAMD ADAFRUIT_ITSYBITSY_M4_EXPRESS" -#elif defined(__SAMD21E18A__) -#define BOARD_TYPE "SAMD21E18A" -#elif defined(__SAMD21G18A__) -#define BOARD_TYPE "SAMD21G18A" -#elif defined(__SAMD51G19A__) -#define BOARD_TYPE "SAMD51G19A" -#elif defined(__SAMD51J19A__) -#define BOARD_TYPE "SAMD51J19A" -#elif defined(__SAMD51J20A__) -#define BOARD_TYPE "SAMD51J20A" -#elif defined(__SAM3X8E__) -#define BOARD_TYPE "SAM3X8E" -#elif defined(__CPU_ARC__) -#define BOARD_TYPE "CPU_ARC" -#elif defined(__SAMD51__) -#define BOARD_TYPE "SAMD51" -#else -#define BOARD_TYPE "SAMD Unknown" -#endif + #if defined(ARDUINO_SAMD_ZERO) + #define BOARD_TYPE "SAMD Zero" + #elif defined(ARDUINO_SAMD_MKR1000) + #define BOARD_TYPE "SAMD MKR1000" + #elif defined(ARDUINO_SAMD_MKRWIFI1010) + #define BOARD_TYPE "SAMD MKRWIFI1010" + #elif defined(ARDUINO_SAMD_NANO_33_IOT) + #define BOARD_TYPE "SAMD NANO_33_IOT" + #elif defined(ARDUINO_SAMD_MKRFox1200) + #define BOARD_TYPE "SAMD MKRFox1200" + #elif ( defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) ) + #define BOARD_TYPE "SAMD MKRWAN13X0" + #elif defined(ARDUINO_SAMD_MKRGSM1400) + #define BOARD_TYPE "SAMD MKRGSM1400" + #elif defined(ARDUINO_SAMD_MKRNB1500) + #define BOARD_TYPE "SAMD MKRNB1500" + #elif defined(ARDUINO_SAMD_MKRVIDOR4000) + #define BOARD_TYPE "SAMD MKRVIDOR4000" + #elif defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) + #define BOARD_TYPE "SAMD ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS" + #elif defined(ADAFRUIT_ITSYBITSY_M4_EXPRESS) + #define BOARD_TYPE "SAMD ADAFRUIT_ITSYBITSY_M4_EXPRESS" + #elif defined(__SAMD21E18A__) + #define BOARD_TYPE "SAMD21E18A" + #elif defined(__SAMD21G18A__) + #define BOARD_TYPE "SAMD21G18A" + #elif defined(__SAMD51G19A__) + #define BOARD_TYPE "SAMD51G19A" + #elif defined(__SAMD51J19A__) + #define BOARD_TYPE "SAMD51J19A" + #elif defined(__SAMD51J20A__) + #define BOARD_TYPE "SAMD51J20A" + #elif defined(__SAM3X8E__) + #define BOARD_TYPE "SAM3X8E" + #elif defined(__CPU_ARC__) + #define BOARD_TYPE "CPU_ARC" + #elif defined(__SAMD51__) + #define BOARD_TYPE "SAMD51" + #else + #define BOARD_TYPE "SAMD Unknown" + #endif #endif @@ -98,7 +87,74 @@ #define EEPROM_START 0 #define EEPROM_SIZE (2 * 1024) -#include "WiFiNINA_Pinout_Generic.h" +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// #include diff --git a/examples/SAMD_WiFiNINA/dynamicParams.h b/examples/SAMD_WiFiNINA/dynamicParams.h index 5dec7f10..8ad2436f 100644 --- a/examples/SAMD_WiFiNINA/dynamicParams.h +++ b/examples/SAMD_WiFiNINA/dynamicParams.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - dynamicParams.h for SAMD_WiFiNINA.ino - For SAMD boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + dynamicParams.h for SAMD_WiFiNINA.ino + For SAMD boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef dynamicParams_h @@ -26,7 +15,7 @@ #include "defines.h" -#define USE_DYNAMIC_PARAMETERS true +// USE_DYNAMIC_PARAMETERS defined in defined.h /////////////// Start dynamic Credentials /////////////// @@ -67,8 +56,8 @@ MenuItem myMenuItems [] = { "tk1", "Token1", Blynk_Token1, MAX_BLYNK_TOKEN_LEN }, { "sv2", "Blynk Server2", Blynk_Server2, MAX_BLYNK_SERVER_LEN }, { "tk2", "Token2", Blynk_Token2, MAX_BLYNK_TOKEN_LEN }, - { "pt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, - { "mq", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "prt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, + { "mqt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, }; uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; diff --git a/examples/SAMD_WiFiNINA_MQTT/Credentials.h b/examples/SAMD_WiFiNINA_MQTT/Credentials.h index d11a61d6..334eab42 100644 --- a/examples/SAMD_WiFiNINA_MQTT/Credentials.h +++ b/examples/SAMD_WiFiNINA_MQTT/Credentials.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - Credentials.h for SAMD_WiFiNINA_MQTT.ino - For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + Credentials.h for SAMD_WiFiNINA_MQTT.ino + For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef Credentials_h @@ -54,7 +43,7 @@ typedef struct Configuration } WiFiNINA_Configuration; */ -#define TO_LOAD_DEFAULT_CONFIG_DATA true +#define TO_LOAD_DEFAULT_CONFIG_DATA false #if TO_LOAD_DEFAULT_CONFIG_DATA diff --git a/examples/SAMD_WiFiNINA_MQTT/SAMD_WiFiNINA_MQTT.ino b/examples/SAMD_WiFiNINA_MQTT/SAMD_WiFiNINA_MQTT.ino index fea838a6..056dc561 100644 --- a/examples/SAMD_WiFiNINA_MQTT/SAMD_WiFiNINA_MQTT.ino +++ b/examples/SAMD_WiFiNINA_MQTT/SAMD_WiFiNINA_MQTT.ino @@ -1,25 +1,27 @@ -/**************************************************************************************************************************** - SAMD_WiFiNINA_MQTT.ino - For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + SAMD_WiFiNINA_MQTT.ino + For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ /**************************************************************************************************************************** You have to modify file ./libraries/Adafruit_MQTT_Library/Adafruit_MQTT.cpp as follows to avoid dtostrf error, if exists @@ -284,6 +286,11 @@ void MQTT_connect() #endif } +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + void setup() { // Debug console @@ -292,13 +299,28 @@ void setup() pinMode(LED_PIN, OUTPUT); - Serial.println("\nStart SAMD_WiFiNINA on " + String(BOARD_TYPE)); + delay(200); + + Serial.print(F("\nStarting SAMD_WiFiNINA_MQTT on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); WiFiManager_NINA = new WiFiManager_NINA_Lite(); // Optional to change default AP IP(192.168.4.1) and channel(10) //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); - WiFiManager_NINA->setConfigPortalChannel(1); + WiFiManager_NINA->setConfigPortalChannel(0); + +#if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif // Set customized DHCP HostName WiFiManager_NINA->begin(HOST_NAME); @@ -307,21 +329,20 @@ void setup() } #if USE_DYNAMIC_PARAMETERS -void displayCredentials(void) +void displayCredentials() { - Serial.println("\nYour stored Credentials :"); + Serial.println(F("\nYour stored Credentials :")); - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); } } -#endif -void loop() +void displayCredentialsInLoop() { - -#if USE_DYNAMIC_PARAMETERS static bool displayedCredentials = false; if (!displayedCredentials) @@ -340,8 +361,16 @@ void loop() } } } +} + #endif +void loop() +{ WiFiManager_NINA->run(); check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif } diff --git a/examples/SAMD_WiFiNINA_MQTT/defines.h b/examples/SAMD_WiFiNINA_MQTT/defines.h index 0656cf62..11cebb4e 100644 --- a/examples/SAMD_WiFiNINA_MQTT/defines.h +++ b/examples/SAMD_WiFiNINA_MQTT/defines.h @@ -1,95 +1,84 @@ /**************************************************************************************************************************** - defines.h for SAMD_WiFiNINA_MQTT.ino - For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + defines.h for SAMD_WiFiNINA_MQTT.ino + For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef defines_h #define defines_h /* Comment this out to disable prints and save space */ -#define DEBUG_WIFI_WEBSERVER_PORT Serial -#define WIFININA_DEBUG_OUTPUT Serial +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial -#define WIFININA_DEBUG true +#define _WIFININA_LOGLEVEL_ 2 -#define DRD_GENERIC_DEBUG true +#define DRD_GENERIC_DEBUG true #if ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ || defined(__SAMD51G19A__) || defined(__SAMD21G18A__) ) -#if defined(WIFININA_USE_SAMD) -#undef WIFININA_USE_SAMD -#undef WIFI_USE_SAMD -#endif -#define WIFININA_USE_SAMD true -#define WIFI_USE_SAMD true + #if defined(WIFININA_USE_SAMD) + #undef WIFININA_USE_SAMD + #undef WIFI_USE_SAMD + #endif + #define WIFININA_USE_SAMD true + #define WIFI_USE_SAMD true #else -#error This code is intended to run only on the SAMD boards ! Please check your Tools->Board setting. + #error This code is intended to run only on the SAMD boards ! Please check your Tools->Board setting. #endif #if defined(WIFININA_USE_SAMD) -#if defined(ARDUINO_SAMD_ZERO) -#define BOARD_TYPE "SAMD Zero" -#elif defined(ARDUINO_SAMD_MKR1000) -#define BOARD_TYPE "SAMD MKR1000" -#elif defined(ARDUINO_SAMD_MKRWIFI1010) -#define BOARD_TYPE "SAMD MKRWIFI1010" -#elif defined(ARDUINO_SAMD_NANO_33_IOT) -#define BOARD_TYPE "SAMD NANO_33_IOT" -#elif defined(ARDUINO_SAMD_MKRFox1200) -#define BOARD_TYPE "SAMD MKRFox1200" -#elif ( defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) ) -#define BOARD_TYPE "SAMD MKRWAN13X0" -#elif defined(ARDUINO_SAMD_MKRGSM1400) -#define BOARD_TYPE "SAMD MKRGSM1400" -#elif defined(ARDUINO_SAMD_MKRNB1500) -#define BOARD_TYPE "SAMD MKRNB1500" -#elif defined(ARDUINO_SAMD_MKRVIDOR4000) -#define BOARD_TYPE "SAMD MKRVIDOR4000" -#elif defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) -#define BOARD_TYPE "SAMD ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS" -#elif defined(ADAFRUIT_ITSYBITSY_M4_EXPRESS) -#define BOARD_TYPE "SAMD ADAFRUIT_ITSYBITSY_M4_EXPRESS" -#elif defined(__SAMD21E18A__) -#define BOARD_TYPE "SAMD21E18A" -#elif defined(__SAMD21G18A__) -#define BOARD_TYPE "SAMD21G18A" -#elif defined(__SAMD51G19A__) -#define BOARD_TYPE "SAMD51G19A" -#elif defined(__SAMD51J19A__) -#define BOARD_TYPE "SAMD51J19A" -#elif defined(__SAMD51J20A__) -#define BOARD_TYPE "SAMD51J20A" -#elif defined(__SAM3X8E__) -#define BOARD_TYPE "SAM3X8E" -#elif defined(__CPU_ARC__) -#define BOARD_TYPE "CPU_ARC" -#elif defined(__SAMD51__) -#define BOARD_TYPE "SAMD51" -#else -#define BOARD_TYPE "SAMD Unknown" -#endif + #if defined(ARDUINO_SAMD_ZERO) + #define BOARD_TYPE "SAMD Zero" + #elif defined(ARDUINO_SAMD_MKR1000) + #define BOARD_TYPE "SAMD MKR1000" + #elif defined(ARDUINO_SAMD_MKRWIFI1010) + #define BOARD_TYPE "SAMD MKRWIFI1010" + #elif defined(ARDUINO_SAMD_NANO_33_IOT) + #define BOARD_TYPE "SAMD NANO_33_IOT" + #elif defined(ARDUINO_SAMD_MKRFox1200) + #define BOARD_TYPE "SAMD MKRFox1200" + #elif ( defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) ) + #define BOARD_TYPE "SAMD MKRWAN13X0" + #elif defined(ARDUINO_SAMD_MKRGSM1400) + #define BOARD_TYPE "SAMD MKRGSM1400" + #elif defined(ARDUINO_SAMD_MKRNB1500) + #define BOARD_TYPE "SAMD MKRNB1500" + #elif defined(ARDUINO_SAMD_MKRVIDOR4000) + #define BOARD_TYPE "SAMD MKRVIDOR4000" + #elif defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) + #define BOARD_TYPE "SAMD ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS" + #elif defined(ADAFRUIT_ITSYBITSY_M4_EXPRESS) + #define BOARD_TYPE "SAMD ADAFRUIT_ITSYBITSY_M4_EXPRESS" + #elif defined(__SAMD21E18A__) + #define BOARD_TYPE "SAMD21E18A" + #elif defined(__SAMD21G18A__) + #define BOARD_TYPE "SAMD21G18A" + #elif defined(__SAMD51G19A__) + #define BOARD_TYPE "SAMD51G19A" + #elif defined(__SAMD51J19A__) + #define BOARD_TYPE "SAMD51J19A" + #elif defined(__SAMD51J20A__) + #define BOARD_TYPE "SAMD51J20A" + #elif defined(__SAM3X8E__) + #define BOARD_TYPE "SAM3X8E" + #elif defined(__CPU_ARC__) + #define BOARD_TYPE "CPU_ARC" + #elif defined(__SAMD51__) + #define BOARD_TYPE "SAMD51" + #else + #define BOARD_TYPE "SAMD Unknown" + #endif #endif @@ -98,7 +87,74 @@ #define EEPROM_START 0 #define EEPROM_SIZE (2 * 1024) -#include "WiFiNINA_Pinout_Generic.h" +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// #include diff --git a/examples/SAMD_WiFiNINA_MQTT/dynamicParams.h b/examples/SAMD_WiFiNINA_MQTT/dynamicParams.h index cdc25a23..c8279493 100644 --- a/examples/SAMD_WiFiNINA_MQTT/dynamicParams.h +++ b/examples/SAMD_WiFiNINA_MQTT/dynamicParams.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - dynamicParams.h for SAMD_WiFiNINA_MQTT.ino - For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + dynamicParams.h for SAMD_WiFiNINA_MQTT.ino + For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef dynamicParams_h @@ -26,7 +15,7 @@ #include "defines.h" -#define USE_DYNAMIC_PARAMETERS true +// USE_DYNAMIC_PARAMETERS defined in defined.h /////////////// Start dynamic Credentials /////////////// @@ -57,7 +46,6 @@ char AIO_SERVER [AIO_SERVER_LEN + 1] = "io.adafruit.com"; char AIO_SERVERPORT [AIO_SERVERPORT_LEN + 1] = "1883"; //1883, or 8883 for SSL - char AIO_USERNAME [AIO_USERNAME_LEN + 1] = "private"; char AIO_KEY [AIO_KEY_LEN + 1] = "private"; diff --git a/examples/SAM_DUE_WiFiNINA/Credentials.h b/examples/SAM_DUE_WiFiNINA/Credentials.h index 5073db69..42235885 100644 --- a/examples/SAM_DUE_WiFiNINA/Credentials.h +++ b/examples/SAM_DUE_WiFiNINA/Credentials.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - Credentials.h for SAM_DUE_WiFiNINA.ino - For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + Credentials.h for SAM_DUE_WiFiNINA.ino + For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef Credentials_h @@ -54,7 +43,7 @@ typedef struct Configuration } WiFiNINA_Configuration; */ -#define TO_LOAD_DEFAULT_CONFIG_DATA true +#define TO_LOAD_DEFAULT_CONFIG_DATA false #if TO_LOAD_DEFAULT_CONFIG_DATA diff --git a/examples/SAM_DUE_WiFiNINA/SAM_DUE_WiFiNINA.ino b/examples/SAM_DUE_WiFiNINA/SAM_DUE_WiFiNINA.ino index 7fb1a8af..63f90d0a 100644 --- a/examples/SAM_DUE_WiFiNINA/SAM_DUE_WiFiNINA.ino +++ b/examples/SAM_DUE_WiFiNINA/SAM_DUE_WiFiNINA.ino @@ -1,25 +1,28 @@ -/**************************************************************************************************************************** - SAM_DUE_WiFiNINA.ino - For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + SAM_DUE_WiFiNINA.ino + For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license +Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ + #include "defines.h" #include "Credentials.h" #include "dynamicParams.h" @@ -60,44 +63,62 @@ void check_status() WiFiManager_NINA_Lite* WiFiManager_NINA; +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + void setup() { // Debug console Serial.begin(115200); while (!Serial); - Serial.println("\nStart SAM_DUE_WiFiNINA on " + String(BOARD_TYPE)); + delay(200); + + Serial.print(F("\nStarting SAM_DUE_WiFiNINA on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); WiFiManager_NINA = new WiFiManager_NINA_Lite(); // Optional to change default AP IP(192.168.4.1) and channel(10) //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); - //WiFiManager_NINA->setConfigPortalChannel(1); + WiFiManager_NINA->setConfigPortalChannel(0); + +#if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif // Set customized DHCP HostName - WiFiManager_NINA->begin("DUE-WiFiNINA-ABCDEF"); + WiFiManager_NINA->begin(HOST_NAME); //Or use default Hostname "DUE-WiFiNINA-XXXXXX" //WiFiManager_NINA->begin(); + } #if USE_DYNAMIC_PARAMETERS -void displayCredentials(void) +void displayCredentials() { - Serial.println("\nYour stored Credentials :"); + Serial.println(F("\nYour stored Credentials :")); - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); } } -#endif -void loop() +void displayCredentialsInLoop() { - WiFiManager_NINA->run(); - check_status(); - -#if USE_DYNAMIC_PARAMETERS static bool displayedCredentials = false; if (!displayedCredentials) @@ -116,5 +137,16 @@ void loop() } } } +} + #endif + +void loop() +{ + WiFiManager_NINA->run(); + check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif } diff --git a/examples/SAM_DUE_WiFiNINA/defines.h b/examples/SAM_DUE_WiFiNINA/defines.h index 68c83e58..16b4ad5a 100644 --- a/examples/SAM_DUE_WiFiNINA/defines.h +++ b/examples/SAM_DUE_WiFiNINA/defines.h @@ -1,43 +1,32 @@ /**************************************************************************************************************************** - defines.h for SAM_DUE_WiFiNINA.ino - For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + defines.h for SAM_DUE_WiFiNINA.ino + For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef defines_h #define defines_h /* Comment this out to disable prints and save space */ -#define DEBUG_WIFI_WEBSERVER_PORT Serial -#define WIFININA_DEBUG_OUTPUT Serial +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial -#define WIFININA_DEBUG true +#define _WIFININA_LOGLEVEL_ 2 -#define DRD_GENERIC_DEBUG true +#define DRD_GENERIC_DEBUG true #if ( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) -#if defined(WIFININA_USE_SAM_DUE) -#undef WIFININA_USE_SAM_DUE -#endif -#define WIFININA_USE_SAM_DUE true -#warning Use SAM_DUE architecture + #if defined(WIFININA_USE_SAM_DUE) + #undef WIFININA_USE_SAM_DUE + #endif + #define WIFININA_USE_SAM_DUE true + #warning Use SAM_DUE architecture #endif #if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA) || \ @@ -46,20 +35,89 @@ #endif #if defined(WIFININA_USE_SAM_DUE) -// For SAM DUE -#if defined(ARDUINO_SAM_DUE) -#define BOARD_TYPE "SAM DUE" -#elif defined(__SAM3X8E__) -#define BOARD_TYPE "SAM SAM3X8E" -#else -#define BOARD_TYPE "SAM Unknown" -#endif + // For SAM DUE + #if defined(ARDUINO_SAM_DUE) + #define BOARD_TYPE "SAM DUE" + #elif defined(__SAM3X8E__) + #define BOARD_TYPE "SAM SAM3X8E" + #else + #define BOARD_TYPE "SAM Unknown" + #endif #endif // Start location in EEPROM to store config data. Default 0 // Config data Size currently is 128 bytes) #define EEPROM_START 0 +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// + #include #define HOST_NAME "DUE-Master-Controller" diff --git a/examples/SAM_DUE_WiFiNINA/dynamicParams.h b/examples/SAM_DUE_WiFiNINA/dynamicParams.h index e88b5b87..9a4e6e49 100644 --- a/examples/SAM_DUE_WiFiNINA/dynamicParams.h +++ b/examples/SAM_DUE_WiFiNINA/dynamicParams.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - dynamicParams.h for SAM_DUE_WiFiNINA.ino - For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + dynamicParams.h for SAM_DUE_WiFiNINA.ino + For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef dynamicParams_h diff --git a/examples/SAM_DUE_WiFiNINA_MQTT/Credentials.h b/examples/SAM_DUE_WiFiNINA_MQTT/Credentials.h index 77d753c9..25cbb99d 100644 --- a/examples/SAM_DUE_WiFiNINA_MQTT/Credentials.h +++ b/examples/SAM_DUE_WiFiNINA_MQTT/Credentials.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - Credentials.h for SAM_DUE_WiFiNINA_MQTT.ino - For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + Credentials.h for SAM_DUE_WiFiNINA_MQTT.ino + For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef Credentials_h @@ -54,7 +43,7 @@ typedef struct Configuration } WiFiNINA_Configuration; */ -#define TO_LOAD_DEFAULT_CONFIG_DATA true +#define TO_LOAD_DEFAULT_CONFIG_DATA false #if TO_LOAD_DEFAULT_CONFIG_DATA diff --git a/examples/SAM_DUE_WiFiNINA_MQTT/SAM_DUE_WiFiNINA_MQTT.ino b/examples/SAM_DUE_WiFiNINA_MQTT/SAM_DUE_WiFiNINA_MQTT.ino index f4f9ddb6..1de1e89c 100644 --- a/examples/SAM_DUE_WiFiNINA_MQTT/SAM_DUE_WiFiNINA_MQTT.ino +++ b/examples/SAM_DUE_WiFiNINA_MQTT/SAM_DUE_WiFiNINA_MQTT.ino @@ -1,25 +1,27 @@ -/**************************************************************************************************************************** - SAM_DUE_WiFiNINA_MQTT.ino - For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + SAM_DUE_WiFiNINA_MQTT.ino + For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ /**************************************************************************************************************************** You have to modify file ./libraries/Adafruit_MQTT_Library/Adafruit_MQTT.cpp as follows to avoid dtostrf error @@ -284,6 +286,11 @@ void MQTT_connect() #endif } +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + void setup() { // Debug console @@ -292,36 +299,51 @@ void setup() pinMode(LED_PIN, OUTPUT); - Serial.println("\nStart DUE_WiFiNINA_MQTT on " + String(BOARD_TYPE)); + delay(200); + + Serial.print(F("\nStarting SAM_DUE_WiFiNINA_MQTT on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); WiFiManager_NINA = new WiFiManager_NINA_Lite(); // Optional to change default AP IP(192.168.4.1) and channel(10) //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); - WiFiManager_NINA->setConfigPortalChannel(1); + WiFiManager_NINA->setConfigPortalChannel(0); + +#if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif // Set customized DHCP HostName WiFiManager_NINA->begin(HOST_NAME); //Or use default Hostname "DUE-WiFiNINA-XXXXXX" //WiFiManager_NINA->begin(); + } #if USE_DYNAMIC_PARAMETERS -void displayCredentials(void) +void displayCredentials() { - Serial.println("\nYour stored Credentials :"); + Serial.println(F("\nYour stored Credentials :")); - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); } } -#endif -void loop() +void displayCredentialsInLoop() { - -#if USE_DYNAMIC_PARAMETERS static bool displayedCredentials = false; if (!displayedCredentials) @@ -340,8 +362,16 @@ void loop() } } } +} + #endif +void loop() +{ WiFiManager_NINA->run(); check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif } diff --git a/examples/SAM_DUE_WiFiNINA_MQTT/defines.h b/examples/SAM_DUE_WiFiNINA_MQTT/defines.h index 3b6ce7ec..5e628c80 100644 --- a/examples/SAM_DUE_WiFiNINA_MQTT/defines.h +++ b/examples/SAM_DUE_WiFiNINA_MQTT/defines.h @@ -1,43 +1,32 @@ /**************************************************************************************************************************** - defines.h for SAM_DUE_WiFiNINA_MQTT.ino - For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + defines.h for SAM_DUE_WiFiNINA_MQTT.ino + For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef defines_h #define defines_h /* Comment this out to disable prints and save space */ -#define DEBUG_WIFI_WEBSERVER_PORT Serial -#define WIFININA_DEBUG_OUTPUT Serial +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial -#define WIFININA_DEBUG true +#define _WIFININA_LOGLEVEL_ 2 -#define DRD_GENERIC_DEBUG true +#define DRD_GENERIC_DEBUG true #if ( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) -#if defined(WIFININA_USE_SAM_DUE) -#undef WIFININA_USE_SAM_DUE -#endif -#define WIFININA_USE_SAM_DUE true -#warning Use SAM_DUE architecture + #if defined(WIFININA_USE_SAM_DUE) + #undef WIFININA_USE_SAM_DUE + #endif + #define WIFININA_USE_SAM_DUE true + #warning Use SAM_DUE architecture #endif #if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA) || \ @@ -46,20 +35,89 @@ #endif #if defined(WIFININA_USE_SAM_DUE) -// For SAM DUE -#if defined(ARDUINO_SAM_DUE) -#define BOARD_TYPE "SAM DUE" -#elif defined(__SAM3X8E__) -#define BOARD_TYPE "SAM SAM3X8E" -#else -#define BOARD_TYPE "SAM Unknown" -#endif + // For SAM DUE + #if defined(ARDUINO_SAM_DUE) + #define BOARD_TYPE "SAM DUE" + #elif defined(__SAM3X8E__) + #define BOARD_TYPE "SAM SAM3X8E" + #else + #define BOARD_TYPE "SAM Unknown" + #endif #endif // Start location in EEPROM to store config data. Default 0 // Config data Size currently is 128 bytes) #define EEPROM_START 0 +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// + #include #define HOST_NAME "DUE-Master-Controller" diff --git a/examples/SAM_DUE_WiFiNINA_MQTT/dynamicParams.h b/examples/SAM_DUE_WiFiNINA_MQTT/dynamicParams.h index 682e94f0..fa01db70 100644 --- a/examples/SAM_DUE_WiFiNINA_MQTT/dynamicParams.h +++ b/examples/SAM_DUE_WiFiNINA_MQTT/dynamicParams.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - dynamicParams.h for SAM_DUE_WiFiNINA_MQTT.ino - For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + dynamicParams.h for SAM_DUE_WiFiNINA_MQTT.ino + For SAM DUE boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef dynamicParams_h @@ -26,7 +15,7 @@ #include "defines.h" -#define USE_DYNAMIC_PARAMETERS true +// USE_DYNAMIC_PARAMETERS defined in defined.h /////////////// Start dynamic Credentials /////////////// diff --git a/examples/STM32_WiFiNINA/Credentials.h b/examples/STM32_WiFiNINA/Credentials.h index 51b731b0..72030770 100644 --- a/examples/STM32_WiFiNINA/Credentials.h +++ b/examples/STM32_WiFiNINA/Credentials.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - Credentials.h for STM32_WiFiNINA.ino - For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + Credentials.h for STM32_WiFiNINA.ino + For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef Credentials_h @@ -54,7 +43,7 @@ typedef struct Configuration } WiFiNINA_Configuration; */ -#define TO_LOAD_DEFAULT_CONFIG_DATA true +#define TO_LOAD_DEFAULT_CONFIG_DATA false #if TO_LOAD_DEFAULT_CONFIG_DATA diff --git a/examples/STM32_WiFiNINA/STM32_WiFiNINA.ino b/examples/STM32_WiFiNINA/STM32_WiFiNINA.ino index a73abb6f..8e8713b8 100644 --- a/examples/STM32_WiFiNINA/STM32_WiFiNINA.ino +++ b/examples/STM32_WiFiNINA/STM32_WiFiNINA.ino @@ -1,25 +1,28 @@ -/**************************************************************************************************************************** - STM32_WiFiNINA.ino - For STM32 boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + STM32_WiFiNINA.ino + For STM32 boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ + #include "defines.h" #include "Credentials.h" #include "dynamicParams.h" @@ -60,44 +63,62 @@ void check_status() WiFiManager_NINA_Lite* WiFiManager_NINA; +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + void setup() { // Debug console Serial.begin(115200); while (!Serial); - Serial.println("\nStart STM32_ESP8266Shield on " + String(BOARD_TYPE)); + delay(200); + + Serial.print(F("\nStarting STM32_WiFiNINA on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); WiFiManager_NINA = new WiFiManager_NINA_Lite(); // Optional to change default AP IP(192.168.4.1) and channel(10) //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); - //WiFiManager_NINA->setConfigPortalChannel(1); + WiFiManager_NINA->setConfigPortalChannel(0); + +#if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif // Set customized DHCP HostName - WiFiManager_NINA->begin("STM32-WiFiNINA-ABCDEF"); + WiFiManager_NINA->begin(HOST_NAME); //Or use default Hostname "STM32-WiFiNINA-XXXXXX" //WiFiManager_NINA->begin(); + } #if USE_DYNAMIC_PARAMETERS -void displayCredentials(void) +void displayCredentials() { - Serial.println("\nYour stored Credentials :"); + Serial.println(F("\nYour stored Credentials :")); - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); } } -#endif -void loop() +void displayCredentialsInLoop() { - WiFiManager_NINA->run(); - check_status(); - -#if USE_DYNAMIC_PARAMETERS static bool displayedCredentials = false; if (!displayedCredentials) @@ -116,5 +137,16 @@ void loop() } } } +} + #endif + +void loop() +{ + WiFiManager_NINA->run(); + check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif } diff --git a/examples/STM32_WiFiNINA/defines.h b/examples/STM32_WiFiNINA/defines.h index de91f25b..b929eae6 100644 --- a/examples/STM32_WiFiNINA/defines.h +++ b/examples/STM32_WiFiNINA/defines.h @@ -1,78 +1,136 @@ /**************************************************************************************************************************** - defines.h for STM32_WiFiNINA.ino - For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + defines.h for STM32_WiFiNINA.ino + For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef defines_h #define defines_h /* Comment this out to disable prints and save space */ -#define DEBUG_WIFI_WEBSERVER_PORT Serial -#define WIFININA_DEBUG_OUTPUT Serial +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial -#define WIFININA_DEBUG true +#define _WIFININA_LOGLEVEL_ 2 -#define DRD_GENERIC_DEBUG true +#define DRD_GENERIC_DEBUG true -#if ( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) ) -#if defined(WIFININA_USE_STM32) -#undef WIFININA_USE_STM32 -#undef WIFI_USE_STM32 -#endif -#define WIFININA_USE_STM32 true -#define WIFI_USE_STM32 true +#if ( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \ + defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \ + defined(STM32WB) || defined(STM32MP1) ) + #if defined(WIFININA_USE_STM32) + #undef WIFININA_USE_STM32 + #undef WIFI_USE_STM32 + #endif + #define WIFININA_USE_STM32 true + #define WIFI_USE_STM32 true #endif #if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(CORE_TEENSY) || !(WIFININA_USE_STM32) ) -//#error This code is intended to run on STM32 platform! Please check your Tools->Board setting. + //#error This code is intended to run on STM32 platform! Please check your Tools->Board setting. #endif #if WIFININA_USE_STM32 -#if defined(STM32F0) -#define BOARD_TYPE "STM32F0" -#error Board STM32F0 not supported -#elif defined(STM32F1) -#define BOARD_TYPE "STM32F1" -#elif defined(STM32F2) -#define BOARD_TYPE "STM32F2" -#elif defined(STM32F3) -#define BOARD_TYPE "STM32F3" -#elif defined(STM32F4) -#define BOARD_TYPE "STM32F4" -#elif defined(STM32F7) -#define BOARD_TYPE "STM32F7" -#else -#warning STM32 unknown board selected -#define BOARD_TYPE "STM32 Unknown" -#endif + #if defined(STM32F0) + #define BOARD_TYPE "STM32F0" + #error Board STM32F0 not supported + #elif defined(STM32F1) + #define BOARD_TYPE "STM32F1" + #elif defined(STM32F2) + #define BOARD_TYPE "STM32F2" + #elif defined(STM32F3) + #define BOARD_TYPE "STM32F3" + #elif defined(STM32F4) + #define BOARD_TYPE "STM32F4" + #elif defined(STM32F7) + #define BOARD_TYPE "STM32F7" + #else + #warning STM32 unknown board selected + #define BOARD_TYPE "STM32 Unknown" + #endif #else -// For Mega -#define BOARD_TYPE "AVR Mega" + // For Mega + #define BOARD_TYPE "AVR Mega" #endif // Start location in EEPROM to store config data. Default 0 // Config data Size currently is 128 bytes) #define EEPROM_START 0 -#include "WiFiNINA_Pinout_Generic.h" +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// #include diff --git a/examples/STM32_WiFiNINA/dynamicParams.h b/examples/STM32_WiFiNINA/dynamicParams.h index 6b996d66..159c734b 100644 --- a/examples/STM32_WiFiNINA/dynamicParams.h +++ b/examples/STM32_WiFiNINA/dynamicParams.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - dynamicParams.h for STM32_WiFiNINA.ino - For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + dynamicParams.h for STM32_WiFiNINA.ino + For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef dynamicParams_h @@ -26,7 +15,7 @@ #include "defines.h" -#define USE_DYNAMIC_PARAMETERS true +// USE_DYNAMIC_PARAMETERS defined in defined.h /////////////// Start dynamic Credentials /////////////// @@ -67,8 +56,8 @@ MenuItem myMenuItems [] = { "tk1", "Token1", Blynk_Token1, MAX_BLYNK_TOKEN_LEN }, { "sv2", "Blynk Server2", Blynk_Server2, MAX_BLYNK_SERVER_LEN }, { "tk2", "Token2", Blynk_Token2, MAX_BLYNK_TOKEN_LEN }, - { "pt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, - { "mq", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, + { "prt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, + { "mqt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, }; uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; diff --git a/examples/STM32_WiFiNINA_MQTT/Credentials.h b/examples/STM32_WiFiNINA_MQTT/Credentials.h index 8a248f05..27f9d191 100644 --- a/examples/STM32_WiFiNINA_MQTT/Credentials.h +++ b/examples/STM32_WiFiNINA_MQTT/Credentials.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - Credentials.h for STM32_WiFiNINA_MQTT.ino - For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + Credentials.h for STM32_WiFiNINA_MQTT.ino + For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef Credentials_h @@ -54,7 +43,7 @@ typedef struct Configuration } WiFiNINA_Configuration; */ -#define TO_LOAD_DEFAULT_CONFIG_DATA true +#define TO_LOAD_DEFAULT_CONFIG_DATA false #if TO_LOAD_DEFAULT_CONFIG_DATA diff --git a/examples/STM32_WiFiNINA_MQTT/STM32_WiFiNINA_MQTT.ino b/examples/STM32_WiFiNINA_MQTT/STM32_WiFiNINA_MQTT.ino index 0c42f8c7..15738efc 100644 --- a/examples/STM32_WiFiNINA_MQTT/STM32_WiFiNINA_MQTT.ino +++ b/examples/STM32_WiFiNINA_MQTT/STM32_WiFiNINA_MQTT.ino @@ -1,25 +1,27 @@ -/**************************************************************************************************************************** - STM32_WiFiNINA_MQTT.ino - For STM32 boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ + /********************************************************************************************************************************* + STM32_WiFiNINA_MQTT.ino + For STM32 boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ /**************************************************************************************************************************** You have to modify file ./libraries/Adafruit_MQTT_Library/Adafruit_MQTT.cpp as follows to avoid dtostrf error @@ -284,6 +286,11 @@ void MQTT_connect() #endif } +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + void setup() { // Debug console @@ -292,13 +299,28 @@ void setup() pinMode(LED_PIN, OUTPUT); - Serial.println("\nStart STM32_WiFiNINA_MQTT on " + String(BOARD_TYPE)); + delay(200); + + Serial.print(F("\nStarting STM32_WiFiNINA_MQTT on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); WiFiManager_NINA = new WiFiManager_NINA_Lite(); // Optional to change default AP IP(192.168.4.1) and channel(10) //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); - WiFiManager_NINA->setConfigPortalChannel(1); + WiFiManager_NINA->setConfigPortalChannel(0); + + #if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif // Set customized DHCP HostName WiFiManager_NINA->begin(HOST_NAME); @@ -307,21 +329,20 @@ void setup() } #if USE_DYNAMIC_PARAMETERS -void displayCredentials(void) +void displayCredentials() { - Serial.println("\nYour stored Credentials :"); + Serial.println(F("\nYour stored Credentials :")); - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - Serial.println(String(myMenuItems[i].displayName) + " = " + myMenuItems[i].pdata); + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); } } -#endif -void loop() +void displayCredentialsInLoop() { - -#if USE_DYNAMIC_PARAMETERS static bool displayedCredentials = false; if (!displayedCredentials) @@ -340,8 +361,16 @@ void loop() } } } +} + #endif +void loop() +{ WiFiManager_NINA->run(); check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif } diff --git a/examples/STM32_WiFiNINA_MQTT/defines.h b/examples/STM32_WiFiNINA_MQTT/defines.h index d138a393..4365e36e 100644 --- a/examples/STM32_WiFiNINA_MQTT/defines.h +++ b/examples/STM32_WiFiNINA_MQTT/defines.h @@ -1,77 +1,137 @@ /**************************************************************************************************************************** - defines.h for STM32_WiFiNINA_MQTT.ino - For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + defines.h for STM32_WiFiNINA_MQTT.ino + For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef defines_h #define defines_h /* Comment this out to disable prints and save space */ -#define DEBUG_WIFI_WEBSERVER_PORT Serial -#define WIFININA_DEBUG_OUTPUT Serial - -#define WIFININA_DEBUG true - -#define DRD_GENERIC_DEBUG true - -#if ( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) ) -#if defined(WIFININA_USE_STM32) -#undef WIFININA_USE_STM32 -#undef WIFI_USE_STM32 -#endif -#define WIFININA_USE_STM32 true -#define WIFI_USE_STM32 true +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial + +#define _WIFININA_LOGLEVEL_ 2 + +#define DRD_GENERIC_DEBUG true + +#if ( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \ + defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \ + defined(STM32WB) || defined(STM32MP1) ) + #if defined(WIFININA_USE_STM32) + #undef WIFININA_USE_STM32 + #undef WIFI_USE_STM32 + #endif + #define WIFININA_USE_STM32 true + #define WIFI_USE_STM32 true #endif #if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(CORE_TEENSY) || !(WIFININA_USE_STM32) ) -//#error This code is intended to run on STM32 platform! Please check your Tools->Board setting. + //#error This code is intended to run on STM32 platform! Please check your Tools->Board setting. #endif #if WIFININA_USE_STM32 -#if defined(STM32F0) -#define BOARD_TYPE "STM32F0" -#error Board STM32F0 not supported -#elif defined(STM32F1) -#define BOARD_TYPE "STM32F1" -#elif defined(STM32F2) -#define BOARD_TYPE "STM32F2" -#elif defined(STM32F3) -#define BOARD_TYPE "STM32F3" -#elif defined(STM32F4) -#define BOARD_TYPE "STM32F4" -#elif defined(STM32F7) -#define BOARD_TYPE "STM32F7" + #if defined(STM32F0) + #define BOARD_TYPE "STM32F0" + #error Board STM32F0 not supported + #elif defined(STM32F1) + #define BOARD_TYPE "STM32F1" + #elif defined(STM32F2) + #define BOARD_TYPE "STM32F2" + #elif defined(STM32F3) + #define BOARD_TYPE "STM32F3" + #elif defined(STM32F4) + #define BOARD_TYPE "STM32F4" + #elif defined(STM32F7) + #define BOARD_TYPE "STM32F7" + #else + #warning STM32 unknown board selected + #define BOARD_TYPE "STM32 Unknown" + #endif #else -#warning STM32 unknown board selected -#define BOARD_TYPE "STM32 Unknown" -#endif -#else -// For Mega -#define BOARD_TYPE "AVR Mega" + // For Mega + #define BOARD_TYPE "AVR Mega" #endif // Start location in EEPROM to store config data. Default 0 // Config data Size currently is 128 bytes) #define EEPROM_START 0 +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// + #include "WiFiNINA_Pinout_Generic.h" #include diff --git a/examples/STM32_WiFiNINA_MQTT/dynamicParams.h b/examples/STM32_WiFiNINA_MQTT/dynamicParams.h index 37719b9c..96fb9ddf 100644 --- a/examples/STM32_WiFiNINA_MQTT/dynamicParams.h +++ b/examples/STM32_WiFiNINA_MQTT/dynamicParams.h @@ -1,24 +1,13 @@ /**************************************************************************************************************************** - dynamicParams.h for STM32_WiFiNINA_MQTT.ino - For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + dynamicParams.h for STM32_WiFiNINA_MQTT.ino + For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license *****************************************************************************************************************************/ #ifndef dynamicParams_h @@ -26,7 +15,7 @@ #include "defines.h" -#define USE_DYNAMIC_PARAMETERS true +// USE_DYNAMIC_PARAMETERS defined in defined.h /////////////// Start dynamic Credentials /////////////// diff --git a/examples/Teensy_WiFiNINA/Credentials.h b/examples/Teensy_WiFiNINA/Credentials.h new file mode 100644 index 00000000..3413e5f7 --- /dev/null +++ b/examples/Teensy_WiFiNINA/Credentials.h @@ -0,0 +1,88 @@ +/**************************************************************************************************************************** + Credentials.h for Teensy40_WiFiNINA.ino + For Teensy boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef Credentials_h +#define Credentials_h + +#include "defines.h" + +/// Start Default Config Data ////////////////// + +/* +#define SSID_MAX_LEN 32 +//From v1.0.3, WPA2 passwords can be up to 63 characters long. +#define PASS_MAX_LEN 64 + +typedef struct +{ + char wifi_ssid[SSID_MAX_LEN]; + char wifi_pw [PASS_MAX_LEN]; +} WiFi_Credentials; + +#define NUM_WIFI_CREDENTIALS 2 + +// Configurable items besides fixed Header, just add board_name +#define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) +//////////////// + +typedef struct Configuration +{ + char header [16]; + WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + char board_name [24]; + int checkSum; +} WiFiNINA_Configuration; +*/ + +#define TO_LOAD_DEFAULT_CONFIG_DATA false + +#if TO_LOAD_DEFAULT_CONFIG_DATA + +// This feature is primarily used in development to force a known set of values as Config Data +// It will NOT force the Config Portal to activate. Use DRD or erase Config Data with Blynk.clearConfigData() + +// Used mostly for development and debugging. FORCES default values to be loaded each run. +// Config Portal data input will be ignored and overridden by DEFAULT_CONFIG_DATA +//bool LOAD_DEFAULT_CONFIG_DATA = true; + +// Used mostly once debugged. Assumes good data already saved in device. +// Config Portal data input will be override DEFAULT_CONFIG_DATA +bool LOAD_DEFAULT_CONFIG_DATA = false; + +WiFiNINA_Configuration defaultConfig = +{ + //char header[16], dummy, not used + "WIFININA", + // WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + // WiFi_Credentials.wifi_ssid and WiFi_Credentials.wifi_pw + "SSID1", "password1", + "SSID2", "password2", + //char board_name [24]; + "Teensy-Control", + // terminate the list + //int checkSum, dummy, not used + 0 + /////////// End Default Config Data ///////////// +}; + +#else + +bool LOAD_DEFAULT_CONFIG_DATA = false; + +WiFiNINA_Configuration defaultConfig; + +#endif // TO_LOAD_DEFAULT_CONFIG_DATA + +/////////// End Default Config Data ///////////// + + +#endif //Credentials_h diff --git a/examples/Teensy_WiFiNINA/Teensy_WiFiNINA.ino b/examples/Teensy_WiFiNINA/Teensy_WiFiNINA.ino new file mode 100644 index 00000000..7fe91c7b --- /dev/null +++ b/examples/Teensy_WiFiNINA/Teensy_WiFiNINA.ino @@ -0,0 +1,152 @@ +/**************************************************************************************************************************** + Teensy40_WiFiNINA.ino + For Teensy boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ + +#include "defines.h" +#include "Credentials.h" +#include "dynamicParams.h" + +void heartBeatPrint(void) +{ + static int num = 1; + + if (WiFi.status() == WL_CONNECTED) + Serial.print("H"); // H means connected to WiFi + else + Serial.print("F"); // F means not connected to WiFi + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(" "); + } +} + +void check_status() +{ + static unsigned long checkstatus_timeout = 0; + + //KH +#define HEARTBEAT_INTERVAL 600000L + // Print hearbeat every HEARTBEAT_INTERVAL (600) seconds. + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) + { + heartBeatPrint(); + checkstatus_timeout = millis() + HEARTBEAT_INTERVAL; + } +} + +WiFiManager_NINA_Lite* WiFiManager_NINA; + +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + +void setup() +{ + // Debug console + Serial.begin(115200); + while (!Serial); + + delay(200); + + Serial.print(F("\nStarting Teensy_WiFiNINA on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); + + WiFiManager_NINA = new WiFiManager_NINA_Lite(); + + // Optional to change default AP IP(192.168.4.1) and channel(10) + //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); + WiFiManager_NINA->setConfigPortalChannel(0); + +#if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif + + // Set customized DHCP HostName + WiFiManager_NINA->begin(HOST_NAME); + //Or use default Hostname "SAMD-WiFiNINA-XXXXXX" + //WiFiManager_NINA->begin(); + +} + +#if USE_DYNAMIC_PARAMETERS +void displayCredentials() +{ + Serial.println(F("\nYour stored Credentials :")); + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); + } +} + +void displayCredentialsInLoop() +{ + static bool displayedCredentials = false; + + if (!displayedCredentials) + { + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +} + +#endif + +void loop() +{ + WiFiManager_NINA->run(); + check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif +} diff --git a/examples/Teensy_WiFiNINA/defines.h b/examples/Teensy_WiFiNINA/defines.h new file mode 100644 index 00000000..d373d930 --- /dev/null +++ b/examples/Teensy_WiFiNINA/defines.h @@ -0,0 +1,130 @@ +/**************************************************************************************************************************** + defines.h for Teensy40_WiFiNINA.ino + For Teensy boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef defines_h +#define defines_h + +/* Comment this out to disable prints and save space */ +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial + +#define _WIFININA_LOGLEVEL_ 2 + +#define DRD_GENERIC_DEBUG true + +#if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || !defined(CORE_TEENSY) ) +# error This code is intended to run on Teensy platform! Please check your Tools->Board setting. +#endif + +#ifdef CORE_TEENSY + + #if defined(__IMXRT1062__) + // For Teensy 4.0 / 4.1 + #define BOARD_TYPE "TEENSY 4.0" + #elif defined(__MK66FX1M0__) + #define BOARD_TYPE "Teensy 3.6" + #elif defined(__MK64FX512__) + #define BOARD_TYPE "Teensy 3.5" + #elif defined(__MKL26Z64__) + #define BOARD_TYPE "Teensy LC" + #elif defined(__MK20DX256__) + #define BOARD_TYPE "Teensy 3.2" // and Teensy 3.1 (obsolete) + #elif defined(__MK20DX128__) + #define BOARD_TYPE "Teensy 3.0" + #elif defined(__AVR_AT90USB1286__) + #error Teensy 2.0++ not supported yet + #elif defined(__AVR_ATmega32U4__) + #error Teensy 2.0 not supported yet + #else + // For Other Boards + #define BOARD_TYPE "Unknown Teensy Board" + #endif +#endif + +// Start location in EEPROM to store config data. Default 0 +// Config data Size currently is 128 bytes) +#define EEPROM_START 0 + +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// + +#include + +#define HOST_NAME "Teensy-Master-Controller" + +#endif //defines_h diff --git a/examples/Teensy_WiFiNINA/dynamicParams.h b/examples/Teensy_WiFiNINA/dynamicParams.h new file mode 100644 index 00000000..07532a10 --- /dev/null +++ b/examples/Teensy_WiFiNINA/dynamicParams.h @@ -0,0 +1,74 @@ +/**************************************************************************************************************************** + dynamicParams.h for Teensy40_WiFiNINA.ino + For Teensy boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef dynamicParams_h +#define dynamicParams_h + +#include "defines.h" + +// USE_DYNAMIC_PARAMETERS defined in defined.h + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #define MAX_ID_LEN 5 + #define MAX_DISPLAY_NAME_LEN 16 + + typedef struct + { + char id [MAX_ID_LEN + 1]; + char displayName [MAX_DISPLAY_NAME_LEN + 1]; + char *pdata; + uint8_t maxlen; + } MenuItem; +**************************************/ + +#if USE_DYNAMIC_PARAMETERS + +#define MAX_BLYNK_SERVER_LEN 34 +#define MAX_BLYNK_TOKEN_LEN 34 + +char Blynk_Server1 [MAX_BLYNK_SERVER_LEN + 1] = "account.duckdns.org"; +char Blynk_Token1 [MAX_BLYNK_TOKEN_LEN + 1] = "token1"; + +char Blynk_Server2 [MAX_BLYNK_SERVER_LEN + 1] = "account.ddns.net"; +char Blynk_Token2 [MAX_BLYNK_TOKEN_LEN + 1] = "token2"; + +#define MAX_BLYNK_PORT_LEN 6 +char Blynk_Port [MAX_BLYNK_PORT_LEN + 1] = "8080"; + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = "mqtt.duckdns.org"; + +MenuItem myMenuItems [] = +{ + { "sv1", "Blynk Server1", Blynk_Server1, MAX_BLYNK_SERVER_LEN }, + { "tk1", "Token1", Blynk_Token1, MAX_BLYNK_TOKEN_LEN }, + { "sv2", "Blynk Server2", Blynk_Server2, MAX_BLYNK_SERVER_LEN }, + { "tk2", "Token2", Blynk_Token2, MAX_BLYNK_TOKEN_LEN }, + { "prt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, + { "mqt", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, +}; + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; + +#else + +MenuItem myMenuItems [] = {}; + +uint16_t NUM_MENU_ITEMS = 0; + +#endif //USE_DYNAMIC_PARAMETERS + + +#endif //dynamicParams_h diff --git a/examples/Teensy_WiFiNINA_MQTT/Credentials.h b/examples/Teensy_WiFiNINA_MQTT/Credentials.h new file mode 100644 index 00000000..3d888c0b --- /dev/null +++ b/examples/Teensy_WiFiNINA_MQTT/Credentials.h @@ -0,0 +1,88 @@ +/**************************************************************************************************************************** + Credentials.h for Teensy40_WiFiNINA_MQTT.ino + For Teensy boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef Credentials_h +#define Credentials_h + +#include "defines.h" + +/// Start Default Config Data ////////////////// + +/* +#define SSID_MAX_LEN 32 +//From v1.0.3, WPA2 passwords can be up to 63 characters long. +#define PASS_MAX_LEN 64 + +typedef struct +{ + char wifi_ssid[SSID_MAX_LEN]; + char wifi_pw [PASS_MAX_LEN]; +} WiFi_Credentials; + +#define NUM_WIFI_CREDENTIALS 2 + +// Configurable items besides fixed Header, just add board_name +#define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) +//////////////// + +typedef struct Configuration +{ + char header [16]; + WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + char board_name [24]; + int checkSum; +} WiFiNINA_Configuration; +*/ + +#define TO_LOAD_DEFAULT_CONFIG_DATA false + +#if TO_LOAD_DEFAULT_CONFIG_DATA + +// This feature is primarily used in development to force a known set of values as Config Data +// It will NOT force the Config Portal to activate. Use DRD or erase Config Data with Blynk.clearConfigData() + +// Used mostly for development and debugging. FORCES default values to be loaded each run. +// Config Portal data input will be ignored and overridden by DEFAULT_CONFIG_DATA +//bool LOAD_DEFAULT_CONFIG_DATA = true; + +// Used mostly once debugged. Assumes good data already saved in device. +// Config Portal data input will be override DEFAULT_CONFIG_DATA +bool LOAD_DEFAULT_CONFIG_DATA = false; + +WiFiNINA_Configuration defaultConfig = +{ + //char header[16], dummy, not used + "WIFININA", + // WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + // WiFi_Credentials.wifi_ssid and WiFi_Credentials.wifi_pw + "SSID1", "password1", + "SSID2", "password2", + //char board_name [24]; + "Teensy-MQTT", + // terminate the list + //int checkSum, dummy, not used + 0 + /////////// End Default Config Data ///////////// +}; + +#else + +bool LOAD_DEFAULT_CONFIG_DATA = false; + +WiFiNINA_Configuration defaultConfig; + +#endif // TO_LOAD_DEFAULT_CONFIG_DATA + +/////////// End Default Config Data ///////////// + + +#endif //Credentials_h diff --git a/examples/Teensy_WiFiNINA_MQTT/Teensy_WiFiNINA_MQTT.ino b/examples/Teensy_WiFiNINA_MQTT/Teensy_WiFiNINA_MQTT.ino new file mode 100644 index 00000000..32c6da0f --- /dev/null +++ b/examples/Teensy_WiFiNINA_MQTT/Teensy_WiFiNINA_MQTT.ino @@ -0,0 +1,376 @@ +/**************************************************************************************************************************** + Teensy40_WiFiNINA_MQTT.ino + For Teensy boards using WiFiNINA Modules/Shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ +/**************************************************************************************************************************** + You have to modify file ./libraries/Adafruit_MQTT_Library/Adafruit_MQTT.cpp as follows to avoid dtostrf error + + //#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || \ + // defined(ARDUINO_ARCH_SAMD) + #if !( ESP32 || ESP8266 || defined(CORE_TEENSY) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) || defined(STM32F4) || defined(STM32F7) ) + static char *dtostrf(double val, signed char width, unsigned char prec, char *sout) + { + char fmt[20]; + sprintf(fmt, "%%%d.%df", width, prec); + sprintf(sout, fmt, val); + return sout; + } + #endif + *****************************************************************************************************************************/ + +#include "defines.h" +#include "Credentials.h" +#include "dynamicParams.h" + +#define LOCAL_DEBUG true //false + +#include "Adafruit_MQTT.h" //https://github.com/adafruit/Adafruit_MQTT_Library +#include "Adafruit_MQTT_Client.h" //https://github.com/adafruit/Adafruit_MQTT_Library + +// Create a WiFiClient class to connect to the MQTT server +WiFiClient *client = NULL; + +Adafruit_MQTT_Client *mqtt = NULL; +Adafruit_MQTT_Publish *Temperature = NULL; +Adafruit_MQTT_Subscribe *LED_Control = NULL; + +// You have to get from a sensor. Here is just an example +uint32_t measuredTemp = 5; + +WiFiManager_NINA_Lite* WiFiManager_NINA; + +void heartBeatPrint(void) +{ + static int num = 1; + + if (WiFi.status() == WL_CONNECTED) + Serial.print("W"); // W means connected to WiFi + else + Serial.print("N"); // N means not connected to WiFi + + if (num == 40) + { + Serial.println(); + num = 1; + } + else if (num++ % 5 == 0) + { + Serial.print(" "); + } +} + +void publishMQTT(void) +{ + MQTT_connect(); + + if (Temperature->publish(measuredTemp)) + { + //Serial.println(F("Failed to send value to Temperature feed!")); + Serial.print("T"); // T means publishing OK + } + else + { + //Serial.println(F("Value to Temperature feed sucessfully sent!")); + Serial.print("F"); // F means publishing failure + } +} + +void subscribeMQTT(void) +{ + Adafruit_MQTT_Subscribe *subscription; + + MQTT_connect(); + + while ((subscription = mqtt->readSubscription(5000))) + { + if (subscription == LED_Control) + { + Serial.print(F("\nGot: ")); + Serial.println((char *)LED_Control->lastread); + + if (!strcmp((char*) LED_Control->lastread, "ON")) + { + digitalWrite(LED_PIN, HIGH); + } + else + { + digitalWrite(LED_PIN, LOW); + } + } + } +} + +void check_status() +{ + static unsigned long checkstatus_timeout = 0; + + //KH +#define HEARTBEAT_INTERVAL 5000L + // Print WiFi hearbeat, Publish MQTT Topic every HEARTBEAT_INTERVAL (5) seconds. + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) + { + if (WiFi.status() == WL_CONNECTED) + { + // MQTT related jobs + publishMQTT(); + subscribeMQTT(); + } + + heartBeatPrint(); + checkstatus_timeout = millis() + HEARTBEAT_INTERVAL; + } +} + +void deleteOldInstances(void) +{ + // Delete previous instances + if (mqtt) + { + delete mqtt; + mqtt = NULL; + Serial.println("Deleting old MQTT object"); + } + + if (Temperature) + { + delete Temperature; + Temperature = NULL; + Serial.println("Deleting old Temperature object"); + } +} + +#define USE_GLOBAL_TOPIC true + +#if USE_GLOBAL_TOPIC +String completePubTopic; +String completeSubTopic; +#endif + +void createNewInstances(void) +{ + if (!client) + { + client = new WiFiClient; + + if (client) + { + Serial.println("\nCreating new WiFi client object OK"); + } + else + Serial.println("\nCreating new WiFi client object failed"); + } + + // Create new instances from new data + if (!mqtt) + { + // Setup the MQTT client class by passing in the WiFi client and MQTT server and login details. + mqtt = new Adafruit_MQTT_Client(client, AIO_SERVER, atoi(AIO_SERVERPORT), AIO_USERNAME, AIO_KEY); + + if (mqtt) + { + Serial.println("Creating new MQTT object OK"); + Serial.println(String("AIO_SERVER = ") + AIO_SERVER + ", AIO_SERVERPORT = " + AIO_SERVERPORT); + Serial.println(String("AIO_USERNAME = ") + AIO_USERNAME + ", AIO_KEY = " + AIO_KEY); + } + else + Serial.println("Creating new MQTT object failed"); + } + + if (!Temperature) + { +#if USE_GLOBAL_TOPIC + completePubTopic = String(AIO_USERNAME) + String(AIO_PUB_TOPIC); +#else + // Must be static or global + static String completePubTopic = String(AIO_USERNAME) + String(AIO_PUB_TOPIC); +#endif + + Temperature = new Adafruit_MQTT_Publish(mqtt, completePubTopic.c_str()); + Serial.println(String("Creating new MQTT_Pub_Topic, Temperature = ") + completePubTopic); + + if (Temperature) + { + Serial.println("Creating new Temperature object OK"); + Serial.println(String("Temperature MQTT_Pub_Topic = ") + completePubTopic); + + } + else + Serial.println("Creating new Temperature object failed"); + } + + if (!LED_Control) + { +#if USE_GLOBAL_TOPIC + completeSubTopic = String(AIO_USERNAME) + String(AIO_SUB_TOPIC); +#else + // Must be static or global + static String completeSubTopic = String(AIO_USERNAME) + String(AIO_SUB_TOPIC); +#endif + + LED_Control = new Adafruit_MQTT_Subscribe(mqtt, completeSubTopic.c_str()); + + Serial.println(String("Creating new AIO_SUB_TOPIC, LED_Control = ") + completeSubTopic); + + if (LED_Control) + { + Serial.println("Creating new LED_Control object OK"); + Serial.println(String("LED_Control AIO_SUB_TOPIC = ") + completeSubTopic); + + mqtt->subscribe(LED_Control); + } + else + Serial.println("Creating new LED_Control object failed"); + } +} + +void MQTT_connect() +{ + int8_t ret; + + createNewInstances(); + + // Return if already connected + if (mqtt->connected()) + { + return; + } + +#if LOCAL_DEBUG + Serial.println("\nConnecting to WiFi MQTT (3 attempts)..."); +#endif + + uint8_t attempt = 3; + + while ( (ret = mqtt->connect()) ) + { + // connect will return 0 for connected + Serial.println(mqtt->connectErrorString(ret)); + +#if LOCAL_DEBUG + Serial.println("Another attemtpt to connect to MQTT in 5 seconds..."); +#endif + + mqtt->disconnect(); + delay(5000); // wait 5 seconds + attempt--; + + if (attempt == 0) + { + Serial.println("WiFi MQTT connection failed. Continuing with program..."); + return; + } + } + +#if LOCAL_DEBUG + Serial.println("WiFi MQTT connection successful!"); +#endif +} + +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + +void setup() +{ + // Debug console + Serial.begin(115200); + while (!Serial); + + pinMode(LED_PIN, OUTPUT); + + delay(200); + + Serial.print(F("\nStarting Teensy_WiFiNINA_MQTT on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); + + WiFiManager_NINA = new WiFiManager_NINA_Lite(); + + // Optional to change default AP IP(192.168.4.1) and channel(10) + //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); + WiFiManager_NINA->setConfigPortalChannel(0); + + #if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif + + // Set customized DHCP HostName + WiFiManager_NINA->begin(HOST_NAME); + //Or use default Hostname "SAMD-WiFiNINA-XXXXXX" + //WiFiManager_NINA->begin(); +} + +#if USE_DYNAMIC_PARAMETERS +void displayCredentials() +{ + Serial.println(F("\nYour stored Credentials :")); + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); + } +} + +void displayCredentialsInLoop() +{ + static bool displayedCredentials = false; + + if (!displayedCredentials) + { + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +} + +#endif + +void loop() +{ + WiFiManager_NINA->run(); + check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif +} diff --git a/examples/Teensy_WiFiNINA_MQTT/defines.h b/examples/Teensy_WiFiNINA_MQTT/defines.h new file mode 100644 index 00000000..9c467625 --- /dev/null +++ b/examples/Teensy_WiFiNINA_MQTT/defines.h @@ -0,0 +1,137 @@ +/**************************************************************************************************************************** + defines.h for Teensy40_WiFiNINA_MQTT.ino + For Teensy boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef defines_h +#define defines_h + +/* Comment this out to disable prints and save space */ +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial + +#define _WIFININA_LOGLEVEL_ 2 + +#define DRD_GENERIC_DEBUG true + +#if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || !defined(CORE_TEENSY) ) + #error This code is intended to run on Teensy platform! Please check your Tools->Board setting. +#endif + +#ifdef CORE_TEENSY + + #if defined(__IMXRT1062__) + // For Teensy 4.0 / 4.1 + #define BOARD_TYPE "TEENSY 4.0" + #elif defined(__MK66FX1M0__) + #define BOARD_TYPE "Teensy 3.6" + #elif defined(__MK64FX512__) + #define BOARD_TYPE "Teensy 3.5" + #elif defined(__MKL26Z64__) + #define BOARD_TYPE "Teensy LC" + #elif defined(__MK20DX256__) + #define BOARD_TYPE "Teensy 3.2" // and Teensy 3.1 (obsolete) + #elif defined(__MK20DX128__) + #define BOARD_TYPE "Teensy 3.0" + #elif defined(__AVR_AT90USB1286__) + #error Teensy 2.0++ not supported yet + #elif defined(__AVR_ATmega32U4__) + #error Teensy 2.0 not supported yet + #else + // For Other Boards + #define BOARD_TYPE "Unknown Teensy Board" + #endif +#endif + +// Start location in EEPROM to store config data. Default 0 +// Config data Size currently is 128 bytes) +#define EEPROM_START 0 + +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// + +#include + +#define HOST_NAME "Teensy-Master-Controller" + +#ifdef LED_BUILTIN +#define LED_PIN LED_BUILTIN +#else +#define LED_PIN 13 +#endif + + +#endif //defines_h diff --git a/examples/Teensy_WiFiNINA_MQTT/dynamicParams.h b/examples/Teensy_WiFiNINA_MQTT/dynamicParams.h new file mode 100644 index 00000000..10b93c4f --- /dev/null +++ b/examples/Teensy_WiFiNINA_MQTT/dynamicParams.h @@ -0,0 +1,76 @@ +/**************************************************************************************************************************** + dynamicParams.h for Teensy40_WiFiNINA_MQTT.ino + For Teensy boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef dynamicParams_h +#define dynamicParams_h + +#include "defines.h" + +// USE_DYNAMIC_PARAMETERS defined in defined.h + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #define MAX_ID_LEN 5 + #define MAX_DISPLAY_NAME_LEN 16 + + typedef struct + { + char id [MAX_ID_LEN + 1]; + char displayName [MAX_DISPLAY_NAME_LEN + 1]; + char *pdata; + uint8_t maxlen; + } MenuItem; +**************************************/ + +#if USE_DYNAMIC_PARAMETERS + +#define AIO_SERVER_LEN 20 +#define AIO_SERVERPORT_LEN 6 +#define AIO_USERNAME_LEN 20 +#define AIO_KEY_LEN 40 + +// +#define AIO_PUB_TOPIC_LEN 40 +#define AIO_SUB_TOPIC_LEN 40 + +char AIO_SERVER [AIO_SERVER_LEN + 1] = "io.adafruit.com"; +char AIO_SERVERPORT [AIO_SERVERPORT_LEN + 1] = "1883"; //1883, or 8883 for SSL +char AIO_USERNAME [AIO_USERNAME_LEN + 1] = "private"; +char AIO_KEY [AIO_KEY_LEN + 1] = "private"; + +char AIO_PUB_TOPIC [AIO_PUB_TOPIC_LEN + 1] = "/feeds/Temperature"; +char AIO_SUB_TOPIC [AIO_SUB_TOPIC_LEN + 1] = "/feeds/LED_Control"; + +MenuItem myMenuItems [] = +{ + { "svr", "AIO_SERVER", AIO_SERVER, AIO_SERVER_LEN }, + { "prt", "AIO_SERVERPORT", AIO_SERVERPORT, AIO_SERVERPORT_LEN }, + { "usr", "AIO_USERNAME", AIO_USERNAME, AIO_USERNAME_LEN }, + { "key", "AIO_KEY", AIO_KEY, AIO_KEY_LEN }, + { "pub", "AIO_PUB_TOPIC", AIO_PUB_TOPIC, AIO_PUB_TOPIC_LEN }, + { "sub", "AIO_SUB_TOPIC", AIO_SUB_TOPIC, AIO_SUB_TOPIC_LEN }, +}; + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; + +#else + +MenuItem myMenuItems [] = {}; + +uint16_t NUM_MENU_ITEMS = 0; + +#endif //USE_DYNAMIC_PARAMETERS + + +#endif //dynamicParams_h diff --git a/examples/nRF52_WiFiNINA/Credentials.h b/examples/nRF52_WiFiNINA/Credentials.h new file mode 100644 index 00000000..0d2f1538 --- /dev/null +++ b/examples/nRF52_WiFiNINA/Credentials.h @@ -0,0 +1,88 @@ +/**************************************************************************************************************************** + Credentials.h for nRF52840_WiFiNINA.ino + For nRF52 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef Credentials_h +#define Credentials_h + +#include "defines.h" + +/// Start Default Config Data ////////////////// + +/* +#define SSID_MAX_LEN 32 +//From v1.0.3, WPA2 passwords can be up to 63 characters long. +#define PASS_MAX_LEN 64 + +typedef struct +{ + char wifi_ssid[SSID_MAX_LEN]; + char wifi_pw [PASS_MAX_LEN]; +} WiFi_Credentials; + +#define NUM_WIFI_CREDENTIALS 2 + +// Configurable items besides fixed Header, just add board_name +#define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) +//////////////// + +typedef struct Configuration +{ + char header [16]; + WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + char board_name [24]; + int checkSum; +} WiFiNINA_Configuration; +*/ + +#define TO_LOAD_DEFAULT_CONFIG_DATA false + +#if TO_LOAD_DEFAULT_CONFIG_DATA + +// This feature is primarily used in development to force a known set of values as Config Data +// It will NOT force the Config Portal to activate. Use DRD or erase Config Data with Blynk.clearConfigData() + +// Used mostly for development and debugging. FORCES default values to be loaded each run. +// Config Portal data input will be ignored and overridden by DEFAULT_CONFIG_DATA +//bool LOAD_DEFAULT_CONFIG_DATA = true; + +// Used mostly once debugged. Assumes good data already saved in device. +// Config Portal data input will be override DEFAULT_CONFIG_DATA +bool LOAD_DEFAULT_CONFIG_DATA = false; + +WiFiNINA_Configuration defaultConfig = +{ + //char header[16], dummy, not used + "WIFININA", + // WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + // WiFi_Credentials.wifi_ssid and WiFi_Credentials.wifi_pw + "SSID1", "password1", + "SSID2", "password2", + //char board_name [24]; + "nRF52-Control", + // terminate the list + //int checkSum, dummy, not used + 0 + /////////// End Default Config Data ///////////// +}; + +#else + +bool LOAD_DEFAULT_CONFIG_DATA = false; + +WiFiNINA_Configuration defaultConfig; + +#endif // TO_LOAD_DEFAULT_CONFIG_DATA + +/////////// End Default Config Data ///////////// + + +#endif //Credentials_h diff --git a/examples/nRF52_WiFiNINA/defines.h b/examples/nRF52_WiFiNINA/defines.h new file mode 100644 index 00000000..e6448d08 --- /dev/null +++ b/examples/nRF52_WiFiNINA/defines.h @@ -0,0 +1,147 @@ +/**************************************************************************************************************************** + defines.h for nRF52840_WiFiNINA.ino + For nRF52 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef defines_h +#define defines_h + +/* Comment this out to disable prints and save space */ +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial + +#define _WIFININA_LOGLEVEL_ 2 + +#define DRD_GENERIC_DEBUG true + +#if ( defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) || \ + defined(NRF52840_FEATHER_SENSE) || defined(NRF52840_ITSYBITSY) || defined(NRF52840_CIRCUITPLAY) || defined(NRF52840_CLUE) || \ + defined(NRF52840_METRO) || defined(NRF52840_PCA10056) || defined(PARTICLE_XENON) || defined(NINA_B302_ublox) ) + #if defined(WIFININA_USE_NRF528XX) + #undef WIFININA_USE_NRF528XX + #undef WIFI_USE_NRF528XX + #endif + #define WIFININA_USE_NRF528XX true + #define WIFI_USE_NRF528XX true +#else + #error This code is intended to run only on the NRF528XX boards ! Please check your Tools->Board setting. +#endif + + +#if defined(WIFININA_USE_NRF528XX) + +#if defined(NRF52840_FEATHER) +#define BOARD_TYPE "NRF52840_FEATHER" +#elif defined(NRF52832_FEATHER) +#define BOARD_TYPE "NRF52832_FEATHER" +#elif defined(NRF52840_FEATHER_SENSE) +#define BOARD_TYPE "NRF52840_FEATHER_SENSE" +#elif defined(NRF52840_ITSYBITSY) +#define BOARD_TYPE "NRF52840_ITSYBITSY" +#elif defined(NRF52840_CIRCUITPLAY) +#define BOARD_TYPE "NRF52840_CIRCUITPLAY" +#elif defined(NRF52840_CLUE) +#define BOARD_TYPE "NRF52840_CLUE" +#elif defined(NRF52840_METRO) +#define BOARD_TYPE "NRF52840_METRO" +#elif defined(NRF52840_PCA10056) +#define BOARD_TYPE "NRF52840_PCA10056" +#elif defined(PARTICLE_XENON) +#define BOARD_TYPE "PARTICLE_XENON" +#elif defined(NINA_B302_ublox) +#define BOARD_TYPE "NINA_B302_ublox" +#elif defined(ARDUINO_NRF52_ADAFRUIT) +#define BOARD_TYPE "ARDUINO_NRF52_ADAFRUIT" +#elif defined(NRF52_SERIES) +#define BOARD_TYPE "NRF52_SERIES" +#else +#define BOARD_TYPE "NRF52 Unknown" +#endif + +#endif + +// Start location in EEPROM to store config data. Default 0 +// Config data Size currently is 128 bytes) +#define EEPROM_START + +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// + +#include + +#define HOST_NAME "nRF52-Master-Controller" + +#endif //defines_h diff --git a/examples/nRF52_WiFiNINA/dynamicParams.h b/examples/nRF52_WiFiNINA/dynamicParams.h new file mode 100644 index 00000000..6d72d434 --- /dev/null +++ b/examples/nRF52_WiFiNINA/dynamicParams.h @@ -0,0 +1,74 @@ +/**************************************************************************************************************************** + dynamicParams.h for nRF52840_WiFiNINA.ino + For nRF52 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef dynamicParams_h +#define dynamicParams_h + +#include "defines.h" + +#define USE_DYNAMIC_PARAMETERS true + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #define MAX_ID_LEN 5 + #define MAX_DISPLAY_NAME_LEN 16 + + typedef struct + { + char id [MAX_ID_LEN + 1]; + char displayName [MAX_DISPLAY_NAME_LEN + 1]; + char *pdata; + uint8_t maxlen; + } MenuItem; +**************************************/ + +#if USE_DYNAMIC_PARAMETERS + +#define MAX_BLYNK_SERVER_LEN 34 +#define MAX_BLYNK_TOKEN_LEN 34 + +char Blynk_Server1 [MAX_BLYNK_SERVER_LEN + 1] = "account.duckdns.org"; +char Blynk_Token1 [MAX_BLYNK_TOKEN_LEN + 1] = "token1"; + +char Blynk_Server2 [MAX_BLYNK_SERVER_LEN + 1] = "account.ddns.net"; +char Blynk_Token2 [MAX_BLYNK_TOKEN_LEN + 1] = "token2"; + +#define MAX_BLYNK_PORT_LEN 6 +char Blynk_Port [MAX_BLYNK_PORT_LEN + 1] = "8080"; + +#define MAX_MQTT_SERVER_LEN 34 +char MQTT_Server [MAX_MQTT_SERVER_LEN + 1] = "mqtt.duckdns.org"; + +MenuItem myMenuItems [] = +{ + { "sv1", "Blynk Server1", Blynk_Server1, MAX_BLYNK_SERVER_LEN }, + { "tk1", "Token1", Blynk_Token1, MAX_BLYNK_TOKEN_LEN }, + { "sv2", "Blynk Server2", Blynk_Server2, MAX_BLYNK_SERVER_LEN }, + { "tk2", "Token2", Blynk_Token2, MAX_BLYNK_TOKEN_LEN }, + { "pt", "Port", Blynk_Port, MAX_BLYNK_PORT_LEN }, + { "mq", "MQTT Server", MQTT_Server, MAX_MQTT_SERVER_LEN }, +}; + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; + +#else + +MenuItem myMenuItems [] = {}; + +uint16_t NUM_MENU_ITEMS = 0; + +#endif //USE_DYNAMIC_PARAMETERS + + +#endif //dynamicParams_h diff --git a/examples/nRF52_WiFiNINA/nRF52_WiFiNINA.ino b/examples/nRF52_WiFiNINA/nRF52_WiFiNINA.ino new file mode 100644 index 00000000..05e64903 --- /dev/null +++ b/examples/nRF52_WiFiNINA/nRF52_WiFiNINA.ino @@ -0,0 +1,152 @@ +/**************************************************************************************************************************** + nRF52840_WiFiNINA.ino + For nRF52 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ + +#include "defines.h" +#include "Credentials.h" +#include "dynamicParams.h" + +void heartBeatPrint(void) +{ + static int num = 1; + + if (WiFi.status() == WL_CONNECTED) + Serial.print("H"); // H means connected to WiFi + else + Serial.print("F"); // F means not connected to WiFi + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(" "); + } +} + +void check_status() +{ + static unsigned long checkstatus_timeout = 0; + + //KH +#define HEARTBEAT_INTERVAL 20000L + // Print hearbeat every HEARTBEAT_INTERVAL (20) seconds. + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) + { + heartBeatPrint(); + checkstatus_timeout = millis() + HEARTBEAT_INTERVAL; + } +} + +WiFiManager_NINA_Lite* WiFiManager_NINA; + +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + +void setup() +{ + // Debug console + Serial.begin(115200); + while (!Serial); + + delay(200); + + Serial.print(F("\nStarting nRF52_WiFiNINA on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); + + WiFiManager_NINA = new WiFiManager_NINA_Lite(); + + // Optional to change default AP IP(192.168.4.1) and channel(10) + //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); + WiFiManager_NINA->setConfigPortalChannel(0); + +#if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif + + // Set customized DHCP HostName + WiFiManager_NINA->begin(HOST_NAME); + //Or use default Hostname "nRF52-WiFiNINA-XXXXXX" + //WiFiManager_NINA->begin(); + +} + +#if USE_DYNAMIC_PARAMETERS +void displayCredentials() +{ + Serial.println(F("\nYour stored Credentials :")); + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); + } +} + +void displayCredentialsInLoop() +{ + static bool displayedCredentials = false; + + if (!displayedCredentials) + { + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +} + +#endif + +void loop() +{ + WiFiManager_NINA->run(); + check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif +} diff --git a/examples/nRF52_WiFiNINA_MQTT/Credentials.h b/examples/nRF52_WiFiNINA_MQTT/Credentials.h new file mode 100644 index 00000000..4f0c4416 --- /dev/null +++ b/examples/nRF52_WiFiNINA_MQTT/Credentials.h @@ -0,0 +1,89 @@ +/**************************************************************************************************************************** + Credentials.h for nRF52840_WiFiNINA_MQTT.ino + For nRF52 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef Credentials_h +#define Credentials_h + +#include "defines.h" + +/// Start Default Config Data ////////////////// + +/* +#define SSID_MAX_LEN 32 +//From v1.0.3, WPA2 passwords can be up to 63 characters long. +#define PASS_MAX_LEN 64 + +typedef struct +{ + char wifi_ssid[SSID_MAX_LEN]; + char wifi_pw [PASS_MAX_LEN]; +} WiFi_Credentials; + +#define NUM_WIFI_CREDENTIALS 2 + +// Configurable items besides fixed Header, just add board_name +#define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) +//////////////// + +typedef struct Configuration +{ + char header [16]; + WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + char board_name [24]; + int checkSum; +} WiFiNINA_Configuration; +*/ + +#define TO_LOAD_DEFAULT_CONFIG_DATA false + +#if TO_LOAD_DEFAULT_CONFIG_DATA + +// This feature is primarily used in development to force a known set of values as Config Data +// It will NOT force the Config Portal to activate. Use DRD or erase Config Data with Blynk.clearConfigData() + +// Used mostly for development and debugging. FORCES default values to be loaded each run. +// Config Portal data input will be ignored and overridden by DEFAULT_CONFIG_DATA +//bool LOAD_DEFAULT_CONFIG_DATA = true; + +// Used mostly once debugged. Assumes good data already saved in device. +// Config Portal data input will be override DEFAULT_CONFIG_DATA +bool LOAD_DEFAULT_CONFIG_DATA = false; + + +WiFiNINA_Configuration defaultConfig = +{ + //char header[16], dummy, not used + "WIFININA", + // WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + // WiFi_Credentials.wifi_ssid and WiFi_Credentials.wifi_pw + "SSID1", "password1", + "SSID2", "password2", + //char board_name [24]; + "nRF52_MQTT", + // terminate the list + //int checkSum, dummy, not used + 0 + /////////// End Default Config Data ///////////// +}; + +#else + +bool LOAD_DEFAULT_CONFIG_DATA = false; + +WiFiNINA_Configuration defaultConfig; + +#endif // TO_LOAD_DEFAULT_CONFIG_DATA + +/////////// End Default Config Data ///////////// + + +#endif //Credentials_h diff --git a/examples/nRF52_WiFiNINA_MQTT/defines.h b/examples/nRF52_WiFiNINA_MQTT/defines.h new file mode 100644 index 00000000..f757617d --- /dev/null +++ b/examples/nRF52_WiFiNINA_MQTT/defines.h @@ -0,0 +1,153 @@ +/**************************************************************************************************************************** + defines.h for nRF52840_WiFiNINA_MQTT.ino + For nRF52 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef defines_h +#define defines_h + +/* Comment this out to disable prints and save space */ +#define DEBUG_WIFI_WEBSERVER_PORT Serial +#define WIFININA_DEBUG_OUTPUT Serial + +#define _WIFININA_LOGLEVEL_ 2 + +#define DRD_GENERIC_DEBUG true + +#if ( defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) || \ + defined(NRF52840_FEATHER_SENSE) || defined(NRF52840_ITSYBITSY) || defined(NRF52840_CIRCUITPLAY) || defined(NRF52840_CLUE) || \ + defined(NRF52840_METRO) || defined(NRF52840_PCA10056) || defined(PARTICLE_XENON) || defined(NINA_B302_ublox) ) + #if defined(WIFININA_USE_NRF528XX) + #undef WIFININA_USE_NRF528XX + #undef WIFI_USE_NRF528XX + #endif + #define WIFININA_USE_NRF528XX true + #define WIFI_USE_NRF528XX true +#else + #error This code is intended to run only on the NRF528XX boards ! Please check your Tools->Board setting. +#endif + + +#if defined(WIFININA_USE_NRF528XX) + +#if defined(NRF52840_FEATHER) +#define BOARD_TYPE "NRF52840_FEATHER" +#elif defined(NRF52832_FEATHER) +#define BOARD_TYPE "NRF52832_FEATHER" +#elif defined(NRF52840_FEATHER_SENSE) +#define BOARD_TYPE "NRF52840_FEATHER_SENSE" +#elif defined(NRF52840_ITSYBITSY) +#define BOARD_TYPE "NRF52840_ITSYBITSY" +#elif defined(NRF52840_CIRCUITPLAY) +#define BOARD_TYPE "NRF52840_CIRCUITPLAY" +#elif defined(NRF52840_CLUE) +#define BOARD_TYPE "NRF52840_CLUE" +#elif defined(NRF52840_METRO) +#define BOARD_TYPE "NRF52840_METRO" +#elif defined(NRF52840_PCA10056) +#define BOARD_TYPE "NRF52840_PCA10056" +#elif defined(PARTICLE_XENON) +#define BOARD_TYPE "PARTICLE_XENON" +#elif defined(NINA_B302_ublox) +#define BOARD_TYPE "NINA_B302_ublox" +#elif defined(ARDUINO_NRF52_ADAFRUIT) +#define BOARD_TYPE "ARDUINO_NRF52_ADAFRUIT" +#elif defined(NRF52_SERIES) +#define BOARD_TYPE "NRF52_SERIES" +#else +#define BOARD_TYPE "NRF52 Unknown" +#endif + +#endif + +// Start location in EEPROM to store config data. Default 0 +// Config data Size currently is 128 bytes) +#define EEPROM_START + +///////////////////////////////////////////// + +// Add customs headers from v1.1.0 +#define USING_CUSTOMS_STYLE true +#define USING_CUSTOMS_HEAD_ELEMENT true +#define USING_CORS_FEATURE true + +///////////////////////////////////////////// + +#define USE_WIFI_NINA true +#define USE_WIFI101 false +#define USE_WIFI_CUSTOM false + +#if USE_WIFI_NINA + + #warning Using WIFININA_Generic Library + #define SHIELD_TYPE "WiFiNINA using WiFiNINA_Generic Library" + + #include "WiFiNINA_Pinout_Generic.h" + +#elif USE_WIFI101 + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #define SHIELD_TYPE "WINC1500 using WiFi101 Library" + #warning Using WiFi101 Library + +#elif USE_WIFI_CUSTOM + + #if defined(USE_WIFI_NINA) + #undef USE_WIFI_NINA + #endif + + #define USE_WIFI_NINA false + + #if defined(USE_WIFI101) + #undef USE_WIFI101 + #endif + + #define USE_WIFI101 false + + #define SHIELD_TYPE "Custom using Custom WiFi Library" + #warning Using Custom WiFi Library. You must include here or compile error + +#else + + #define SHIELD_TYPE "Default WiFi using WiFi Library" + #warning Using fallback WiFi.h Library defined in WiFiWebServer Library. + +#endif + +///////////////////////////////////////////// + +// Force some params in Blynk, only valid for library version 1.0.1 and later +#define TIMEOUT_RECONNECT_WIFI 10000L +#define RESET_IF_CONFIG_TIMEOUT true +#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 5 + +// Config Timeout 120s (default 60s) +#define CONFIG_TIMEOUT 120000L + +#define USE_DYNAMIC_PARAMETERS true + +///////////////////////////////////////////// + +#include + +#define HOST_NAME "nRF52-MQTT-Controller" + +#ifdef LED_BUILTIN +#define LED_PIN LED_BUILTIN +#else +#define LED_PIN 13 +#endif + +#endif //defines_h diff --git a/examples/nRF52_WiFiNINA_MQTT/dynamicParams.h b/examples/nRF52_WiFiNINA_MQTT/dynamicParams.h new file mode 100644 index 00000000..bb6226ff --- /dev/null +++ b/examples/nRF52_WiFiNINA_MQTT/dynamicParams.h @@ -0,0 +1,76 @@ +/**************************************************************************************************************************** + dynamicParams.h for nRF52840_WiFiNINA_MQTT.ino + For nRF52 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + *****************************************************************************************************************************/ + +#ifndef dynamicParams_h +#define dynamicParams_h + +#include "defines.h" + +// USE_DYNAMIC_PARAMETERS defined in defined.h + +/////////////// Start dynamic Credentials /////////////// + +//Defined in +/************************************** + #define MAX_ID_LEN 5 + #define MAX_DISPLAY_NAME_LEN 16 + + typedef struct + { + char id [MAX_ID_LEN + 1]; + char displayName [MAX_DISPLAY_NAME_LEN + 1]; + char *pdata; + uint8_t maxlen; + } MenuItem; +**************************************/ + +#if USE_DYNAMIC_PARAMETERS + +#define AIO_SERVER_LEN 20 +#define AIO_SERVERPORT_LEN 6 +#define AIO_USERNAME_LEN 20 +#define AIO_KEY_LEN 40 + +// +#define AIO_PUB_TOPIC_LEN 40 +#define AIO_SUB_TOPIC_LEN 40 + +char AIO_SERVER [AIO_SERVER_LEN + 1] = "io.adafruit.com"; +char AIO_SERVERPORT [AIO_SERVERPORT_LEN + 1] = "1883"; //1883, or 8883 for SSL +char AIO_USERNAME [AIO_USERNAME_LEN + 1] = "private"; +char AIO_KEY [AIO_KEY_LEN + 1] = "private"; + +char AIO_PUB_TOPIC [AIO_PUB_TOPIC_LEN + 1] = "/feeds/Temperature"; +char AIO_SUB_TOPIC [AIO_SUB_TOPIC_LEN + 1] = "/feeds/LED_Control"; + +MenuItem myMenuItems [] = +{ + { "svr", "AIO_SERVER", AIO_SERVER, AIO_SERVER_LEN }, + { "prt", "AIO_SERVERPORT", AIO_SERVERPORT, AIO_SERVERPORT_LEN }, + { "usr", "AIO_USERNAME", AIO_USERNAME, AIO_USERNAME_LEN }, + { "key", "AIO_KEY", AIO_KEY, AIO_KEY_LEN }, + { "pub", "AIO_PUB_TOPIC", AIO_PUB_TOPIC, AIO_PUB_TOPIC_LEN }, + { "sub", "AIO_SUB_TOPIC", AIO_SUB_TOPIC, AIO_SUB_TOPIC_LEN }, +}; + +uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem); //MenuItemSize; + +#else + +MenuItem myMenuItems [] = {}; + +uint16_t NUM_MENU_ITEMS = 0; + +#endif //USE_DYNAMIC_PARAMETERS + + +#endif //dynamicParams_h diff --git a/examples/nRF52_WiFiNINA_MQTT/nRF52_WiFiNINA_MQTT.ino b/examples/nRF52_WiFiNINA_MQTT/nRF52_WiFiNINA_MQTT.ino new file mode 100644 index 00000000..5dc3b2a1 --- /dev/null +++ b/examples/nRF52_WiFiNINA_MQTT/nRF52_WiFiNINA_MQTT.ino @@ -0,0 +1,378 @@ +/********************************************************************************************************************************* + nRF52840_WiFiNINA_MQTT.ino + For nRF52 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ + +/**************************************************************************************************************************** + You have to modify file ./libraries/Adafruit_MQTT_Library/Adafruit_MQTT.cpp as follows to avoid dtostrf error + + //#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || \ + // defined(ARDUINO_ARCH_SAMD) + #if !( ESP32 || ESP8266 || defined(CORE_TEENSY) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) || defined(STM32F4) || defined(STM32F7) ) + static char *dtostrf(double val, signed char width, unsigned char prec, char *sout) + { + char fmt[20]; + sprintf(fmt, "%%%d.%df", width, prec); + sprintf(sout, fmt, val); + return sout; + } + #endif + *****************************************************************************************************************************/ + +#include "defines.h" +#include "Credentials.h" +#include "dynamicParams.h" + +#define LOCAL_DEBUG true //false + +#include "Adafruit_MQTT.h" //https://github.com/adafruit/Adafruit_MQTT_Library +#include "Adafruit_MQTT_Client.h" //https://github.com/adafruit/Adafruit_MQTT_Library + +// Create a WiFiClient class to connect to the MQTT server +WiFiClient *client = NULL; + +Adafruit_MQTT_Client *mqtt = NULL; +Adafruit_MQTT_Publish *Temperature = NULL; +Adafruit_MQTT_Subscribe *LED_Control = NULL; + +// You have to get from a sensor. Here is just an example +uint32_t measuredTemp = 5; + +WiFiManager_NINA_Lite* WiFiManager_NINA; + +void heartBeatPrint(void) +{ + static int num = 1; + + if (WiFi.status() == WL_CONNECTED) + Serial.print("W"); // W means connected to WiFi + else + Serial.print("N"); // N means not connected to WiFi + + if (num == 40) + { + Serial.println(); + num = 1; + } + else if (num++ % 5 == 0) + { + Serial.print(" "); + } +} + +void publishMQTT(void) +{ + MQTT_connect(); + + if (Temperature->publish(measuredTemp)) + { + //Serial.println(F("Failed to send value to Temperature feed!")); + Serial.print("T"); // T means publishing OK + } + else + { + //Serial.println(F("Value to Temperature feed sucessfully sent!")); + Serial.print("F"); // F means publishing failure + } +} + +void subscribeMQTT(void) +{ + Adafruit_MQTT_Subscribe *subscription; + + MQTT_connect(); + + while ((subscription = mqtt->readSubscription(5000))) + { + if (subscription == LED_Control) + { + Serial.print(F("\nGot: ")); + Serial.println((char *)LED_Control->lastread); + + if (!strcmp((char*) LED_Control->lastread, "ON")) + { + digitalWrite(LED_PIN, HIGH); + } + else + { + digitalWrite(LED_PIN, LOW); + } + } + } +} + +void check_status() +{ + static unsigned long checkstatus_timeout = 0; + + //KH +#define HEARTBEAT_INTERVAL 5000L + // Print WiFi hearbeat, Publish MQTT Topic every HEARTBEAT_INTERVAL (5) seconds. + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) + { + if (WiFi.status() == WL_CONNECTED) + { + // MQTT related jobs + publishMQTT(); + subscribeMQTT(); + } + + heartBeatPrint(); + checkstatus_timeout = millis() + HEARTBEAT_INTERVAL; + } +} + +void deleteOldInstances(void) +{ + // Delete previous instances + if (mqtt) + { + delete mqtt; + mqtt = NULL; + Serial.println("Deleting old MQTT object"); + } + + if (Temperature) + { + delete Temperature; + Temperature = NULL; + Serial.println("Deleting old Temperature object"); + } +} + +#define USE_GLOBAL_TOPIC true + +#if USE_GLOBAL_TOPIC +String completePubTopic; +String completeSubTopic; +#endif + +void createNewInstances(void) +{ + if (!client) + { + client = new WiFiClient; + + if (client) + { + Serial.println("\nCreating new WiFi client object OK"); + } + else + Serial.println("\nCreating new WiFi client object failed"); + } + + // Create new instances from new data + if (!mqtt) + { + // Setup the MQTT client class by passing in the WiFi client and MQTT server and login details. + mqtt = new Adafruit_MQTT_Client(client, AIO_SERVER, atoi(AIO_SERVERPORT), AIO_USERNAME, AIO_KEY); + + if (mqtt) + { + Serial.println("Creating new MQTT object OK"); + Serial.println(String("AIO_SERVER = ") + AIO_SERVER + ", AIO_SERVERPORT = " + AIO_SERVERPORT); + Serial.println(String("AIO_USERNAME = ") + AIO_USERNAME + ", AIO_KEY = " + AIO_KEY); + } + else + Serial.println("Creating new MQTT object failed"); + } + + if (!Temperature) + { +#if USE_GLOBAL_TOPIC + completePubTopic = String(AIO_USERNAME) + String(AIO_PUB_TOPIC); +#else + // Must be static or global + static String completePubTopic = String(AIO_USERNAME) + String(AIO_PUB_TOPIC); +#endif + + Temperature = new Adafruit_MQTT_Publish(mqtt, completePubTopic.c_str()); + Serial.println(String("Creating new MQTT_Pub_Topic, Temperature = ") + completePubTopic); + + if (Temperature) + { + Serial.println("Creating new Temperature object OK"); + Serial.println(String("Temperature MQTT_Pub_Topic = ") + completePubTopic); + + } + else + Serial.println("Creating new Temperature object failed"); + } + + if (!LED_Control) + { +#if USE_GLOBAL_TOPIC + completeSubTopic = String(AIO_USERNAME) + String(AIO_SUB_TOPIC); +#else + // Must be static or global + static String completeSubTopic = String(AIO_USERNAME) + String(AIO_SUB_TOPIC); +#endif + + LED_Control = new Adafruit_MQTT_Subscribe(mqtt, completeSubTopic.c_str()); + + Serial.println(String("Creating new AIO_SUB_TOPIC, LED_Control = ") + completeSubTopic); + + if (LED_Control) + { + Serial.println("Creating new LED_Control object OK"); + Serial.println(String("LED_Control AIO_SUB_TOPIC = ") + completeSubTopic); + + mqtt->subscribe(LED_Control); + } + else + Serial.println("Creating new LED_Control object failed"); + } +} + +void MQTT_connect() +{ + int8_t ret; + + createNewInstances(); + + // Return if already connected + if (mqtt->connected()) + { + return; + } + +#if LOCAL_DEBUG + Serial.println("\nConnecting to WiFi MQTT (3 attempts)..."); +#endif + + uint8_t attempt = 3; + + while ( (ret = mqtt->connect()) ) + { + // connect will return 0 for connected + Serial.println(mqtt->connectErrorString(ret)); + +#if LOCAL_DEBUG + Serial.println("Another attemtpt to connect to MQTT in 5 seconds..."); +#endif + + mqtt->disconnect(); + delay(5000); // wait 5 seconds + attempt--; + + if (attempt == 0) + { + Serial.println("WiFi MQTT connection failed. Continuing with program..."); + return; + } + } + +#if LOCAL_DEBUG + Serial.println("WiFi MQTT connection successful!"); +#endif +} + +#if USING_CUSTOMS_STYLE +const char NewCustomsStyle[] /*PROGMEM*/ = ""; +#endif + +void setup() +{ + // Debug console + Serial.begin(115200); + while (!Serial); + + pinMode(LED_PIN, OUTPUT); + + delay(200); + + Serial.print(F("\nStarting nRF52_WiFiNINA_MQTT on ")); Serial.println(BOARD_TYPE); + Serial.println(WIFIMANAGER_NINA_LITE_VERSION); + + WiFiManager_NINA = new WiFiManager_NINA_Lite(); + + // Optional to change default AP IP(192.168.4.1) and channel(10) + //WiFiManager_NINA->setConfigPortalIP(IPAddress(192, 168, 120, 1)); + WiFiManager_NINA->setConfigPortalChannel(0); + +#if USING_CUSTOMS_STYLE + WiFiManager_NINA->setCustomsStyle(NewCustomsStyle); +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + WiFiManager_NINA->setCustomsHeadElement(""); +#endif + +#if USING_CORS_FEATURE + WiFiManager_NINA->setCORSHeader("Your Access-Control-Allow-Origin"); +#endif + + // Set customized DHCP HostName + WiFiManager_NINA->begin(HOST_NAME); + //Or use default Hostname "nRF52-WiFiNINA-XXXXXX" + //WiFiManager_NINA->begin(); + +} + +#if USE_DYNAMIC_PARAMETERS +void displayCredentials() +{ + Serial.println(F("\nYour stored Credentials :")); + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + Serial.print(myMenuItems[i].displayName); + Serial.print(F(" = ")); + Serial.println(myMenuItems[i].pdata); + } +} + +void displayCredentialsInLoop() +{ + static bool displayedCredentials = false; + + if (!displayedCredentials) + { + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + if (!strlen(myMenuItems[i].pdata)) + { + break; + } + + if ( i == (NUM_MENU_ITEMS - 1) ) + { + displayedCredentials = true; + displayCredentials(); + } + } + } +} + +#endif + +void loop() +{ + WiFiManager_NINA->run(); + check_status(); + +#if USE_DYNAMIC_PARAMETERS + displayCredentialsInLoop(); +#endif +} diff --git a/keywords.txt b/keywords.txt index 937f2293..a4e889c8 100644 --- a/keywords.txt +++ b/keywords.txt @@ -32,6 +32,14 @@ clearConfigData KEYWORD2 isConfigDataValid KEYWORD2 resetFunc KEYWORD2 IPAddressToString KEYWORD2 +resetAndEnterConfigPortal KEYWORD2 +resetAndEnterConfigPortalPersistent KEYWORD2 +setCustomsStyle KEYWORD2 +getCustomsStyle KEYWORD2 +setCustomsHeadElement KEYWORD2 +getCustomsHeadElement KEYWORD2 +setCORSHeader KEYWORD2 +getCORSHeader KEYWORD2 ####################################### # Constants (LITERAL1) @@ -42,6 +50,9 @@ IPAddressToString KEYWORD2 CONFIG_DATA_SIZE LITERAL1 NUM_MENU_ITEMS LITERAL1 WIFININA_HTML_HEAD LITERAL1 +WIFININA_HTML_HEAD_START LITERAL1 +WIFININA_HTML_HEAD_STYLE LITERAL1 +WIFININA_HTML_HEAD_END LITERAL1 WIFININA_FLDSET_START LITERAL1 WIFININA_FLDSET_END LITERAL1 WIFININA_HTML_PARAM LITERAL1 @@ -50,3 +61,14 @@ WIFININA_HTML_SCRIPT LITERAL1 WIFININA_HTML_SCRIPT_ITEM LITERAL1 WIFININA_HTML_SCRIPT_END LITERAL1 WIFININA_HTML_END LITERAL1 + +WM_HTTP_HEAD_CL LITERAL1 +WM_HTTP_HEAD_TEXT_HTML LITERAL1 +WM_HTTP_HEAD_TEXT_PLAIN LITERAL1 +WM_HTTP_CACHE_CONTROL LITERAL1 +WM_HTTP_NO_STORE LITERAL1 +WM_HTTP_PRAGMA LITERAL1 +WM_HTTP_NO_CACHE LITERAL1 +WM_HTTP_EXPIRES LITERAL1 +WM_HTTP_CORS LITERAL1 +WM_HTTP_CORS_ALLOW_ALL LITERAL1 diff --git a/library.json b/library.json index 321cbc51..b4edb752 100644 --- a/library.json +++ b/library.json @@ -1,8 +1,8 @@ { "name": "WiFiManager_NINA_Lite", - "version": "1.0.5", + "version": "1.1.0", "keywords": "wifi, wi-fi, MutiWiFi, WiFiNINA, U-Blox, W101, W102, shield, Mega, Teensy, SAM DUE, SAMD21, SAMD51, STM32, nRF52, Credentials, Manager, Config Portal, Double, Reset, Detector", - "description": "Library to configure MultiWiFi/Credentials at runtime for AVR Mega, Teensy, SAM DUE, SAMD21, SAMD51, STM32F/L/H/G/WB/MP1, nRF52, etc. boards running WiFiNINA modules/shields. You can also specify DHCP HostName, static AP and STA IP. Use much less memory compared to full-fledge WiFiManager. Config Portal will be auto-adjusted to match the number of dynamic custom parameters. Optional default Credentials to be autoloaded into Config Portal to use or change instead of manually input. Credentials are saved in LittleFS/InternalFS, EEPROM, FlashStorage or DueFlashStorage. DoubleDetectDetector feature permits entering Config Portal as requested.", + "description": "Library to configure MultiWiFi/Credentials at runtime for AVR Mega, Teensy, SAM DUE, SAMD21, SAMD51, STM32F/L/H/G/WB/MP1, nRF52, etc. boards running WiFiNINA modules/shields. You can also specify DHCP HostName, static AP and STA IP. Use much less memory compared to full-fledge WiFiManager. Config Portal will be auto-adjusted to match the number of dynamic custom parameters. Optional default Credentials to be autoloaded into Config Portal to use or change instead of manually input. Credentials are saved in LittleFS/InternalFS, EEPROM, FlashStorage_SAMD, FlashStorage_STM32 or DueFlashStorage. DoubleDetectDetector feature permits entering Config Portal as requested.", "authors": { "name": "Khoi Hoang", @@ -27,18 +27,24 @@ { "owner": "khoih.prog", "name": "WiFiNINA_Generic", - "version": "^1.8.0", + "version": "^1.8.2", "platforms": ["*"] }, { - "owner": "khoih-prog", + "owner": "khoih.prog", "name": "DoubleResetDetector_Generic", - "version": "^1.0.2", + "version": "^1.0.3", "platforms": ["*"] }, { "owner": "khoih.prog", "name": "FlashStorage_SAMD", + "version": "^1.1.0", + "platforms": ["*"] + }, + { + "owner": "khoih.prog", + "name": "FlashStorage_STM32", "version": "^1.0.0", "platforms": ["*"] }, @@ -51,7 +57,7 @@ { "owner": "khoih-prog", "name": "WiFiWebServer", - "version": "^1.1.0", + "version": "^1.1.1", "platforms": ["*"] }, { diff --git a/library.properties b/library.properties index 5b6982ea..4672efd2 100644 --- a/library.properties +++ b/library.properties @@ -1,11 +1,11 @@ name=WiFiManager_NINA_Lite -version=1.0.5 +version=1.1.0 author=Khoi Hoang maintainer=Khoi Hoang license=MIT -sentence=Light-Weight MultiWiFi/Credentials Manager for AVR Mega, Teensy, SAM DUE, SAMD21, SAMD51, STM32F/L/H/G/WB/MP1, nRF52, etc. boards running U-Blox WiFiNINA modules/shields. Powerful-yet-simple-to-use feature to enable adding dynamic custom parameters. -paragraph=Library to configure MultiWiFi/Credentials at runtime for AVR Mega, Teensy, SAM DUE, SAMD21, SAMD51, STM32F/L/H/G/WB/MP1, nRF52, etc. boards running WiFiNINA modules/shields. You can also specify DHCP HostName, static AP and STA IP. Use much less memory compared to full-fledge WiFiManager. Config Portal will be auto-adjusted to match the number of dynamic custom parameters. Optional default Credentials to be autoloaded into Config Portal to use or change instead of manually input. Credentials are saved in LittleFS/InternalFS, EEPROM, FlashStorage or DueFlashStorage. DoubleDetectDetector feature permits entering Config Portal as requested. +sentence=Light-Weight MultiWiFi/Credentials Manager for AVR Mega, Teensy, SAM DUE, SAMD21, SAMD51, STM32F/L/H/G/WB/MP1, nRF52, etc. boards running U-Blox WiFiNINA / WiFi101 modules/shields. Powerful-yet-simple-to-use feature to enable adding dynamic custom parameters. +paragraph=Library to configure MultiWiFi/Credentials at runtime for AVR Mega, Teensy, SAM DUE, SAMD21, SAMD51, STM32F/L/H/G/WB/MP1, nRF52, etc. boards running WiFiNINA / WiFi101 modules/shields. You can also specify DHCP HostName, static AP and STA IP. Use much less memory compared to full-fledge WiFiManager. Config Portal will be auto-adjusted to match the number of dynamic custom parameters. Optional default Credentials to be autoloaded into Config Portal to use or change instead of manually input. Credentials are saved in LittleFS/InternalFS, EEPROM, FlashStorage_SAMD, FlashStorage_STM32 or DueFlashStorage. DoubleDetectDetector feature permits entering Config Portal as requested. category=Communication url=https://github.com/khoih-prog/WiFiManager_NINA_Lite architectures=* -depends=Functional-VLPP,WiFiNINA_Generic,WiFiWebServer,DoubleResetDetector_Generic +depends=Functional-VLPP,WiFiNINA_Generic,WiFiWebServer,DoubleResetDetector_Generic,FlashStorage_SAMD,FlashStorage_STM32 diff --git a/pics/Enterprise.png b/pics/Enterprise.png new file mode 100644 index 00000000..546415e1 Binary files /dev/null and b/pics/Enterprise.png differ diff --git a/pics/MQTT.png b/pics/MQTT.png new file mode 100644 index 00000000..9f954b23 Binary files /dev/null and b/pics/MQTT.png differ diff --git a/platformio/platformio.ini b/platformio/platformio.ini index d8f452fe..7c410ffc 100644 --- a/platformio/platformio.ini +++ b/platformio/platformio.ini @@ -35,15 +35,19 @@ upload_speed = 921600 lib_deps = ; PlatformIO 4.x - WiFiNINA_Generic@>=1.8.0 - WiFiWebServer@>=1.1.0 + WiFiNINA_Generic@>=1.8.2 + WiFiWebServer@>=1.1.1 Functional-Vlpp@>=1.0.1 - DoubleResetDetector_Generic@>=1.0.2 + DoubleResetDetector_Generic@>=1.0.3 + FlashStorage_SAMD@>=1.1.0 + FlashStorage_STM32@>=1.0.0 ; PlatformIO 5.x -; khoih-prog/WiFiNINA_Generic@>=1.8.0 -; khoih-prog/WiFiWebServer@>=1.1.0 +; khoih.prog/WiFiNINA_Generic@>=1.8.2 +; khoih-prog/WiFiWebServer@>=1.1.1 ; khoih-prog/Functional-Vlpp@>=1.0.1 -; khoih-prog/DoubleResetDetector_Generic@>=1.0.2 +; khoih.prog/DoubleResetDetector_Generic@>=1.0.3 +; khoih.prog/FlashStorage_SAMD@>=1.1.0 +; khoih.prog/FlashStorage_STM32@>=1.0.0 build_flags = ; set your debug output (default=Serial) diff --git a/src/WiFiManager_NINA_Lite.h b/src/WiFiManager_NINA_Lite.h index 983d1f6f..f3ad35da 100644 --- a/src/WiFiManager_NINA_Lite.h +++ b/src/WiFiManager_NINA_Lite.h @@ -1,41 +1,57 @@ -/**************************************************************************************************************************** - WiFiManager_NINA_Lite.h - For AVR or Generic boards using using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + WiFiManager_NINA_Lite.h + For AVR or Generic boards using using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ #ifndef WiFiManager_NINA_Lite_h #define WiFiManager_NINA_Lite_h #if ( defined(ESP8266) || defined(ESP32) || defined(CORE_TEENSY) || defined(NRF52_SERIES) ) -#error This code is not intended to run on the ESP8266, ESP32, nRF52 nor Teensy platform! Please check your Tools->Board setting. + #error This code is not intended to run on the ESP8266, ESP32, nRF52 nor Teensy platform! Please check your Tools->Board setting. #endif -#if !( defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA) ) -#error This code is intended to run on the Mega2560 platform! Please check your Tools->Board setting. +#if !( defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_ADK) ) + #error This code is intended to run on the AVR Mega, Mega2560, Mega ADK platform! Please check your Tools->Board setting. #endif +#define WIFIMANAGER_NINA_LITE_VERSION "WiFiManager_NINA_Lite v1.1.0" + #include #include #include +#ifndef USING_CUSTOMS_STYLE + #define USING_CUSTOMS_STYLE false +#endif + +#ifndef USING_CUSTOMS_HEAD_ELEMENT + #define USING_CUSTOMS_HEAD_ELEMENT false +#endif + +#ifndef USING_CORS_FEATURE + #define USING_CORS_FEATURE false +#endif + ///////// NEW for DRD ///////////// // These defines must be put before #include // to select where to store DoubleResetDetector_Generic's variable. @@ -73,11 +89,15 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; - -// New in v1.0.3 +#if USE_DYNAMIC_PARAMETERS + #warning Using Dynamic Parameters + ///NEW + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#else + #warning Not using Dynamic Parameters +#endif #define SSID_MAX_LEN 32 //From v1.0.3, WPA2 passwords can be up to 63 characters long. @@ -95,11 +115,14 @@ typedef struct #define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) //////////////// +#define HEADER_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; - char board_name [24]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } WiFiNINA_Configuration; @@ -110,6 +133,26 @@ uint16_t CONFIG_DATA_SIZE = sizeof(WiFiNINA_Configuration); extern bool LOAD_DEFAULT_CONFIG_DATA; extern WiFiNINA_Configuration defaultConfig; + +////////////////////////////////////////// + +//KH Add repeatedly used const +//KH, from v1.1.0 +const char WM_HTTP_HEAD_CL[] PROGMEM = "Content-Length"; +const char WM_HTTP_HEAD_TEXT_HTML[] PROGMEM = "text/html"; +const char WM_HTTP_HEAD_TEXT_PLAIN[] PROGMEM = "text/plain"; + +const char WM_HTTP_CACHE_CONTROL[] PROGMEM = "Cache-Control"; +const char WM_HTTP_NO_STORE[] PROGMEM = "no-cache, no-store, must-revalidate"; +const char WM_HTTP_PRAGMA[] PROGMEM = "Pragma"; +const char WM_HTTP_NO_CACHE[] PROGMEM = "no-cache"; +const char WM_HTTP_EXPIRES[] PROGMEM = "Expires"; + +const char WM_HTTP_CORS[] PROGMEM = "Access-Control-Allow-Origin"; +const char WM_HTTP_CORS_ALLOW_ALL[] PROGMEM = "*"; + +////////////////////////////////////////// + String IPAddressToString(IPAddress _address) { String str = String(_address[0]); @@ -129,10 +172,14 @@ class WiFiManager_NINA_Lite WiFiManager_NINA_Lite() { // check for the presence of the shield - if (WiFi.status() == WL_NO_MODULE) +#if USE_WIFI101 + if (WiFi.status() == WL_NO_SHIELD) +#else + if (WiFi.status() == WL_NO_MODULE) +#endif { - DEBUG_WM1(F("NoNINA")); - } + WN_LOGERROR(F("NoWiFi")); + } } ~WiFiManager_NINA_Lite() @@ -143,23 +190,21 @@ class WiFiManager_NINA_Lite bool connectWiFi(const char* ssid, const char* pass) { - DEBUG_WM2(F("Con2:"), ssid); + WN_LOGERROR1(F("Con2:"), ssid); - // New in v1.0.3 setHostname(); - /// - if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) + if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) { displayWiFiData(); } else { - DEBUG_WM1(F("NoW")); + WN_LOGERROR(F("NoW")); return false; } - DEBUG_WM1(F("WOK")); + WN_LOGERROR(F("WOK")); wifi_connected = true; @@ -169,22 +214,20 @@ class WiFiManager_NINA_Lite void begin(const char* ssid, const char* pass ) { - DEBUG_WM1(F("conW")); + WN_LOGERROR(F("conW")); connectWiFi(ssid, pass); } - // New in v1.0.5 void begin(const char *iHostname = "") { #define RETRY_TIMES_CONNECT_WIFI 3 - // New in v1.0.3 if (iHostname[0] == 0) { String randomNum = String(random(0xFFFFFF), HEX); randomNum.toUpperCase(); - String _hostname = "Generic-WiFiNINA-" + randomNum; + String _hostname = "Mega-WiFiNINA-" + randomNum; _hostname.toUpperCase(); getRFC952_hostname(_hostname.c_str()); @@ -195,53 +238,72 @@ class WiFiManager_NINA_Lite getRFC952_hostname(iHostname); } - DEBUG_WM2(F("Hostname="), RFC952_hostname); + WN_LOGERROR1(F("Hostname="), RFC952_hostname); ////// //// New DRD //// drd = new DoubleResetDetector_Generic(DRD_TIMEOUT, DRD_ADDRESS); - bool useConfigPortal = false; + bool noConfigPortal = true; if (drd->detectDoubleReset()) { - DEBUG_WM1(F("Double Reset Detected")); + WN_LOGERROR(F("Double Reset Detected")); - useConfigPortal = true; + noConfigPortal = false; } //// New DRD //// - DEBUG_WM1(F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + + if (LOAD_DEFAULT_CONFIG_DATA) + { + WN_LOGERROR(F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } hadConfigData = getConfigData(); + + isForcedConfigPortal = isForcedCP(); - //// New DRD //// - // useConfigPortal when getConfigData() not OK or DRD'ed - if (hadConfigData && !useConfigPortal) - //// New DRD //// + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { - //hadConfigData = true; + hadConfigData = true; if (connectMultiWiFi(RETRY_TIMES_CONNECT_WIFI)) { - DEBUG_WM1(F("b:WOK")); + WN_LOGERROR(F("b:WOK")); } else { - DEBUG_WM1(F("b:NoW")); + WN_LOGERROR(F("b:NoW")); // failed to connect to WiFi, will start configuration mode startConfigurationMode(); } } else - { - INFO_WM2(F("b:StayInCfgPortal:"), useConfigPortal ? F("DRD") : F("NoCfgDat")); + { + WN_LOGERROR(isForcedConfigPortal? F("bg: isForcedConfigPortal = true") : F("bg: isForcedConfigPortal = false")); + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + } + else + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-non-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + clearForcedCP(); + } + + //To permit autoreset after timeout if DRD/MRD or non-persistent forced-CP + hadConfigData = isForcedConfigPortal ? true : (noConfigPortal ? false : true); // failed to connect to WiFi, will start configuration mode - hadConfigData = false; startConfigurationMode(); } } + #ifndef RETRY_TIMES_RECONNECT_WIFI #define RETRY_TIMES_RECONNECT_WIFI 2 #else @@ -258,22 +320,22 @@ class WiFiManager_NINA_Lite #endif #ifndef RESET_IF_CONFIG_TIMEOUT -#define RESET_IF_CONFIG_TIMEOUT true + #define RESET_IF_CONFIG_TIMEOUT true #endif #ifndef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 #else - // Force range of user-defined TIMES_BEFORE_RESET between 2-100 -#if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) -#warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 -#undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 -#elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) -#warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 -#undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 -#endif + // Force range of user-defined TIMES_BEFORE_RESET between 2-100 + #if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 + #elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 + #endif #endif void run() @@ -307,7 +369,7 @@ class WiFiManager_NINA_Lite { wifiDisconnectedOnce = false; wifi_connected = false; - DEBUG_WM1(F("r:Check&WLost")); + WN_LOGERROR(F("r:Check&WLost")); } else { @@ -329,7 +391,7 @@ class WiFiManager_NINA_Lite if (server) { - //DEBUG_WM1(F("r:handleClient")); + //WN_LOGDEBUG(F("r:handleClient")); server->handleClient(); } @@ -344,7 +406,7 @@ class WiFiManager_NINA_Lite { if (++retryTimes <= CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET) { - DEBUG_WM2(F("r:WLost&TOut.ConW.Retry#"), retryTimes); + WN_LOGERROR1(F("r:WLost&TOut.ConW.Retry#"), retryTimes); } else { @@ -356,11 +418,11 @@ class WiFiManager_NINA_Lite // Not in config mode, try reconnecting before forcing to config mode if ( !wifi_connected ) { - DEBUG_WM1(F("r:WLost.ReconW")); + WN_LOGERROR(F("r:WLost.ReconW")); if (connectMultiWiFi(RETRY_TIMES_RECONNECT_WIFI)) { - DEBUG_WM1(F("r:WOK")); + WN_LOGERROR(F("r:WOK")); } } } @@ -368,25 +430,35 @@ class WiFiManager_NINA_Lite else if (configuration_mode) { configuration_mode = false; - DEBUG_WM1(F("r:gotWBack")); + WN_LOGERROR(F("r:gotWBack")); } } - void setHostname(void) + ////////////////////////////////////////////// + + void setHostname() { if (RFC952_hostname[0] != 0) { +#if USE_WIFI101 + WiFi.hostname(RFC952_hostname); +#elif USE_WIFI_NINA WiFi.setHostname(RFC952_hostname); +#endif } } + + ////////////////////////////////////////////// void setConfigPortalIP(IPAddress portalIP = IPAddress(192, 168, 4, 1)) { portal_apIP = portalIP; } + + ////////////////////////////////////////////// #define MIN_WIFI_CHANNEL 1 - #define MAX_WIFI_CHANNEL 12 // Channel 13 is flaky, because of bad number 13 ;-) + #define MAX_WIFI_CHANNEL 11 // Channel 13 is flaky, because of bad number 13 ;-) int setConfigPortalChannel(int channel = 1) { @@ -401,17 +473,23 @@ class WiFiManager_NINA_Lite return AP_channel; } + ////////////////////////////////////////////// + void setConfigPortal(String ssid = "", String pass = "") { portal_ssid = ssid; portal_pass = pass; } + + ////////////////////////////////////////////// void setSTAStaticIPConfig(IPAddress ip) { static_IP = ip; } + ////////////////////////////////////////////// + String getWiFiSSID(uint8_t index) { if (index >= NUM_WIFI_CREDENTIALS) @@ -420,8 +498,10 @@ class WiFiManager_NINA_Lite if (!hadConfigData) getConfigData(); - return (String(WiFiNINA_config.WiFi_Creds[index].wifi_ssid)); + return (String(WIFININA_config.WiFi_Creds[index].wifi_ssid)); } + + ////////////////////////////////////////////// String getWiFiPW(uint8_t index) { @@ -431,14 +511,18 @@ class WiFiManager_NINA_Lite if (!hadConfigData) getConfigData(); - return (String(WiFiNINA_config.WiFi_Creds[index].wifi_pw)); + return (String(WIFININA_config.WiFi_Creds[index].wifi_pw)); } + + ////////////////////////////////////////////// - bool getWiFiStatus(void) + bool getWiFiStatus() { return wifi_connected; } + ////////////////////////////////////////////// + WiFiNINA_Configuration* getFullConfigData(WiFiNINA_Configuration *configData) { if (!hadConfigData) @@ -446,40 +530,146 @@ class WiFiManager_NINA_Lite // Check if NULL pointer if (configData) - memcpy(configData, &WiFiNINA_config, sizeof(WiFiNINA_Configuration)); + memcpy(configData, &WIFININA_config, sizeof(WiFiNINA_Configuration)); return (configData); } + + ////////////////////////////////////////////// - String localIP(void) + String localIP() { ipAddress = IPAddressToString(WiFi.localIP()); return ipAddress; } + + ////////////////////////////////////////////// void clearConfigData() { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } +#endif saveConfigData(); } - bool isConfigDataValid(void) + ////////////////////////////////////////////// + + bool isConfigDataValid() { return hadConfigData; } + + ////////////////////////////////////////////// + + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// void resetFunc() { asm volatile (" jmp 0"); } + + ////////////////////////////////////// + + // Add customs headers from v1.1.0 + + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + +#if USING_CUSTOMS_STYLE + //sets a custom style, such as color + // ""; + void setCustomsStyle(const char* CustomsStyle = WIFININA_HTML_HEAD_STYLE) + { + WIFININA_HTML_HEAD_CUSTOMS_STYLE = CustomsStyle; + WN_LOGDEBUG1(F("Set CustomsStyle to : "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + } + + const char* getCustomsStyle() + { + WN_LOGDEBUG1(F("Get CustomsStyle = "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + return WIFININA_HTML_HEAD_CUSTOMS_STYLE; + } +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + //sets a custom element to add to head, like a new style tag + void setCustomsHeadElement(const char* CustomsHeadElement = NULL) + { + _CustomsHeadElement = CustomsHeadElement; + WN_LOGDEBUG1(F("Set CustomsHeadElement to : "), _CustomsHeadElement); + } + + const char* getCustomsHeadElement() + { + WN_LOGDEBUG1(F("Get CustomsHeadElement = "), _CustomsHeadElement); + return _CustomsHeadElement; + } +#endif + +#if USING_CORS_FEATURE + void setCORSHeader(const char* CORSHeaders = NULL) + { + _CORS_Header = CORSHeaders; + + WN_LOGDEBUG1(F("Set CORS Header to : "), _CORS_Header); + } + + const char* getCORSHeader() + { + WN_LOGDEBUG1(F("Get CORS Header = "), _CORS_Header); + return _CORS_Header; + } +#endif + + ////////////////////////////////////// + private: String ipAddress = "0.0.0.0"; @@ -489,8 +679,11 @@ class WiFiManager_NINA_Lite unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; - WiFiNINA_Configuration WiFiNINA_config; + WiFiNINA_Configuration WIFININA_config; uint16_t totalDataSize = 0; @@ -504,6 +697,24 @@ class WiFiManager_NINA_Lite String portal_pass = ""; IPAddress static_IP = IPAddress(0, 0, 0, 0); + + ///////////////////////////////////// + + // Add customs headers from v1.1.0 + +#if USING_CUSTOMS_STYLE + const char* WIFININA_HTML_HEAD_CUSTOMS_STYLE = NULL; +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + const char* _CustomsHeadElement = NULL; +#endif + +#if USING_CORS_FEATURE + const char* _CORS_Header = WM_HTTP_CORS_ALLOW_ALL; //"*"; +#endif + + ////////////////////////////////////// #define RFC952_HOSTNAME_MAXLEN 24 char RFC952_hostname[RFC952_HOSTNAME_MAXLEN + 1]; @@ -533,65 +744,117 @@ class WiFiManager_NINA_Lite void displayConfigData(WiFiNINA_Configuration configData) { - DEBUG_WM6(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, - F(",PW="), configData.WiFi_Creds[0].wifi_pw); - DEBUG_WM4(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); - DEBUG_WM2(F("BName="), configData.board_name); + WN_LOGERROR5(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, + F(",PW="), configData.WiFi_Creds[0].wifi_pw); + WN_LOGERROR3(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); + WN_LOGERROR1(F("BName="), configData.board_name); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - DEBUG_WM6("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); - } + WN_LOGERROR5("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); + } +#endif } - void displayWiFiData(void) + void displayWiFiData() { - DEBUG_WM4(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); - DEBUG_WM2(F("IP="), localIP() ); + WN_LOGERROR3(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); + WN_LOGERROR1(F("IP="), localIP() ); } -#define WIFININA_BOARD_TYPE "WIFININA" -#define WM_NO_CONFIG "blank" +#define WIFININA_BOARD_TYPE "WIFININA" +#define WM_NO_CONFIG "blank" #ifndef EEPROM_SIZE -#define EEPROM_SIZE 4096 + #define EEPROM_SIZE 4096 #else -#if (EEPROM_SIZE > 4096) -#warning EEPROM_SIZE must be <= 4096. Reset to 4096 -#undef EEPROM_SIZE -#define EEPROM_SIZE 4096 -#endif -#if (EEPROM_SIZE < CONFIG_DATA_SIZE) -#warning EEPROM_SIZE must be > CONFIG_DATA_SIZE. Reset to 512 -#undef EEPROM_SIZE -#define EEPROM_SIZE 512 -#endif + #if (EEPROM_SIZE > 4096) + #warning EEPROM_SIZE must be <= 4096. Reset to 4096 + #undef EEPROM_SIZE + #define EEPROM_SIZE 4096 + #endif + #if (EEPROM_SIZE < CONFIG_DATA_SIZE) + #warning EEPROM_SIZE must be > CONFIG_DATA_SIZE. Reset to 512 + #undef EEPROM_SIZE + #define EEPROM_SIZE 512 + #endif #endif #ifndef EEPROM_START -#define EEPROM_START 0 //define 256 in DRD -#warning EEPROM_START not defined. Set to 0 + #define EEPROM_START 0 //define 256 in DRD + #warning EEPROM_START not defined. Set to 0 #else -#if (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE) -#error EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE. Please adjust. -#endif + #if (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE) + #error EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE. Please adjust. + #endif #endif // Stating positon to store Blynk8266_WM_config -#define NINA_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) +#define CONFIG_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) int calcChecksum() { int checkSum = 0; - for (uint16_t index = 0; index < (sizeof(WiFiNINA_config) - sizeof(WiFiNINA_config.checkSum)); index++) + for (uint16_t index = 0; index < (sizeof(WIFININA_config) - sizeof(WIFININA_config.checkSum)); index++) { - checkSum += * ( ( (byte*) &WiFiNINA_config ) + index); + checkSum += * ( ( (byte*) &WIFININA_config ) + index); } return checkSum; } - bool checkDynamicData(void) + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + + WN_LOGERROR(isPersistent ? F("setForcedCP Persistent") : F("setForcedCP non-Persistent")); + + EEPROM.put(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + + void clearForcedCP() + { + EEPROM.put(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, 0); + } + + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + EEPROM.get(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS + + bool checkDynamicData() { int checkSum = 0; int readCheckSum; @@ -599,7 +862,7 @@ class WiFiManager_NINA_Lite #define BUFFER_LEN 128 char readBuffer[BUFFER_LEN + 1]; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config); // Find the longest pdata, then dynamically allocate buffer. Remember to free when done // This is used to store tempo data to calculate checksum to see of data is valid @@ -610,7 +873,7 @@ class WiFiManager_NINA_Lite if (myMenuItems[i].maxlen > BUFFER_LEN) { // Size too large, abort and flag false - DEBUG_WM1(F("ChkCrR: Error Small Buffer.")); + WN_LOGDEBUG(F("ChkCrR: Error Small Buffer.")); return false; } } @@ -627,7 +890,7 @@ class WiFiManager_NINA_Lite // NULL terminated readBuffer[myMenuItems[i].maxlen] = 0; - DEBUG_WM4(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen); + WN_LOGDEBUG3(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen); for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) { @@ -639,7 +902,7 @@ class WiFiManager_NINA_Lite EEPROM.get(offset, readCheckSum); - DEBUG_WM4(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + WN_LOGDEBUG3(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { @@ -649,13 +912,15 @@ class WiFiManager_NINA_Lite return true; } - bool EEPROM_getDynamicData(void) + ////////////////////////////////////////////// + + bool EEPROM_getDynamicData() { int readCheckSum; int checkSum = 0; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config); - totalDataSize = sizeof(WiFiNINA_config) + sizeof(readCheckSum); + totalDataSize = sizeof(WIFININA_config) + sizeof(readCheckSum); for (int i = 0; i < NUM_MENU_ITEMS; i++) { @@ -675,7 +940,7 @@ class WiFiManager_NINA_Lite EEPROM.get(offset, readCheckSum); - DEBUG_WM4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + WN_LOGDEBUG3(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { @@ -684,17 +949,19 @@ class WiFiManager_NINA_Lite return true; } + + ////////////////////////////////////////////// - void EEPROM_putDynamicData(void) + void EEPROM_putDynamicData() { int checkSum = 0; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config); for (int i = 0; i < NUM_MENU_ITEMS; i++) { char* _pointer = myMenuItems[i].pdata; - //DEBUG_WM4(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + //WN_LOGDEBUG3(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++,offset++) { @@ -705,28 +972,83 @@ class WiFiManager_NINA_Lite } EEPROM.put(offset, checkSum); - //EEPROM.commit(); - DEBUG_WM2(F("CrCCSum=0x"), String(checkSum, HEX)); + WN_LOGDEBUG1(F("CrCCSum=0x"), String(checkSum, HEX)); + } +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define SERVER_MAX_LEN 32 + //#define TOKEN_MAX_LEN 36 + + // NULL Terminating to be sure + WIFININA_config.header[HEADER_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.board_name[BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// + + bool EEPROM_get() + { + EEPROM.get(CONFIG_EEPROM_START, WIFININA_config); + + NULLTerminateConfig(); + + return true; + } + + ////////////////////////////////////////////// + + void EEPROM_put() + { + EEPROM.put(CONFIG_EEPROM_START, WIFININA_config); + } + + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + WIFININA_config.checkSum = calChecksum; + + WN_LOGERROR5(F("SaveEEPROM,Sz="), EEPROM.length(), F(",DataSz="), totalDataSize, F(",CSum=0x"), String(calChecksum, HEX)); + + EEPROM_put(); + +#if USE_DYNAMIC_PARAMETERS + EEPROM_putDynamicData(); +#endif } + ////////////////////////////////////////////// + // New from v1.0.5 - void loadAndSaveDefaultConfigData(void) + void loadAndSaveDefaultConfigData() { // Load Default Config Data from Sketch - memcpy(&WiFiNINA_config, &defaultConfig, sizeof(WiFiNINA_config)); - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); // Including config and dynamic data, and assume valid saveConfigData(); - DEBUG_WM1(F("======= Start Loaded Config Data =======")); - displayConfigData(WiFiNINA_config); + WN_LOGERROR(F("======= Start Loaded Config Data =======")); + displayConfigData(WIFININA_config); } + ////////////////////////////////////////////// + bool getConfigData() { - bool dynamicDataValid; + bool dynamicDataValid = true; int calChecksum; hadConfigData = false; @@ -745,120 +1067,130 @@ class WiFiManager_NINA_Lite else { // Load stored config data from EEPROM - DEBUG_WM2(F("EEPROMsz:"), EEPROM_SIZE); - EEPROM.get(NINA_EEPROM_START, WiFiNINA_config); + WN_LOGERROR1(F("EEPROMsz:"), EEPROM_SIZE); + WN_LOGERROR1(F("EEPROM Length():"), EEPROM.length()); - // Load stored dynamic data from EEPROM - // Verify ChkSum - dynamicDataValid = checkDynamicData(); + EEPROM_get(); + // Verify ChkSum calChecksum = calcChecksum(); - DEBUG_WM4(F("CCSum=0x"), String(calChecksum, HEX), F(",RCSum=0x"), String(WiFiNINA_config.checkSum, HEX)); - - if (dynamicDataValid) - { - EEPROM_getDynamicData(); - - DEBUG_WM1(F("Valid Stored Dynamic Data")); - DEBUG_WM1(F("======= Start Stored Config Data =======")); - displayConfigData(WiFiNINA_config); - - // Don't need Config Portal anymore - return true; - } - else + WN_LOGERROR3(F("CCSum=0x"), String(calChecksum, HEX), + F(",RCSum=0x"), String(WIFININA_config.checkSum, HEX)); + +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from LittleFS + dynamicDataValid = checkDynamicData(); +#endif + + // If checksum = 0 => simulated EEPROM has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == WIFININA_config.checkSum) ) { - // Invalid Stored config data => Config Portal - DEBUG_WM1(F("Invalid Stored Dynamic Data. Load default from Sketch")); - - // Load Default Config Data from Sketch, better than just "blank" - loadAndSaveDefaultConfigData(); - - // Need Config Portal here as data can be just dummy - // Even if you don't open CP, you're OK on next boot if your default config data is valid - return false; - } + if (dynamicDataValid) + { + #if USE_DYNAMIC_PARAMETERS + EEPROM_getDynamicData(); + + WN_LOGERROR(F("Valid Stored Dynamic Data")); + #endif + + WN_LOGERROR(F("======= Start Stored Config Data =======")); + displayConfigData(WIFININA_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + WN_LOGERROR(F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } } - if ( (strncmp(WiFiNINA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || - (calChecksum != WiFiNINA_config.checkSum) || !dynamicDataValid ) + if ( (strncmp(WIFININA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || + (calChecksum != WIFININA_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (WIFININA_config.checkSum == 0) ) ) { // Including Credentials CSum - DEBUG_WM2(F("InitCfgFile,sz="), sizeof(WiFiNINA_config)); + WN_LOGERROR1(F("InitCfgFile,sz="), sizeof(WIFININA_config)); // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) { - memcpy(&WiFiNINA_config, &defaultConfig, sizeof(WiFiNINA_config)); + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); } else { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } +#endif - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); - strcpy(WiFiNINA_config.board_name, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.board_name, WM_NO_CONFIG); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } +#endif } - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - DEBUG_WM4(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); + WN_LOGDEBUG3(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); } +#endif // Don't need - WiFiNINA_config.checkSum = 0; + WIFININA_config.checkSum = 0; saveConfigData(); return false; } - else if ( !strncmp(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strlen(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) || - !strlen(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) || - !strlen(WiFiNINA_config.WiFi_Creds[0].wifi_pw) || - !strlen(WiFiNINA_config.WiFi_Creds[1].wifi_pw) ) + else if ( !strncmp(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_pw) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_pw) ) { // If SSID, PW ="nothing", stay in config mode forever until having config Data. return false; } else { - displayConfigData(WiFiNINA_config); + displayConfigData(WIFININA_config); } return true; } - - void saveConfigData() - { - int calChecksum = calcChecksum(); - WiFiNINA_config.checkSum = calChecksum; - - DEBUG_WM6(F("SaveEEPROM,Sz="), EEPROM.length(), F(",DataSz="), totalDataSize, F(",CSum=0x"), String(calChecksum, HEX)); - - //EEPROM_put(); - EEPROM.put(NINA_EEPROM_START, WiFiNINA_config); - EEPROM_putDynamicData(); - } + + ////////////////////////////////////////////// // New connection logic from v1.0.5 bool connectMultiWiFi(int retry_time) @@ -869,35 +1201,35 @@ class WiFiManager_NINA_Lite static int lastConnectedIndex = 255; - DEBUG_WM1(F("ConMultiWifi")); + WN_LOGDEBUG(F("ConMultiWifi")); if (static_IP != IPAddress(0, 0, 0, 0)) { - DEBUG_WM1(F("UseStatIP")); + WN_LOGDEBUG(F("UseStatIP")); WiFi.config(static_IP); } if (lastConnectedIndex != 255) { index = (lastConnectedIndex + 1) % NUM_WIFI_CREDENTIALS; - DEBUG_WM4(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); + WN_LOGDEBUG3(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); } - DEBUG_WM4(F("con2WF:SSID="), WiFiNINA_config.WiFi_Creds[index].wifi_ssid, - F(",PW="), WiFiNINA_config.WiFi_Creds[index].wifi_pw); + WN_LOGDEBUG3(F("con2WF:SSID="), WIFININA_config.WiFi_Creds[index].wifi_ssid, + F(",PW="), WIFININA_config.WiFi_Creds[index].wifi_pw); while ( !wifi_connected && ( 0 < retry_time ) ) { - DEBUG_WM2(F("Remaining retry_time="), retry_time); + WN_LOGDEBUG1(F("Remaining retry_time="), retry_time); - status = WiFi.begin(WiFiNINA_config.WiFi_Creds[index].wifi_ssid, WiFiNINA_config.WiFi_Creds[index].wifi_pw); + status = WiFi.begin(WIFININA_config.WiFi_Creds[index].wifi_ssid, WIFININA_config.WiFi_Creds[index].wifi_pw); // Need restart WiFi at beginning of each cycle if (status == WL_CONNECTED) { wifi_connected = true; lastConnectedIndex = index; - DEBUG_WM2(F("WOK, lastConnectedIndex="), lastConnectedIndex); + WN_LOGDEBUG1(F("WOK, lastConnectedIndex="), lastConnectedIndex); break; } @@ -910,23 +1242,25 @@ class WiFiManager_NINA_Lite if (retry_time <= 0) { - DEBUG_WM4(F("Failed using index="), index, F(", retry_time="), retry_time); + WN_LOGDEBUG3(F("Failed using index="), index, F(", retry_time="), retry_time); } if (wifi_connected) { - DEBUG_WM1(F("con2WF:OK")); + WN_LOGDEBUG(F("con2WF:OK")); displayWiFiData(); } else { - DEBUG_WM1(F("con2WF:failed")); + WN_LOGDEBUG(F("con2WF:failed")); // Can't connect, so try another index next time. Faking this index is OK and lost lastConnectedIndex = index; } return wifi_connected; } + + ////////////////////////////////////////////// void createHTML(String& root_html_template) { @@ -952,41 +1286,75 @@ udVal('nm',document.getElementById('nm').value);"; String pitem; - root_html_template += WIFININA_FLDSET_START; - - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + if (NUM_MENU_ITEMS > 0) { - pitem = WIFININA_HTML_PARAM; - pitem.replace("{b}", myMenuItems[i].displayName); - pitem.replace("{v}", myMenuItems[i].id); - pitem.replace("{i}", myMenuItems[i].id); - - root_html_template += pitem; + root_html_template += WIFI_GENERIC_FLDSET_START; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + pitem = String(WIFI_GENERIC_HTML_PARAM); + + pitem.replace("{b}", myMenuItems[i].displayName); + pitem.replace("{v}", myMenuItems[i].id); + pitem.replace("{i}", myMenuItems[i].id); + + root_html_template += pitem; + } + + root_html_template += WIFI_GENERIC_FLDSET_END; } - - root_html_template += WIFININA_FLDSET_END; +#endif + root_html_template += WIFININA_HTML_BUTTON; root_html_template += WIFININA_HTML_SCRIPT; - for (int i = 0; i < NUM_MENU_ITEMS; i++) - { - pitem = WIFININA_HTML_SCRIPT_ITEM; - - pitem.replace("{d}", myMenuItems[i].id); - - root_html_template += pitem; +#if USE_DYNAMIC_PARAMETERS + if (NUM_MENU_ITEMS > 0) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + pitem = String(WIFI_GENERIC_HTML_SCRIPT_ITEM); + + pitem.replace("{d}", myMenuItems[i].id); + + root_html_template += pitem; + } } +#endif root_html_template += WIFININA_HTML_SCRIPT_END; root_html_template += WIFININA_HTML_END; return; } + + ////////////////////////////////////////////// + + void serverSendHeaders() + { + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CACHE_CONTROL:"), WM_HTTP_CACHE_CONTROL, "=", WM_HTTP_NO_STORE); + server->sendHeader(WM_HTTP_CACHE_CONTROL, WM_HTTP_NO_STORE); + +#if USING_CORS_FEATURE + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CORS:"), WM_HTTP_CORS, " : ", _CORS_Header); + server->sendHeader(WM_HTTP_CORS, _CORS_Header); +#endif + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_PRAGMA:"), WM_HTTP_PRAGMA, " : ", WM_HTTP_NO_CACHE); + server->sendHeader(WM_HTTP_PRAGMA, WM_HTTP_NO_CACHE); + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_EXPIRES:"), WM_HTTP_EXPIRES, " : ", "-1"); + server->sendHeader(WM_HTTP_EXPIRES, "-1"); + } + + ////////////////////////////////////////////// void handleRequest() { if (server) - { + { String key = server->arg("key"); String value = server->arg("value"); @@ -994,35 +1362,45 @@ udVal('nm',document.getElementById('nm').value);"; if (key == "" && value == "") { + // New from v1.1.0 + serverSendHeaders(); + ////// + String result; createHTML(result); - + // Reset configTimeout to stay here until finished. configTimeout = 0; - + if ( RFC952_hostname[0] != 0 ) { // Replace only if Hostname is valid - result.replace("AVR_WM_NINA_Lite", RFC952_hostname); + result.replace("SAMD_WM_NINA_Lite", RFC952_hostname); } - else if ( WiFiNINA_config.board_name[0] != 0 ) + else if ( WIFININA_config.board_name[0] != 0 ) { // Or replace only if board_name is valid. Otherwise, keep intact - result.replace("AVR_WM_NINA_Lite", WiFiNINA_config.board_name); + result.replace("SAMD_WM_NINA_Lite", WIFININA_config.board_name); } - result.replace("[[id]]", WiFiNINA_config.WiFi_Creds[0].wifi_ssid); - result.replace("[[pw]]", WiFiNINA_config.WiFi_Creds[0].wifi_pw); - result.replace("[[id1]]", WiFiNINA_config.WiFi_Creds[1].wifi_ssid); - result.replace("[[pw1]]", WiFiNINA_config.WiFi_Creds[1].wifi_pw); - result.replace("[[nm]]", WiFiNINA_config.board_name); + result.replace("[[id]]", WIFININA_config.WiFi_Creds[0].wifi_ssid); + result.replace("[[pw]]", WIFININA_config.WiFi_Creds[0].wifi_pw); + result.replace("[[id1]]", WIFININA_config.WiFi_Creds[1].wifi_ssid); + result.replace("[[pw1]]", WIFININA_config.WiFi_Creds[1].wifi_pw); + result.replace("[[nm]]", WIFININA_config.board_name); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { String toChange = String("[[") + myMenuItems[i].id + "]]"; result.replace(toChange, myMenuItems[i].pdata); } +#endif + + WN_LOGDEBUG1(F("h:HTML page size:"), result.length()); + WN_LOGDEBUG1(F("h:HTML="), result); + server->send(200, "text/html", result); return; @@ -1030,78 +1408,138 @@ udVal('nm',document.getElementById('nm').value);"; if (number_items_Updated == 0) { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); } - if (key == "id") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + + WN_LOGDEBUG1(F("h: Init menuItemUpdated :" ), NUM_MENU_ITEMS); + } + else + { + WN_LOGERROR(F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool id_Updated = false; + static bool pw_Updated = false; + static bool id1_Updated = false; + static bool pw1_Updated = false; + static bool nm_Updated = false; + + if (!id_Updated && (key == String("id"))) + { + WN_LOGDEBUG(F("h:repl id")); + id_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) - 1); + strncpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1); } - else if (key == "pw") - { + else if (!pw_Updated && (key == String("pw"))) + { + WN_LOGDEBUG(F("h:repl pw")); + pw_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_pw) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_pw) - 1); + strncpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1); } - else if (key == "id1") - { + else if (!id1_Updated && (key == String("id1"))) + { + WN_LOGDEBUG(F("h:repl id1")); + id1_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) - 1); + strncpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1); } - else if (key == "pw1") - { + else if (!pw1_Updated && (key == String("pw1"))) + { + WN_LOGDEBUG(F("h:repl pw1")); + pw1_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_pw) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_pw) - 1); + strncpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { + WN_LOGDEBUG(F("h:repl nm")); + nm_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.board_name) - 1) - strcpy(WiFiNINA_config.board_name, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.board_name) - 1) + strcpy(WIFININA_config.board_name, value.c_str()); else - strncpy(WiFiNINA_config.board_name, value.c_str(), sizeof(WiFiNINA_config.board_name) - 1); + strncpy(WIFININA_config.board_name, value.c_str(), sizeof(WIFININA_config.board_name) - 1); } - - for (int i = 0; i < NUM_MENU_ITEMS; i++) + else { - if (key == myMenuItems[i].id) - { - DEBUG_WM4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); - number_items_Updated++; + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) + { + WN_LOGDEBUG3(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + + menuItemUpdated[i] = true; + + number_items_Updated++; - // Actual size of pdata is [maxlen + 1] - memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); - if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) - strcpy(myMenuItems[i].pdata, value.c_str()); - else - strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) + strcpy(myMenuItems[i].pdata, value.c_str()); + else + strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + + break; + } } +#endif } + + WN_LOGDEBUG1(F("h:items updated ="), number_items_Updated); + WN_LOGDEBUG3(F("h:key ="), key, ", value =", value); server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif { - DEBUG_WM1(F("h:UpdEEPROM")); + WN_LOGDEBUG(F("h:UpdEEPROM")); saveConfigData(); - DEBUG_WM1(F("h:Rst")); + WN_LOGDEBUG(F("h:Rst")); // TO DO : what command to reset // Delay then reset the board after save data @@ -1110,11 +1548,16 @@ udVal('nm',document.getElementById('nm').value);"; } } // if (server) } + + ////////////////////////////////////////////// + +#ifndef CONFIG_TIMEOUT + #warning Default CONFIG_TIMEOUT = 60s + #define CONFIG_TIMEOUT 60000L +#endif void startConfigurationMode() { -#define CONFIG_TIMEOUT 60000L - WiFi.config(portal_apIP); if ( (portal_ssid == "") || portal_pass == "" ) @@ -1130,20 +1573,22 @@ udVal('nm',document.getElementById('nm').value);"; uint16_t channel; - // Use random channel if AP_channel == 0 - //srand(MAX_WIFI_CHANNEL); - srand((uint16_t) millis()); - + // Use random channel if AP_channel == 0 if (AP_channel == 0) - channel = (rand() % MAX_WIFI_CHANNEL) + 1; //random(MAX_WIFI_CHANNEL) + 1; + channel = (millis() % MAX_WIFI_CHANNEL) + 1; else channel = AP_channel; - INFO_WM4(F("SSID="), portal_ssid, F(",PW="), portal_pass); - INFO_WM4(F("IP="), portal_apIP, F(",CH="), channel); + WN_LOGERROR3(F("SSID="), portal_ssid, F(",PW="), portal_pass); + WN_LOGERROR3(F("IP="), portal_apIP, F(",CH="), channel); +#if USE_ESP_AT_SHIELD + // start access point, AP only,default channel 10 + WiFi.beginAP(portal_ssid.c_str(), channel, portal_pass.c_str(), ENC_TYPE_WPA2_PSK, true); +#else // start access point, AP only,default channel 10 WiFi.beginAP(portal_ssid.c_str(), portal_pass.c_str(), channel); +#endif if (!server) @@ -1162,10 +1607,17 @@ udVal('nm',document.getElementById('nm').value);"; // If there is no saved config Data, stay in config mode forever until having config Data. // or SSID, PW, Server,Token ="nothing" if (hadConfigData) + { configTimeout = millis() + CONFIG_TIMEOUT; + + WN_LOGDEBUG3(F("s:millis() = "), millis(), F(", configTimeout = "), configTimeout); + } else + { configTimeout = 0; - + + WN_LOGDEBUG(F("s:configTimeout = 0")); + } configuration_mode = true; } }; diff --git a/src/WiFiManager_NINA_Lite_DUE.h b/src/WiFiManager_NINA_Lite_DUE.h index f9809b6a..12ba519d 100644 --- a/src/WiFiManager_NINA_Lite_DUE.h +++ b/src/WiFiManager_NINA_Lite_DUE.h @@ -1,32 +1,34 @@ -/**************************************************************************************************************************** - WiFiManager_NINA_Lite_DUE.h - For SAM DUE boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + WiFiManager_NINA_Lite_DUE.h + For SAM DUE boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ #ifndef WiFiManager_NINA_Lite_DUE_h #define WiFiManager_NINA_Lite_DUE_h #if ( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) #if defined(WIFININA_USE_SAM_DUE) - #undef WIFININA_USE_SAM_DUE + #undef WIFININA_USE_SAM_DUE #endif #define WIFININA_USE_SAM_DUE true #warning Use SAM_DUE architecture from WiFiManager_NINA_Lite_DUE @@ -34,9 +36,11 @@ #if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA) || \ defined(CORE_TEENSY) || defined(CORE_TEENSY) || !(WIFININA_USE_SAM_DUE) ) -#error This code is intended to run on the SAM DUE platform! Please check your Tools->Board setting. + #error This code is intended to run on the SAM DUE platform! Please check your Tools->Board setting. #endif +#define WIFIMANAGER_NINA_LITE_VERSION "WiFiManager_NINA_Lite v1.1.0" + #include #include @@ -45,6 +49,20 @@ DueFlashStorage dueFlashStorageData; +///////////////////////////////////// + +#ifndef USING_CUSTOMS_STYLE + #define USING_CUSTOMS_STYLE false +#endif + +#ifndef USING_CUSTOMS_HEAD_ELEMENT + #define USING_CUSTOMS_HEAD_ELEMENT false +#endif + +#ifndef USING_CORS_FEATURE + #define USING_CORS_FEATURE false +#endif + ///////// NEW for DRD ///////////// // These defines must be put before #include // to select where to store DoubleResetDetector_Generic's variable. @@ -81,11 +99,15 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; - -// New in v1.0.3 +#if USE_DYNAMIC_PARAMETERS + #warning Using Dynamic Parameters + ///NEW + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#else + #warning Not using Dynamic Parameters +#endif #define SSID_MAX_LEN 32 //From v1.0.3, WPA2 passwords can be up to 63 characters long. @@ -103,11 +125,14 @@ typedef struct #define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) //////////////// +#define HEADER_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; - char board_name [24]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } WiFiNINA_Configuration; @@ -119,7 +144,12 @@ extern bool LOAD_DEFAULT_CONFIG_DATA; extern WiFiNINA_Configuration defaultConfig; // -- HTML page fragments -const char WIFININA_HTML_HEAD[] /*PROGMEM*/ = "SAM_DUE_WM_NINA_Lite
\ + +const char WIFININA_HTML_HEAD_START[] /*PROGMEM*/ = "SAM_DUE_WM_NINA_Lite"; + +const char WIFININA_HTML_HEAD_STYLE[] /*PROGMEM*/ = ""; + +const char WIFININA_HTML_HEAD_END[] /*PROGMEM*/ = "
\
\
\
\ @@ -140,7 +170,25 @@ udVal('nm',document.getElementById('nm').value);"; const char WIFININA_HTML_SCRIPT_ITEM[] /*PROGMEM*/ = "udVal('{d}',document.getElementById('{d}').value);"; const char WIFININA_HTML_SCRIPT_END[] /*PROGMEM*/ = "alert('Updated');}"; const char WIFININA_HTML_END[] /*PROGMEM*/ = ""; -/// + +////////////////////////////////////////// + +//KH Add repeatedly used const +//KH, from v1.1.0 +const char WM_HTTP_HEAD_CL[] PROGMEM = "Content-Length"; +const char WM_HTTP_HEAD_TEXT_HTML[] PROGMEM = "text/html"; +const char WM_HTTP_HEAD_TEXT_PLAIN[] PROGMEM = "text/plain"; + +const char WM_HTTP_CACHE_CONTROL[] PROGMEM = "Cache-Control"; +const char WM_HTTP_NO_STORE[] PROGMEM = "no-cache, no-store, must-revalidate"; +const char WM_HTTP_PRAGMA[] PROGMEM = "Pragma"; +const char WM_HTTP_NO_CACHE[] PROGMEM = "no-cache"; +const char WM_HTTP_EXPIRES[] PROGMEM = "Expires"; + +const char WM_HTTP_CORS[] PROGMEM = "Access-Control-Allow-Origin"; +const char WM_HTTP_CORS_ALLOW_ALL[] PROGMEM = "*"; + +////////////////////////////////////////// String IPAddressToString(IPAddress _address) @@ -162,37 +210,39 @@ class WiFiManager_NINA_Lite WiFiManager_NINA_Lite() { // check for the presence of the shield - if (WiFi.status() == WL_NO_SHIELD) +#if USE_WIFI101 + if (WiFi.status() == WL_NO_SHIELD) +#else + if (WiFi.status() == WL_NO_MODULE) +#endif { - DEBUG_WM1(F("NoNINA")); - } + WN_LOGERROR(F("NoWiFi")); + } } ~WiFiManager_NINA_Lite() { if (server) - delete server; + delete server; } bool connectWiFi(const char* ssid, const char* pass) { - DEBUG_WM2(F("Con2:"), ssid); + WN_LOGERROR1(F("Con2:"), ssid); - // New in v1.0.3 setHostname(); - /// - if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) + if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) { displayWiFiData(); } else { - DEBUG_WM1(F("NoW")); + WN_LOGERROR(F("NoW")); return false; } - DEBUG_WM1(F("WOK")); + WN_LOGERROR(F("WOK")); wifi_connected = true; @@ -202,16 +252,14 @@ class WiFiManager_NINA_Lite void begin(const char* ssid, const char* pass ) { - DEBUG_WM1(F("conW")); + WN_LOGERROR(F("conW")); connectWiFi(ssid, pass); } - // New in v1.0.5 void begin(const char *iHostname = "") { #define RETRY_TIMES_CONNECT_WIFI 3 - // New in v1.0.3 if (iHostname[0] == 0) { String randomNum = String(random(0xFFFFFF), HEX); @@ -228,53 +276,72 @@ class WiFiManager_NINA_Lite getRFC952_hostname(iHostname); } - DEBUG_WM2(F("Hostname="), RFC952_hostname); + WN_LOGERROR1(F("Hostname="), RFC952_hostname); ////// //// New DRD //// drd = new DoubleResetDetector_Generic(DRD_TIMEOUT, DRD_ADDRESS); - bool useConfigPortal = false; + bool noConfigPortal = true; if (drd->detectDoubleReset()) { - DEBUG_WM1(F("Double Reset Detected")); + WN_LOGERROR(F("Double Reset Detected")); - useConfigPortal = true; + noConfigPortal = false; } //// New DRD //// - DEBUG_WM1(F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + + if (LOAD_DEFAULT_CONFIG_DATA) + { + WN_LOGERROR(F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } hadConfigData = getConfigData(); + + isForcedConfigPortal = isForcedCP(); - //// New DRD //// - // useConfigPortal when getConfigData() not OK or DRD'ed - if (hadConfigData && !useConfigPortal) - //// New DRD //// + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { - //hadConfigData = true; + hadConfigData = true; if (connectMultiWiFi(RETRY_TIMES_CONNECT_WIFI)) { - DEBUG_WM1(F("b:WOK")); + WN_LOGERROR(F("b:WOK")); } else { - DEBUG_WM1(F("b:NoW")); + WN_LOGERROR(F("b:NoW")); // failed to connect to WiFi, will start configuration mode startConfigurationMode(); } } else - { - INFO_WM2(F("b:StayInCfgPortal:"), useConfigPortal ? F("DRD") : F("NoCfgDat")); + { + WN_LOGERROR(isForcedConfigPortal? F("bg: isForcedConfigPortal = true") : F("bg: isForcedConfigPortal = false")); + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + } + else + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-non-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + clearForcedCP(); + } + + //To permit autoreset after timeout if DRD/MRD or non-persistent forced-CP + hadConfigData = isForcedConfigPortal ? true : (noConfigPortal ? false : true); // failed to connect to WiFi, will start configuration mode - hadConfigData = false; startConfigurationMode(); } } + #ifndef RETRY_TIMES_RECONNECT_WIFI #define RETRY_TIMES_RECONNECT_WIFI 2 #else @@ -291,22 +358,22 @@ class WiFiManager_NINA_Lite #endif #ifndef RESET_IF_CONFIG_TIMEOUT -#define RESET_IF_CONFIG_TIMEOUT true + #define RESET_IF_CONFIG_TIMEOUT true #endif #ifndef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 #else - // Force range of user-defined TIMES_BEFORE_RESET between 2-100 -#if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) -#warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 -#undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 -#elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) -#warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 -#undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 -#endif + // Force range of user-defined TIMES_BEFORE_RESET between 2-100 + #if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 + #elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 + #endif #endif void run() @@ -340,7 +407,7 @@ class WiFiManager_NINA_Lite { wifiDisconnectedOnce = false; wifi_connected = false; - DEBUG_WM1(F("r:Check&WLost")); + WN_LOGERROR(F("r:Check&WLost")); } else { @@ -362,7 +429,7 @@ class WiFiManager_NINA_Lite if (server) { - //DEBUG_WM1(F("r:handleClient")); + //WN_LOGDEBUG(F("r:handleClient")); server->handleClient(); } @@ -377,7 +444,7 @@ class WiFiManager_NINA_Lite { if (++retryTimes <= CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET) { - DEBUG_WM2(F("r:WLost&TOut.ConW.Retry#"), retryTimes); + WN_LOGERROR1(F("r:WLost&TOut.ConW.Retry#"), retryTimes); } else { @@ -389,11 +456,11 @@ class WiFiManager_NINA_Lite // Not in config mode, try reconnecting before forcing to config mode if ( !wifi_connected ) { - DEBUG_WM1(F("r:WLost.ReconW")); + WN_LOGERROR(F("r:WLost.ReconW")); if (connectMultiWiFi(RETRY_TIMES_RECONNECT_WIFI)) { - DEBUG_WM1(F("r:WOK")); + WN_LOGERROR(F("r:WOK")); } } } @@ -401,25 +468,35 @@ class WiFiManager_NINA_Lite else if (configuration_mode) { configuration_mode = false; - DEBUG_WM1(F("r:gotWBack")); + WN_LOGERROR(F("r:gotWBack")); } } - void setHostname(void) + ////////////////////////////////////////////// + + void setHostname() { if (RFC952_hostname[0] != 0) { +#if USE_WIFI101 + WiFi.hostname(RFC952_hostname); +#elif USE_WIFI_NINA WiFi.setHostname(RFC952_hostname); +#endif } } + + ////////////////////////////////////////////// void setConfigPortalIP(IPAddress portalIP = IPAddress(192, 168, 4, 1)) { portal_apIP = portalIP; } + + ////////////////////////////////////////////// #define MIN_WIFI_CHANNEL 1 - #define MAX_WIFI_CHANNEL 12 // Channel 13 is flaky, because of bad number 13 ;-) + #define MAX_WIFI_CHANNEL 11 // Channel 13 is flaky, because of bad number 13 ;-) int setConfigPortalChannel(int channel = 1) { @@ -434,17 +511,23 @@ class WiFiManager_NINA_Lite return AP_channel; } + ////////////////////////////////////////////// + void setConfigPortal(String ssid = "", String pass = "") { portal_ssid = ssid; portal_pass = pass; } + + ////////////////////////////////////////////// void setSTAStaticIPConfig(IPAddress ip) { static_IP = ip; } + ////////////////////////////////////////////// + String getWiFiSSID(uint8_t index) { if (index >= NUM_WIFI_CREDENTIALS) @@ -453,8 +536,10 @@ class WiFiManager_NINA_Lite if (!hadConfigData) getConfigData(); - return (String(WiFiNINA_config.WiFi_Creds[index].wifi_ssid)); + return (String(WIFININA_config.WiFi_Creds[index].wifi_ssid)); } + + ////////////////////////////////////////////// String getWiFiPW(uint8_t index) { @@ -464,14 +549,18 @@ class WiFiManager_NINA_Lite if (!hadConfigData) getConfigData(); - return (String(WiFiNINA_config.WiFi_Creds[index].wifi_pw)); + return (String(WIFININA_config.WiFi_Creds[index].wifi_pw)); } + + ////////////////////////////////////////////// - bool getWiFiStatus(void) + bool getWiFiStatus() { return wifi_connected; } + ////////////////////////////////////////////// + WiFiNINA_Configuration* getFullConfigData(WiFiNINA_Configuration *configData) { if (!hadConfigData) @@ -479,40 +568,146 @@ class WiFiManager_NINA_Lite // Check if NULL pointer if (configData) - memcpy(configData, &WiFiNINA_config, sizeof(WiFiNINA_Configuration)); + memcpy(configData, &WIFININA_config, sizeof(WiFiNINA_Configuration)); return (configData); } + + ////////////////////////////////////////////// - String localIP(void) + String localIP() { ipAddress = IPAddressToString(WiFi.localIP()); return ipAddress; } + + ////////////////////////////////////////////// void clearConfigData() { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } +#endif saveConfigData(); } - bool isConfigDataValid(void) + ////////////////////////////////////////////// + + bool isConfigDataValid() { return hadConfigData; } + + ////////////////////////////////////////////// + + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// void resetFunc() { rstc_start_software_reset(RSTC); } + + ////////////////////////////////////// + + // Add customs headers from v1.1.0 + + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + +#if USING_CUSTOMS_STYLE + //sets a custom style, such as color + // ""; + void setCustomsStyle(const char* CustomsStyle = WIFININA_HTML_HEAD_STYLE) + { + WIFININA_HTML_HEAD_CUSTOMS_STYLE = CustomsStyle; + WN_LOGDEBUG1(F("Set CustomsStyle to : "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + } + + const char* getCustomsStyle() + { + WN_LOGDEBUG1(F("Get CustomsStyle = "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + return WIFININA_HTML_HEAD_CUSTOMS_STYLE; + } +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + //sets a custom element to add to head, like a new style tag + void setCustomsHeadElement(const char* CustomsHeadElement = NULL) + { + _CustomsHeadElement = CustomsHeadElement; + WN_LOGDEBUG1(F("Set CustomsHeadElement to : "), _CustomsHeadElement); + } + + const char* getCustomsHeadElement() + { + WN_LOGDEBUG1(F("Get CustomsHeadElement = "), _CustomsHeadElement); + return _CustomsHeadElement; + } +#endif + +#if USING_CORS_FEATURE + void setCORSHeader(const char* CORSHeaders = NULL) + { + _CORS_Header = CORSHeaders; + + WN_LOGDEBUG1(F("Set CORS Header to : "), _CORS_Header); + } + + const char* getCORSHeader() + { + WN_LOGDEBUG1(F("Get CORS Header = "), _CORS_Header); + return _CORS_Header; + } +#endif + + ////////////////////////////////////// + private: String ipAddress = "0.0.0.0"; @@ -522,8 +717,11 @@ class WiFiManager_NINA_Lite unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; - WiFiNINA_Configuration WiFiNINA_config; + WiFiNINA_Configuration WIFININA_config; uint16_t totalDataSize = 0; @@ -537,6 +735,24 @@ class WiFiManager_NINA_Lite String portal_pass = ""; IPAddress static_IP = IPAddress(0, 0, 0, 0); + + ///////////////////////////////////// + + // Add customs headers from v1.1.0 + +#if USING_CUSTOMS_STYLE + const char* WIFININA_HTML_HEAD_CUSTOMS_STYLE = NULL; +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + const char* _CustomsHeadElement = NULL; +#endif + +#if USING_CORS_FEATURE + const char* _CORS_Header = WM_HTTP_CORS_ALLOW_ALL; //"*"; +#endif + + ////////////////////////////////////// #define RFC952_HOSTNAME_MAXLEN 24 char RFC952_hostname[RFC952_HOSTNAME_MAXLEN + 1]; @@ -566,47 +782,118 @@ class WiFiManager_NINA_Lite void displayConfigData(WiFiNINA_Configuration configData) { - DEBUG_WM6(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, - F(",PW="), configData.WiFi_Creds[0].wifi_pw); - DEBUG_WM4(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); - DEBUG_WM2(F("BName="), configData.board_name); + WN_LOGERROR5(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, + F(",PW="), configData.WiFi_Creds[0].wifi_pw); + WN_LOGERROR3(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); + WN_LOGERROR1(F("BName="), configData.board_name); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - DEBUG_WM6("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); - } + WN_LOGERROR5("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); + } +#endif } - void displayWiFiData(void) + void displayWiFiData() { - DEBUG_WM4(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); - DEBUG_WM2(F("IP="), localIP() ); + WN_LOGERROR3(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); + WN_LOGERROR1(F("IP="), localIP() ); } -#define WIFININA_BOARD_TYPE "WIFININA" -#define WM_NO_CONFIG "blank" +#define WIFININA_BOARD_TYPE "WIFININA" +#define WM_NO_CONFIG "blank" #ifndef EEPROM_START -#define EEPROM_START 0 -#warning EEPROM_START not defined. Set to 0 + #define EEPROM_START 0 + #warning EEPROM_START not defined. Set to 0 #endif // Stating positon to store Blynk8266_WM_config -#define NINA_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) +#define CONFIG_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) int calcChecksum() { int checkSum = 0; - for (uint16_t index = 0; index < (sizeof(WiFiNINA_config) - sizeof(WiFiNINA_config.checkSum)); index++) + for (uint16_t index = 0; index < (sizeof(WIFININA_config) - sizeof(WIFININA_config.checkSum)); index++) { - checkSum += * ( ( (byte*) &WiFiNINA_config ) + index); + checkSum += * ( ( (byte*) &WIFININA_config ) + index); } return checkSum; } + + ////////////////////////////////////////////// + + void saveForcedCP(uint32_t value) + { + uint32_t readForcedConfigPortalFlag = value; + + uint16_t offset = CONFIG_EEPROM_START + CONFIG_DATA_SIZE; + + dueFlashStorageData.write(offset, (byte *) &readForcedConfigPortalFlag, sizeof(readForcedConfigPortalFlag)); + } + + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + + WN_LOGERROR(isPersistent ? F("setForcedCP Persistent") : F("setForcedCP non-Persistent")); + + saveForcedCP(readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + + void clearForcedCP() + { + uint32_t readForcedConfigPortalFlag = 0; + + WN_LOGERROR(F("clearForcedCP")); + + saveForcedCP(readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + uint16_t offset = CONFIG_EEPROM_START + CONFIG_DATA_SIZE; + + byte* dataPointer = (byte* ) dueFlashStorageData.readAddress(offset); + + memcpy(&readForcedConfigPortalFlag, dataPointer, sizeof(readForcedConfigPortalFlag)); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS - bool checkDynamicData(void) + bool checkDynamicData() { int checkSum = 0; int readCheckSum; @@ -619,7 +906,7 @@ class WiFiManager_NINA_Lite #define BIG_BUFFER_LEN 768 byte bigBuffer[BIG_BUFFER_LEN + 1]; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config); // Make address 4-byte aligned if ( (offset % 4) != 0 ) @@ -636,10 +923,10 @@ class WiFiManager_NINA_Lite { totalLength += myMenuItems[i].maxlen; - if ( (totalLength > BIG_BUFFER_LEN) || (myMenuItems[i].maxlen > BIG_BUFFER_LEN) ) + if ( (totalLength > BIG_BUFFER_LEN) ) { // Size too large, abort and flag false - DEBUG_WM1(F("ChkCrR: Error Small Buffer.")); + WN_LOGDEBUG(F("ChkCrR: Error Small Buffer.")); return false; } } @@ -668,7 +955,7 @@ class WiFiManager_NINA_Lite memcpy(&readCheckSum, &bigBuffer[byteCount], sizeof(readCheckSum)); - DEBUG_WM4(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + WN_LOGDEBUG3(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum ) { @@ -678,15 +965,11 @@ class WiFiManager_NINA_Lite return true; } - bool dueFlashStorage_get(void) - { - uint16_t offset = NINA_EEPROM_START; - - byte* dataPointer = (byte* ) dueFlashStorageData.readAddress(offset); - - memcpy(&WiFiNINA_config, dataPointer, sizeof(WiFiNINA_config)); - - offset += sizeof(WiFiNINA_config); + ////////////////////////////////////////////// + + bool dueFlashStorage_getDynamicData() + { + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; // Make address 4-byte aligned if ( (offset % 4) != 0 ) @@ -699,13 +982,14 @@ class WiFiManager_NINA_Lite uint16_t byteCount = 0; - byte buffer[768]; + #define BIG_BUFFER_LEN 768 + byte buffer[BIG_BUFFER_LEN + 1]; - dataPointer = (byte* ) dueFlashStorageData.readAddress(offset); + byte* dataPointer = (byte* ) dueFlashStorageData.readAddress(offset); memcpy(buffer, dataPointer, sizeof(buffer)); - totalDataSize = sizeof(WiFiNINA_config) + sizeof(readCheckSum); + totalDataSize = sizeof(WIFININA_config) + sizeof(readCheckSum); for (int i = 0; i < NUM_MENU_ITEMS; i++) { @@ -720,14 +1004,15 @@ class WiFiManager_NINA_Lite *_pointer = buffer[byteCount]; checkSum += *_pointer; - } + } } memcpy(&readCheckSum, &buffer[byteCount], sizeof(readCheckSum)); byteCount += sizeof(readCheckSum); - DEBUG_WM6(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX), F(",TotalDataSz="), totalDataSize); + WN_LOGERROR5(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX), + F(",TotalDataSz="), totalDataSize); if ( checkSum != readCheckSum) { @@ -735,15 +1020,13 @@ class WiFiManager_NINA_Lite } return true; - } + } - void dueFlashStorage_put(void) - { - uint16_t offset = NINA_EEPROM_START; - - dueFlashStorageData.write(offset, (byte *) &WiFiNINA_config, sizeof(WiFiNINA_config)); - - offset += sizeof(WiFiNINA_config); + ////////////////////////////////////////////// + + void dueFlashStorage_putDynamicData() + { + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; // Make address 4-byte aligned if ( (offset % 4) != 0 ) @@ -760,14 +1043,14 @@ class WiFiManager_NINA_Lite for (int i = 0; i < NUM_MENU_ITEMS; i++) { char* _pointer = myMenuItems[i].pdata; - - //DEBUG_WM4(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + + WN_LOGDEBUG3(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++, _pointer++, /*offset++,*/ byteCount++) { if (byteCount >= sizeof(buffer)) { - DEBUG_WM2(F("Danger:dynamic data too long >"), sizeof(buffer)); + WN_LOGERROR1(F("Danger:dynamic data too long >"), sizeof(buffer)); } buffer[byteCount] = *_pointer; @@ -781,32 +1064,94 @@ class WiFiManager_NINA_Lite dueFlashStorageData.write(offset, buffer, byteCount); - DEBUG_WM4(F("CrCCSum=0x"), String(checkSum, HEX), F(",byteCount="), byteCount); + WN_LOGERROR3(F("CrCCSum=0x"), String(checkSum, HEX), F(",byteCount="), byteCount); + } +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define SERVER_MAX_LEN 32 + //#define TOKEN_MAX_LEN 36 + + // NULL Terminating to be sure + WIFININA_config.header[HEADER_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.board_name[BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// + + bool dueFlashStorage_get() + { + uint16_t offset = CONFIG_EEPROM_START; + + byte* dataPointer = (byte* ) dueFlashStorageData.readAddress(offset); + + memcpy(&WIFININA_config, dataPointer, sizeof(WIFININA_config)); + + NULLTerminateConfig(); + + return true; + } + + ////////////////////////////////////////////// + + void dueFlashStorage_put() + { + uint16_t offset = CONFIG_EEPROM_START; + + dueFlashStorageData.write(offset, (byte *) &WIFININA_config, sizeof(WIFININA_config)); + } + + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + WIFININA_config.checkSum = calChecksum; + + WN_LOGERROR3(F("SaveData,Sz="), totalDataSize, F(",ChkSum=0x"), String(calChecksum, HEX)); + + dueFlashStorage_put(); + +#if USE_DYNAMIC_PARAMETERS + dueFlashStorage_putDynamicData(); +#endif } + + ////////////////////////////////////////////// // New from v1.0.5 - void loadAndSaveDefaultConfigData(void) + void loadAndSaveDefaultConfigData() { // Load Default Config Data from Sketch - memcpy(&WiFiNINA_config, &defaultConfig, sizeof(WiFiNINA_config)); - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); // Including config and dynamic data, and assume valid saveConfigData(); - DEBUG_WM1(F("======= Start Loaded Config Data =======")); - displayConfigData(WiFiNINA_config); + WN_LOGDEBUG(F("======= Start Loaded Config Data =======")); + displayConfigData(WIFININA_config); } + + ////////////////////////////////////////////// bool getConfigData() { - bool dynamicDataValid; + bool dynamicDataValid = true; int calChecksum; hadConfigData = false; // For DUE, DATA_LENGTH = ((IFLASH1_PAGE_SIZE/sizeof(byte))*4) = 1KBytes - DEBUG_WM2(F("Simulate EEPROM, Sz:"), DATA_LENGTH); + WN_LOGERROR1(F("Simulate EEPROM, Sz:"), DATA_LENGTH); // Use new LOAD_DEFAULT_CONFIG_DATA logic if (LOAD_DEFAULT_CONFIG_DATA) @@ -821,116 +1166,126 @@ class WiFiManager_NINA_Lite { // Load stored config / dynamic data from dueFlashStorage // Verify ChkSum - dynamicDataValid = checkDynamicData(); + dueFlashStorage_get(); + calChecksum = calcChecksum(); - DEBUG_WM4(F("CCSum=0x"), String(calChecksum, HEX), F(",RCSum=0x"), String(WiFiNINA_config.checkSum, HEX)); + WN_LOGERROR3(F("CCSum=0x"), String(calChecksum, HEX), + F(",RCSum=0x"), String(WIFININA_config.checkSum, HEX)); - if (dynamicDataValid) - { - dueFlashStorage_get(); - - DEBUG_WM1(F("Valid Stored Dynamic Data")); - DEBUG_WM1(F("======= Start Stored Config Data =======")); - displayConfigData(WiFiNINA_config); - - // Don't need Config Portal anymore - return true; - } - else +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from dueFlashStorage + dynamicDataValid = checkDynamicData(); +#endif + // If checksum = 0 => DueFlashStorage has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == WIFININA_config.checkSum) ) { - // Invalid Stored config data => Config Portal - DEBUG_WM1(F("Invalid Stored Dynamic Data. Load default from Sketch")); - - // Load Default Config Data from Sketch, better than just "blank" - loadAndSaveDefaultConfigData(); - - // Need Config Portal here as data can be just dummy - // Even if you don't open CP, you're OK on next boot if your default config data is valid - return false; - } + if (dynamicDataValid) + { + #if USE_DYNAMIC_PARAMETERS + dueFlashStorage_getDynamicData(); + + WN_LOGERROR(F("Valid Stored Dynamic Data")); + #endif + WN_LOGERROR(F("======= Start Stored Config Data =======")); + displayConfigData(WIFININA_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + WN_LOGERROR(F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } } - if ( (strncmp(WiFiNINA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || - (calChecksum != WiFiNINA_config.checkSum) || !dynamicDataValid ) + if ( (strncmp(WIFININA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || + (calChecksum != WIFININA_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (WIFININA_config.checkSum == 0) ) ) { // Including Credentials CSum - DEBUG_WM2(F("InitCfgFile,sz="), sizeof(WiFiNINA_config)); + WN_LOGERROR1(F("InitCfgFile,sz="), sizeof(WIFININA_config)); // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) { - memcpy(&WiFiNINA_config, &defaultConfig, sizeof(WiFiNINA_config)); + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); } else { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } +#endif - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); - strcpy(WiFiNINA_config.board_name, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.board_name, WM_NO_CONFIG); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } +#endif } - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - DEBUG_WM4(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); + WN_LOGDEBUG3(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); } +#endif // Don't need - WiFiNINA_config.checkSum = 0; + WIFININA_config.checkSum = 0; saveConfigData(); - - //dueFlashStorage_put(); return false; } - else if ( !strncmp(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strlen(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) || - !strlen(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) || - !strlen(WiFiNINA_config.WiFi_Creds[0].wifi_pw) || - !strlen(WiFiNINA_config.WiFi_Creds[1].wifi_pw) ) + else if ( !strncmp(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_pw) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_pw) ) { // If SSID, PW ="nothing", stay in config mode forever until having config Data. return false; } else { - displayConfigData(WiFiNINA_config); + displayConfigData(WIFININA_config); } return true; } - - void saveConfigData() - { - int calChecksum = calcChecksum(); - WiFiNINA_config.checkSum = calChecksum; - - DEBUG_WM4(F("SaveData,Sz="), totalDataSize, F(",ChkSum=0x"), String(calChecksum, HEX)); - - dueFlashStorage_put(); - } - + + ////////////////////////////////////////////// + // New connection logic from v1.0.5 bool connectMultiWiFi(int retry_time) { @@ -940,35 +1295,35 @@ class WiFiManager_NINA_Lite static int lastConnectedIndex = 255; - DEBUG_WM1(F("ConMultiWifi")); + WN_LOGDEBUG(F("ConMultiWifi")); if (static_IP != IPAddress(0, 0, 0, 0)) { - DEBUG_WM1(F("UseStatIP")); + WN_LOGDEBUG(F("UseStatIP")); WiFi.config(static_IP); } if (lastConnectedIndex != 255) { index = (lastConnectedIndex + 1) % NUM_WIFI_CREDENTIALS; - DEBUG_WM4(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); + WN_LOGDEBUG3(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); } - DEBUG_WM4(F("con2WF:SSID="), WiFiNINA_config.WiFi_Creds[index].wifi_ssid, - F(",PW="), WiFiNINA_config.WiFi_Creds[index].wifi_pw); + WN_LOGDEBUG3(F("con2WF:SSID="), WIFININA_config.WiFi_Creds[index].wifi_ssid, + F(",PW="), WIFININA_config.WiFi_Creds[index].wifi_pw); while ( !wifi_connected && ( 0 < retry_time ) ) { - DEBUG_WM2(F("Remaining retry_time="), retry_time); + WN_LOGDEBUG1(F("Remaining retry_time="), retry_time); - status = WiFi.begin(WiFiNINA_config.WiFi_Creds[index].wifi_ssid, WiFiNINA_config.WiFi_Creds[index].wifi_pw); + status = WiFi.begin(WIFININA_config.WiFi_Creds[index].wifi_ssid, WIFININA_config.WiFi_Creds[index].wifi_pw); // Need restart WiFi at beginning of each cycle if (status == WL_CONNECTED) { wifi_connected = true; lastConnectedIndex = index; - DEBUG_WM2(F("WOK, lastConnectedIndex="), lastConnectedIndex); + WN_LOGDEBUG1(F("WOK, lastConnectedIndex="), lastConnectedIndex); break; } @@ -981,32 +1336,51 @@ class WiFiManager_NINA_Lite if (retry_time <= 0) { - DEBUG_WM4(F("Failed using index="), index, F(", retry_time="), retry_time); + WN_LOGDEBUG3(F("Failed using index="), index, F(", retry_time="), retry_time); } if (wifi_connected) { - DEBUG_WM1(F("con2WF:OK")); + WN_LOGDEBUG(F("con2WF:OK")); displayWiFiData(); } else { - DEBUG_WM1(F("con2WF:failed")); + WN_LOGDEBUG(F("con2WF:failed")); // Can't connect, so try another index next time. Faking this index is OK and lost lastConnectedIndex = index; } return wifi_connected; } + + ////////////////////////////////////////////// // NEW void createHTML(String& root_html_template) { String pitem; - root_html_template = String(WIFININA_HTML_HEAD) + WIFININA_FLDSET_START; + root_html_template = WIFININA_HTML_HEAD_START; - for (int i = 0; i < NUM_MENU_ITEMS; i++) + #if USING_CUSTOMS_STYLE + // Using Customs style when not NULL + if (WIFININA_HTML_HEAD_CUSTOMS_STYLE) + root_html_template += WIFININA_HTML_HEAD_CUSTOMS_STYLE; + else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #endif + + #if USING_CUSTOMS_HEAD_ELEMENT + if (_CustomsHeadElement) + root_html_template += _CustomsHeadElement; + #endif + + root_html_template += String(WIFININA_HTML_HEAD_END) + WIFININA_FLDSET_START; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { pitem = String(WIFININA_HTML_PARAM); @@ -1019,7 +1393,7 @@ class WiFiManager_NINA_Lite root_html_template += String(WIFININA_FLDSET_END) + WIFININA_HTML_BUTTON + WIFININA_HTML_SCRIPT; - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { pitem = String(WIFININA_HTML_SCRIPT_ITEM); @@ -1032,11 +1406,33 @@ class WiFiManager_NINA_Lite return; } + + ////////////////////////////////////////////// + + void serverSendHeaders() + { + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CACHE_CONTROL:"), WM_HTTP_CACHE_CONTROL, "=", WM_HTTP_NO_STORE); + server->sendHeader(WM_HTTP_CACHE_CONTROL, WM_HTTP_NO_STORE); + +#if USING_CORS_FEATURE + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CORS:"), WM_HTTP_CORS, " : ", _CORS_Header); + server->sendHeader(WM_HTTP_CORS, _CORS_Header); +#endif + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_PRAGMA:"), WM_HTTP_PRAGMA, " : ", WM_HTTP_NO_CACHE); + server->sendHeader(WM_HTTP_PRAGMA, WM_HTTP_NO_CACHE); + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_EXPIRES:"), WM_HTTP_EXPIRES, " : ", "-1"); + server->sendHeader(WM_HTTP_EXPIRES, "-1"); + } + + ////////////////////////////////////////////// void handleRequest() { if (server) - { + { String key = server->arg("key"); String value = server->arg("value"); @@ -1044,6 +1440,10 @@ class WiFiManager_NINA_Lite if (key == "" && value == "") { + // New from v1.1.0 + serverSendHeaders(); + ////// + String result; createHTML(result); @@ -1053,26 +1453,32 @@ class WiFiManager_NINA_Lite if ( RFC952_hostname[0] != 0 ) { // Replace only if Hostname is valid - result.replace("SAM_DUE_WM_NINA_Lite", RFC952_hostname); + result.replace("SAMD_WM_NINA_Lite", RFC952_hostname); } - else if ( WiFiNINA_config.board_name[0] != 0 ) + else if ( WIFININA_config.board_name[0] != 0 ) { // Or replace only if board_name is valid. Otherwise, keep intact - result.replace("SAM_DUE_WM_NINA_Lite", WiFiNINA_config.board_name); + result.replace("SAMD_WM_NINA_Lite", WIFININA_config.board_name); } - result.replace("[[id]]", WiFiNINA_config.WiFi_Creds[0].wifi_ssid); - result.replace("[[pw]]", WiFiNINA_config.WiFi_Creds[0].wifi_pw); - result.replace("[[id1]]", WiFiNINA_config.WiFi_Creds[1].wifi_ssid); - result.replace("[[pw1]]", WiFiNINA_config.WiFi_Creds[1].wifi_pw); - result.replace("[[nm]]", WiFiNINA_config.board_name); + result.replace("[[id]]", WIFININA_config.WiFi_Creds[0].wifi_ssid); + result.replace("[[pw]]", WIFININA_config.WiFi_Creds[0].wifi_pw); + result.replace("[[id1]]", WIFININA_config.WiFi_Creds[1].wifi_ssid); + result.replace("[[pw1]]", WIFININA_config.WiFi_Creds[1].wifi_pw); + result.replace("[[nm]]", WIFININA_config.board_name); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { String toChange = String("[[") + myMenuItems[i].id + "]]"; result.replace(toChange, myMenuItems[i].pdata); } +#endif + + WN_LOGDEBUG1(F("h:HTML page size:"), result.length()); + WN_LOGDEBUG1(F("h:HTML="), result); + server->send(200, "text/html", result); return; @@ -1080,78 +1486,138 @@ class WiFiManager_NINA_Lite if (number_items_Updated == 0) { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); } - if (key == "id") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + + WN_LOGDEBUG1(F("h: Init menuItemUpdated :" ), NUM_MENU_ITEMS); + } + else + { + WN_LOGERROR(F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool id_Updated = false; + static bool pw_Updated = false; + static bool id1_Updated = false; + static bool pw1_Updated = false; + static bool nm_Updated = false; + + if (!id_Updated && (key == String("id"))) + { + WN_LOGDEBUG(F("h:repl id")); + id_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) - 1); + strncpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1); } - else if (key == "pw") - { + else if (!pw_Updated && (key == String("pw"))) + { + WN_LOGDEBUG(F("h:repl pw")); + pw_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_pw) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_pw) - 1); + strncpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1); } - else if (key == "id1") - { + else if (!id1_Updated && (key == String("id1"))) + { + WN_LOGDEBUG(F("h:repl id1")); + id1_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) - 1); + strncpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1); } - else if (key == "pw1") - { + else if (!pw1_Updated && (key == String("pw1"))) + { + WN_LOGDEBUG(F("h:repl pw1")); + pw1_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_pw) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_pw) - 1); + strncpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { + WN_LOGDEBUG(F("h:repl nm")); + nm_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.board_name) - 1) - strcpy(WiFiNINA_config.board_name, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.board_name) - 1) + strcpy(WIFININA_config.board_name, value.c_str()); else - strncpy(WiFiNINA_config.board_name, value.c_str(), sizeof(WiFiNINA_config.board_name) - 1); + strncpy(WIFININA_config.board_name, value.c_str(), sizeof(WIFININA_config.board_name) - 1); } - - for (int i = 0; i < NUM_MENU_ITEMS; i++) + else { - if (key == myMenuItems[i].id) - { - DEBUG_WM4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); - number_items_Updated++; + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) + { + WN_LOGDEBUG3(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + + menuItemUpdated[i] = true; + + number_items_Updated++; - // Actual size of pdata is [maxlen + 1] - memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); - if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) - strcpy(myMenuItems[i].pdata, value.c_str()); - else - strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) + strcpy(myMenuItems[i].pdata, value.c_str()); + else + strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + + break; + } } +#endif } + + WN_LOGDEBUG1(F("h:items updated ="), number_items_Updated); + WN_LOGDEBUG3(F("h:key ="), key, ", value =", value); server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif { - DEBUG_WM1(F("h:UpdFlash")); + WN_LOGDEBUG(F("h:UpdFlash")); saveConfigData(); - DEBUG_WM1(F("h:Rst")); + WN_LOGDEBUG(F("h:Rst")); // TO DO : what command to reset // Delay then reset the board after save data @@ -1160,11 +1626,16 @@ class WiFiManager_NINA_Lite } } // if (server) } + + ////////////////////////////////////////////// + +#ifndef CONFIG_TIMEOUT + #warning Default CONFIG_TIMEOUT = 60s + #define CONFIG_TIMEOUT 60000L +#endif void startConfigurationMode() { -#define CONFIG_TIMEOUT 60000L - WiFi.config(portal_apIP); if ( (portal_ssid == "") || portal_pass == "" ) @@ -1180,20 +1651,22 @@ class WiFiManager_NINA_Lite uint16_t channel; - // Use random channel if AP_channel == 0 - //srand(MAX_WIFI_CHANNEL); - srand((uint16_t) millis()); - + // Use random channel if AP_channel == 0 if (AP_channel == 0) - channel = (rand() % MAX_WIFI_CHANNEL) + 1; //random(MAX_WIFI_CHANNEL) + 1; + channel = (millis() % MAX_WIFI_CHANNEL) + 1; else channel = AP_channel; - INFO_WM4(F("SSID="), portal_ssid, F(",PW="), portal_pass); - INFO_WM4(F("IP="), portal_apIP, F(",CH="), channel); + WN_LOGERROR3(F("SSID="), portal_ssid, F(",PW="), portal_pass); + WN_LOGERROR3(F("IP="), portal_apIP, F(",CH="), channel); +#if USE_ESP_AT_SHIELD + // start access point, AP only,default channel 10 + WiFi.beginAP(portal_ssid.c_str(), channel, portal_pass.c_str(), ENC_TYPE_WPA2_PSK, true); +#else // start access point, AP only,default channel 10 WiFi.beginAP(portal_ssid.c_str(), portal_pass.c_str(), channel); +#endif if (!server) @@ -1212,9 +1685,17 @@ class WiFiManager_NINA_Lite // If there is no saved config Data, stay in config mode forever until having config Data. // or SSID, PW, Server,Token ="nothing" if (hadConfigData) + { configTimeout = millis() + CONFIG_TIMEOUT; + + WN_LOGDEBUG3(F("s:millis() = "), millis(), F(", configTimeout = "), configTimeout); + } else + { configTimeout = 0; + + WN_LOGDEBUG(F("s:configTimeout = 0")); + } configuration_mode = true; } diff --git a/src/WiFiManager_NINA_Lite_Debug.h b/src/WiFiManager_NINA_Lite_Debug.h index 5d1650c0..99a95128 100644 --- a/src/WiFiManager_NINA_Lite_Debug.h +++ b/src/WiFiManager_NINA_Lite_Debug.h @@ -1,25 +1,27 @@ -/**************************************************************************************************************************** - WiFiManager_NINA_Lite_Debug.h - For Mega, Teensy, SAM DUE, SAMD and STM32 boards using WiFiNINA modules/shields - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + WiFiManager_NINA_Lite_Debug.h + For Mega, Teensy, SAM DUE, SAMD and STM32 boards using WiFiNINA modules/shields + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ #ifndef WiFiManager_NINA_Lite_Debug_h #define WiFiManager_NINA_Lite_Debug_h @@ -28,35 +30,61 @@ #define WIFININA_DEBUG false #endif - // Use these to always display - #define INFO_WM1(p1) { WIFININA_DEBUG_OUTPUT.print(F("*NN: ")); WIFININA_DEBUG_OUTPUT.println(p1); } - #define INFO_WM2(p1,p2) { WIFININA_DEBUG_OUTPUT.print(F("*NN: ")); WIFININA_DEBUG_OUTPUT.print(p1); \ - WIFININA_DEBUG_OUTPUT.println(p2); } - #define INFO_WM3(p1,p2,p3) { WIFININA_DEBUG_OUTPUT.print(F("*NN: ")); WIFININA_DEBUG_OUTPUT.print(p1); \ - WIFININA_DEBUG_OUTPUT.print(p2); WIFININA_DEBUG_OUTPUT.println(p3); } - #define INFO_WM4(p1,p2,p3,p4) { WIFININA_DEBUG_OUTPUT.print(F("*NN: ")); WIFININA_DEBUG_OUTPUT.print(p1); \ - WIFININA_DEBUG_OUTPUT.print(p2); WIFININA_DEBUG_OUTPUT.print(p3); WIFININA_DEBUG_OUTPUT.println(p4); } - #define INFO_WM6(p1,p2,p3,p4,p5,p6) { WIFININA_DEBUG_OUTPUT.print(F("*NN: ")); WIFININA_DEBUG_OUTPUT.print(p1); \ - WIFININA_DEBUG_OUTPUT.print(p2); WIFININA_DEBUG_OUTPUT.print(p3); WIFININA_DEBUG_OUTPUT.print(p4); \ - WIFININA_DEBUG_OUTPUT.print(p5); WIFININA_DEBUG_OUTPUT.println(p6); } - -#if WIFININA_DEBUG - #define DEBUG_WM1(p1) { WIFININA_DEBUG_OUTPUT.print(F("*NN: ")); WIFININA_DEBUG_OUTPUT.println(p1); } - #define DEBUG_WM2(p1,p2) { WIFININA_DEBUG_OUTPUT.print(F("*NN: ")); WIFININA_DEBUG_OUTPUT.print(p1); \ - WIFININA_DEBUG_OUTPUT.println(p2); } - #define DEBUG_WM3(p1,p2,p3) { WIFININA_DEBUG_OUTPUT.print(F("*NN: ")); WIFININA_DEBUG_OUTPUT.print(p1); \ - WIFININA_DEBUG_OUTPUT.print(p2); WIFININA_DEBUG_OUTPUT.println(p3); } - #define DEBUG_WM4(p1,p2,p3,p4) { WIFININA_DEBUG_OUTPUT.print(F("*NN: ")); WIFININA_DEBUG_OUTPUT.print(p1); \ - WIFININA_DEBUG_OUTPUT.print(p2); WIFININA_DEBUG_OUTPUT.print(p3); WIFININA_DEBUG_OUTPUT.println(p4); } - #define DEBUG_WM6(p1,p2,p3,p4,p5,p6) { WIFININA_DEBUG_OUTPUT.print(F("*NN: ")); WIFININA_DEBUG_OUTPUT.print(p1); \ - WIFININA_DEBUG_OUTPUT.print(p2); WIFININA_DEBUG_OUTPUT.print(p3); WIFININA_DEBUG_OUTPUT.print(p4); \ - WIFININA_DEBUG_OUTPUT.print(p5); WIFININA_DEBUG_OUTPUT.println(p6); } +#ifdef WIFININA_DEBUG_OUTPUT + #define DBG_PORT_WN WIFININA_DEBUG_OUTPUT #else - #define DEBUG_WM1(p1) - #define DEBUG_WM2(p1,p2) - #define DEBUG_WM3(p1,p2,p3) - #define DEBUG_WM4(p1,p2,p3,p4) - #define DEBUG_WM6(p1,p2,p3,p4,p5,p6) + #define DBG_PORT_WN Serial +#endif + +// Change _WIFININA_LOGLEVEL_ to set tracing and logging verbosity +// 0: DISABLED: no logging +// 1: ERROR: errors +// 2: WARN: errors and warnings +// 3: INFO: errors, warnings and informational (default) +// 4: DEBUG: errors, warnings, informational and debug + +#ifndef _WIFININA_LOGLEVEL_ + #define _WIFININA_LOGLEVEL_ 0 #endif +const char WN_MARK[] = "[WN] "; + +#define WN_PRINT_MARK DBG_PORT_WN.print(WN_MARK) + +#define WN_PRINT DBG_PORT_WN.print +#define WN_PRINTLN DBG_PORT_WN.println + +// Error waitResponse message +#define ERROR_RESPONSE ":Error waitResponse" + +#define WN_LOGERROR0(x) if(_WIFININA_LOGLEVEL_>0) { WN_PRINT(x); } +#define WN_LOGERROR(x) if(_WIFININA_LOGLEVEL_>0) { WN_PRINT_MARK; WN_PRINTLN(x); } +#define WN_LOGERROR1(x,y) if(_WIFININA_LOGLEVEL_>0) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINTLN(y); } +#define WN_LOGERROR2(x,y,z) if(_WIFININA_LOGLEVEL_>0) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINTLN(z); } +#define WN_LOGERROR3(x,y,z,w) if(_WIFININA_LOGLEVEL_>0) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINT(z); WN_PRINTLN(w); } +#define WN_LOGERROR5(x,y,z,w,xx,yy) if(_WIFININA_LOGLEVEL_>0) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINT(z); WN_PRINT(w); WN_PRINT(xx); WN_PRINTLN(yy); } + +#define WN_LOGWARN0(x) if(_WIFININA_LOGLEVEL_>1) { WN_PRINT(x); } +#define WN_LOGWARN(x) if(_WIFININA_LOGLEVEL_>1) { WN_PRINT_MARK; WN_PRINTLN(x); } +#define WN_LOGWARN1(x,y) if(_WIFININA_LOGLEVEL_>1) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINTLN(y); } +#define WN_LOGWARN2(x,y,z) if(_WIFININA_LOGLEVEL_>1) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINTLN(z); } +#define WN_LOGWARN3(x,y,z,w) if(_WIFININA_LOGLEVEL_>1) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINT(z); WN_PRINTLN(w); } +#define WN_LOGWARN5(x,y,z,w,xx,yy) if(_WIFININA_LOGLEVEL_>1) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINT(z); WN_PRINT(w); WN_PRINT(xx); WN_PRINTLN(yy); } + +#define WN_LOGINFO0(x) if(_WIFININA_LOGLEVEL_>2) { WN_PRINT(x); } +#define WN_LOGINFO(x) if(_WIFININA_LOGLEVEL_>2) { WN_PRINT_MARK; WN_PRINTLN(x); } +#define WN_LOGINFO1(x,y) if(_WIFININA_LOGLEVEL_>2) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINTLN(y); } +#define WN_LOGINFO2(x,y,z) if(_WIFININA_LOGLEVEL_>3) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINTLN(z); } +#define WN_LOGINFO3(x,y,z,w) if(_WIFININA_LOGLEVEL_>3) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINT(z); WN_PRINTLN(w); } +#define WN_LOGINFO5(x,y,z,w,xx,yy) if(_WIFININA_LOGLEVEL_>2) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINT(z); WN_PRINT(w); WN_PRINT(xx); WN_PRINTLN(yy); } + +#define WN_LOGDEBUG0(x) if(_WIFININA_LOGLEVEL_>3) { WN_PRINT(x); } +#define WN_LOGDEBUG(x) if(_WIFININA_LOGLEVEL_>3) { WN_PRINT_MARK; WN_PRINTLN(x); } +#define WN_LOGDEBUG1(x,y) if(_WIFININA_LOGLEVEL_>3) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINTLN(y); } +#define WN_LOGDEBUG2(x,y,z) if(_WIFININA_LOGLEVEL_>3) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINTLN(z); } +#define WN_LOGDEBUG3(x,y,z,w) if(_WIFININA_LOGLEVEL_>3) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINT(z); WN_PRINTLN(w); } +#define WN_LOGDEBUG5(x,y,z,w,xx,yy) if(_WIFININA_LOGLEVEL_>3) { WN_PRINT_MARK; WN_PRINT(x); WN_PRINT(y); WN_PRINT(z); WN_PRINT(w); WN_PRINT(xx); WN_PRINTLN(yy); } + +////// + #endif //WiFiManager_NINA_Lite_Debug_h diff --git a/src/WiFiManager_NINA_Lite_SAMD.h b/src/WiFiManager_NINA_Lite_SAMD.h index fc53b83a..8bec219d 100644 --- a/src/WiFiManager_NINA_Lite_SAMD.h +++ b/src/WiFiManager_NINA_Lite_SAMD.h @@ -1,25 +1,27 @@ -/**************************************************************************************************************************** - WiFiManager_NINA_Lite_SAMD.h - For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + WiFiManager_NINA_Lite_SAMD.h + For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ #ifndef WiFiManager_NINA_Lite_SAMD_h #define WiFiManager_NINA_Lite_SAMD_h @@ -28,17 +30,16 @@ || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ - || defined(__SAMD51G19A__) || defined(__SAMD21G18A__) ) -#if defined(WIFININA_USE_SAMD) -#undef WIFININA_USE_SAMD -#endif -#define WIFININA_USE_SAMD true + || defined(__SAMD51G19A__) || defined(__SAMD51P19A__) || defined(__SAMD21G18A__) ) + #if defined(WIFININA_USE_SAMD) + #undef WIFININA_USE_SAMD + #endif + #define WIFININA_USE_SAMD true +#else + #error This code is intended to run on the SAMD platform! Please check your Tools->Board setting. #endif -#if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA) || \ - defined(CORE_TEENSY) || !(WIFININA_USE_SAMD) ) -#error This code is intended to run on the SAMD platform! Please check your Tools->Board setting. -#endif +#define WIFIMANAGER_NINA_LITE_VERSION "WiFiManager_NINA_Lite v1.1.0" #include // Include EEPROM-like API for FlashStorage @@ -46,6 +47,19 @@ #include //https://github.com/khoih-prog/FlashStorage_SAMD #include + +#ifndef USING_CUSTOMS_STYLE + #define USING_CUSTOMS_STYLE false +#endif + +#ifndef USING_CUSTOMS_HEAD_ELEMENT + #define USING_CUSTOMS_HEAD_ELEMENT false +#endif + +#ifndef USING_CORS_FEATURE + #define USING_CORS_FEATURE false +#endif + ///////// NEW for DRD ///////////// // These defines must be put before #include // to select where to store DoubleResetDetector_Generic's variable. @@ -53,7 +67,7 @@ #define DRD_FLAG_DATA_SIZE 4 #ifndef DRD_GENERIC_DEBUG -#define DRD_GENERIC_DEBUG false + #define DRD_GENERIC_DEBUG false #endif #include //https://github.com/khoih-prog/DoubleResetDetector_Generic @@ -82,14 +96,18 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; - -// New in v1.0.3 +#if USE_DYNAMIC_PARAMETERS + #warning Using Dynamic Parameters + ///NEW + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#else + #warning Not using Dynamic Parameters +#endif #define SSID_MAX_LEN 32 -//From v1.0.3, WPA2 passwords can be up to 63 characters long. +// WPA2 passwords can be up to 63 characters long. #define PASS_MAX_LEN 64 typedef struct @@ -104,23 +122,30 @@ typedef struct #define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) //////////////// +#define HEADER_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; - char board_name [24]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } WiFiNINA_Configuration; // Currently CONFIG_DATA_SIZE = 236 = (16 + 96 * 2 + 4 + 24) uint16_t CONFIG_DATA_SIZE = sizeof(WiFiNINA_Configuration); -///New from v1.0.4 extern bool LOAD_DEFAULT_CONFIG_DATA; extern WiFiNINA_Configuration defaultConfig; // -- HTML page fragments -const char WIFININA_HTML_HEAD[] /*PROGMEM*/ = "SAMD_WM_NINA_Lite
\ + +const char WIFININA_HTML_HEAD_START[] /*PROGMEM*/ = "SAMD_WM_NINA_Lite"; + +const char WIFININA_HTML_HEAD_STYLE[] /*PROGMEM*/ = ""; + +const char WIFININA_HTML_HEAD_END[] /*PROGMEM*/ = "
\
\
\
\ @@ -141,7 +166,25 @@ udVal('nm',document.getElementById('nm').value);"; const char WIFININA_HTML_SCRIPT_ITEM[] /*PROGMEM*/ = "udVal('{d}',document.getElementById('{d}').value);"; const char WIFININA_HTML_SCRIPT_END[] /*PROGMEM*/ = "alert('Updated');}"; const char WIFININA_HTML_END[] /*PROGMEM*/ = ""; -/// + +////////////////////////////////////////// + +//KH Add repeatedly used const +//KH, from v1.1.0 +const char WM_HTTP_HEAD_CL[] PROGMEM = "Content-Length"; +const char WM_HTTP_HEAD_TEXT_HTML[] PROGMEM = "text/html"; +const char WM_HTTP_HEAD_TEXT_PLAIN[] PROGMEM = "text/plain"; + +const char WM_HTTP_CACHE_CONTROL[] PROGMEM = "Cache-Control"; +const char WM_HTTP_NO_STORE[] PROGMEM = "no-cache, no-store, must-revalidate"; +const char WM_HTTP_PRAGMA[] PROGMEM = "Pragma"; +const char WM_HTTP_NO_CACHE[] PROGMEM = "no-cache"; +const char WM_HTTP_EXPIRES[] PROGMEM = "Expires"; + +const char WM_HTTP_CORS[] PROGMEM = "Access-Control-Allow-Origin"; +const char WM_HTTP_CORS_ALLOW_ALL[] PROGMEM = "*"; + +////////////////////////////////////////// String IPAddressToString(IPAddress _address) @@ -163,9 +206,13 @@ class WiFiManager_NINA_Lite WiFiManager_NINA_Lite() { // check for the presence of the shield - if (WiFi.status() == WL_NO_MODULE) +#if USE_WIFI101 + if (WiFi.status() == WL_NO_SHIELD) +#else + if (WiFi.status() == WL_NO_MODULE) +#endif { - DEBUG_WM1(F("NoNINA")); + WN_LOGERROR(F("NoWiFi")); } } @@ -177,11 +224,9 @@ class WiFiManager_NINA_Lite bool connectWiFi(const char* ssid, const char* pass) { - DEBUG_WM2(F("Con2:"), ssid); + WN_LOGERROR1(F("Con2:"), ssid); - // New in v1.0.3 setHostname(); - /// if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) { @@ -189,11 +234,11 @@ class WiFiManager_NINA_Lite } else { - DEBUG_WM1(F("NoW")); + WN_LOGERROR(F("NoW")); return false; } - DEBUG_WM1(F("WOK")); + WN_LOGERROR(F("WOK")); wifi_connected = true; @@ -203,16 +248,14 @@ class WiFiManager_NINA_Lite void begin(const char* ssid, const char* pass ) { - DEBUG_WM1(F("conW")); + WN_LOGERROR(F("conW")); connectWiFi(ssid, pass); } - // New in v1.0.5 void begin(const char *iHostname = "") { #define RETRY_TIMES_CONNECT_WIFI 3 - // New in v1.0.3 if (iHostname[0] == 0) { String randomNum = String(random(0xFFFFFF), HEX); @@ -229,53 +272,72 @@ class WiFiManager_NINA_Lite getRFC952_hostname(iHostname); } - DEBUG_WM2(F("Hostname="), RFC952_hostname); + WN_LOGERROR1(F("Hostname="), RFC952_hostname); ////// //// New DRD //// drd = new DoubleResetDetector_Generic(DRD_TIMEOUT, DRD_ADDRESS); - bool useConfigPortal = false; + bool noConfigPortal = true; if (drd->detectDoubleReset()) { - DEBUG_WM1(F("Double Reset Detected")); + WN_LOGERROR(F("Double Reset Detected")); - useConfigPortal = true; + noConfigPortal = false; } //// New DRD //// - DEBUG_WM1(F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + + if (LOAD_DEFAULT_CONFIG_DATA) + { + WN_LOGERROR(F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } hadConfigData = getConfigData(); + + isForcedConfigPortal = isForcedCP(); - //// New DRD //// - // useConfigPortal when getConfigData() not OK or DRD'ed - if (hadConfigData && !useConfigPortal) - //// New DRD //// + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { - //hadConfigData = true; + hadConfigData = true; if (connectMultiWiFi(RETRY_TIMES_CONNECT_WIFI)) { - DEBUG_WM1(F("b:WOK")); + WN_LOGERROR(F("b:WOK")); } else { - DEBUG_WM1(F("b:NoW")); + WN_LOGERROR(F("b:NoW")); // failed to connect to WiFi, will start configuration mode startConfigurationMode(); } } else - { - INFO_WM2(F("b:StayInCfgPortal:"), useConfigPortal ? F("DRD") : F("NoCfgDat")); + { + WN_LOGERROR(isForcedConfigPortal? F("bg: isForcedConfigPortal = true") : F("bg: isForcedConfigPortal = false")); + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + } + else + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-non-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + clearForcedCP(); + } + + //To permit autoreset after timeout if DRD/MRD or non-persistent forced-CP + hadConfigData = isForcedConfigPortal ? true : (noConfigPortal ? false : true); // failed to connect to WiFi, will start configuration mode - hadConfigData = false; startConfigurationMode(); } } + #ifndef RETRY_TIMES_RECONNECT_WIFI #define RETRY_TIMES_RECONNECT_WIFI 2 #else @@ -292,22 +354,22 @@ class WiFiManager_NINA_Lite #endif #ifndef RESET_IF_CONFIG_TIMEOUT -#define RESET_IF_CONFIG_TIMEOUT true + #define RESET_IF_CONFIG_TIMEOUT true #endif #ifndef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 #else - // Force range of user-defined TIMES_BEFORE_RESET between 2-100 -#if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) -#warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 -#undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 -#elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) -#warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 -#undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 -#endif + // Force range of user-defined TIMES_BEFORE_RESET between 2-100 + #if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 + #elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 + #endif #endif void run() @@ -341,7 +403,7 @@ class WiFiManager_NINA_Lite { wifiDisconnectedOnce = false; wifi_connected = false; - DEBUG_WM1(F("r:Check&WLost")); + WN_LOGERROR(F("r:Check&WLost")); } else { @@ -363,7 +425,7 @@ class WiFiManager_NINA_Lite if (server) { - //DEBUG_WM1(F("r:handleClient")); + //WN_LOGDEBUG(F("r:handleClient")); server->handleClient(); } @@ -378,7 +440,7 @@ class WiFiManager_NINA_Lite { if (++retryTimes <= CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET) { - DEBUG_WM2(F("r:WLost&TOut.ConW.Retry#"), retryTimes); + WN_LOGERROR1(F("r:WLost&TOut.ConW.Retry#"), retryTimes); } else { @@ -390,11 +452,11 @@ class WiFiManager_NINA_Lite // Not in config mode, try reconnecting before forcing to config mode if ( !wifi_connected ) { - DEBUG_WM1(F("r:WLost.ReconW")); + WN_LOGERROR(F("r:WLost.ReconW")); if (connectMultiWiFi(RETRY_TIMES_RECONNECT_WIFI)) { - DEBUG_WM1(F("r:WOK")); + WN_LOGERROR(F("r:WOK")); } } } @@ -402,25 +464,35 @@ class WiFiManager_NINA_Lite else if (configuration_mode) { configuration_mode = false; - DEBUG_WM1(F("r:gotWBack")); + WN_LOGERROR(F("r:gotWBack")); } } - void setHostname(void) + ////////////////////////////////////////////// + + void setHostname() { if (RFC952_hostname[0] != 0) { +#if USE_WIFI101 + WiFi.hostname(RFC952_hostname); +#elif USE_WIFI_NINA WiFi.setHostname(RFC952_hostname); +#endif } } + + ////////////////////////////////////////////// void setConfigPortalIP(IPAddress portalIP = IPAddress(192, 168, 4, 1)) { portal_apIP = portalIP; } + + ////////////////////////////////////////////// #define MIN_WIFI_CHANNEL 1 - #define MAX_WIFI_CHANNEL 12 // Channel 13 is flaky, because of bad number 13 ;-) + #define MAX_WIFI_CHANNEL 11 // Channel 13 is flaky, because of bad number 13 ;-) int setConfigPortalChannel(int channel = 1) { @@ -435,17 +507,23 @@ class WiFiManager_NINA_Lite return AP_channel; } + ////////////////////////////////////////////// + void setConfigPortal(String ssid = "", String pass = "") { portal_ssid = ssid; portal_pass = pass; } + + ////////////////////////////////////////////// void setSTAStaticIPConfig(IPAddress ip) { static_IP = ip; } - + + ////////////////////////////////////////////// + String getWiFiSSID(uint8_t index) { if (index >= NUM_WIFI_CREDENTIALS) @@ -454,8 +532,10 @@ class WiFiManager_NINA_Lite if (!hadConfigData) getConfigData(); - return (String(WiFiNINA_config.WiFi_Creds[index].wifi_ssid)); + return (String(WIFININA_config.WiFi_Creds[index].wifi_ssid)); } + + ////////////////////////////////////////////// String getWiFiPW(uint8_t index) { @@ -465,14 +545,18 @@ class WiFiManager_NINA_Lite if (!hadConfigData) getConfigData(); - return (String(WiFiNINA_config.WiFi_Creds[index].wifi_pw)); + return (String(WIFININA_config.WiFi_Creds[index].wifi_pw)); } - bool getWiFiStatus(void) + ////////////////////////////////////////////// + + bool getWiFiStatus() { return wifi_connected; } + ////////////////////////////////////////////// + WiFiNINA_Configuration* getFullConfigData(WiFiNINA_Configuration *configData) { if (!hadConfigData) @@ -480,35 +564,83 @@ class WiFiManager_NINA_Lite // Check if NULL pointer if (configData) - memcpy(configData, &WiFiNINA_config, sizeof(WiFiNINA_Configuration)); + memcpy(configData, &WIFININA_config, sizeof(WiFiNINA_Configuration)); return (configData); } + + ////////////////////////////////////////////// - String localIP(void) + String localIP() { ipAddress = IPAddressToString(WiFi.localIP()); return ipAddress; } + + ////////////////////////////////////////////// void clearConfigData() { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } +#endif saveConfigData(); } - bool isConfigDataValid(void) + ////////////////////////////////////////////// + + bool isConfigDataValid() { return hadConfigData; } + + ////////////////////////////////////////////// + + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// void resetFunc() { @@ -540,6 +672,64 @@ class WiFiManager_NINA_Lite #endif } + ////////////////////////////////////// + + // Add customs headers from v1.1.0 + + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + +#if USING_CUSTOMS_STYLE + //sets a custom style, such as color + // ""; + void setCustomsStyle(const char* CustomsStyle = WIFININA_HTML_HEAD_STYLE) + { + WIFININA_HTML_HEAD_CUSTOMS_STYLE = CustomsStyle; + WN_LOGDEBUG1(F("Set CustomsStyle to : "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + } + + const char* getCustomsStyle() + { + WN_LOGDEBUG1(F("Get CustomsStyle = "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + return WIFININA_HTML_HEAD_CUSTOMS_STYLE; + } +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + //sets a custom element to add to head, like a new style tag + void setCustomsHeadElement(const char* CustomsHeadElement = NULL) + { + _CustomsHeadElement = CustomsHeadElement; + WN_LOGDEBUG1(F("Set CustomsHeadElement to : "), _CustomsHeadElement); + } + + const char* getCustomsHeadElement() + { + WN_LOGDEBUG1(F("Get CustomsHeadElement = "), _CustomsHeadElement); + return _CustomsHeadElement; + } +#endif + +#if USING_CORS_FEATURE + void setCORSHeader(const char* CORSHeaders = NULL) + { + _CORS_Header = CORSHeaders; + + WN_LOGDEBUG1(F("Set CORS Header to : "), _CORS_Header); + } + + const char* getCORSHeader() + { + WN_LOGDEBUG1(F("Get CORS Header = "), _CORS_Header); + return _CORS_Header; + } +#endif + + ////////////////////////////////////// + + private: String ipAddress = "0.0.0.0"; @@ -549,8 +739,11 @@ class WiFiManager_NINA_Lite unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; - WiFiNINA_Configuration WiFiNINA_config; + WiFiNINA_Configuration WIFININA_config; uint16_t totalDataSize = 0; @@ -565,6 +758,24 @@ class WiFiManager_NINA_Lite IPAddress static_IP = IPAddress(0, 0, 0, 0); + ///////////////////////////////////// + + // Add customs headers from v1.1.0 + +#if USING_CUSTOMS_STYLE + const char* WIFININA_HTML_HEAD_CUSTOMS_STYLE = NULL; +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + const char* _CustomsHeadElement = NULL; +#endif + +#if USING_CORS_FEATURE + const char* _CORS_Header = WM_HTTP_CORS_ALLOW_ALL; //"*"; +#endif + + ////////////////////////////////////// + #define RFC952_HOSTNAME_MAXLEN 24 char RFC952_hostname[RFC952_HOSTNAME_MAXLEN + 1]; @@ -593,54 +804,108 @@ class WiFiManager_NINA_Lite void displayConfigData(WiFiNINA_Configuration configData) { - DEBUG_WM6(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, - F(",PW="), configData.WiFi_Creds[0].wifi_pw); - DEBUG_WM4(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); - DEBUG_WM2(F("BName="), configData.board_name); + WN_LOGERROR5(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, + F(",PW="), configData.WiFi_Creds[0].wifi_pw); + WN_LOGERROR3(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); + WN_LOGERROR1(F("BName="), configData.board_name); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - DEBUG_WM6("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); - } + WN_LOGERROR5("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); + } +#endif } - void displayWiFiData(void) + void displayWiFiData() { - DEBUG_WM4(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); - DEBUG_WM2(F("IP="), localIP() ); + WN_LOGERROR3(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); + WN_LOGERROR1(F("IP="), localIP() ); } -#define WIFININA_BOARD_TYPE "WIFININA" -#define WM_NO_CONFIG "blank" +#define WIFININA_BOARD_TYPE "WIFININA" +#define WM_NO_CONFIG "blank" // DRD_FLAG_DATA_SIZE is 4, to store DRD flag, defined in DRD #if (EEPROM_SIZE < DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) -#error EEPROM_SIZE must be > CONFIG_DATA_SIZE. + #error EEPROM_SIZE must be > CONFIG_DATA_SIZE. #endif #ifndef EEPROM_START -#define EEPROM_START 0 -#warning EEPROM_START not defined. Set to 0 + #define EEPROM_START 0 + #warning EEPROM_START not defined. Set to 0 #else -#if (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE) -#error EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE. Please adjust. -#endif + #if (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE > EEPROM_SIZE) + #error EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE > EEPROM_SIZE. Please adjust. + #endif #endif // Stating positon to store Blynk8266_WM_config -#define NINA_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) +#define CONFIG_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) int calcChecksum() { int checkSum = 0; - for (uint16_t index = 0; index < (sizeof(WiFiNINA_config) - sizeof(WiFiNINA_config.checkSum)); index++) + for (uint16_t index = 0; index < (sizeof(WIFININA_config) - sizeof(WIFININA_config.checkSum)); index++) { - checkSum += * ( ( (byte*) &WiFiNINA_config ) + index); + checkSum += * ( ( (byte*) &WIFININA_config ) + index); } return checkSum; } + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + + WN_LOGERROR(isPersistent ? F("setForcedCP Persistent") : F("setForcedCP non-Persistent")); + + EEPROM.put(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + EEPROM.commit(); + } + + ////////////////////////////////////////////// + + void clearForcedCP() + { + EEPROM.put(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, 0); + EEPROM.commit(); + } + + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + EEPROM.get(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS + bool checkDynamicData(void) { // It's too bad that emulate EEPROM.read()/write() can only deal with bytes. @@ -649,28 +914,50 @@ class WiFiManager_NINA_Lite int checkSum = 0; int readCheckSum; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); - + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + + #define BUFFER_LEN 128 + char readBuffer[BUFFER_LEN + 1]; + // Find the longest pdata, then dynamically allocate buffer. Remember to free when done // This is used to store tempo data to calculate checksum to see of data is valid // We dont like to destroy myMenuItems[i].pdata with invalid data - - for (int i = 0; i < NUM_MENU_ITEMS; i++) - { - for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++, offset++) - { - checkSum += EEPROM.read(offset); - } - } - - uint8_t* _pointer = (uint8_t *) &readCheckSum; - for (int i = 0; i < sizeof(readCheckSum); i++, _pointer++, offset++) - { - *_pointer = EEPROM.read(offset); - } + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + if (myMenuItems[i].maxlen > BUFFER_LEN) + { + // Size too large, abort and flag false + WN_LOGERROR(F("ChkCrR: Error Small Buffer.")); + return false; + } + } + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + char* _pointer = readBuffer; + + // Prepare buffer, more than enough + memset(readBuffer, 0, sizeof(readBuffer)); + + // Read more than necessary, but OK and easier to code + EEPROM.get(offset, readBuffer); + // NULL terminated + readBuffer[myMenuItems[i].maxlen] = 0; + + WN_LOGDEBUG3(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen); + + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) + { + checkSum += *_pointer; + } + + offset += myMenuItems[i].maxlen; + } + + EEPROM.get(offset, readCheckSum); - DEBUG_WM4(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + WN_LOGERROR3(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { @@ -680,26 +967,22 @@ class WiFiManager_NINA_Lite return true; } - bool EEPROM_get() - { - // It's too bad that emulate EEPROM.read()/write() can only deal with bytes. - // Have to read/write each byte. To rewrite the library - - uint16_t offset = NINA_EEPROM_START; - - uint8_t* _pointer = (uint8_t *) &WiFiNINA_config; - - for (int i = 0; i < sizeof(WiFiNINA_config); i++, _pointer++, offset++) - { - *_pointer = EEPROM.read(offset); - } - + ////////////////////////////////////////////// + + bool EEPROM_getDynamicData() + { int checkSum = 0; int readCheckSum; - totalDataSize = sizeof(WiFiNINA_config) + sizeof(readCheckSum); + totalDataSize = sizeof(WIFININA_config) + sizeof(readCheckSum); + + // Using FORCED_CONFIG_PORTAL_FLAG_DATA + //offset += FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + + uint8_t* _pointer; - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { _pointer = (uint8_t *) myMenuItems[i].pdata; totalDataSize += myMenuItems[i].maxlen; @@ -711,88 +994,132 @@ class WiFiManager_NINA_Lite { *_pointer = EEPROM.read(offset); checkSum += *_pointer; - } - } - - _pointer = (uint8_t *) &readCheckSum; - - for (int i = 0; i < sizeof(readCheckSum); i++, _pointer++, offset++) - { - *_pointer = EEPROM.read(offset); + } } + + EEPROM.get(offset, readCheckSum); - DEBUG_WM4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + WN_LOGERROR3(F("CrCCSum="), String(checkSum, HEX), F(",CrRCSum="), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { return false; } - + return true; - } + } - void EEPROM_put() + ////////////////////////////////////////////// + + void EEPROM_putDynamicData() { // It's too bad that emulate EEPROM.read()/writ() can only deal with bytes. - // Have to read/write each byte. To rewrite the library - - uint16_t offset = NINA_EEPROM_START; - - uint8_t* _pointer = (uint8_t *) &WiFiNINA_config; - - for (int i = 0; i < sizeof(WiFiNINA_config); i++, _pointer++, offset++) - { - EEPROM.write(offset, *_pointer); - } - + // Have to read/write each byte. To rewrite the library int checkSum = 0; + + // Using FORCED_CONFIG_PORTAL_FLAG_DATA + //offset += FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + uint8_t* _pointer; - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { _pointer = (uint8_t *) myMenuItems[i].pdata; - - //DEBUG_WM4(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + + WN_LOGDEBUG3(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++,offset++) { EEPROM.write(offset, *_pointer); checkSum += *_pointer; - } + } } + + EEPROM.put(offset, checkSum); + + WN_LOGERROR1(F("CrCCSum=0x"), String(checkSum, HEX)); + + EEPROM.commit(); + } + +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define SERVER_MAX_LEN 32 + //#define TOKEN_MAX_LEN 36 - _pointer = (uint8_t *) &checkSum; + // NULL Terminating to be sure + WIFININA_config.header[HEADER_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.board_name[BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// + + bool EEPROM_get() + { + EEPROM.get(CONFIG_EEPROM_START, WIFININA_config); - for (int i = 0; i < sizeof(checkSum); i++, _pointer++, offset++) - { - EEPROM.write(offset, *_pointer); - } + NULLTerminateConfig(); - EEPROM.commit(); + return true; + } + + ////////////////////////////////////////////// + + void EEPROM_put() + { + EEPROM.put(CONFIG_EEPROM_START, WIFININA_config); + EEPROM.commit(); + } + + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + WIFININA_config.checkSum = calChecksum; - DEBUG_WM2(F("CrCCSum=0x"), String(checkSum, HEX)); + WN_LOGERROR5(F("SaveEEPROM,Sz="), EEPROM.length(), F(",DataSz="), totalDataSize, F(",WCSum=0x"), String(calChecksum, HEX)); + + EEPROM_put(); + +#if USE_DYNAMIC_PARAMETERS + EEPROM_putDynamicData(); +#endif } - // New from v1.0.5 - void loadAndSaveDefaultConfigData(void) + ////////////////////////////////////////////// + + void loadAndSaveDefaultConfigData() { // Load Default Config Data from Sketch - memcpy(&WiFiNINA_config, &defaultConfig, sizeof(WiFiNINA_config)); - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); // Including config and dynamic data, and assume valid saveConfigData(); - DEBUG_WM1(F("======= Start Loaded Config Data =======")); - displayConfigData(WiFiNINA_config); + WN_LOGERROR(F("======= Start Loaded Config Data =======")); + displayConfigData(WIFININA_config); } + ////////////////////////////////////////////// + bool getConfigData() { - bool dynamicDataValid; - int calChecksum; + bool dynamicDataValid = true; + int calChecksum; - hadConfigData = false; + hadConfigData = false; // Use new LOAD_DEFAULT_CONFIG_DATA logic if (LOAD_DEFAULT_CONFIG_DATA) @@ -805,118 +1132,128 @@ class WiFiManager_NINA_Lite } else { - // Load stored config / dynamic data from dueFlashStorage - // Verify ChkSum - dynamicDataValid = checkDynamicData(); + // Get config data + EEPROM_get(); + // Verify ChkSum calChecksum = calcChecksum(); - DEBUG_WM4(F("CCSum=0x"), String(calChecksum, HEX), F(",RCSum=0x"), String(WiFiNINA_config.checkSum, HEX)); - - if (dynamicDataValid) - { - // CkSum verified, Now get valid config/ dynamic data - EEPROM_get(); - - DEBUG_WM1(F("Valid Stored Dynamic Data")); - DEBUG_WM1(F("======= Start Stored Config Data =======")); - displayConfigData(WiFiNINA_config); - - // Don't need Config Portal anymore - return true; + WN_LOGERROR3(F("CCSum=0x"), String(calChecksum, HEX), + F(",RCSum=0x"), String(WIFININA_config.checkSum, HEX)); + +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from EEPROM + dynamicDataValid = checkDynamicData(); +#endif + + // If checksum = 0 => FlashStorage has been cleared (by uploading new FW, etc) => force to CP + if ( (calChecksum != 0) && (calChecksum == WIFININA_config.checkSum) ) + { + if (dynamicDataValid) + { +#if USE_DYNAMIC_PARAMETERS + // CkSum verified, Now get valid config/ dynamic data + EEPROM_getDynamicData(); + + WN_LOGERROR(F("Valid Stored Dynamic Data")); +#endif + WN_LOGERROR(F("======= Start Stored Config Data =======")); + displayConfigData(WIFININA_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + WN_LOGERROR(F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } } - else - { - // Invalid Stored config data => Config Portal - DEBUG_WM1(F("Invalid Stored Dynamic Data. Load default from Sketch")); - - // Load Default Config Data from Sketch, better than just "blank" - loadAndSaveDefaultConfigData(); - - // Need Config Portal here as data can be just dummy - // Even if you don't open CP, you're OK on next boot if your default config data is valid - return false; - } } - if ( (strncmp(WiFiNINA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || - (calChecksum != WiFiNINA_config.checkSum) || !dynamicDataValid ) + if ( (strncmp(WIFININA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || + (calChecksum != WIFININA_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (WIFININA_config.checkSum == 0) ) ) { // Including Credentials CSum - DEBUG_WM2(F("InitCfgFile,sz="), sizeof(WiFiNINA_config)); + WN_LOGERROR1(F("InitCfgFile,sz="), sizeof(WIFININA_config)); // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) { - memcpy(&WiFiNINA_config, &defaultConfig, sizeof(WiFiNINA_config)); + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); } else { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } +#endif - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); - strcpy(WiFiNINA_config.board_name, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.board_name, WM_NO_CONFIG); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } +#endif } - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - DEBUG_WM4(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); + WN_LOGDEBUG3(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); } +#endif // Don't need - WiFiNINA_config.checkSum = 0; + WIFININA_config.checkSum = 0; saveConfigData(); return false; } - else if ( !strncmp(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strlen(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) || - !strlen(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) || - !strlen(WiFiNINA_config.WiFi_Creds[0].wifi_pw) || - !strlen(WiFiNINA_config.WiFi_Creds[1].wifi_pw) ) + else if ( !strncmp(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_pw) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_pw) ) { // If SSID, PW ="nothing", stay in config mode forever until having config Data. return false; } else { - displayConfigData(WiFiNINA_config); + displayConfigData(WIFININA_config); } return true; } - void saveConfigData() - { - int calChecksum = calcChecksum(); - WiFiNINA_config.checkSum = calChecksum; - - DEBUG_WM6(F("SaveEEPROM,sz="), EEPROM.length(), F(",Datasz="), totalDataSize, F(",CSum=0x"), String(calChecksum, HEX)); - - EEPROM_put(); - } + ////////////////////////////////////////////// - // New connection logic from v1.0.5 bool connectMultiWiFi(int retry_time) { int sleep_time = 250; @@ -925,35 +1262,35 @@ class WiFiManager_NINA_Lite static int lastConnectedIndex = 255; - DEBUG_WM1(F("ConMultiWifi")); + WN_LOGDEBUG(F("ConMultiWifi")); if (static_IP != IPAddress(0, 0, 0, 0)) { - DEBUG_WM1(F("UseStatIP")); + WN_LOGDEBUG(F("UseStatIP")); WiFi.config(static_IP); } if (lastConnectedIndex != 255) { index = (lastConnectedIndex + 1) % NUM_WIFI_CREDENTIALS; - DEBUG_WM4(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); + WN_LOGDEBUG3(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); } - DEBUG_WM4(F("con2WF:SSID="), WiFiNINA_config.WiFi_Creds[index].wifi_ssid, - F(",PW="), WiFiNINA_config.WiFi_Creds[index].wifi_pw); + WN_LOGERROR3(F("con2WF:SSID="), WIFININA_config.WiFi_Creds[index].wifi_ssid, + F(",PW="), WIFININA_config.WiFi_Creds[index].wifi_pw); while ( !wifi_connected && ( 0 < retry_time ) ) { - DEBUG_WM2(F("Remaining retry_time="), retry_time); + WN_LOGDEBUG1(F("Remaining retry_time="), retry_time); - status = WiFi.begin(WiFiNINA_config.WiFi_Creds[index].wifi_ssid, WiFiNINA_config.WiFi_Creds[index].wifi_pw); + status = WiFi.begin(WIFININA_config.WiFi_Creds[index].wifi_ssid, WIFININA_config.WiFi_Creds[index].wifi_pw); // Need restart WiFi at beginning of each cycle if (status == WL_CONNECTED) { wifi_connected = true; lastConnectedIndex = index; - DEBUG_WM2(F("WOK, lastConnectedIndex="), lastConnectedIndex); + WN_LOGDEBUG1(F("WOK, lastConnectedIndex="), lastConnectedIndex); break; } @@ -966,17 +1303,17 @@ class WiFiManager_NINA_Lite if (retry_time <= 0) { - DEBUG_WM4(F("Failed using index="), index, F(", retry_time="), retry_time); + WN_LOGERROR3(F("Failed using index="), index, F(", retry_time="), retry_time); } if (wifi_connected) { - DEBUG_WM1(F("con2WF:OK")); + WN_LOGERROR(F("con2WF:OK")); displayWiFiData(); } else { - DEBUG_WM1(F("con2WF:failed")); + WN_LOGERROR(F("con2WF:failed")); // Can't connect, so try another index next time. Faking this index is OK and lost lastConnectedIndex = index; } @@ -984,14 +1321,33 @@ class WiFiManager_NINA_Lite return wifi_connected; } + ////////////////////////////////////////////// + // NEW void createHTML(String& root_html_template) { String pitem; - root_html_template = String(WIFININA_HTML_HEAD) + WIFININA_FLDSET_START; + root_html_template = WIFININA_HTML_HEAD_START; + + #if USING_CUSTOMS_STYLE + // Using Customs style when not NULL + if (WIFININA_HTML_HEAD_CUSTOMS_STYLE) + root_html_template += WIFININA_HTML_HEAD_CUSTOMS_STYLE; + else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #endif + + #if USING_CUSTOMS_HEAD_ELEMENT + if (_CustomsHeadElement) + root_html_template += _CustomsHeadElement; + #endif - for (int i = 0; i < NUM_MENU_ITEMS; i++) + root_html_template += String(WIFININA_HTML_HEAD_END) + WIFININA_FLDSET_START; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { pitem = String(WIFININA_HTML_PARAM); @@ -1004,7 +1360,7 @@ class WiFiManager_NINA_Lite root_html_template += String(WIFININA_FLDSET_END) + WIFININA_HTML_BUTTON + WIFININA_HTML_SCRIPT; - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { pitem = String(WIFININA_HTML_SCRIPT_ITEM); @@ -1017,11 +1373,33 @@ class WiFiManager_NINA_Lite return; } + + ////////////////////////////////////////////// + + void serverSendHeaders() + { + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CACHE_CONTROL:"), WM_HTTP_CACHE_CONTROL, "=", WM_HTTP_NO_STORE); + server->sendHeader(WM_HTTP_CACHE_CONTROL, WM_HTTP_NO_STORE); + +#if USING_CORS_FEATURE + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CORS:"), WM_HTTP_CORS, " : ", _CORS_Header); + server->sendHeader(WM_HTTP_CORS, _CORS_Header); +#endif + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_PRAGMA:"), WM_HTTP_PRAGMA, " : ", WM_HTTP_NO_CACHE); + server->sendHeader(WM_HTTP_PRAGMA, WM_HTTP_NO_CACHE); + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_EXPIRES:"), WM_HTTP_EXPIRES, " : ", "-1"); + server->sendHeader(WM_HTTP_EXPIRES, "-1"); + } + + ////////////////////////////////////////////// void handleRequest() { if (server) - { + { String key = server->arg("key"); String value = server->arg("value"); @@ -1029,6 +1407,10 @@ class WiFiManager_NINA_Lite if (key == "" && value == "") { + // New from v1.1.0 + serverSendHeaders(); + ////// + String result; createHTML(result); @@ -1040,24 +1422,30 @@ class WiFiManager_NINA_Lite // Replace only if Hostname is valid result.replace("SAMD_WM_NINA_Lite", RFC952_hostname); } - else if ( WiFiNINA_config.board_name[0] != 0 ) + else if ( WIFININA_config.board_name[0] != 0 ) { // Or replace only if board_name is valid. Otherwise, keep intact - result.replace("SAMD_WM_NINA_Lite", WiFiNINA_config.board_name); + result.replace("SAMD_WM_NINA_Lite", WIFININA_config.board_name); } - result.replace("[[id]]", WiFiNINA_config.WiFi_Creds[0].wifi_ssid); - result.replace("[[pw]]", WiFiNINA_config.WiFi_Creds[0].wifi_pw); - result.replace("[[id1]]", WiFiNINA_config.WiFi_Creds[1].wifi_ssid); - result.replace("[[pw1]]", WiFiNINA_config.WiFi_Creds[1].wifi_pw); - result.replace("[[nm]]", WiFiNINA_config.board_name); + result.replace("[[id]]", WIFININA_config.WiFi_Creds[0].wifi_ssid); + result.replace("[[pw]]", WIFININA_config.WiFi_Creds[0].wifi_pw); + result.replace("[[id1]]", WIFININA_config.WiFi_Creds[1].wifi_ssid); + result.replace("[[pw1]]", WIFININA_config.WiFi_Creds[1].wifi_pw); + result.replace("[[nm]]", WIFININA_config.board_name); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { String toChange = String("[[") + myMenuItems[i].id + "]]"; result.replace(toChange, myMenuItems[i].pdata); } +#endif + + WN_LOGDEBUG1(F("h:HTML page size:"), result.length()); + WN_LOGDEBUG1(F("h:HTML="), result); + server->send(200, "text/html", result); return; @@ -1065,78 +1453,142 @@ class WiFiManager_NINA_Lite if (number_items_Updated == 0) { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); } - if (key == "id") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + + WN_LOGDEBUG1(F("h: Init menuItemUpdated :" ), NUM_MENU_ITEMS); + } + else + { + WN_LOGERROR(F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool id_Updated = false; + static bool pw_Updated = false; + static bool id1_Updated = false; + static bool pw1_Updated = false; + static bool nm_Updated = false; + + if (!id_Updated && (key == String("id"))) + { + WN_LOGDEBUG(F("h:repl id")); + id_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) - 1); + strncpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1); } - else if (key == "pw") - { + else if (!pw_Updated && (key == String("pw"))) + { + WN_LOGDEBUG(F("h:repl pw")); + pw_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_pw) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_pw) - 1); + strncpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1); } - else if (key == "id1") - { + else if (!id1_Updated && (key == String("id1"))) + { + WN_LOGDEBUG(F("h:repl id1")); + id1_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) - 1); + strncpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1); } - else if (key == "pw1") - { + else if (!pw1_Updated && (key == String("pw1"))) + { + WN_LOGDEBUG(F("h:repl pw1")); + pw1_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_pw) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_pw) - 1); + strncpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { + WN_LOGDEBUG(F("h:repl nm")); + nm_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.board_name) - 1) - strcpy(WiFiNINA_config.board_name, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.board_name) - 1) + strcpy(WIFININA_config.board_name, value.c_str()); else - strncpy(WiFiNINA_config.board_name, value.c_str(), sizeof(WiFiNINA_config.board_name) - 1); + strncpy(WIFININA_config.board_name, value.c_str(), sizeof(WIFININA_config.board_name) - 1); } - - for (int i = 0; i < NUM_MENU_ITEMS; i++) + else { - if (key == myMenuItems[i].id) - { - DEBUG_WM4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); - number_items_Updated++; + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) + { + WN_LOGDEBUG3(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + + menuItemUpdated[i] = true; + + number_items_Updated++; - // Actual size of pdata is [maxlen + 1] - memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); - if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) - strcpy(myMenuItems[i].pdata, value.c_str()); - else - strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) + strcpy(myMenuItems[i].pdata, value.c_str()); + else + strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + + break; + } } +#endif } + + WN_LOGDEBUG1(F("h:items updated ="), number_items_Updated); + WN_LOGDEBUG3(F("h:key ="), key, ", value =", value); server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif { - DEBUG_WM1(F("h:UpdEEPROM")); + WN_LOGERROR(F("h:UpdEEPROM")); saveConfigData(); + + // Done with CP, Clear CP Flag here if forced + if (isForcedConfigPortal) + clearForcedCP(); - DEBUG_WM1(F("h:Rst")); + WN_LOGERROR(F("h:Rst")); // TO DO : what command to reset // Delay then reset the board after save data @@ -1145,11 +1597,16 @@ class WiFiManager_NINA_Lite } } // if (server) } + + ////////////////////////////////////////////// + +#ifndef CONFIG_TIMEOUT + #warning Default CONFIG_TIMEOUT = 60s + #define CONFIG_TIMEOUT 60000L +#endif void startConfigurationMode() { -#define CONFIG_TIMEOUT 60000L - WiFi.config(portal_apIP); if ( (portal_ssid == "") || portal_pass == "" ) @@ -1165,20 +1622,22 @@ class WiFiManager_NINA_Lite uint16_t channel; - // Use random channel if AP_channel == 0 - //srand(MAX_WIFI_CHANNEL); - srand((uint16_t) millis()); - + // Use random channel if AP_channel == 0 if (AP_channel == 0) - channel = (rand() % MAX_WIFI_CHANNEL) + 1; //random(MAX_WIFI_CHANNEL) + 1; + channel = (millis() % MAX_WIFI_CHANNEL) + 1; else channel = AP_channel; - INFO_WM4(F("SSID="), portal_ssid, F(",PW="), portal_pass); - INFO_WM4(F("IP="), portal_apIP, F(",CH="), channel); + WN_LOGERROR3(F("SSID="), portal_ssid, F(",PW="), portal_pass); + WN_LOGERROR3(F("IP="), portal_apIP, F(",CH="), channel); +#if USE_ESP_AT_SHIELD + // start access point, AP only,default channel 10 + WiFi.beginAP(portal_ssid.c_str(), channel, portal_pass.c_str(), ENC_TYPE_WPA2_PSK, true); +#else // start access point, AP only,default channel 10 WiFi.beginAP(portal_ssid.c_str(), portal_pass.c_str(), channel); +#endif if (!server) @@ -1190,16 +1649,24 @@ class WiFiManager_NINA_Lite if (server) { - server->on("/", [this](){ handleRequest(); }); + server->on("/", [this](){ handleRequest(); }); server->begin(); } // If there is no saved config Data, stay in config mode forever until having config Data. // or SSID, PW, Server,Token ="nothing" if (hadConfigData) + { configTimeout = millis() + CONFIG_TIMEOUT; + + WN_LOGDEBUG3(F("s:millis() = "), millis(), F(", configTimeout = "), configTimeout); + } else + { configTimeout = 0; + + WN_LOGDEBUG(F("s:configTimeout = 0")); + } configuration_mode = true; } diff --git a/src/WiFiManager_NINA_Lite_SAMD_CP.h b/src/WiFiManager_NINA_Lite_SAMD_CP.h new file mode 100644 index 00000000..fe27070e --- /dev/null +++ b/src/WiFiManager_NINA_Lite_SAMD_CP.h @@ -0,0 +1,1768 @@ +/**************************************************************************************************************************** + WiFiManager_NINA_Lite_SAMD.h + For SAMD boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.0.5 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + *****************************************************************************************************************************/ + +#ifndef WiFiManager_NINA_Lite_SAMD_h +#define WiFiManager_NINA_Lite_SAMD_h + +#if ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ + || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ + || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ + || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ + || defined(__SAMD51G19A__) || defined(__SAMD51P19A__) || defined(__SAMD21G18A__) ) + #if defined(WIFININA_USE_SAMD) + #undef WIFININA_USE_SAMD + #endif + #define WIFININA_USE_SAMD true +#else + #error This code is intended to run on the SAMD platform! Please check your Tools->Board setting. +#endif + +#define WIFIMANAGER_NINA_LITE_VERSION "WiFiManager_NINA_Lite v1.1.0" + +#include +// Include EEPROM-like API for FlashStorage +//#include //https://github.com/cmaglie/FlashStorage +#include //https://github.com/khoih-prog/FlashStorage_SAMD +#include + +///////// NEW for DRD ///////////// +// These defines must be put before #include +// to select where to store DoubleResetDetector_Generic's variable. +// Otherwise, library will use default EEPROM storage +#define DRD_FLAG_DATA_SIZE 4 + +#ifndef DRD_GENERIC_DEBUG +#define DRD_GENERIC_DEBUG false +#endif + +#include //https://github.com/khoih-prog/DoubleResetDetector_Generic + +// Number of seconds after reset during which a +// subseqent reset will be considered a double reset. +#define DRD_TIMEOUT 10 + +// RTC Memory Address for the DoubleResetDetector_Generic to use +#define DRD_ADDRESS 0 + +DoubleResetDetector_Generic* drd; + +///////// NEW for DRD ///////////// + +//NEW +#define MAX_ID_LEN 5 +#define MAX_DISPLAY_NAME_LEN 16 + +typedef struct +{ + char id [MAX_ID_LEN + 1]; + char displayName [MAX_DISPLAY_NAME_LEN + 1]; + char *pdata; + uint8_t maxlen; +} MenuItem; +// + +#if USE_DYNAMIC_PARAMETERS + #warning Using Dynamic Parameters + ///NEW + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#else + #warning Not using Dynamic Parameters +#endif + +#define SSID_MAX_LEN 32 +// WPA2 passwords can be up to 63 characters long. +#define PASS_MAX_LEN 64 + +typedef struct +{ + char wifi_ssid[SSID_MAX_LEN]; + char wifi_pw [PASS_MAX_LEN]; +} WiFi_Credentials; + +#define NUM_WIFI_CREDENTIALS 2 + +// Configurable items besides fixed Header +#define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) +//////////////// + +#define HEADER_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + +typedef struct Configuration +{ + char header [HEADER_MAX_LEN]; + WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + char board_name [BOARD_NAME_MAX_LEN]; + int checkSum; +} WiFiNINA_Configuration; + +// Currently CONFIG_DATA_SIZE = 236 = (16 + 96 * 2 + 4 + 24) +uint16_t CONFIG_DATA_SIZE = sizeof(WiFiNINA_Configuration); + +extern bool LOAD_DEFAULT_CONFIG_DATA; +extern WiFiNINA_Configuration defaultConfig; + +// -- HTML page fragments + +const char WIFININA_HTML_HEAD_START[] /*PROGMEM*/ = "SAMD_WM_NINA_Lite"; + +const char WIFININA_HTML_HEAD_STYLE[] /*PROGMEM*/ = ""; + +const char WIFININA_HTML_HEAD_END[] /*PROGMEM*/ = "
\ +
\ +
\ +
\ +
\ +
"; + +const char WIFININA_FLDSET_START[] /*PROGMEM*/ = "
"; +const char WIFININA_FLDSET_END[] /*PROGMEM*/ = "
"; +const char WIFININA_HTML_PARAM[] /*PROGMEM*/ = "
"; +const char WIFININA_HTML_BUTTON[] /*PROGMEM*/ = "
"; +const char WIFININA_HTML_SCRIPT[] /*PROGMEM*/ = ""; +const char WIFININA_HTML_END[] /*PROGMEM*/ = ""; + +////////////////////////////////////////// + +//KH Add repeatedly used const +//KH, from v1.1.0 +const char WM_HTTP_HEAD_CL[] PROGMEM = "Content-Length"; +const char WM_HTTP_HEAD_TEXT_HTML[] PROGMEM = "text/html"; +const char WM_HTTP_HEAD_TEXT_PLAIN[] PROGMEM = "text/plain"; + +const char WM_HTTP_CACHE_CONTROL[] PROGMEM = "Cache-Control"; +const char WM_HTTP_NO_STORE[] PROGMEM = "no-cache, no-store, must-revalidate"; +const char WM_HTTP_PRAGMA[] PROGMEM = "Pragma"; +const char WM_HTTP_NO_CACHE[] PROGMEM = "no-cache"; +const char WM_HTTP_EXPIRES[] PROGMEM = "Expires"; + +const char WM_HTTP_CORS[] PROGMEM = "Access-Control-Allow-Origin"; +const char WM_HTTP_CORS_ALLOW_ALL[] PROGMEM = "*"; + +////////////////////////////////////////// + + +String IPAddressToString(IPAddress _address) +{ + String str = String(_address[0]); + str += "."; + str += String(_address[1]); + str += "."; + str += String(_address[2]); + str += "."; + str += String(_address[3]); + return str; +} + +class WiFiManager_NINA_Lite +{ + public: + + WiFiManager_NINA_Lite() + { + // check for the presence of the shield +#if USE_WIFI101 + if (WiFi.status() == WL_NO_SHIELD) +#else + if (WiFi.status() == WL_NO_MODULE) +#endif + { + NN_LOGERROR(F("NoWiFi")); + } + } + + ~WiFiManager_NINA_Lite() + { + if (server) + delete server; + } + + bool connectWiFi(const char* ssid, const char* pass) + { + NN_LOGERROR1(F("Con2:"), ssid); + + setHostname(); + + if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) + { + displayWiFiData(); + } + else + { + NN_LOGERROR(F("NoW")); + return false; + } + + NN_LOGERROR(F("WOK")); + + wifi_connected = true; + + return true; + } + + void begin(const char* ssid, + const char* pass ) + { + NN_LOGERROR(F("conW")); + connectWiFi(ssid, pass); + } + + void begin(const char *iHostname = "") + { + #define RETRY_TIMES_CONNECT_WIFI 3 + + if (iHostname[0] == 0) + { + String randomNum = String(random(0xFFFFFF), HEX); + randomNum.toUpperCase(); + + String _hostname = "SAMD-WIFI_GENERIC-" + randomNum; + _hostname.toUpperCase(); + + getRFC952_hostname(_hostname.c_str()); + } + else + { + // Prepare and store the hostname only not NULL + getRFC952_hostname(iHostname); + } + + NN_LOGERROR1(F("Hostname="), RFC952_hostname); + ////// + + //// New DRD //// + drd = new DoubleResetDetector_Generic(DRD_TIMEOUT, DRD_ADDRESS); + bool noConfigPortal = true; + + if (drd->detectDoubleReset()) + { + NN_LOGERROR(F("Double Reset Detected")); + + noConfigPortal = false; + } + //// New DRD //// + + if (LOAD_DEFAULT_CONFIG_DATA) + { + NN_LOGERROR(F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } + + hadConfigData = getConfigData(); + + isForcedConfigPortal = isForcedCP(); + + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) + { + hadConfigData = true; + + if (connectMultiWiFi(RETRY_TIMES_CONNECT_WIFI)) + { + NN_LOGERROR(F("b:WOK")); + } + else + { + NN_LOGERROR(F("b:NoW")); + // failed to connect to WiFi, will start configuration mode + startConfigurationMode(); + } + } + else + { + NN_LOGERROR(isForcedConfigPortal? F("bg: isForcedConfigPortal = true") : F("bg: isForcedConfigPortal = false")); + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + NN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + } + else + { + NN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-non-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + clearForcedCP(); + } + + //To permit autoreset after timeout if DRD/MRD or non-persistent forced-CP + hadConfigData = isForcedConfigPortal ? true : (noConfigPortal ? false : true); + + // failed to connect to WiFi, will start configuration mode + startConfigurationMode(); + } + } + + +#ifndef RETRY_TIMES_RECONNECT_WIFI + #define RETRY_TIMES_RECONNECT_WIFI 2 +#else + // Force range of user-defined RETRY_TIMES_RECONNECT_WIFI between 2-5 times + #if (RETRY_TIMES_RECONNECT_WIFI < 2) + #warning RETRY_TIMES_RECONNECT_WIFI too low. Reseting to 2 + #undef RETRY_TIMES_RECONNECT_WIFI + #define RETRY_TIMES_RECONNECT_WIFI 2 + #elif (RETRY_TIMES_RECONNECT_WIFI > 5) + #warning RETRY_TIMES_RECONNECT_WIFI too high. Reseting to 5 + #undef RETRY_TIMES_RECONNECT_WIFI + #define RETRY_TIMES_RECONNECT_WIFI 5 + #endif +#endif + +#ifndef RESET_IF_CONFIG_TIMEOUT + #define RESET_IF_CONFIG_TIMEOUT true +#endif + +#ifndef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 +#else + // Force range of user-defined TIMES_BEFORE_RESET between 2-100 + #if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 + #elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 + #endif +#endif + + void run() + { + static int retryTimes = 0; + static bool wifiDisconnectedOnce = false; + + // Lost connection in running. Give chance to reconfig. + // Check WiFi status every 5s and update status + // Check twice to be sure wifi disconnected is real + static unsigned long checkstatus_timeout = 0; + #define WIFI_STATUS_CHECK_INTERVAL 5000L + + //// New DRD //// + // Call the double reset detector loop method every so often, + // so that it can recognise when the timeout expires. + // You can also call drd.stop() when you wish to no longer + // consider the next reset as a double reset. + drd->loop(); + //// New DRD //// + + if ( !configuration_mode && (millis() > checkstatus_timeout) ) + { + if (WiFi.status() == WL_CONNECTED) + { + wifi_connected = true; + } + else + { + if (wifiDisconnectedOnce) + { + wifiDisconnectedOnce = false; + wifi_connected = false; + NN_LOGERROR(F("r:Check&WLost")); + } + else + { + wifiDisconnectedOnce = true; + } + } + + checkstatus_timeout = millis() + WIFI_STATUS_CHECK_INTERVAL; + } + + // Lost connection in running. Give chance to reconfig. + if ( !wifi_connected ) + { + // If configTimeout but user hasn't connected to configWeb => try to reconnect WiFi + // But if user has connected to configWeb, stay there until done, then reset hardware + if ( configuration_mode && ( configTimeout == 0 || millis() < configTimeout ) ) + { + retryTimes = 0; + + if (server) + { + //NN_LOGDEBUG(F("r:handleClient")); + server->handleClient(); + } + + return; + } + else + { +#if RESET_IF_CONFIG_TIMEOUT + // If we're here but still in configuration_mode, permit running TIMES_BEFORE_RESET times before reset hardware + // to permit user another chance to config. + if ( configuration_mode && (configTimeout != 0) ) + { + if (++retryTimes <= CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET) + { + NN_LOGERROR1(F("r:WLost&TOut.ConW.Retry#"), retryTimes); + } + else + { + resetFunc(); //call reset + } + } +#endif + + // Not in config mode, try reconnecting before forcing to config mode + if ( !wifi_connected ) + { + NN_LOGERROR(F("r:WLost.ReconW")); + + if (connectMultiWiFi(RETRY_TIMES_RECONNECT_WIFI)) + { + NN_LOGERROR(F("r:WOK")); + } + } + } + } + else if (configuration_mode) + { + configuration_mode = false; + NN_LOGERROR(F("r:gotWBack")); + } + } + + ////////////////////////////////////////////// + + void setHostname() + { + if (RFC952_hostname[0] != 0) + { +#if USE_WIFI101 + WiFi.hostname(RFC952_hostname); +#elif USE_WIFI_NINA + WiFi.setHostname(RFC952_hostname); +#endif + } + } + + ////////////////////////////////////////////// + + void setConfigPortalIP(IPAddress portalIP = IPAddress(192, 168, 4, 1)) + { + portal_apIP = portalIP; + } + + ////////////////////////////////////////////// + + #define MIN_WIFI_CHANNEL 1 + #define MAX_WIFI_CHANNEL 11 // Channel 13 is flaky, because of bad number 13 ;-) + + int setConfigPortalChannel(int channel = 1) + { + // If channel < MIN_WIFI_CHANNEL - 1 or channel > MAX_WIFI_CHANNEL => channel = 1 + // If channel == 0 => will use random channel from MIN_WIFI_CHANNEL to MAX_WIFI_CHANNEL + // If (MIN_WIFI_CHANNEL <= channel <= MAX_WIFI_CHANNEL) => use it + if ( (channel < MIN_WIFI_CHANNEL - 1) || (channel > MAX_WIFI_CHANNEL) ) + AP_channel = 1; + else if ( (channel >= MIN_WIFI_CHANNEL - 1) && (channel <= MAX_WIFI_CHANNEL) ) + AP_channel = channel; + + return AP_channel; + } + + ////////////////////////////////////////////// + + void setConfigPortal(String ssid = "", String pass = "") + { + portal_ssid = ssid; + portal_pass = pass; + } + + ////////////////////////////////////////////// + + void setSTAStaticIPConfig(IPAddress ip) + { + static_IP = ip; + } + + ////////////////////////////////////////////// + + String getWiFiSSID(uint8_t index) + { + if (index >= NUM_WIFI_CREDENTIALS) + return String(""); + + if (!hadConfigData) + getConfigData(); + + return (String(WIFININA_config.WiFi_Creds[index].wifi_ssid)); + } + + ////////////////////////////////////////////// + + String getWiFiPW(uint8_t index) + { + if (index >= NUM_WIFI_CREDENTIALS) + return String(""); + + if (!hadConfigData) + getConfigData(); + + return (String(WIFININA_config.WiFi_Creds[index].wifi_pw)); + } + + ////////////////////////////////////////////// + + bool getWiFiStatus() + { + return wifi_connected; + } + + ////////////////////////////////////////////// + + WiFiNINA_Configuration* getFullConfigData(WiFiNINA_Configuration *configData) + { + if (!hadConfigData) + getConfigData(); + + // Check if NULL pointer + if (configData) + memcpy(configData, &WIFININA_config, sizeof(WiFiNINA_Configuration)); + + return (configData); + } + + ////////////////////////////////////////////// + + String localIP() + { + ipAddress = IPAddressToString(WiFi.localIP()); + + return ipAddress; + } + + ////////////////////////////////////////////// + + void clearConfigData() + { + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + } +#endif + + saveConfigData(); + } + + ////////////////////////////////////////////// + + bool isConfigDataValid() + { + return hadConfigData; + } + + ////////////////////////////////////////////// + + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// + + void resetFunc() + { + // Best one. Possibly don't need the WDT + NVIC_SystemReset(); + +#if ( defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) || defined(__SAMD51G19A__) ) + // For SAMD51 + // see Table 17-5 Timeout Period (valid values 0-11) + WDT->CONFIG.reg = 5; + WDT->CTRLA.reg = WDT_CTRLA_ENABLE; + // To check if OK or bit.ENABLE/CLEAR + while (WDT->SYNCBUSY.bit.WEN == 1); + + // use the WDT watchdog timer to force a system reset. + WDT->CLEAR.reg= 0x00; + // To check if OK or bit.ENABLE/CLEAR + while (WDT->SYNCBUSY.bit.WEN == 1); +#else + // For SAMD21, etc + // see Table 17-5 Timeout Period (valid values 0-11) + WDT->CONFIG.reg = 5; + WDT->CTRL.reg = WDT_CTRL_ENABLE; + while (WDT->STATUS.bit.SYNCBUSY == 1); + + // use the WDT watchdog timer to force a system reset. + WDT->CLEAR.reg= 0x00; + while (WDT->STATUS.bit.SYNCBUSY == 1); +#endif + } + + ////////////////////////////////////// + + // Add customs headers from v1.1.0 + + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + +#if USING_CUSTOMS_STYLE + //sets a custom style, such as color + // ""; + void setCustomsStyle(const char* CustomsStyle = WIFININA_HTML_HEAD_STYLE) + { + WIFININA_HTML_HEAD_CUSTOMS_STYLE = CustomsStyle; + NN_LOGDEBUG1(F("Set CustomsStyle to : "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + } + + const char* getCustomsStyle() + { + NN_LOGDEBUG1(F("Get CustomsStyle = "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + return WIFININA_HTML_HEAD_CUSTOMS_STYLE; + } +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + //sets a custom element to add to head, like a new style tag + void setCustomsHeadElement(const char* CustomsHeadElement = NULL) + { + _CustomsHeadElement = CustomsHeadElement; + NN_LOGDEBUG1(F("Set CustomsHeadElement to : "), _CustomsHeadElement); + } + + const char* getCustomsHeadElement() + { + NN_LOGDEBUG1(F("Get CustomsHeadElement = "), _CustomsHeadElement); + return _CustomsHeadElement; + } +#endif + +#if USING_CORS_FEATURE + void setCORSHeader(const char* CORSHeaders = NULL) + { + _CORS_Header = CORSHeaders; + + NN_LOGDEBUG1(F("Set CORS Header to : "), _CORS_Header); + } + + const char* getCORSHeader() + { + NN_LOGDEBUG1(F("Get CORS Header = "), _CORS_Header); + return _CORS_Header; + } +#endif + + ////////////////////////////////////// + + + private: + String ipAddress = "0.0.0.0"; + + WiFiWebServer* server = NULL; + + bool configuration_mode = false; + + unsigned long configTimeout; + bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; + + WiFiNINA_Configuration WIFININA_config; + + uint16_t totalDataSize = 0; + + String macAddress = ""; + bool wifi_connected = false; + + IPAddress portal_apIP = IPAddress(192, 168, 4, 1); + int AP_channel = 10; + + String portal_ssid = ""; + String portal_pass = ""; + + IPAddress static_IP = IPAddress(0, 0, 0, 0); + +///////////////////////////////////// + + // Add customs headers from v1.1.0 + +#if USING_CUSTOMS_STYLE + const char* WIFININA_HTML_HEAD_CUSTOMS_STYLE = NULL; +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + const char* _CustomsHeadElement = NULL; +#endif + +#if USING_CORS_FEATURE + const char* _CORS_Header = WM_HTTP_CORS_ALLOW_ALL; //"*"; +#endif + + ////////////////////////////////////// + +#define RFC952_HOSTNAME_MAXLEN 24 + char RFC952_hostname[RFC952_HOSTNAME_MAXLEN + 1]; + + char* getRFC952_hostname(const char* iHostname) + { + memset(RFC952_hostname, 0, sizeof(RFC952_hostname)); + + size_t len = ( RFC952_HOSTNAME_MAXLEN < strlen(iHostname) ) ? RFC952_HOSTNAME_MAXLEN : strlen(iHostname); + + size_t j = 0; + + for (size_t i = 0; i < len - 1; i++) + { + if ( isalnum(iHostname[i]) || iHostname[i] == '-' ) + { + RFC952_hostname[j] = iHostname[i]; + j++; + } + } + // no '-' as last char + if ( isalnum(iHostname[len - 1]) || (iHostname[len - 1] != '-') ) + RFC952_hostname[j] = iHostname[len - 1]; + + return RFC952_hostname; + } + + void displayConfigData(WiFiNINA_Configuration configData) + { + NN_LOGERROR5(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, + F(",PW="), configData.WiFi_Creds[0].wifi_pw); + NN_LOGERROR3(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); + NN_LOGERROR1(F("BName="), configData.board_name); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + NN_LOGERROR5("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); + } +#endif + } + + void displayWiFiData() + { + NN_LOGERROR3(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); + NN_LOGERROR1(F("IP="), localIP() ); + } + +#define WIFININA_BOARD_TYPE "WIFININA" +#define WM_NO_CONFIG "blank" + +// DRD_FLAG_DATA_SIZE is 4, to store DRD flag, defined in DRD +#if (EEPROM_SIZE < DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) +#error EEPROM_SIZE must be > CONFIG_DATA_SIZE. +#endif + +#ifndef EEPROM_START + #define EEPROM_START 0 + #warning EEPROM_START not defined. Set to 0 +#else + #if (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE > EEPROM_SIZE) + #error EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE > EEPROM_SIZE. Please adjust. + #endif +#endif + +// Stating positon to store Blynk8266_WM_config +#define CONFIG_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) + + int calcChecksum() + { + int checkSum = 0; + for (uint16_t index = 0; index < (sizeof(WIFININA_config) - sizeof(WIFININA_config.checkSum)); index++) + { + checkSum += * ( ( (byte*) &WIFININA_config ) + index); + } + + return checkSum; + } + + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + + NN_LOGERROR(isPersistent ? F("setForcedCP Persistent") : F("setForcedCP non-Persistent")); + + uint16_t offset = CONFIG_EEPROM_START + CONFIG_DATA_SIZE; + + uint8_t* _pointer = (uint8_t *) &readForcedConfigPortalFlag; + + for (uint16_t i = 0; i < sizeof(readForcedConfigPortalFlag); i++, _pointer++, offset++) + { + EEPROM.write(offset, *_pointer); + } + + EEPROM.commit(); + } + + void clearForcedCP() + { + uint32_t readForcedConfigPortalFlag = 0; + + uint16_t offset = CONFIG_EEPROM_START + CONFIG_DATA_SIZE; + + uint8_t* _pointer = (uint8_t *) &readForcedConfigPortalFlag; + + for (uint16_t i = 0; i < sizeof(readForcedConfigPortalFlag); i++, _pointer++, offset++) + { + EEPROM.write(offset, *_pointer); + } + + EEPROM.commit(); + } + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + uint16_t offset = CONFIG_EEPROM_START + CONFIG_DATA_SIZE; + + uint8_t* _pointer = (uint8_t *) &readForcedConfigPortalFlag; + + for (uint16_t i = 0; i < sizeof(readForcedConfigPortalFlag); i++, _pointer++, offset++) + { + *_pointer = EEPROM.read(offset); + } + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS + + bool checkDynamicData(void) + { + // It's too bad that emulate EEPROM.read()/write() can only deal with bytes. + // Have to read/write each byte. To rewrite the library + + int checkSum = 0; + int readCheckSum; + + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + + // Find the longest pdata, then dynamically allocate buffer. Remember to free when done + // This is used to store tempo data to calculate checksum to see of data is valid + // We dont like to destroy myMenuItems[i].pdata with invalid data + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++, offset++) + { + checkSum += EEPROM.read(offset); + } + } + + uint8_t* _pointer = (uint8_t *) &readCheckSum; + + for (uint16_t i = 0; i < sizeof(readCheckSum); i++, _pointer++, offset++) + { + *_pointer = EEPROM.read(offset); + } + + NN_LOGERROR3(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + + if ( checkSum != readCheckSum) + { + return false; + } + + return true; + } + + ////////////////////////////////////////////// + + bool EEPROM_getDynamicData() + { + int checkSum = 0; + int readCheckSum; + + totalDataSize = sizeof(WIFININA_config) + sizeof(readCheckSum); + + // Using FORCED_CONFIG_PORTAL_FLAG_DATA + //offset += FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + uint8_t* _pointer; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + _pointer = (uint8_t *) myMenuItems[i].pdata; + totalDataSize += myMenuItems[i].maxlen; + + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++, _pointer++, offset++) + { + *_pointer = EEPROM.read(offset); + checkSum += *_pointer; + } + } + + _pointer = (uint8_t *) &readCheckSum; + + for (uint16_t i = 0; i < sizeof(readCheckSum); i++, _pointer++, offset++) + { + *_pointer = EEPROM.read(offset); + } + + NN_LOGERROR3(F("CrCCSum="), String(checkSum, HEX), F(",CrRCSum="), String(readCheckSum, HEX)); + + if ( checkSum != readCheckSum) + { + return false; + } + + return true; + } + + ////////////////////////////////////////////// + + void EEPROM_putDynamicData() + { + // It's too bad that emulate EEPROM.read()/writ() can only deal with bytes. + // Have to read/write each byte. To rewrite the library + int checkSum = 0; + + // Using FORCED_CONFIG_PORTAL_FLAG_DATA + //offset += FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config) + FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE; + uint8_t* _pointer; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + _pointer = (uint8_t *) myMenuItems[i].pdata; + + NN_LOGDEBUG3(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++,offset++) + { + EEPROM.write(offset, *_pointer); + + checkSum += *_pointer; + } + } + + _pointer = (uint8_t *) &checkSum; + + for (uint16_t i = 0; i < sizeof(checkSum); i++, _pointer++, offset++) + { + EEPROM.write(offset, *_pointer); + } + + NN_LOGERROR1(F("CrCCSum=0x"), String(checkSum, HEX)); + + EEPROM.commit(); + } + +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define SERVER_MAX_LEN 32 + //#define TOKEN_MAX_LEN 36 + + // NULL Terminating to be sure + WIFININA_config.header[HEADER_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.board_name[BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// + + bool EEPROM_get() + { + // It's too bad that emulate EEPROM.read()/write() can only deal with bytes. + // Have to read/write each byte. To rewrite the library + + uint16_t offset = CONFIG_EEPROM_START; + + uint8_t* _pointer = (uint8_t *) &WIFININA_config; + + for (uint16_t i = 0; i < sizeof(WIFININA_config); i++, _pointer++, offset++) + { + *_pointer = EEPROM.read(offset); + } + + NULLTerminateConfig(); + + return true; + } + + ////////////////////////////////////////////// + + void EEPROM_put() + { + // It's too bad that emulate EEPROM.read()/writ() can only deal with bytes. + // Have to read/write each byte. To rewrite the library + + uint16_t offset = CONFIG_EEPROM_START; + + uint8_t* _pointer = (uint8_t *) &WIFININA_config; + + for (uint16_t i = 0; i < sizeof(WIFININA_config); i++, _pointer++, offset++) + { + EEPROM.write(offset, *_pointer); + } + + EEPROM.commit(); + } + + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + WIFININA_config.checkSum = calChecksum; + + NN_LOGERROR5(F("SaveEEPROM,Sz="), EEPROM.length(), F(",DataSz="), totalDataSize, F(",WCSum=0x"), String(calChecksum, HEX)); + + EEPROM_put(); + +#if USE_DYNAMIC_PARAMETERS + EEPROM_putDynamicData(); +#endif + } + + ////////////////////////////////////////////// + + void loadAndSaveDefaultConfigData() + { + // Load Default Config Data from Sketch + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); + + // Including config and dynamic data, and assume valid + saveConfigData(); + + NN_LOGERROR(F("======= Start Loaded Config Data =======")); + displayConfigData(WIFININA_config); + } + + ////////////////////////////////////////////// + + bool getConfigData() + { + bool dynamicDataValid = true; + int calChecksum; + + hadConfigData = false; + + // Use new LOAD_DEFAULT_CONFIG_DATA logic + if (LOAD_DEFAULT_CONFIG_DATA) + { + // Load Config Data from Sketch + loadAndSaveDefaultConfigData(); + + // Don't need Config Portal anymore + return true; + } + else + { + // Get config data + EEPROM_get(); + + // Verify ChkSum + calChecksum = calcChecksum(); + + NN_LOGERROR3(F("CCSum=0x"), String(calChecksum, HEX), + F(",RCSum=0x"), String(WIFININA_config.checkSum, HEX)); + +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from EEPROM + dynamicDataValid = checkDynamicData(); +#endif + + // If checksum = 0 => FlashStorage has been cleared (by uploading new FW, etc) => force to CP + if ( (calChecksum != 0) && (calChecksum == WIFININA_config.checkSum) ) + { + if (dynamicDataValid) + { +#if USE_DYNAMIC_PARAMETERS + // CkSum verified, Now get valid config/ dynamic data + EEPROM_getDynamicData(); + + NN_LOGERROR(F("Valid Stored Dynamic Data")); +#endif + NN_LOGERROR(F("======= Start Stored Config Data =======")); + displayConfigData(WIFININA_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + NN_LOGERROR(F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } + } + + if ( (strncmp(WIFININA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || + (calChecksum != WIFININA_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (WIFININA_config.checkSum == 0) ) ) + { + // Including Credentials CSum + NN_LOGERROR1(F("InitCfgFile,sz="), sizeof(WIFININA_config)); + + // doesn't have any configuration + if (LOAD_DEFAULT_CONFIG_DATA) + { + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); + } + else + { + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + } +#endif + + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.board_name, WM_NO_CONFIG); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); + } +#endif + } + + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + NN_LOGDEBUG3(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); + } +#endif + + // Don't need + WIFININA_config.checkSum = 0; + + saveConfigData(); + + return false; + } + else if ( !strncmp(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_pw) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_pw) ) + { + // If SSID, PW ="nothing", stay in config mode forever until having config Data. + return false; + } + else + { + displayConfigData(WIFININA_config); + } + + return true; + } + + ////////////////////////////////////////////// + + bool connectMultiWiFi(int retry_time) + { + int sleep_time = 250; + int index = 0; + uint8_t status; + + static int lastConnectedIndex = 255; + + NN_LOGDEBUG(F("ConMultiWifi")); + + if (static_IP != IPAddress(0, 0, 0, 0)) + { + NN_LOGDEBUG(F("UseStatIP")); + WiFi.config(static_IP); + } + + if (lastConnectedIndex != 255) + { + index = (lastConnectedIndex + 1) % NUM_WIFI_CREDENTIALS; + NN_LOGDEBUG3(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); + } + + NN_LOGERROR3(F("con2WF:SSID="), WIFININA_config.WiFi_Creds[index].wifi_ssid, + F(",PW="), WIFININA_config.WiFi_Creds[index].wifi_pw); + + while ( !wifi_connected && ( 0 < retry_time ) ) + { + NN_LOGDEBUG1(F("Remaining retry_time="), retry_time); + + status = WiFi.begin(WIFININA_config.WiFi_Creds[index].wifi_ssid, WIFININA_config.WiFi_Creds[index].wifi_pw); + + // Need restart WiFi at beginning of each cycle + if (status == WL_CONNECTED) + { + wifi_connected = true; + lastConnectedIndex = index; + NN_LOGDEBUG1(F("WOK, lastConnectedIndex="), lastConnectedIndex); + + break; + } + else + { + delay(sleep_time); + retry_time--; + } + } + + if (retry_time <= 0) + { + NN_LOGERROR3(F("Failed using index="), index, F(", retry_time="), retry_time); + } + + if (wifi_connected) + { + NN_LOGERROR(F("con2WF:OK")); + displayWiFiData(); + } + else + { + NN_LOGERROR(F("con2WF:failed")); + // Can't connect, so try another index next time. Faking this index is OK and lost + lastConnectedIndex = index; + } + + return wifi_connected; + } + + ////////////////////////////////////////////// + + /** Is this an IP? */ + bool isIp(String str) + { + for (unsigned int i = 0; i < str.length(); i++) + { + int c = str.charAt(i); + + if (c != '.' && (c < '0' || c > '9')) + { + return false; + } + } + + return true; + } + + ////////////////////////////////////////////// + + /** + HTTPD redirector (NOT WORKING YET) + Redirect to captive portal if we got a request for another domain. + Return true in that case so the page handler do not try to handle the request again. + */ + bool captivePortal() + { + NN_LOGERROR1(F("captivePortal: hostHeader = "), server->hostHeader()); + + //if (!isIp(server->hostHeader())) + { + NN_LOGERROR1(F("Request redirected to captive portal : "), (String) F("http://") + IPAddressToString(portal_apIP)); + + server->sendHeader(F("Location"), (String) F("http://") + IPAddressToString(portal_apIP), true); + server->send(302, WM_HTTP_HEAD_TEXT_PLAIN, ""); + server->client().stop(); + + return true; + } + + return false; + } + + ////////////////////////////////////////////// + + // NEW + void createHTML(String& root_html_template) + { + String pitem; + + root_html_template = WIFININA_HTML_HEAD_START; + + #if USING_CUSTOMS_STYLE + // Using Customs style when not NULL + if (WIFININA_HTML_HEAD_CUSTOMS_STYLE) + root_html_template += WIFININA_HTML_HEAD_CUSTOMS_STYLE; + else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #endif + + #if USING_CUSTOMS_HEAD_ELEMENT + if (_CustomsHeadElement) + root_html_template += _CustomsHeadElement; + #endif + + root_html_template += String(WIFININA_HTML_HEAD_END) + WIFININA_FLDSET_START; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + pitem = String(WIFININA_HTML_PARAM); + + pitem.replace("{b}", myMenuItems[i].displayName); + pitem.replace("{v}", myMenuItems[i].id); + pitem.replace("{i}", myMenuItems[i].id); + + root_html_template += pitem; + } + + root_html_template += String(WIFININA_FLDSET_END) + WIFININA_HTML_BUTTON + WIFININA_HTML_SCRIPT; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + pitem = String(WIFININA_HTML_SCRIPT_ITEM); + + pitem.replace("{d}", myMenuItems[i].id); + + root_html_template += pitem; + } + + root_html_template += String(WIFININA_HTML_SCRIPT_END) + WIFININA_HTML_END; + + return; + } + + ////////////////////////////////////////////// + + void serverSendHeaders() + { + NN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CACHE_CONTROL:"), WM_HTTP_CACHE_CONTROL, "=", WM_HTTP_NO_STORE); + server->sendHeader(WM_HTTP_CACHE_CONTROL, WM_HTTP_NO_STORE); + +#if USING_CORS_FEATURE + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + NN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CORS:"), WM_HTTP_CORS, " : ", _CORS_Header); + server->sendHeader(WM_HTTP_CORS, _CORS_Header); +#endif + + NN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_PRAGMA:"), WM_HTTP_PRAGMA, " : ", WM_HTTP_NO_CACHE); + server->sendHeader(WM_HTTP_PRAGMA, WM_HTTP_NO_CACHE); + + NN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_EXPIRES:"), WM_HTTP_EXPIRES, " : ", "-1"); + server->sendHeader(WM_HTTP_EXPIRES, "-1"); + } + + ////////////////////////////////////////////// + + void handleRequest() + { + if (server) + { + String key = server->arg("key"); + String value = server->arg("value"); + + static int number_items_Updated = 0; + + if (key == "" && value == "") + { + // New from v1.1.0 + serverSendHeaders(); + ////// + + String result; + createHTML(result); + + // Reset configTimeout to stay here until finished. + configTimeout = 0; + + if ( RFC952_hostname[0] != 0 ) + { + // Replace only if Hostname is valid + result.replace("SAMD_WM_NINA_Lite", RFC952_hostname); + } + else if ( WIFININA_config.board_name[0] != 0 ) + { + // Or replace only if board_name is valid. Otherwise, keep intact + result.replace("SAMD_WM_NINA_Lite", WIFININA_config.board_name); + } + + result.replace("[[id]]", WIFININA_config.WiFi_Creds[0].wifi_ssid); + result.replace("[[pw]]", WIFININA_config.WiFi_Creds[0].wifi_pw); + result.replace("[[id1]]", WIFININA_config.WiFi_Creds[1].wifi_ssid); + result.replace("[[pw1]]", WIFININA_config.WiFi_Creds[1].wifi_pw); + result.replace("[[nm]]", WIFININA_config.board_name); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + String toChange = String("[[") + myMenuItems[i].id + "]]"; + result.replace(toChange, myMenuItems[i].pdata); + } +#endif + + + NN_LOGDEBUG1(F("h:HTML page size:"), result.length()); + NN_LOGDEBUG1(F("h:HTML="), result); + + server->send(200, "text/html", result); + + return; + } + + if (number_items_Updated == 0) + { + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); + } + +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) + { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + + NN_LOGDEBUG1(F("h: Init menuItemUpdated :" ), NUM_MENU_ITEMS); + } + else + { + NN_LOGERROR(F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool id_Updated = false; + static bool pw_Updated = false; + static bool id1_Updated = false; + static bool pw1_Updated = false; + static bool nm_Updated = false; + + if (!id_Updated && (key == String("id"))) + { + NN_LOGDEBUG(F("h:repl id")); + id_Updated = true; + + number_items_Updated++; + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); + else + strncpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1); + } + else if (!pw_Updated && (key == String("pw"))) + { + NN_LOGDEBUG(F("h:repl pw")); + pw_Updated = true; + + number_items_Updated++; + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str()); + else + strncpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1); + } + else if (!id1_Updated && (key == String("id1"))) + { + NN_LOGDEBUG(F("h:repl id1")); + id1_Updated = true; + + number_items_Updated++; + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); + else + strncpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1); + } + else if (!pw1_Updated && (key == String("pw1"))) + { + NN_LOGDEBUG(F("h:repl pw1")); + pw1_Updated = true; + + number_items_Updated++; + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str()); + else + strncpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1); + } + else if (!nm_Updated && (key == String("nm"))) + { + NN_LOGDEBUG(F("h:repl nm")); + nm_Updated = true; + + number_items_Updated++; + if (strlen(value.c_str()) < sizeof(WIFININA_config.board_name) - 1) + strcpy(WIFININA_config.board_name, value.c_str()); + else + strncpy(WIFININA_config.board_name, value.c_str(), sizeof(WIFININA_config.board_name) - 1); + } + else + { + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) + { + NN_LOGDEBUG3(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + + menuItemUpdated[i] = true; + + number_items_Updated++; + + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + + if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) + strcpy(myMenuItems[i].pdata, value.c_str()); + else + strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + + break; + } + } +#endif + } + + NN_LOGDEBUG1(F("h:items updated ="), number_items_Updated); + NN_LOGDEBUG3(F("h:key ="), key, ", value =", value); + + server->send(200, "text/html", "OK"); + +#if USE_DYNAMIC_PARAMETERS + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif + { + NN_LOGERROR(F("h:UpdEEPROM")); + + saveConfigData(); + + // Done with CP, Clear CP Flag here if forced + if (isForcedConfigPortal) + clearForcedCP(); + + NN_LOGERROR(F("h:Rst")); + + // TO DO : what command to reset + // Delay then reset the board after save data + delay(1000); + resetFunc(); //call reset + } + } // if (server) + } + + ////////////////////////////////////////////// + + + void handleNotFound() + { + if (captivePortal()) + { + // If captive portal redirect instead of displaying the error page. + return; + } + + String message = "File Not Found\n\n"; + + message += "URI: "; + message += server->uri(); + message += "\nMethod: "; + message += (server->method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server->args(); + message += "\n"; + + for (uint8_t i = 0; i < server->args(); i++) + { + message += " " + server->argName(i) + ": " + server->arg(i) + "\n"; + } + + server->sendHeader(WM_HTTP_CACHE_CONTROL, WM_HTTP_NO_STORE); + server->sendHeader(WM_HTTP_PRAGMA, WM_HTTP_NO_CACHE); + server->sendHeader(WM_HTTP_EXPIRES, "-1"); + + server->send(404, WM_HTTP_HEAD_TEXT_PLAIN, message); + } + + ////////////////////////////////////////////// + +#ifndef CONFIG_TIMEOUT + #warning Default CONFIG_TIMEOUT = 60s + #define CONFIG_TIMEOUT 60000L +#endif + + void startConfigurationMode() + { + WiFi.config(portal_apIP); + + if ( (portal_ssid == "") || portal_pass == "" ) + { + String randomNum = String(random(0xFFFFFF), HEX); + randomNum.toUpperCase(); + + portal_ssid = "WIFININA_" + randomNum; + portal_pass = "MyWIFININA_" + randomNum; + } + + // start access point, AP only, channel 10 + + uint16_t channel; + + // Use random channel if AP_channel == 0 + if (AP_channel == 0) + channel = (millis() % MAX_WIFI_CHANNEL) + 1; + else + channel = AP_channel; + + NN_LOGERROR3(F("SSID="), portal_ssid, F(",PW="), portal_pass); + NN_LOGERROR3(F("IP="), portal_apIP, F(",CH="), channel); + +#if USE_ESP_AT_SHIELD + // start access point, AP only,default channel 10 + WiFi.beginAP(portal_ssid.c_str(), channel, portal_pass.c_str(), ENC_TYPE_WPA2_PSK, true); +#else + // start access point, AP only,default channel 10 + WiFi.beginAP(portal_ssid.c_str(), portal_pass.c_str(), channel); +#endif + + + if (!server) + { + server = new WiFiWebServer; + } + + //See https://stackoverflow.com/questions/39803135/c-unresolved-overloaded-function-type?rq=1 + + if (server) + { + server->on("/", [this](){ handleRequest(); }); + server->onNotFound([this](){ handleNotFound(); }); + + server->begin(); + } + + // If there is no saved config Data, stay in config mode forever until having config Data. + // or SSID, PW, Server,Token ="nothing" + if (hadConfigData) + { + configTimeout = millis() + CONFIG_TIMEOUT; + + NN_LOGDEBUG3(F("s:millis() = "), millis(), F(", configTimeout = "), configTimeout); + } + else + { + configTimeout = 0; + + NN_LOGDEBUG(F("s:configTimeout = 0")); + } + + configuration_mode = true; + } +}; + + +#endif //WiFiManager_NINA_Lite_SAMD_h diff --git a/src/WiFiManager_NINA_Lite_STM32.h b/src/WiFiManager_NINA_Lite_STM32.h index 321a3633..6064c0f8 100644 --- a/src/WiFiManager_NINA_Lite_STM32.h +++ b/src/WiFiManager_NINA_Lite_STM32.h @@ -1,44 +1,62 @@ -/**************************************************************************************************************************** - WiFiManager_NINA_Lite_STM32.h - For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + WiFiManager_NINA_Lite_STM32.h + For STM32 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ #ifndef WiFiManager_NINA_Lite_STM32_h #define WiFiManager_NINA_Lite_STM32_h -#if ( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) ) -#if defined(WIFININA_USE_STM32) -#undef WIFININA_USE_STM32 -#endif -#define WIFININA_USE_STM32 true +#if ( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \ + defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \ + defined(STM32WB) || defined(STM32MP1) ) + #if defined(WIFININA_USE_STM32) + #undef WIFININA_USE_STM32 + #endif + #define WIFININA_USE_STM32 true #endif #if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(CORE_TEENSY) || !(WIFININA_USE_STM32) ) -#error This code is intended to run on STM32 platform! Please check your Tools->Board setting. + #error This code is intended to run on STM32 platform! Please check your Tools->Board setting. #endif +#define WIFIMANAGER_NINA_LITE_VERSION "WiFiManager_NINA_Lite v1.1.0" + #include #include #include +#ifndef USING_CUSTOMS_STYLE + #define USING_CUSTOMS_STYLE false +#endif + +#ifndef USING_CUSTOMS_HEAD_ELEMENT + #define USING_CUSTOMS_HEAD_ELEMENT false +#endif + +#ifndef USING_CORS_FEATURE + #define USING_CORS_FEATURE false +#endif + ///////// NEW for DRD ///////////// // These defines must be put before #include // to select where to store DoubleResetDetector_Generic's variable. @@ -75,11 +93,15 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; - -// New in v1.0.3 +#if USE_DYNAMIC_PARAMETERS + #warning Using Dynamic Parameters + ///NEW + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#else + #warning Not using Dynamic Parameters +#endif #define SSID_MAX_LEN 32 //From v1.0.3, WPA2 passwords can be up to 63 characters long. @@ -97,11 +119,14 @@ typedef struct #define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) //////////////// +#define HEADER_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; - char board_name [24]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } WiFiNINA_Configuration; @@ -113,7 +138,12 @@ extern bool LOAD_DEFAULT_CONFIG_DATA; extern WiFiNINA_Configuration defaultConfig; // -- HTML page fragments -const char WIFININA_HTML_HEAD[] /*PROGMEM*/ = "STM32_WM_NINA_Lite
\ + +const char WIFININA_HTML_HEAD_START[] /*PROGMEM*/ = "STM32_WM_NINA_Lite"; + +const char WIFININA_HTML_HEAD_STYLE[] /*PROGMEM*/ = ""; + +const char WIFININA_HTML_HEAD_END[] /*PROGMEM*/ = "
\
\
\
\ @@ -134,7 +164,25 @@ udVal('nm',document.getElementById('nm').value);"; const char WIFININA_HTML_SCRIPT_ITEM[] /*PROGMEM*/ = "udVal('{d}',document.getElementById('{d}').value);"; const char WIFININA_HTML_SCRIPT_END[] /*PROGMEM*/ = "alert('Updated');}"; const char WIFININA_HTML_END[] /*PROGMEM*/ = ""; -/// + +////////////////////////////////////////// + +//KH Add repeatedly used const +//KH, from v1.1.0 +const char WM_HTTP_HEAD_CL[] PROGMEM = "Content-Length"; +const char WM_HTTP_HEAD_TEXT_HTML[] PROGMEM = "text/html"; +const char WM_HTTP_HEAD_TEXT_PLAIN[] PROGMEM = "text/plain"; + +const char WM_HTTP_CACHE_CONTROL[] PROGMEM = "Cache-Control"; +const char WM_HTTP_NO_STORE[] PROGMEM = "no-cache, no-store, must-revalidate"; +const char WM_HTTP_PRAGMA[] PROGMEM = "Pragma"; +const char WM_HTTP_NO_CACHE[] PROGMEM = "no-cache"; +const char WM_HTTP_EXPIRES[] PROGMEM = "Expires"; + +const char WM_HTTP_CORS[] PROGMEM = "Access-Control-Allow-Origin"; +const char WM_HTTP_CORS_ALLOW_ALL[] PROGMEM = "*"; + +////////////////////////////////////////// String IPAddressToString(IPAddress _address) { @@ -155,37 +203,39 @@ class WiFiManager_NINA_Lite WiFiManager_NINA_Lite() { // check for the presence of the shield - if (WiFi.status() == WL_NO_SHIELD) +#if USE_WIFI101 + if (WiFi.status() == WL_NO_SHIELD) +#else + if (WiFi.status() == WL_NO_MODULE) +#endif { - DEBUG_WM1(F("NoNINA")); - } + WN_LOGERROR(F("NoWiFi")); + } } ~WiFiManager_NINA_Lite() { if (server) - delete server; + delete server; } bool connectWiFi(const char* ssid, const char* pass) { - DEBUG_WM2(F("Con2:"), ssid); + WN_LOGERROR1(F("Con2:"), ssid); - // New in v1.0.3 setHostname(); - /// - if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) + if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) { displayWiFiData(); } else { - DEBUG_WM1(F("NoW")); + WN_LOGERROR(F("NoW")); return false; } - DEBUG_WM1(F("WOK")); + WN_LOGERROR(F("WOK")); wifi_connected = true; @@ -195,16 +245,14 @@ class WiFiManager_NINA_Lite void begin(const char* ssid, const char* pass ) { - DEBUG_WM1(F("conW")); + WN_LOGERROR(F("conW")); connectWiFi(ssid, pass); } - // New in v1.0.5 void begin(const char *iHostname = "") { #define RETRY_TIMES_CONNECT_WIFI 3 - // New in v1.0.3 if (iHostname[0] == 0) { String randomNum = String(random(0xFFFFFF), HEX); @@ -221,53 +269,72 @@ class WiFiManager_NINA_Lite getRFC952_hostname(iHostname); } - DEBUG_WM2(F("Hostname="), RFC952_hostname); + WN_LOGERROR1(F("Hostname="), RFC952_hostname); ////// //// New DRD //// drd = new DoubleResetDetector_Generic(DRD_TIMEOUT, DRD_ADDRESS); - bool useConfigPortal = false; + bool noConfigPortal = true; if (drd->detectDoubleReset()) { - DEBUG_WM1(F("Double Reset Detected")); + WN_LOGERROR(F("Double Reset Detected")); - useConfigPortal = true; + noConfigPortal = false; } //// New DRD //// - DEBUG_WM1(F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + + if (LOAD_DEFAULT_CONFIG_DATA) + { + WN_LOGERROR(F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } hadConfigData = getConfigData(); + + isForcedConfigPortal = isForcedCP(); - //// New DRD //// - // useConfigPortal when getConfigData() not OK or DRD'ed - if (hadConfigData && !useConfigPortal) - //// New DRD //// + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { - //hadConfigData = true; + hadConfigData = true; if (connectMultiWiFi(RETRY_TIMES_CONNECT_WIFI)) { - DEBUG_WM1(F("b:WOK")); + WN_LOGERROR(F("b:WOK")); } else { - DEBUG_WM1(F("b:NoW")); + WN_LOGERROR(F("b:NoW")); // failed to connect to WiFi, will start configuration mode startConfigurationMode(); } } else - { - INFO_WM2(F("b:StayInCfgPortal:"), useConfigPortal ? F("DRD") : F("NoCfgDat")); + { + WN_LOGERROR(isForcedConfigPortal? F("bg: isForcedConfigPortal = true") : F("bg: isForcedConfigPortal = false")); + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + } + else + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-non-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + clearForcedCP(); + } + + //To permit autoreset after timeout if DRD/MRD or non-persistent forced-CP + hadConfigData = isForcedConfigPortal ? true : (noConfigPortal ? false : true); // failed to connect to WiFi, will start configuration mode - hadConfigData = false; startConfigurationMode(); } } + #ifndef RETRY_TIMES_RECONNECT_WIFI #define RETRY_TIMES_RECONNECT_WIFI 2 #else @@ -284,22 +351,22 @@ class WiFiManager_NINA_Lite #endif #ifndef RESET_IF_CONFIG_TIMEOUT -#define RESET_IF_CONFIG_TIMEOUT true + #define RESET_IF_CONFIG_TIMEOUT true #endif #ifndef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 #else - // Force range of user-defined TIMES_BEFORE_RESET between 2-100 -#if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) -#warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 -#undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 -#elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) -#warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 -#undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 -#endif + // Force range of user-defined TIMES_BEFORE_RESET between 2-100 + #if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 + #elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 + #endif #endif void run() @@ -333,7 +400,7 @@ class WiFiManager_NINA_Lite { wifiDisconnectedOnce = false; wifi_connected = false; - DEBUG_WM1(F("r:Check&WLost")); + WN_LOGERROR(F("r:Check&WLost")); } else { @@ -355,7 +422,7 @@ class WiFiManager_NINA_Lite if (server) { - //DEBUG_WM1(F("r:handleClient")); + //WN_LOGDEBUG(F("r:handleClient")); server->handleClient(); } @@ -370,7 +437,7 @@ class WiFiManager_NINA_Lite { if (++retryTimes <= CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET) { - DEBUG_WM2(F("r:WLost&TOut.ConW.Retry#"), retryTimes); + WN_LOGERROR1(F("r:WLost&TOut.ConW.Retry#"), retryTimes); } else { @@ -382,11 +449,11 @@ class WiFiManager_NINA_Lite // Not in config mode, try reconnecting before forcing to config mode if ( !wifi_connected ) { - DEBUG_WM1(F("r:WLost.ReconW")); + WN_LOGERROR(F("r:WLost.ReconW")); if (connectMultiWiFi(RETRY_TIMES_RECONNECT_WIFI)) { - DEBUG_WM1(F("r:WOK")); + WN_LOGERROR(F("r:WOK")); } } } @@ -394,25 +461,35 @@ class WiFiManager_NINA_Lite else if (configuration_mode) { configuration_mode = false; - DEBUG_WM1(F("r:gotWBack")); + WN_LOGERROR(F("r:gotWBack")); } } - void setHostname(void) + ////////////////////////////////////////////// + + void setHostname() { if (RFC952_hostname[0] != 0) { +#if USE_WIFI101 + WiFi.hostname(RFC952_hostname); +#elif USE_WIFI_NINA WiFi.setHostname(RFC952_hostname); +#endif } } + + ////////////////////////////////////////////// void setConfigPortalIP(IPAddress portalIP = IPAddress(192, 168, 4, 1)) { portal_apIP = portalIP; } + + ////////////////////////////////////////////// #define MIN_WIFI_CHANNEL 1 - #define MAX_WIFI_CHANNEL 12 // Channel 13 is flaky, because of bad number 13 ;-) + #define MAX_WIFI_CHANNEL 11 // Channel 13 is flaky, because of bad number 13 ;-) int setConfigPortalChannel(int channel = 1) { @@ -427,17 +504,23 @@ class WiFiManager_NINA_Lite return AP_channel; } + ////////////////////////////////////////////// + void setConfigPortal(String ssid = "", String pass = "") { portal_ssid = ssid; portal_pass = pass; } + + ////////////////////////////////////////////// void setSTAStaticIPConfig(IPAddress ip) { static_IP = ip; } + ////////////////////////////////////////////// + String getWiFiSSID(uint8_t index) { if (index >= NUM_WIFI_CREDENTIALS) @@ -446,8 +529,10 @@ class WiFiManager_NINA_Lite if (!hadConfigData) getConfigData(); - return (String(WiFiNINA_config.WiFi_Creds[index].wifi_ssid)); + return (String(WIFININA_config.WiFi_Creds[index].wifi_ssid)); } + + ////////////////////////////////////////////// String getWiFiPW(uint8_t index) { @@ -457,14 +542,18 @@ class WiFiManager_NINA_Lite if (!hadConfigData) getConfigData(); - return (String(WiFiNINA_config.WiFi_Creds[index].wifi_pw)); + return (String(WIFININA_config.WiFi_Creds[index].wifi_pw)); } + + ////////////////////////////////////////////// - bool getWiFiStatus(void) + bool getWiFiStatus() { return wifi_connected; } + ////////////////////////////////////////////// + WiFiNINA_Configuration* getFullConfigData(WiFiNINA_Configuration *configData) { if (!hadConfigData) @@ -472,41 +561,147 @@ class WiFiManager_NINA_Lite // Check if NULL pointer if (configData) - memcpy(configData, &WiFiNINA_config, sizeof(WiFiNINA_Configuration)); + memcpy(configData, &WIFININA_config, sizeof(WiFiNINA_Configuration)); return (configData); } + + ////////////////////////////////////////////// - String localIP(void) + String localIP() { ipAddress = IPAddressToString(WiFi.localIP()); return ipAddress; } + + ////////////////////////////////////////////// void clearConfigData() { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } +#endif saveConfigData(); } - bool isConfigDataValid(void) + ////////////////////////////////////////////// + + bool isConfigDataValid() { return hadConfigData; } + + ////////////////////////////////////////////// + + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// void resetFunc() { - void(*resetFunc)(void) = 0; + void(*resetFunc)() = 0; resetFunc(); } + + ////////////////////////////////////// + + // Add customs headers from v1.1.0 + + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + +#if USING_CUSTOMS_STYLE + //sets a custom style, such as color + // ""; + void setCustomsStyle(const char* CustomsStyle = WIFININA_HTML_HEAD_STYLE) + { + WIFININA_HTML_HEAD_CUSTOMS_STYLE = CustomsStyle; + WN_LOGDEBUG1(F("Set CustomsStyle to : "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + } + + const char* getCustomsStyle() + { + WN_LOGDEBUG1(F("Get CustomsStyle = "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + return WIFININA_HTML_HEAD_CUSTOMS_STYLE; + } +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + //sets a custom element to add to head, like a new style tag + void setCustomsHeadElement(const char* CustomsHeadElement = NULL) + { + _CustomsHeadElement = CustomsHeadElement; + WN_LOGDEBUG1(F("Set CustomsHeadElement to : "), _CustomsHeadElement); + } + + const char* getCustomsHeadElement() + { + WN_LOGDEBUG1(F("Get CustomsHeadElement = "), _CustomsHeadElement); + return _CustomsHeadElement; + } +#endif + +#if USING_CORS_FEATURE + void setCORSHeader(const char* CORSHeaders = NULL) + { + _CORS_Header = CORSHeaders; + + WN_LOGDEBUG1(F("Set CORS Header to : "), _CORS_Header); + } + + const char* getCORSHeader() + { + WN_LOGDEBUG1(F("Get CORS Header = "), _CORS_Header); + return _CORS_Header; + } +#endif + + ////////////////////////////////////// + private: String ipAddress = "0.0.0.0"; @@ -516,8 +711,11 @@ class WiFiManager_NINA_Lite unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; - WiFiNINA_Configuration WiFiNINA_config; + WiFiNINA_Configuration WIFININA_config; uint16_t totalDataSize = 0; @@ -531,6 +729,24 @@ class WiFiManager_NINA_Lite String portal_pass = ""; IPAddress static_IP = IPAddress(0, 0, 0, 0); + + ///////////////////////////////////// + + // Add customs headers from v1.1.0 + +#if USING_CUSTOMS_STYLE + const char* WIFININA_HTML_HEAD_CUSTOMS_STYLE = NULL; +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + const char* _CustomsHeadElement = NULL; +#endif + +#if USING_CORS_FEATURE + const char* _CORS_Header = WM_HTTP_CORS_ALLOW_ALL; //"*"; +#endif + + ////////////////////////////////////// #define RFC952_HOSTNAME_MAXLEN 24 char RFC952_hostname[RFC952_HOSTNAME_MAXLEN + 1]; @@ -560,65 +776,136 @@ class WiFiManager_NINA_Lite void displayConfigData(WiFiNINA_Configuration configData) { - DEBUG_WM6(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, - F(",PW="), configData.WiFi_Creds[0].wifi_pw); - DEBUG_WM4(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); - DEBUG_WM2(F("BName="), configData.board_name); + WN_LOGERROR5(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, + F(",PW="), configData.WiFi_Creds[0].wifi_pw); + WN_LOGERROR3(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); + WN_LOGERROR1(F("BName="), configData.board_name); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - DEBUG_WM6("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); - } + WN_LOGERROR5("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); + } +#endif } - void displayWiFiData(void) + void displayWiFiData() { - DEBUG_WM4(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); - DEBUG_WM2(F("IP="), localIP() ); + WN_LOGERROR3(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); + WN_LOGERROR1(F("IP="), localIP() ); } -#define WIFININA_BOARD_TYPE "WIFININA" -#define WM_NO_CONFIG "blank" +#define WIFININA_BOARD_TYPE "WIFININA" +#define WM_NO_CONFIG "blank" #ifndef EEPROM_SIZE -#define EEPROM_SIZE 4096 + #define EEPROM_SIZE 4096 #else -#if (EEPROM_SIZE > 4096) -#warning EEPROM_SIZE must be <= 4096. Reset to 4096 -#undef EEPROM_SIZE -#define EEPROM_SIZE 4096 -#endif -#if (EEPROM_SIZE < CONFIG_DATA_SIZE) -#warning EEPROM_SIZE must be > CONFIG_DATA_SIZE. Reset to 512 -#undef EEPROM_SIZE -#define EEPROM_SIZE 512 -#endif + #if (EEPROM_SIZE > 4096) + #warning EEPROM_SIZE must be <= 4096. Reset to 4096 + #undef EEPROM_SIZE + #define EEPROM_SIZE 4096 + #endif + #if (EEPROM_SIZE < CONFIG_DATA_SIZE) + #warning EEPROM_SIZE must be > CONFIG_DATA_SIZE. Reset to 512 + #undef EEPROM_SIZE + #define EEPROM_SIZE 512 + #endif #endif #ifndef EEPROM_START -#define EEPROM_START 0 //define 256 in DRD -#warning EEPROM_START not defined. Set to 0 + #define EEPROM_START 0 //define 256 in DRD + #warning EEPROM_START not defined. Set to 0 #else -#if (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE) -#error EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE. Please adjust. -#endif + #if (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE) + #error EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE. Please adjust. + #endif #endif // Stating positon to store Blynk8266_WM_config -#define NINA_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) +#define CONFIG_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) int calcChecksum() { int checkSum = 0; - for (uint16_t index = 0; index < (sizeof(WiFiNINA_config) - sizeof(WiFiNINA_config.checkSum)); index++) + for (uint16_t index = 0; index < (sizeof(WIFININA_config) - sizeof(WIFININA_config.checkSum)); index++) { - checkSum += * ( ( (byte*) &WiFiNINA_config ) + index); + checkSum += * ( ( (byte*) &WIFININA_config ) + index); } return checkSum; } + +////////////////////////////////////////////// + +#if defined(DATA_EEPROM_BASE) + // For STM32 devices having integrated EEPROM. + #include + #warning STM32 devices have integrated EEPROM. Not using buffered API. +#else + /** + Most STM32 devices don't have an integrated EEPROM. To emulate a EEPROM, the STM32 Arduino core emulated + the operation of an EEPROM with the help of the embedded flash. + Writing to a flash is very expensive operation, since a whole flash page needs to be written, even if you only + want to access the flash byte-wise. + The STM32 Arduino core provides a buffered access API to the emulated EEPROM. The library has allocated the + buffer even if you don't use the buffered API, so it's strongly suggested to use the buffered API anyhow. + */ + #include // https://github.com/khoih-prog/FlashStorage_STM32 + #warning STM32 devices have no integrated EEPROM. Using buffered API with FlashStorage_STM32 library +#endif // #if defined(DATA_EEPROM_BASE) + +////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + + WN_LOGERROR(isPersistent ? F("setForcedCP Persistent") : F("setForcedCP non-Persistent")); + + EEPROM.put(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + + void clearForcedCP() + { + EEPROM.put(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, 0); + } + + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + EEPROM.get(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS - bool checkDynamicData(void) + bool checkDynamicData() { int checkSum = 0; int readCheckSum; @@ -626,7 +913,7 @@ class WiFiManager_NINA_Lite #define BUFFER_LEN 128 char readBuffer[BUFFER_LEN + 1]; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config); // Find the longest pdata, then dynamically allocate buffer. Remember to free when done // This is used to store tempo data to calculate checksum to see of data is valid @@ -637,7 +924,7 @@ class WiFiManager_NINA_Lite if (myMenuItems[i].maxlen > BUFFER_LEN) { // Size too large, abort and flag false - DEBUG_WM1(F("ChkCrR: Error Small Buffer.")); + WN_LOGDEBUG(F("ChkCrR: Error Small Buffer.")); return false; } } @@ -654,7 +941,7 @@ class WiFiManager_NINA_Lite // NULL terminated readBuffer[myMenuItems[i].maxlen] = 0; - DEBUG_WM4(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen); + WN_LOGDEBUG3(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen); for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) { @@ -666,7 +953,7 @@ class WiFiManager_NINA_Lite EEPROM.get(offset, readCheckSum); - DEBUG_WM4(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + WN_LOGDEBUG3(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { @@ -676,13 +963,15 @@ class WiFiManager_NINA_Lite return true; } - bool EEPROM_getDynamicData(void) + ////////////////////////////////////////////// + + bool EEPROM_getDynamicData() { int readCheckSum; int checkSum = 0; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config); - totalDataSize = sizeof(WiFiNINA_config) + sizeof(readCheckSum); + totalDataSize = sizeof(WIFININA_config) + sizeof(readCheckSum); for (int i = 0; i < NUM_MENU_ITEMS; i++) { @@ -702,7 +991,7 @@ class WiFiManager_NINA_Lite EEPROM.get(offset, readCheckSum); - DEBUG_WM4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + WN_LOGDEBUG3(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { @@ -711,17 +1000,19 @@ class WiFiManager_NINA_Lite return true; } + + ////////////////////////////////////////////// - void EEPROM_putDynamicData(void) + void EEPROM_putDynamicData() { int checkSum = 0; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config); for (int i = 0; i < NUM_MENU_ITEMS; i++) { char* _pointer = myMenuItems[i].pdata; - //DEBUG_WM4(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + //WN_LOGDEBUG3(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++,offset++) { @@ -732,33 +1023,89 @@ class WiFiManager_NINA_Lite } EEPROM.put(offset, checkSum); - //EEPROM.commit(); - DEBUG_WM2(F("CrCCSum=0x"), String(checkSum, HEX)); + WN_LOGDEBUG1(F("CrCCSum=0x"), String(checkSum, HEX)); + } +#endif // #if USE_DYNAMIC_PARAMETERS + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define SERVER_MAX_LEN 32 + //#define TOKEN_MAX_LEN 36 + + // NULL Terminating to be sure + WIFININA_config.header[HEADER_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.board_name[BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// + + bool EEPROM_get() + { + EEPROM.get(CONFIG_EEPROM_START, WIFININA_config); + NULLTerminateConfig(); + + return true; + } + + ////////////////////////////////////////////// + + void EEPROM_put() + { + EEPROM.put(CONFIG_EEPROM_START, WIFININA_config); + } + + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + WIFININA_config.checkSum = calChecksum; + + WN_LOGERROR5(F("SaveEEPROM,Sz="), EEPROM.length(), F(",DataSz="), totalDataSize, F(",CSum=0x"), String(calChecksum, HEX)); + + EEPROM_put(); + +#if USE_DYNAMIC_PARAMETERS + EEPROM_putDynamicData(); +#endif } + ////////////////////////////////////////////// + // New from v1.0.5 - void loadAndSaveDefaultConfigData(void) + void loadAndSaveDefaultConfigData() { // Load Default Config Data from Sketch - memcpy(&WiFiNINA_config, &defaultConfig, sizeof(WiFiNINA_config)); - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); // Including config and dynamic data, and assume valid saveConfigData(); - DEBUG_WM1(F("======= Start Loaded Config Data =======")); - displayConfigData(WiFiNINA_config); + WN_LOGERROR(F("======= Start Loaded Config Data =======")); + displayConfigData(WIFININA_config); } + ////////////////////////////////////////////// + bool getConfigData() { - bool dynamicDataValid; + bool dynamicDataValid = true; int calChecksum; hadConfigData = false; - EEPROM.begin(); +#if defined(DATA_EEPROM_BASE) + EEPROM.begin(); +#endif // Use new LOAD_DEFAULT_CONFIG_DATA logic if (LOAD_DEFAULT_CONFIG_DATA) @@ -772,120 +1119,130 @@ class WiFiManager_NINA_Lite else { // Load stored config data from EEPROM - DEBUG_WM2(F("EEPROMsz:"), EEPROM_SIZE); - EEPROM.get(NINA_EEPROM_START, WiFiNINA_config); + WN_LOGERROR1(F("EEPROMsz:"), EEPROM_SIZE); + WN_LOGERROR1(F("EEPROM Length():"), EEPROM.length()); - // Load stored dynamic data from EEPROM - // Verify ChkSum - dynamicDataValid = checkDynamicData(); + EEPROM_get(); + // Verify ChkSum calChecksum = calcChecksum(); - DEBUG_WM4(F("CCSum=0x"), String(calChecksum, HEX), F(",RCSum=0x"), String(WiFiNINA_config.checkSum, HEX)); - - if (dynamicDataValid) - { - EEPROM_getDynamicData(); - - DEBUG_WM1(F("Valid Stored Dynamic Data")); - DEBUG_WM1(F("======= Start Stored Config Data =======")); - displayConfigData(WiFiNINA_config); - - // Don't need Config Portal anymore - return true; - } - else + WN_LOGERROR3(F("CCSum=0x"), String(calChecksum, HEX), + F(",RCSum=0x"), String(WIFININA_config.checkSum, HEX)); + +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from LittleFS + dynamicDataValid = checkDynamicData(); +#endif + + // If checksum = 0 => simulated EEPROM has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == WIFININA_config.checkSum) ) { - // Invalid Stored config data => Config Portal - DEBUG_WM1(F("Invalid Stored Dynamic Data. Load default from Sketch")); - - // Load Default Config Data from Sketch, better than just "blank" - loadAndSaveDefaultConfigData(); - - // Need Config Portal here as data can be just dummy - // Even if you don't open CP, you're OK on next boot if your default config data is valid - return false; - } + if (dynamicDataValid) + { + #if USE_DYNAMIC_PARAMETERS + EEPROM_getDynamicData(); + + WN_LOGERROR(F("Valid Stored Dynamic Data")); + #endif + + WN_LOGERROR(F("======= Start Stored Config Data =======")); + displayConfigData(WIFININA_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + WN_LOGERROR(F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } } - if ( (strncmp(WiFiNINA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || - (calChecksum != WiFiNINA_config.checkSum) || !dynamicDataValid ) + if ( (strncmp(WIFININA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || + (calChecksum != WIFININA_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (WIFININA_config.checkSum == 0) ) ) { // Including Credentials CSum - DEBUG_WM2(F("InitCfgFile,sz="), sizeof(WiFiNINA_config)); + WN_LOGERROR1(F("InitCfgFile,sz="), sizeof(WIFININA_config)); // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) { - memcpy(&WiFiNINA_config, &defaultConfig, sizeof(WiFiNINA_config)); + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); } else { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } +#endif - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); - strcpy(WiFiNINA_config.board_name, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.board_name, WM_NO_CONFIG); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } +#endif } - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - DEBUG_WM4(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); + WN_LOGDEBUG3(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); } +#endif // Don't need - WiFiNINA_config.checkSum = 0; + WIFININA_config.checkSum = 0; saveConfigData(); return false; } - else if ( !strncmp(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strlen(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) || - !strlen(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) || - !strlen(WiFiNINA_config.WiFi_Creds[0].wifi_pw) || - !strlen(WiFiNINA_config.WiFi_Creds[1].wifi_pw) ) + else if ( !strncmp(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_pw) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_pw) ) { // If SSID, PW ="nothing", stay in config mode forever until having config Data. return false; } else { - displayConfigData(WiFiNINA_config); + displayConfigData(WIFININA_config); } return true; } - - void saveConfigData() - { - int calChecksum = calcChecksum(); - WiFiNINA_config.checkSum = calChecksum; - - DEBUG_WM6(F("SaveEEPROM,Sz="), EEPROM.length(), F(",DataSz="), totalDataSize, F(",CSum=0x"), String(calChecksum, HEX)); - - //EEPROM_put(); - EEPROM.put(NINA_EEPROM_START, WiFiNINA_config); - EEPROM_putDynamicData(); - } + + ////////////////////////////////////////////// // New connection logic from v1.0.5 bool connectMultiWiFi(int retry_time) @@ -896,35 +1253,35 @@ class WiFiManager_NINA_Lite static int lastConnectedIndex = 255; - DEBUG_WM1(F("ConMultiWifi")); + WN_LOGDEBUG(F("ConMultiWifi")); if (static_IP != IPAddress(0, 0, 0, 0)) { - DEBUG_WM1(F("UseStatIP")); + WN_LOGDEBUG(F("UseStatIP")); WiFi.config(static_IP); } if (lastConnectedIndex != 255) { index = (lastConnectedIndex + 1) % NUM_WIFI_CREDENTIALS; - DEBUG_WM4(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); + WN_LOGDEBUG3(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); } - DEBUG_WM4(F("con2WF:SSID="), WiFiNINA_config.WiFi_Creds[index].wifi_ssid, - F(",PW="), WiFiNINA_config.WiFi_Creds[index].wifi_pw); + WN_LOGDEBUG3(F("con2WF:SSID="), WIFININA_config.WiFi_Creds[index].wifi_ssid, + F(",PW="), WIFININA_config.WiFi_Creds[index].wifi_pw); while ( !wifi_connected && ( 0 < retry_time ) ) { - DEBUG_WM2(F("Remaining retry_time="), retry_time); + WN_LOGDEBUG1(F("Remaining retry_time="), retry_time); - status = WiFi.begin(WiFiNINA_config.WiFi_Creds[index].wifi_ssid, WiFiNINA_config.WiFi_Creds[index].wifi_pw); + status = WiFi.begin(WIFININA_config.WiFi_Creds[index].wifi_ssid, WIFININA_config.WiFi_Creds[index].wifi_pw); // Need restart WiFi at beginning of each cycle if (status == WL_CONNECTED) { wifi_connected = true; lastConnectedIndex = index; - DEBUG_WM2(F("WOK, lastConnectedIndex="), lastConnectedIndex); + WN_LOGDEBUG1(F("WOK, lastConnectedIndex="), lastConnectedIndex); break; } @@ -937,32 +1294,51 @@ class WiFiManager_NINA_Lite if (retry_time <= 0) { - DEBUG_WM4(F("Failed using index="), index, F(", retry_time="), retry_time); + WN_LOGDEBUG3(F("Failed using index="), index, F(", retry_time="), retry_time); } if (wifi_connected) { - DEBUG_WM1(F("con2WF:OK")); + WN_LOGDEBUG(F("con2WF:OK")); displayWiFiData(); } else { - DEBUG_WM1(F("con2WF:failed")); + WN_LOGDEBUG(F("con2WF:failed")); // Can't connect, so try another index next time. Faking this index is OK and lost lastConnectedIndex = index; } return wifi_connected; } + + ////////////////////////////////////////////// // NEW void createHTML(String& root_html_template) { String pitem; - root_html_template = String(WIFININA_HTML_HEAD) + WIFININA_FLDSET_START; + root_html_template = WIFININA_HTML_HEAD_START; - for (int i = 0; i < NUM_MENU_ITEMS; i++) + #if USING_CUSTOMS_STYLE + // Using Customs style when not NULL + if (WIFININA_HTML_HEAD_CUSTOMS_STYLE) + root_html_template += WIFININA_HTML_HEAD_CUSTOMS_STYLE; + else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #endif + + #if USING_CUSTOMS_HEAD_ELEMENT + if (_CustomsHeadElement) + root_html_template += _CustomsHeadElement; + #endif + + root_html_template += String(WIFININA_HTML_HEAD_END) + WIFININA_FLDSET_START; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { pitem = String(WIFININA_HTML_PARAM); @@ -975,7 +1351,7 @@ class WiFiManager_NINA_Lite root_html_template += String(WIFININA_FLDSET_END) + WIFININA_HTML_BUTTON + WIFININA_HTML_SCRIPT; - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { pitem = String(WIFININA_HTML_SCRIPT_ITEM); @@ -988,11 +1364,33 @@ class WiFiManager_NINA_Lite return; } + + ////////////////////////////////////////////// + + void serverSendHeaders() + { + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CACHE_CONTROL:"), WM_HTTP_CACHE_CONTROL, "=", WM_HTTP_NO_STORE); + server->sendHeader(WM_HTTP_CACHE_CONTROL, WM_HTTP_NO_STORE); + +#if USING_CORS_FEATURE + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CORS:"), WM_HTTP_CORS, " : ", _CORS_Header); + server->sendHeader(WM_HTTP_CORS, _CORS_Header); +#endif + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_PRAGMA:"), WM_HTTP_PRAGMA, " : ", WM_HTTP_NO_CACHE); + server->sendHeader(WM_HTTP_PRAGMA, WM_HTTP_NO_CACHE); + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_EXPIRES:"), WM_HTTP_EXPIRES, " : ", "-1"); + server->sendHeader(WM_HTTP_EXPIRES, "-1"); + } + + ////////////////////////////////////////////// void handleRequest() { if (server) - { + { String key = server->arg("key"); String value = server->arg("value"); @@ -1000,35 +1398,45 @@ class WiFiManager_NINA_Lite if (key == "" && value == "") { + // New from v1.1.0 + serverSendHeaders(); + ////// + String result; createHTML(result); // Reset configTimeout to stay here until finished. configTimeout = 0; - + if ( RFC952_hostname[0] != 0 ) { // Replace only if Hostname is valid - result.replace("STM32_WM_NINA_Lite", RFC952_hostname); + result.replace("SAMD_WM_NINA_Lite", RFC952_hostname); } - else if ( WiFiNINA_config.board_name[0] != 0 ) + else if ( WIFININA_config.board_name[0] != 0 ) { // Or replace only if board_name is valid. Otherwise, keep intact - result.replace("STM32_WM_NINA_Lite", WiFiNINA_config.board_name); + result.replace("SAMD_WM_NINA_Lite", WIFININA_config.board_name); } - result.replace("[[id]]", WiFiNINA_config.WiFi_Creds[0].wifi_ssid); - result.replace("[[pw]]", WiFiNINA_config.WiFi_Creds[0].wifi_pw); - result.replace("[[id1]]", WiFiNINA_config.WiFi_Creds[1].wifi_ssid); - result.replace("[[pw1]]", WiFiNINA_config.WiFi_Creds[1].wifi_pw); - result.replace("[[nm]]", WiFiNINA_config.board_name); + result.replace("[[id]]", WIFININA_config.WiFi_Creds[0].wifi_ssid); + result.replace("[[pw]]", WIFININA_config.WiFi_Creds[0].wifi_pw); + result.replace("[[id1]]", WIFININA_config.WiFi_Creds[1].wifi_ssid); + result.replace("[[pw1]]", WIFININA_config.WiFi_Creds[1].wifi_pw); + result.replace("[[nm]]", WIFININA_config.board_name); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { String toChange = String("[[") + myMenuItems[i].id + "]]"; result.replace(toChange, myMenuItems[i].pdata); } +#endif + + WN_LOGDEBUG1(F("h:HTML page size:"), result.length()); + WN_LOGDEBUG1(F("h:HTML="), result); + server->send(200, "text/html", result); return; @@ -1036,78 +1444,138 @@ class WiFiManager_NINA_Lite if (number_items_Updated == 0) { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); } - if (key == "id") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + + WN_LOGDEBUG1(F("h: Init menuItemUpdated :" ), NUM_MENU_ITEMS); + } + else + { + WN_LOGERROR(F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool id_Updated = false; + static bool pw_Updated = false; + static bool id1_Updated = false; + static bool pw1_Updated = false; + static bool nm_Updated = false; + + if (!id_Updated && (key == String("id"))) + { + WN_LOGDEBUG(F("h:repl id")); + id_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) - 1); + strncpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1); } - else if (key == "pw") - { + else if (!pw_Updated && (key == String("pw"))) + { + WN_LOGDEBUG(F("h:repl pw")); + pw_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_pw) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_pw) - 1); + strncpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1); } - else if (key == "id1") - { + else if (!id1_Updated && (key == String("id1"))) + { + WN_LOGDEBUG(F("h:repl id1")); + id1_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) - 1); + strncpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1); } - else if (key == "pw1") - { + else if (!pw1_Updated && (key == String("pw1"))) + { + WN_LOGDEBUG(F("h:repl pw1")); + pw1_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_pw) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_pw) - 1); + strncpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { + WN_LOGDEBUG(F("h:repl nm")); + nm_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.board_name) - 1) - strcpy(WiFiNINA_config.board_name, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.board_name) - 1) + strcpy(WIFININA_config.board_name, value.c_str()); else - strncpy(WiFiNINA_config.board_name, value.c_str(), sizeof(WiFiNINA_config.board_name) - 1); + strncpy(WIFININA_config.board_name, value.c_str(), sizeof(WIFININA_config.board_name) - 1); } - - for (int i = 0; i < NUM_MENU_ITEMS; i++) + else { - if (key == myMenuItems[i].id) - { - DEBUG_WM4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); - number_items_Updated++; + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) + { + WN_LOGDEBUG3(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + + menuItemUpdated[i] = true; + + number_items_Updated++; - // Actual size of pdata is [maxlen + 1] - memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); - if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) - strcpy(myMenuItems[i].pdata, value.c_str()); - else - strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) + strcpy(myMenuItems[i].pdata, value.c_str()); + else + strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + + break; + } } +#endif } + + WN_LOGDEBUG1(F("h:items updated ="), number_items_Updated); + WN_LOGDEBUG3(F("h:key ="), key, ", value =", value); server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif { - DEBUG_WM1(F("h:UpdEEPROM")); + WN_LOGDEBUG(F("h:UpdEEPROM")); saveConfigData(); - DEBUG_WM1(F("h:Rst")); + WN_LOGDEBUG(F("h:Rst")); // TO DO : what command to reset // Delay then reset the board after save data @@ -1116,11 +1584,16 @@ class WiFiManager_NINA_Lite } } // if (server) } + + ////////////////////////////////////////////// + +#ifndef CONFIG_TIMEOUT + #warning Default CONFIG_TIMEOUT = 60s + #define CONFIG_TIMEOUT 60000L +#endif void startConfigurationMode() { -#define CONFIG_TIMEOUT 60000L - WiFi.config(portal_apIP); if ( (portal_ssid == "") || portal_pass == "" ) @@ -1136,20 +1609,22 @@ class WiFiManager_NINA_Lite uint16_t channel; - // Use random channel if AP_channel == 0 - //srand(MAX_WIFI_CHANNEL); - srand((uint16_t) millis()); - + // Use random channel if AP_channel == 0 if (AP_channel == 0) - channel = (rand() % MAX_WIFI_CHANNEL) + 1; //random(MAX_WIFI_CHANNEL) + 1; + channel = (millis() % MAX_WIFI_CHANNEL) + 1; else channel = AP_channel; - INFO_WM4(F("SSID="), portal_ssid, F(",PW="), portal_pass); - INFO_WM4(F("IP="), portal_apIP, F(",CH="), channel); + WN_LOGERROR3(F("SSID="), portal_ssid, F(",PW="), portal_pass); + WN_LOGERROR3(F("IP="), portal_apIP, F(",CH="), channel); +#if USE_ESP_AT_SHIELD + // start access point, AP only,default channel 10 + WiFi.beginAP(portal_ssid.c_str(), channel, portal_pass.c_str(), ENC_TYPE_WPA2_PSK, true); +#else // start access point, AP only,default channel 10 WiFi.beginAP(portal_ssid.c_str(), portal_pass.c_str(), channel); +#endif if (!server) @@ -1168,9 +1643,17 @@ class WiFiManager_NINA_Lite // If there is no saved config Data, stay in config mode forever until having config Data. // or SSID, PW, Server,Token ="nothing" if (hadConfigData) + { configTimeout = millis() + CONFIG_TIMEOUT; + + WN_LOGDEBUG3(F("s:millis() = "), millis(), F(", configTimeout = "), configTimeout); + } else + { configTimeout = 0; + + WN_LOGDEBUG(F("s:configTimeout = 0")); + } configuration_mode = true; } diff --git a/src/WiFiManager_NINA_Lite_Teensy.h b/src/WiFiManager_NINA_Lite_Teensy.h index 595719ad..36b2b886 100644 --- a/src/WiFiManager_NINA_Lite_Teensy.h +++ b/src/WiFiManager_NINA_Lite_Teensy.h @@ -1,43 +1,59 @@ -/**************************************************************************************************************************** - Esp8266_AT_WM_Lite_Teensy.h - For Teensy boards using using WiFiNINA modules/shields, using much less code to support boards with smaller memory - - WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards - (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy - configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. - - Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite - Licensed under MIT license - Version: 1.0.5 - - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.0 K Hoang 26/03/2020 Initial coding - 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards - 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. - 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. - SSID password maxlen is 63 now. Permit special chars # and % in input data. - 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. - 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. - *****************************************************************************************************************************/ +/********************************************************************************************************************************* + Esp8266_AT_WM_Lite_Teensy.h + For Teensy boards using using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ #ifndef WiFiManager_NINA_Lite_Teensy_h #define WiFiManager_NINA_Lite_Teensy_h #if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA) || !defined(CORE_TEENSY) ) -#error This code is intended to run on Teensy platform! Please check your Tools->Board setting. + #error This code is intended to run on Teensy platform! Please check your Tools->Board setting. #endif #if defined(__AVR_AT90USB1286__) -#error Teensy 2.0++ not supported yet + #error Teensy 2.0++ not supported yet #elif defined(__AVR_ATmega32U4__) -#error Teensy 2.0 not supported yet + #error Teensy 2.0 not supported yet #endif +#define WIFIMANAGER_NINA_LITE_VERSION "WiFiManager_NINA_Lite v1.1.0" + #include #include #include +#ifndef USING_CUSTOMS_STYLE + #define USING_CUSTOMS_STYLE false +#endif + +#ifndef USING_CUSTOMS_HEAD_ELEMENT + #define USING_CUSTOMS_HEAD_ELEMENT false +#endif + +#ifndef USING_CORS_FEATURE + #define USING_CORS_FEATURE false +#endif + ///////// NEW for DRD ///////////// // These defines must be put before #include // to select where to store DoubleResetDetector_Generic's variable. @@ -74,11 +90,15 @@ typedef struct } MenuItem; // -///NEW -extern uint16_t NUM_MENU_ITEMS; -extern MenuItem myMenuItems []; - -// New in v1.0.3 +#if USE_DYNAMIC_PARAMETERS + #warning Using Dynamic Parameters + ///NEW + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#else + #warning Not using Dynamic Parameters +#endif #define SSID_MAX_LEN 32 //From v1.0.3, WPA2 passwords can be up to 63 characters long. @@ -96,11 +116,14 @@ typedef struct #define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) //////////////// +#define HEADER_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + typedef struct Configuration { - char header [16]; + char header [HEADER_MAX_LEN]; WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; - char board_name [24]; + char board_name [BOARD_NAME_MAX_LEN]; int checkSum; } WiFiNINA_Configuration; @@ -112,7 +135,12 @@ extern bool LOAD_DEFAULT_CONFIG_DATA; extern WiFiNINA_Configuration defaultConfig; // -- HTML page fragments -const char WIFININA_HTML_HEAD[] /*PROGMEM*/ = "Teensy_WM_NINA_Lite
\ + +const char WIFININA_HTML_HEAD_START[] /*PROGMEM*/ = "Teensy_WM_NINA_Lite"; + +const char WIFININA_HTML_HEAD_STYLE[] /*PROGMEM*/ = ""; + +const char WIFININA_HTML_HEAD_END[] /*PROGMEM*/ = "
\
\
\
\ @@ -133,7 +161,25 @@ udVal('nm',document.getElementById('nm').value);"; const char WIFININA_HTML_SCRIPT_ITEM[] /*PROGMEM*/ = "udVal('{d}',document.getElementById('{d}').value);"; const char WIFININA_HTML_SCRIPT_END[] /*PROGMEM*/ = "alert('Updated');}"; const char WIFININA_HTML_END[] /*PROGMEM*/ = ""; -/// + +////////////////////////////////////////// + +//KH Add repeatedly used const +//KH, from v1.1.0 +const char WM_HTTP_HEAD_CL[] PROGMEM = "Content-Length"; +const char WM_HTTP_HEAD_TEXT_HTML[] PROGMEM = "text/html"; +const char WM_HTTP_HEAD_TEXT_PLAIN[] PROGMEM = "text/plain"; + +const char WM_HTTP_CACHE_CONTROL[] PROGMEM = "Cache-Control"; +const char WM_HTTP_NO_STORE[] PROGMEM = "no-cache, no-store, must-revalidate"; +const char WM_HTTP_PRAGMA[] PROGMEM = "Pragma"; +const char WM_HTTP_NO_CACHE[] PROGMEM = "no-cache"; +const char WM_HTTP_EXPIRES[] PROGMEM = "Expires"; + +const char WM_HTTP_CORS[] PROGMEM = "Access-Control-Allow-Origin"; +const char WM_HTTP_CORS_ALLOW_ALL[] PROGMEM = "*"; + +////////////////////////////////////////// String IPAddressToString(IPAddress _address) @@ -155,10 +201,14 @@ class WiFiManager_NINA_Lite WiFiManager_NINA_Lite() { // check for the presence of the shield - if (WiFi.status() == WL_NO_MODULE) +#if USE_WIFI101 + if (WiFi.status() == WL_NO_SHIELD) +#else + if (WiFi.status() == WL_NO_MODULE) +#endif { - DEBUG_WM1(F("NoNINA")); - } + WN_LOGERROR(F("NoWiFi")); + } } ~WiFiManager_NINA_Lite() @@ -169,19 +219,21 @@ class WiFiManager_NINA_Lite bool connectWiFi(const char* ssid, const char* pass) { - DEBUG_WM2(F("Con2:"), ssid); + WN_LOGERROR1(F("Con2:"), ssid); + + setHostname(); - if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) + if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) { displayWiFiData(); } else { - DEBUG_WM1(F("NoW")); + WN_LOGERROR(F("NoW")); return false; } - DEBUG_WM1(F("WOK")); + WN_LOGERROR(F("WOK")); wifi_connected = true; @@ -191,16 +243,14 @@ class WiFiManager_NINA_Lite void begin(const char* ssid, const char* pass ) { - DEBUG_WM1(F("conW")); + WN_LOGERROR(F("conW")); connectWiFi(ssid, pass); } - // New in v1.0.5 void begin(const char *iHostname = "") { #define RETRY_TIMES_CONNECT_WIFI 3 - // New in v1.0.3 if (iHostname[0] == 0) { String randomNum = String(random(0xFFFFFF), HEX); @@ -217,53 +267,72 @@ class WiFiManager_NINA_Lite getRFC952_hostname(iHostname); } - DEBUG_WM2(F("Hostname="), RFC952_hostname); + WN_LOGERROR1(F("Hostname="), RFC952_hostname); ////// //// New DRD //// drd = new DoubleResetDetector_Generic(DRD_TIMEOUT, DRD_ADDRESS); - bool useConfigPortal = false; + bool noConfigPortal = true; if (drd->detectDoubleReset()) { - DEBUG_WM1(F("Double Reset Detected")); + WN_LOGERROR(F("Double Reset Detected")); - useConfigPortal = true; + noConfigPortal = false; } //// New DRD //// - DEBUG_WM1(F("======= Start Default Config Data =======")); - displayConfigData(defaultConfig); + + if (LOAD_DEFAULT_CONFIG_DATA) + { + WN_LOGERROR(F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } hadConfigData = getConfigData(); + + isForcedConfigPortal = isForcedCP(); - //// New DRD //// - // useConfigPortal when getConfigData() not OK or DRD'ed - if (hadConfigData && !useConfigPortal) - //// New DRD //// + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) { - //hadConfigData = true; + hadConfigData = true; if (connectMultiWiFi(RETRY_TIMES_CONNECT_WIFI)) { - DEBUG_WM1(F("b:WOK")); + WN_LOGERROR(F("b:WOK")); } else { - DEBUG_WM1(F("b:NoW")); + WN_LOGERROR(F("b:NoW")); // failed to connect to WiFi, will start configuration mode startConfigurationMode(); } } else - { - INFO_WM2(F("b:StayInCfgPortal:"), useConfigPortal ? F("DRD") : F("NoCfgDat")); + { + WN_LOGERROR(isForcedConfigPortal? F("bg: isForcedConfigPortal = true") : F("bg: isForcedConfigPortal = false")); + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + } + else + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-non-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + clearForcedCP(); + } + + //To permit autoreset after timeout if DRD/MRD or non-persistent forced-CP + hadConfigData = isForcedConfigPortal ? true : (noConfigPortal ? false : true); // failed to connect to WiFi, will start configuration mode - hadConfigData = false; startConfigurationMode(); } } + #ifndef RETRY_TIMES_RECONNECT_WIFI #define RETRY_TIMES_RECONNECT_WIFI 2 #else @@ -280,22 +349,22 @@ class WiFiManager_NINA_Lite #endif #ifndef RESET_IF_CONFIG_TIMEOUT -#define RESET_IF_CONFIG_TIMEOUT true + #define RESET_IF_CONFIG_TIMEOUT true #endif #ifndef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 #else - // Force range of user-defined TIMES_BEFORE_RESET between 2-100 -#if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) -#warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 -#undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 -#elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) -#warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 -#undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET -#define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 -#endif + // Force range of user-defined TIMES_BEFORE_RESET between 2-100 + #if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 + #elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 + #endif #endif void run() @@ -329,7 +398,7 @@ class WiFiManager_NINA_Lite { wifiDisconnectedOnce = false; wifi_connected = false; - DEBUG_WM1(F("r:Check&WLost")); + WN_LOGERROR(F("r:Check&WLost")); } else { @@ -351,7 +420,7 @@ class WiFiManager_NINA_Lite if (server) { - //DEBUG_WM1(F("r:handleClient")); + //WN_LOGDEBUG(F("r:handleClient")); server->handleClient(); } @@ -366,7 +435,7 @@ class WiFiManager_NINA_Lite { if (++retryTimes <= CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET) { - DEBUG_WM2(F("r:WLost&TOut.ConW.Retry#"), retryTimes); + WN_LOGERROR1(F("r:WLost&TOut.ConW.Retry#"), retryTimes); } else { @@ -378,11 +447,11 @@ class WiFiManager_NINA_Lite // Not in config mode, try reconnecting before forcing to config mode if ( !wifi_connected ) { - DEBUG_WM1(F("r:WLost.ReconW")); + WN_LOGERROR(F("r:WLost.ReconW")); if (connectMultiWiFi(RETRY_TIMES_RECONNECT_WIFI)) { - DEBUG_WM1(F("r:WOK")); + WN_LOGERROR(F("r:WOK")); } } } @@ -390,25 +459,35 @@ class WiFiManager_NINA_Lite else if (configuration_mode) { configuration_mode = false; - DEBUG_WM1(F("r:gotWBack")); + WN_LOGERROR(F("r:gotWBack")); } } - void setHostname(void) + ////////////////////////////////////////////// + + void setHostname() { if (RFC952_hostname[0] != 0) { +#if USE_WIFI101 + WiFi.hostname(RFC952_hostname); +#elif USE_WIFI_NINA WiFi.setHostname(RFC952_hostname); +#endif } } + + ////////////////////////////////////////////// void setConfigPortalIP(IPAddress portalIP = IPAddress(192, 168, 4, 1)) { portal_apIP = portalIP; } + + ////////////////////////////////////////////// #define MIN_WIFI_CHANNEL 1 - #define MAX_WIFI_CHANNEL 12 // Channel 13 is flaky, because of bad number 13 ;-) + #define MAX_WIFI_CHANNEL 11 // Channel 13 is flaky, because of bad number 13 ;-) int setConfigPortalChannel(int channel = 1) { @@ -423,17 +502,23 @@ class WiFiManager_NINA_Lite return AP_channel; } + ////////////////////////////////////////////// + void setConfigPortal(String ssid = "", String pass = "") { portal_ssid = ssid; portal_pass = pass; } + + ////////////////////////////////////////////// void setSTAStaticIPConfig(IPAddress ip) { static_IP = ip; } + ////////////////////////////////////////////// + String getWiFiSSID(uint8_t index) { if (index >= NUM_WIFI_CREDENTIALS) @@ -442,8 +527,10 @@ class WiFiManager_NINA_Lite if (!hadConfigData) getConfigData(); - return (String(WiFiNINA_config.WiFi_Creds[index].wifi_ssid)); + return (String(WIFININA_config.WiFi_Creds[index].wifi_ssid)); } + + ////////////////////////////////////////////// String getWiFiPW(uint8_t index) { @@ -453,14 +540,18 @@ class WiFiManager_NINA_Lite if (!hadConfigData) getConfigData(); - return (String(WiFiNINA_config.WiFi_Creds[index].wifi_pw)); + return (String(WIFININA_config.WiFi_Creds[index].wifi_pw)); } + + ////////////////////////////////////////////// - bool getWiFiStatus(void) + bool getWiFiStatus() { return wifi_connected; } + ////////////////////////////////////////////// + WiFiNINA_Configuration* getFullConfigData(WiFiNINA_Configuration *configData) { if (!hadConfigData) @@ -468,35 +559,83 @@ class WiFiManager_NINA_Lite // Check if NULL pointer if (configData) - memcpy(configData, &WiFiNINA_config, sizeof(WiFiNINA_Configuration)); + memcpy(configData, &WIFININA_config, sizeof(WiFiNINA_Configuration)); return (configData); } + + ////////////////////////////////////////////// - String localIP(void) + String localIP() { ipAddress = IPAddressToString(WiFi.localIP()); return ipAddress; } + + ////////////////////////////////////////////// void clearConfigData() { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } +#endif saveConfigData(); } - bool isConfigDataValid(void) + ////////////////////////////////////////////// + + bool isConfigDataValid() { return hadConfigData; } + + ////////////////////////////////////////////// + + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// void resetFunc() { @@ -504,10 +643,68 @@ class WiFiManager_NINA_Lite // Teensy 4.0 SCB_AIRCR = 0x05FA0004; //write value for restart for Teensy #else - void(*resetFunc)(void) = 0; + void(*resetFunc)() = 0; resetFunc(); #endif } + + ////////////////////////////////////// + + // Add customs headers from v1.1.0 + + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + +#if USING_CUSTOMS_STYLE + //sets a custom style, such as color + // ""; + void setCustomsStyle(const char* CustomsStyle = WIFININA_HTML_HEAD_STYLE) + { + WIFININA_HTML_HEAD_CUSTOMS_STYLE = CustomsStyle; + WN_LOGDEBUG1(F("Set CustomsStyle to : "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + } + + const char* getCustomsStyle() + { + WN_LOGDEBUG1(F("Get CustomsStyle = "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + return WIFININA_HTML_HEAD_CUSTOMS_STYLE; + } +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + //sets a custom element to add to head, like a new style tag + void setCustomsHeadElement(const char* CustomsHeadElement = NULL) + { + _CustomsHeadElement = CustomsHeadElement; + WN_LOGDEBUG1(F("Set CustomsHeadElement to : "), _CustomsHeadElement); + } + + const char* getCustomsHeadElement() + { + WN_LOGDEBUG1(F("Get CustomsHeadElement = "), _CustomsHeadElement); + return _CustomsHeadElement; + } +#endif + +#if USING_CORS_FEATURE + void setCORSHeader(const char* CORSHeaders = NULL) + { + _CORS_Header = CORSHeaders; + + WN_LOGDEBUG1(F("Set CORS Header to : "), _CORS_Header); + } + + const char* getCORSHeader() + { + WN_LOGDEBUG1(F("Get CORS Header = "), _CORS_Header); + return _CORS_Header; + } +#endif + + ////////////////////////////////////// + private: String ipAddress = "0.0.0.0"; @@ -517,8 +714,11 @@ class WiFiManager_NINA_Lite unsigned long configTimeout; bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; - WiFiNINA_Configuration WiFiNINA_config; + WiFiNINA_Configuration WIFININA_config; uint16_t totalDataSize = 0; @@ -532,6 +732,24 @@ class WiFiManager_NINA_Lite String portal_pass = ""; IPAddress static_IP = IPAddress(0, 0, 0, 0); + + ///////////////////////////////////// + + // Add customs headers from v1.1.0 + +#if USING_CUSTOMS_STYLE + const char* WIFININA_HTML_HEAD_CUSTOMS_STYLE = NULL; +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + const char* _CustomsHeadElement = NULL; +#endif + +#if USING_CORS_FEATURE + const char* _CORS_Header = WM_HTTP_CORS_ALLOW_ALL; //"*"; +#endif + + ////////////////////////////////////// #define RFC952_HOSTNAME_MAXLEN 24 char RFC952_hostname[RFC952_HOSTNAME_MAXLEN + 1]; @@ -561,25 +779,27 @@ class WiFiManager_NINA_Lite void displayConfigData(WiFiNINA_Configuration configData) { - DEBUG_WM6(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, - F(",PW="), configData.WiFi_Creds[0].wifi_pw); - DEBUG_WM4(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); - DEBUG_WM2(F("BName="), configData.board_name); + WN_LOGERROR5(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, + F(",PW="), configData.WiFi_Creds[0].wifi_pw); + WN_LOGERROR3(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); + WN_LOGERROR1(F("BName="), configData.board_name); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - DEBUG_WM6("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); - } + WN_LOGERROR5("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); + } +#endif } - void displayWiFiData(void) + void displayWiFiData() { - DEBUG_WM4(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); - DEBUG_WM2(F("IP="), localIP() ); + WN_LOGERROR3(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); + WN_LOGERROR1(F("IP="), localIP() ); } -#define WIFININA_BOARD_TYPE "WIFININA" -#define WM_NO_CONFIG "blank" +#define WIFININA_BOARD_TYPE "WIFININA" +#define WM_NO_CONFIG "blank" //#define EEPROM_SIZE E2END //#define EEPROM_SIZE 512 @@ -621,44 +841,94 @@ class WiFiManager_NINA_Lite */ #ifndef EEPROM_SIZE -#define EEPROM_SIZE 512 + #define EEPROM_SIZE 512 #else -#if (EEPROM_SIZE > 4096) -#warning EEPROM_SIZE must be <= 4096. Reset to 4096 -#undef EEPROM_SIZE -#define EEPROM_SIZE 4096 -#endif -#if (EEPROM_SIZE < CONFIG_DATA_SIZE) -#warning EEPROM_SIZE must be > CONFIG_DATA_SIZE. Reset to 512 -#undef EEPROM_SIZE -#define EEPROM_SIZE 512 -#endif + #if (EEPROM_SIZE > 4096) + #warning EEPROM_SIZE must be <= 4096. Reset to 4096 + #undef EEPROM_SIZE + #define EEPROM_SIZE 4096 + #endif + #if (EEPROM_SIZE < CONFIG_DATA_SIZE) + #warning EEPROM_SIZE must be > CONFIG_DATA_SIZE. Reset to 512 + #undef EEPROM_SIZE + #define EEPROM_SIZE 512 + #endif #endif #ifndef EEPROM_START -#define EEPROM_START 0 //define 256 in DRD -#warning EEPROM_START not defined. Set to 0 + #define EEPROM_START 0 //define 256 in DRD + #warning EEPROM_START not defined. Set to 0 #else -#if (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE) -#error EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE. Please adjust. -#endif + #if (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE) + #error EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE > EEPROM_SIZE. Please adjust. + #endif #endif // Stating positon to store Blynk8266_WM_config -#define NINA_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) +#define CONFIG_EEPROM_START (EEPROM_START + DRD_FLAG_DATA_SIZE) int calcChecksum() { int checkSum = 0; - for (uint16_t index = 0; index < (sizeof(WiFiNINA_config) - sizeof(WiFiNINA_config.checkSum)); index++) + for (uint16_t index = 0; index < (sizeof(WIFININA_config) - sizeof(WIFININA_config.checkSum)); index++) { - checkSum += * ( ( (byte*) &WiFiNINA_config ) + index); + checkSum += * ( ( (byte*) &WIFININA_config ) + index); } return checkSum; } - bool checkDynamicData(void) + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + + WN_LOGERROR(isPersistent ? F("setForcedCP Persistent") : F("setForcedCP non-Persistent")); + + EEPROM.put(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + + void clearForcedCP() + { + EEPROM.put(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, 0); + } + + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + EEPROM.get(CONFIG_EEPROM_START + CONFIG_DATA_SIZE, readForcedConfigPortalFlag); + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS + + bool checkDynamicData() { int checkSum = 0; int readCheckSum; @@ -666,7 +936,7 @@ class WiFiManager_NINA_Lite #define BUFFER_LEN 128 char readBuffer[BUFFER_LEN + 1]; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config); // Find the longest pdata, then dynamically allocate buffer. Remember to free when done // This is used to store tempo data to calculate checksum to see of data is valid @@ -677,7 +947,7 @@ class WiFiManager_NINA_Lite if (myMenuItems[i].maxlen > BUFFER_LEN) { // Size too large, abort and flag false - DEBUG_WM1(F("ChkCrR: Error Small Buffer.")); + WN_LOGDEBUG(F("ChkCrR: Error Small Buffer.")); return false; } } @@ -694,7 +964,7 @@ class WiFiManager_NINA_Lite // NULL terminated readBuffer[myMenuItems[i].maxlen] = 0; - DEBUG_WM4(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen); + WN_LOGDEBUG3(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen); for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) { @@ -706,7 +976,7 @@ class WiFiManager_NINA_Lite EEPROM.get(offset, readCheckSum); - DEBUG_WM4(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + WN_LOGDEBUG3(F("ChkCrR:CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { @@ -716,13 +986,15 @@ class WiFiManager_NINA_Lite return true; } - bool EEPROM_getDynamicData(void) + ////////////////////////////////////////////// + + bool EEPROM_getDynamicData() { int readCheckSum; int checkSum = 0; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config); - totalDataSize = sizeof(WiFiNINA_config) + sizeof(readCheckSum); + totalDataSize = sizeof(WIFININA_config) + sizeof(readCheckSum); for (int i = 0; i < NUM_MENU_ITEMS; i++) { @@ -742,7 +1014,7 @@ class WiFiManager_NINA_Lite EEPROM.get(offset, readCheckSum); - DEBUG_WM4(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + WN_LOGDEBUG3(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); if ( checkSum != readCheckSum) { @@ -751,17 +1023,19 @@ class WiFiManager_NINA_Lite return true; } + + ////////////////////////////////////////////// - void EEPROM_putDynamicData(void) + void EEPROM_putDynamicData() { int checkSum = 0; - uint16_t offset = NINA_EEPROM_START + sizeof(WiFiNINA_config); + uint16_t offset = CONFIG_EEPROM_START + sizeof(WIFININA_config); for (int i = 0; i < NUM_MENU_ITEMS; i++) { char* _pointer = myMenuItems[i].pdata; - //DEBUG_WM4(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + WN_LOGDEBUG3(F("pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++,offset++) { @@ -772,33 +1046,89 @@ class WiFiManager_NINA_Lite } EEPROM.put(offset, checkSum); - //EEPROM.commit(); - DEBUG_WM2(F("CrCCSum=0x"), String(checkSum, HEX)); + WN_LOGERROR1(F("CrCCSum=0x"), String(checkSum, HEX)); + } +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define SERVER_MAX_LEN 32 + //#define TOKEN_MAX_LEN 36 + + // NULL Terminating to be sure + WIFININA_config.header[HEADER_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.board_name[BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// + + bool EEPROM_get() + { + EEPROM.get(CONFIG_EEPROM_START, WIFININA_config); + NULLTerminateConfig(); + + return true; + } + + ////////////////////////////////////////////// + + void EEPROM_put() + { + EEPROM.put(CONFIG_EEPROM_START, WIFININA_config); } + ////////////////////////////////////////////// + + void saveConfigData() + { + int calChecksum = calcChecksum(); + WIFININA_config.checkSum = calChecksum; + + WN_LOGERROR5(F("SaveEEPROM,Sz="), EEPROM.length(), F(",DataSz="), totalDataSize, F(",CSum=0x"), String(calChecksum, HEX)); + + EEPROM_put(); + +#if USE_DYNAMIC_PARAMETERS + EEPROM_putDynamicData(); +#endif + } + + ////////////////////////////////////////////// + // New from v1.0.5 - void loadAndSaveDefaultConfigData(void) + void loadAndSaveDefaultConfigData() { // Load Default Config Data from Sketch - memcpy(&WiFiNINA_config, &defaultConfig, sizeof(WiFiNINA_config)); - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); // Including config and dynamic data, and assume valid saveConfigData(); - DEBUG_WM1(F("======= Start Loaded Config Data =======")); - displayConfigData(WiFiNINA_config); + WN_LOGERROR(F("======= Start Loaded Config Data =======")); + displayConfigData(WIFININA_config); } + ////////////////////////////////////////////// + bool getConfigData() { - bool dynamicDataValid; - int calChecksum; + bool dynamicDataValid = true; + int calChecksum; - hadConfigData = false; + hadConfigData = false; - EEPROM.begin(); + EEPROM.begin(); + + WN_LOGERROR1(F("InitEEPROM,sz="), EEPROM.length()); // Use new LOAD_DEFAULT_CONFIG_DATA logic if (LOAD_DEFAULT_CONFIG_DATA) @@ -812,120 +1142,129 @@ class WiFiManager_NINA_Lite else { // Load stored config data from EEPROM - DEBUG_WM2(F("EEPROMsz:"), EEPROM_SIZE); - EEPROM.get(NINA_EEPROM_START, WiFiNINA_config); + WN_LOGERROR1(F("EEPROMsz:"), EEPROM_SIZE); - // Load stored dynamic data from EEPROM - // Verify ChkSum - dynamicDataValid = checkDynamicData(); + EEPROM_get(); + // Verify ChkSum calChecksum = calcChecksum(); - DEBUG_WM4(F("CCSum=0x"), String(calChecksum, HEX), F(",RCSum=0x"), String(WiFiNINA_config.checkSum, HEX)); + WN_LOGERROR3(F("CCSum=0x"), String(calChecksum, HEX), + F(",RCSum=0x"), String(WIFININA_config.checkSum, HEX)); + +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from EEPROM + dynamicDataValid = checkDynamicData(); +#endif - if (dynamicDataValid) + // If checksum = 0 => simulated EEPROM has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == WIFININA_config.checkSum) ) { - EEPROM_getDynamicData(); - - DEBUG_WM1(F("Valid Stored Dynamic Data")); - DEBUG_WM1(F("======= Start Stored Config Data =======")); - displayConfigData(WiFiNINA_config); - - // Don't need Config Portal anymore - return true; - } - else - { - // Invalid Stored config data => Config Portal - DEBUG_WM1(F("Invalid Stored Dynamic Data. Load default from Sketch")); - - // Load Default Config Data from Sketch, better than just "blank" - loadAndSaveDefaultConfigData(); - - // Need Config Portal here as data can be just dummy - // Even if you don't open CP, you're OK on next boot if your default config data is valid - return false; - } - } + if (dynamicDataValid) + { +#if USE_DYNAMIC_PARAMETERS + EEPROM_getDynamicData(); + + WN_LOGERROR(F("Valid Stored Dynamic Data")); +#endif + + WN_LOGERROR(F("======= Start Stored Config Data =======")); + displayConfigData(WIFININA_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + WN_LOGERROR(F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } + } - if ( (strncmp(WiFiNINA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || - (calChecksum != WiFiNINA_config.checkSum) || !dynamicDataValid ) + if ( (strncmp(WIFININA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || + (calChecksum != WIFININA_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (WIFININA_config.checkSum == 0) ) ) { // Including Credentials CSum - DEBUG_WM2(F("InitCfgFile,sz="), sizeof(WiFiNINA_config)); + WN_LOGERROR1(F("InitCfgFile,sz="), sizeof(WIFININA_config)); // doesn't have any configuration if (LOAD_DEFAULT_CONFIG_DATA) { - memcpy(&WiFiNINA_config, &defaultConfig, sizeof(WiFiNINA_config)); + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); } else { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { // Actual size of pdata is [maxlen + 1] memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); } +#endif - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); - strcpy(WiFiNINA_config.board_name, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.board_name, WM_NO_CONFIG); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); } +#endif } - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { - DEBUG_WM4(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); + WN_LOGDEBUG3(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); } +#endif // Don't need - WiFiNINA_config.checkSum = 0; + WIFININA_config.checkSum = 0; saveConfigData(); return false; } - else if ( !strncmp(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strncmp(WiFiNINA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || - !strlen(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) || - !strlen(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) || - !strlen(WiFiNINA_config.WiFi_Creds[0].wifi_pw) || - !strlen(WiFiNINA_config.WiFi_Creds[1].wifi_pw) ) + else if ( !strncmp(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_pw) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_pw) ) { // If SSID, PW ="nothing", stay in config mode forever until having config Data. return false; } else { - displayConfigData(WiFiNINA_config); + displayConfigData(WIFININA_config); } return true; } - - void saveConfigData() - { - int calChecksum = calcChecksum(); - WiFiNINA_config.checkSum = calChecksum; - - DEBUG_WM6(F("SaveEEPROM,Sz="), EEPROM.length(), F(",DataSz="), totalDataSize, F(",CSum=0x"), String(calChecksum, HEX)); - - //EEPROM_put(); - EEPROM.put(NINA_EEPROM_START, WiFiNINA_config); - EEPROM_putDynamicData(); - } + + ////////////////////////////////////////////// // New connection logic from v1.0.5 bool connectMultiWiFi(int retry_time) @@ -936,35 +1275,35 @@ class WiFiManager_NINA_Lite static int lastConnectedIndex = 255; - DEBUG_WM1(F("ConMultiWifi")); + WN_LOGDEBUG(F("ConMultiWifi")); if (static_IP != IPAddress(0, 0, 0, 0)) { - DEBUG_WM1(F("UseStatIP")); + WN_LOGDEBUG(F("UseStatIP")); WiFi.config(static_IP); } if (lastConnectedIndex != 255) { index = (lastConnectedIndex + 1) % NUM_WIFI_CREDENTIALS; - DEBUG_WM4(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); + WN_LOGDEBUG3(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); } - DEBUG_WM4(F("con2WF:SSID="), WiFiNINA_config.WiFi_Creds[index].wifi_ssid, - F(",PW="), WiFiNINA_config.WiFi_Creds[index].wifi_pw); + WN_LOGDEBUG3(F("con2WF:SSID="), WIFININA_config.WiFi_Creds[index].wifi_ssid, + F(",PW="), WIFININA_config.WiFi_Creds[index].wifi_pw); while ( !wifi_connected && ( 0 < retry_time ) ) { - DEBUG_WM2(F("Remaining retry_time="), retry_time); + WN_LOGDEBUG1(F("Remaining retry_time="), retry_time); - status = WiFi.begin(WiFiNINA_config.WiFi_Creds[index].wifi_ssid, WiFiNINA_config.WiFi_Creds[index].wifi_pw); + status = WiFi.begin(WIFININA_config.WiFi_Creds[index].wifi_ssid, WIFININA_config.WiFi_Creds[index].wifi_pw); // Need restart WiFi at beginning of each cycle if (status == WL_CONNECTED) { wifi_connected = true; lastConnectedIndex = index; - DEBUG_WM2(F("WOK, lastConnectedIndex="), lastConnectedIndex); + WN_LOGDEBUG1(F("WOK, lastConnectedIndex="), lastConnectedIndex); break; } @@ -977,32 +1316,51 @@ class WiFiManager_NINA_Lite if (retry_time <= 0) { - DEBUG_WM4(F("Failed using index="), index, F(", retry_time="), retry_time); + WN_LOGDEBUG3(F("Failed using index="), index, F(", retry_time="), retry_time); } if (wifi_connected) { - DEBUG_WM1(F("con2WF:OK")); + WN_LOGDEBUG(F("con2WF:OK")); displayWiFiData(); } else { - DEBUG_WM1(F("con2WF:failed")); + WN_LOGDEBUG(F("con2WF:failed")); // Can't connect, so try another index next time. Faking this index is OK and lost lastConnectedIndex = index; } return wifi_connected; } + + ////////////////////////////////////////////// // NEW void createHTML(String& root_html_template) { String pitem; - root_html_template = String(WIFININA_HTML_HEAD) + WIFININA_FLDSET_START; + root_html_template = WIFININA_HTML_HEAD_START; - for (int i = 0; i < NUM_MENU_ITEMS; i++) + #if USING_CUSTOMS_STYLE + // Using Customs style when not NULL + if (WIFININA_HTML_HEAD_CUSTOMS_STYLE) + root_html_template += WIFININA_HTML_HEAD_CUSTOMS_STYLE; + else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #endif + + #if USING_CUSTOMS_HEAD_ELEMENT + if (_CustomsHeadElement) + root_html_template += _CustomsHeadElement; + #endif + + root_html_template += String(WIFININA_HTML_HEAD_END) + WIFININA_FLDSET_START; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { pitem = String(WIFININA_HTML_PARAM); @@ -1015,7 +1373,7 @@ class WiFiManager_NINA_Lite root_html_template += String(WIFININA_FLDSET_END) + WIFININA_HTML_BUTTON + WIFININA_HTML_SCRIPT; - for (int i = 0; i < NUM_MENU_ITEMS; i++) + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { pitem = String(WIFININA_HTML_SCRIPT_ITEM); @@ -1028,11 +1386,33 @@ class WiFiManager_NINA_Lite return; } + + ////////////////////////////////////////////// + + void serverSendHeaders() + { + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CACHE_CONTROL:"), WM_HTTP_CACHE_CONTROL, "=", WM_HTTP_NO_STORE); + server->sendHeader(WM_HTTP_CACHE_CONTROL, WM_HTTP_NO_STORE); + +#if USING_CORS_FEATURE + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CORS:"), WM_HTTP_CORS, " : ", _CORS_Header); + server->sendHeader(WM_HTTP_CORS, _CORS_Header); +#endif + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_PRAGMA:"), WM_HTTP_PRAGMA, " : ", WM_HTTP_NO_CACHE); + server->sendHeader(WM_HTTP_PRAGMA, WM_HTTP_NO_CACHE); + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_EXPIRES:"), WM_HTTP_EXPIRES, " : ", "-1"); + server->sendHeader(WM_HTTP_EXPIRES, "-1"); + } + + ////////////////////////////////////////////// void handleRequest() { if (server) - { + { String key = server->arg("key"); String value = server->arg("value"); @@ -1040,35 +1420,45 @@ class WiFiManager_NINA_Lite if (key == "" && value == "") { + // New from v1.1.0 + serverSendHeaders(); + ////// + String result; createHTML(result); - + // Reset configTimeout to stay here until finished. configTimeout = 0; - + if ( RFC952_hostname[0] != 0 ) { // Replace only if Hostname is valid - result.replace("Teensy_WM_NINA_Lite", RFC952_hostname); + result.replace("SAMD_WM_NINA_Lite", RFC952_hostname); } - else if ( WiFiNINA_config.board_name[0] != 0 ) + else if ( WIFININA_config.board_name[0] != 0 ) { // Or replace only if board_name is valid. Otherwise, keep intact - result.replace("Teensy_WM_NINA_Lite", WiFiNINA_config.board_name); + result.replace("SAMD_WM_NINA_Lite", WIFININA_config.board_name); } - result.replace("[[id]]", WiFiNINA_config.WiFi_Creds[0].wifi_ssid); - result.replace("[[pw]]", WiFiNINA_config.WiFi_Creds[0].wifi_pw); - result.replace("[[id1]]", WiFiNINA_config.WiFi_Creds[1].wifi_ssid); - result.replace("[[pw1]]", WiFiNINA_config.WiFi_Creds[1].wifi_pw); - result.replace("[[nm]]", WiFiNINA_config.board_name); + result.replace("[[id]]", WIFININA_config.WiFi_Creds[0].wifi_ssid); + result.replace("[[pw]]", WIFININA_config.WiFi_Creds[0].wifi_pw); + result.replace("[[id1]]", WIFININA_config.WiFi_Creds[1].wifi_ssid); + result.replace("[[pw1]]", WIFININA_config.WiFi_Creds[1].wifi_pw); + result.replace("[[nm]]", WIFININA_config.board_name); - for (int i = 0; i < NUM_MENU_ITEMS; i++) +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) { String toChange = String("[[") + myMenuItems[i].id + "]]"; result.replace(toChange, myMenuItems[i].pdata); } +#endif + + WN_LOGDEBUG1(F("h:HTML page size:"), result.length()); + WN_LOGDEBUG1(F("h:HTML="), result); + server->send(200, "text/html", result); return; @@ -1076,78 +1466,138 @@ class WiFiManager_NINA_Lite if (number_items_Updated == 0) { - memset(&WiFiNINA_config, 0, sizeof(WiFiNINA_config)); - strcpy(WiFiNINA_config.header, WIFININA_BOARD_TYPE); + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); } - if (key == "id") +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + + WN_LOGDEBUG1(F("h: Init menuItemUpdated :" ), NUM_MENU_ITEMS); + } + else + { + WN_LOGERROR(F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool id_Updated = false; + static bool pw_Updated = false; + static bool id1_Updated = false; + static bool pw1_Updated = false; + static bool nm_Updated = false; + + if (!id_Updated && (key == String("id"))) + { + WN_LOGDEBUG(F("h:repl id")); + id_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_ssid) - 1); + strncpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1); } - else if (key == "pw") - { + else if (!pw_Updated && (key == String("pw"))) + { + WN_LOGDEBUG(F("h:repl pw")); + pw_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_pw) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[0].wifi_pw) - 1); + strncpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1); } - else if (key == "id1") - { + else if (!id1_Updated && (key == String("id1"))) + { + WN_LOGDEBUG(F("h:repl id1")); + id1_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_ssid) - 1); + strncpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1); } - else if (key == "pw1") - { + else if (!pw1_Updated && (key == String("pw1"))) + { + WN_LOGDEBUG(F("h:repl pw1")); + pw1_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_pw) - 1) - strcpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str()); else - strncpy(WiFiNINA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WiFiNINA_config.WiFi_Creds[1].wifi_pw) - 1); + strncpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1); } - else if (key == "nm") + else if (!nm_Updated && (key == String("nm"))) { + WN_LOGDEBUG(F("h:repl nm")); + nm_Updated = true; + number_items_Updated++; - if (strlen(value.c_str()) < sizeof(WiFiNINA_config.board_name) - 1) - strcpy(WiFiNINA_config.board_name, value.c_str()); + if (strlen(value.c_str()) < sizeof(WIFININA_config.board_name) - 1) + strcpy(WIFININA_config.board_name, value.c_str()); else - strncpy(WiFiNINA_config.board_name, value.c_str(), sizeof(WiFiNINA_config.board_name) - 1); + strncpy(WIFININA_config.board_name, value.c_str(), sizeof(WIFININA_config.board_name) - 1); } - - for (int i = 0; i < NUM_MENU_ITEMS; i++) + else { - if (key == myMenuItems[i].id) - { - DEBUG_WM4(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); - number_items_Updated++; + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) + { + WN_LOGDEBUG3(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + + menuItemUpdated[i] = true; + + number_items_Updated++; - // Actual size of pdata is [maxlen + 1] - memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); - if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) - strcpy(myMenuItems[i].pdata, value.c_str()); - else - strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) + strcpy(myMenuItems[i].pdata, value.c_str()); + else + strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + + break; + } } +#endif } + + WN_LOGDEBUG1(F("h:items updated ="), number_items_Updated); + WN_LOGDEBUG3(F("h:key ="), key, ", value =", value); server->send(200, "text/html", "OK"); - // NEW +#if USE_DYNAMIC_PARAMETERS if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif { - DEBUG_WM1(F("h:UpdEEPROM")); + WN_LOGDEBUG(F("h:UpdEEPROM")); saveConfigData(); - DEBUG_WM1(F("h:Rst")); + WN_LOGDEBUG(F("h:Rst")); // TO DO : what command to reset // Delay then reset the board after save data @@ -1157,6 +1607,8 @@ class WiFiManager_NINA_Lite } // if (server) } + ////////////////////////////////////////////// + #if 0 uint8_t macTeensy[6]; @@ -1173,10 +1625,15 @@ class WiFiManager_NINA_Lite } #endif + ////////////////////////////////////////////// + +#ifndef CONFIG_TIMEOUT + #warning Default CONFIG_TIMEOUT = 60s + #define CONFIG_TIMEOUT 60000L +#endif + void startConfigurationMode() { -#define CONFIG_TIMEOUT 60000L - WiFi.config(portal_apIP); if ( (portal_ssid == "") || portal_pass == "" ) @@ -1201,20 +1658,22 @@ class WiFiManager_NINA_Lite uint16_t channel; - // Use random channel if AP_channel == 0 - //srand(MAX_WIFI_CHANNEL); - srand((uint16_t) millis()); - + // Use random channel if AP_channel == 0 if (AP_channel == 0) - channel = (rand() % MAX_WIFI_CHANNEL) + 1; //random(MAX_WIFI_CHANNEL) + 1; + channel = (millis() % MAX_WIFI_CHANNEL) + 1; else channel = AP_channel; - INFO_WM4(F("SSID="), portal_ssid, F(",PW="), portal_pass); - INFO_WM4(F("IP="), portal_apIP, F(",CH="), channel); + WN_LOGERROR3(F("SSID="), portal_ssid, F(",PW="), portal_pass); + WN_LOGERROR3(F("IP="), portal_apIP, F(",CH="), channel); +#if USE_ESP_AT_SHIELD + // start access point, AP only,default channel 10 + WiFi.beginAP(portal_ssid.c_str(), channel, portal_pass.c_str(), ENC_TYPE_WPA2_PSK, true); +#else // start access point, AP only,default channel 10 WiFi.beginAP(portal_ssid.c_str(), portal_pass.c_str(), channel); +#endif if (!server) { @@ -1232,9 +1691,17 @@ class WiFiManager_NINA_Lite // If there is no saved config Data, stay in config mode forever until having config Data. // or SSID, PW, Server,Token ="nothing" if (hadConfigData) + { configTimeout = millis() + CONFIG_TIMEOUT; + + WN_LOGDEBUG3(F("s:millis() = "), millis(), F(", configTimeout = "), configTimeout); + } else + { configTimeout = 0; + + WN_LOGDEBUG(F("s:configTimeout = 0")); + } configuration_mode = true; } diff --git a/src/WiFiManager_NINA_Lite_nRF52.h b/src/WiFiManager_NINA_Lite_nRF52.h new file mode 100644 index 00000000..d39ea08e --- /dev/null +++ b/src/WiFiManager_NINA_Lite_nRF52.h @@ -0,0 +1,1898 @@ +/********************************************************************************************************************************* + WiFiManager_NINA_Lite_nRF52.h + For nRF52 boards using WiFiNINA modules/shields, using much less code to support boards with smaller memory + + WiFiManager_NINA_WM_Lite is a library for the Mega, Teensy, SAM DUE, SAMD and STM32 boards + (https://github.com/khoih-prog/WiFiManager_NINA_Lite) to enable store Credentials in EEPROM/LittleFS for easy + configuration/reconfiguration and autoconnect/autoreconnect of WiFi and other services without Hardcoding. + + Built by Khoi Hoang https://github.com/khoih-prog/WiFiManager_NINA_Lite + Licensed under MIT license + Version: 1.1.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 26/03/2020 Initial coding + 1.0.1 K Hoang 27/03/2020 Fix SAMD soft-reset bug. Add support to remaining boards + 1.0.2 K Hoang 15/04/2020 Fix bug. Add SAMD51 support. + 1.0.3 K Hoang 24/04/2020 Fix bug. Add nRF5 (Adafruit, NINA_B302_ublox, etc.) support. Add MultiWiFi, HostName capability. + SSID password maxlen is 63 now. Permit special chars # and % in input data. + 1.0.4 K Hoang 04/05/2020 Add Configurable Config Portal Title, Default Config Data and DRD. Update examples. + 1.0.5 K Hoang 11/07/2020 Modify LOAD_DEFAULT_CONFIG_DATA logic. Enhance MultiWiFi connection logic. Add MQTT examples. + 1.1.0 K Hoang 19/02/2021 Optimize code and use better FlashStorage_SAMD and FlashStorage_STM32. + Add customs HTML header feature. Fix bug. + **********************************************************************************************************************************/ + +#ifndef WiFiManager_NINA_Lite_nRF52_h +#define WiFiManager_NINA_Lite_nRF52_h + +#if ( defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) ) + #if defined(WIFININA_USE_NRF528XX) + #undef WIFININA_USE_NRF528XX + #endif + #define WIFININA_USE_NRF528XX true +#endif + +#if ( defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA) || \ + defined(CORE_TEENSY) || WIFININA_USE_SAMD || !(WIFININA_USE_NRF528XX) ) + #error This code is intended to run on the SAMD platform! Please check your Tools->Board setting. +#endif + +#define WIFIMANAGER_NINA_LITE_VERSION "WiFiManager_NINA_Lite v1.1.0" + +#include + +//Use LittleFS for nRF52 +#include +#include + +using namespace Adafruit_LittleFS_Namespace; +File file(InternalFS); + +#include + +#ifndef USING_CUSTOMS_STYLE + #define USING_CUSTOMS_STYLE false +#endif + +#ifndef USING_CUSTOMS_HEAD_ELEMENT + #define USING_CUSTOMS_HEAD_ELEMENT false +#endif + +#ifndef USING_CORS_FEATURE + #define USING_CORS_FEATURE false +#endif + +///////// NEW for DRD ///////////// +// These defines must be put before #include +// to select where to store DoubleResetDetector_Generic's variable. +// Otherwise, library will use default EEPROM storage +#define DRD_FLAG_DATA_SIZE 4 + +#ifndef DOUBLERESETDETECTOR_DEBUG +#define DOUBLERESETDETECTOR_DEBUG false +#endif + +#include //https://github.com/khoih-prog/DoubleResetDetector_Generic + +// Number of seconds after reset during which a +// subseqent reset will be considered a double reset. +#define DRD_TIMEOUT 10 + +// RTC Memory Address for the DoubleResetDetector_Generic to use +#define DRD_ADDRESS 0 + +DoubleResetDetector_Generic* drd; + +///////// NEW for DRD ///////////// + + +//NEW +#define MAX_ID_LEN 5 +#define MAX_DISPLAY_NAME_LEN 16 + +typedef struct +{ + char id [MAX_ID_LEN + 1]; + char displayName [MAX_DISPLAY_NAME_LEN + 1]; + char *pdata; + uint8_t maxlen; +} MenuItem; +// + +#if USE_DYNAMIC_PARAMETERS + #warning Using Dynamic Parameters + ///NEW + extern uint16_t NUM_MENU_ITEMS; + extern MenuItem myMenuItems []; + bool *menuItemUpdated = NULL; +#else + #warning Not using Dynamic Parameters +#endif + +#define SSID_MAX_LEN 32 +//From v1.0.3, WPA2 passwords can be up to 63 characters long. +#define PASS_MAX_LEN 64 + +typedef struct +{ + char wifi_ssid[SSID_MAX_LEN]; + char wifi_pw [PASS_MAX_LEN]; +} WiFi_Credentials; + +#define NUM_WIFI_CREDENTIALS 2 + +// Configurable items besides fixed Header, just add board_name +#define NUM_CONFIGURABLE_ITEMS ( ( 2 * NUM_WIFI_CREDENTIALS ) + 1 ) +//////////////// + +#define HEADER_MAX_LEN 16 +#define BOARD_NAME_MAX_LEN 24 + +typedef struct Configuration +{ + char header [HEADER_MAX_LEN]; + WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + char board_name [BOARD_NAME_MAX_LEN]; + int checkSum; +} WiFiNINA_Configuration; + +// Currently CONFIG_DATA_SIZE = 236 = (16 + 96 * 2 + 4 + 24) +uint16_t CONFIG_DATA_SIZE = sizeof(WiFiNINA_Configuration); + +///New from v1.0.4 +extern bool LOAD_DEFAULT_CONFIG_DATA; +extern WiFiNINA_Configuration defaultConfig; + +// -- HTML page fragments + +const char WIFININA_HTML_HEAD_START[] /*PROGMEM*/ = "nRF52_WM_NINA_Lite"; + +const char WIFININA_HTML_HEAD_STYLE[] /*PROGMEM*/ = ""; + +const char WIFININA_HTML_HEAD_END[] /*PROGMEM*/ = "
\ +
\ +
\ +
\ +
\ +
"; + +const char WIFININA_FLDSET_START[] /*PROGMEM*/ = "
"; +const char WIFININA_FLDSET_END[] /*PROGMEM*/ = "
"; +const char WIFININA_HTML_PARAM[] /*PROGMEM*/ = "
"; +const char WIFININA_HTML_BUTTON[] /*PROGMEM*/ = "
"; +const char WIFININA_HTML_SCRIPT[] /*PROGMEM*/ = ""; +const char WIFININA_HTML_END[] /*PROGMEM*/ = ""; + +////////////////////////////////////////// + +//KH Add repeatedly used const +//KH, from v1.1.0 +const char WM_HTTP_HEAD_CL[] PROGMEM = "Content-Length"; +const char WM_HTTP_HEAD_TEXT_HTML[] PROGMEM = "text/html"; +const char WM_HTTP_HEAD_TEXT_PLAIN[] PROGMEM = "text/plain"; + +const char WM_HTTP_CACHE_CONTROL[] PROGMEM = "Cache-Control"; +const char WM_HTTP_NO_STORE[] PROGMEM = "no-cache, no-store, must-revalidate"; +const char WM_HTTP_PRAGMA[] PROGMEM = "Pragma"; +const char WM_HTTP_NO_CACHE[] PROGMEM = "no-cache"; +const char WM_HTTP_EXPIRES[] PROGMEM = "Expires"; + +const char WM_HTTP_CORS[] PROGMEM = "Access-Control-Allow-Origin"; +const char WM_HTTP_CORS_ALLOW_ALL[] PROGMEM = "*"; + +////////////////////////////////////////// + +String IPAddressToString(IPAddress _address) +{ + String str = String(_address[0]); + str += "."; + str += String(_address[1]); + str += "."; + str += String(_address[2]); + str += "."; + str += String(_address[3]); + return str; +} + +class WiFiManager_NINA_Lite +{ + public: + + WiFiManager_NINA_Lite() + { + // check for the presence of the shield +#if USE_WIFI101 + if (WiFi.status() == WL_NO_SHIELD) +#else + if (WiFi.status() == WL_NO_MODULE) +#endif + { + WN_LOGERROR(F("NoWiFi")); + } + } + + ~WiFiManager_NINA_Lite() + { + if (server) + delete server; + } + + bool connectWiFi(const char* ssid, const char* pass) + { + WN_LOGERROR1(F("Con2:"), ssid); + + setHostname(); + + if ( WiFi.begin(ssid, pass) == WL_CONNECTED ) + { + displayWiFiData(); + } + else + { + WN_LOGERROR(F("NoW")); + return false; + } + + WN_LOGERROR(F("WOK")); + + wifi_connected = true; + + return true; + } + + void begin(const char* ssid, + const char* pass ) + { + WN_LOGERROR(F("conW")); + connectWiFi(ssid, pass); + } + + void begin(const char *iHostname = "") + { + #define RETRY_TIMES_CONNECT_WIFI 3 + + if (iHostname[0] == 0) + { + String randomNum = String(random(0xFFFFFF), HEX); + randomNum.toUpperCase(); + + String _hostname = "NRF52-WiFiNINA-" + randomNum; + _hostname.toUpperCase(); + + getRFC952_hostname(_hostname.c_str()); + } + else + { + // Prepare and store the hostname only not NULL + getRFC952_hostname(iHostname); + } + + WN_LOGERROR1(F("Hostname="), RFC952_hostname); + ////// + + //// New DRD //// + drd = new DoubleResetDetector_Generic(DRD_TIMEOUT, DRD_ADDRESS); + bool noConfigPortal = true; + + if (drd->detectDoubleReset()) + { + WN_LOGERROR(F("Double Reset Detected")); + + noConfigPortal = false; + } + //// New DRD //// + + if (LOAD_DEFAULT_CONFIG_DATA) + { + WN_LOGERROR(F("======= Start Default Config Data =======")); + displayConfigData(defaultConfig); + } + + hadConfigData = getConfigData(); + + isForcedConfigPortal = isForcedCP(); + + //// New DRD/MRD //// + // noConfigPortal when getConfigData() OK and no MRD/DRD'ed + if (hadConfigData && noConfigPortal && (!isForcedConfigPortal) ) + { + hadConfigData = true; + + if (connectMultiWiFi(RETRY_TIMES_CONNECT_WIFI)) + { + WN_LOGERROR(F("b:WOK")); + } + else + { + WN_LOGERROR(F("b:NoW")); + // failed to connect to WiFi, will start configuration mode + startConfigurationMode(); + } + } + else + { + WN_LOGERROR(isForcedConfigPortal? F("bg: isForcedConfigPortal = true") : F("bg: isForcedConfigPortal = false")); + + // If not persistent => clear the flag so that after reset. no more CP, even CP not entered and saved + if (persForcedConfigPortal) + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + } + else + { + WN_LOGERROR1(F("bg:Stay forever in CP:"), isForcedConfigPortal ? F("Forced-non-Persistent") : (noConfigPortal ? F("No ConfigDat") : F("DRD/MRD"))); + clearForcedCP(); + } + + //To permit autoreset after timeout if DRD/MRD or non-persistent forced-CP + hadConfigData = isForcedConfigPortal ? true : (noConfigPortal ? false : true); + + // failed to connect to WiFi, will start configuration mode + startConfigurationMode(); + } + } + + +#ifndef RETRY_TIMES_RECONNECT_WIFI + #define RETRY_TIMES_RECONNECT_WIFI 2 +#else + // Force range of user-defined RETRY_TIMES_RECONNECT_WIFI between 2-5 times + #if (RETRY_TIMES_RECONNECT_WIFI < 2) + #warning RETRY_TIMES_RECONNECT_WIFI too low. Reseting to 2 + #undef RETRY_TIMES_RECONNECT_WIFI + #define RETRY_TIMES_RECONNECT_WIFI 2 + #elif (RETRY_TIMES_RECONNECT_WIFI > 5) + #warning RETRY_TIMES_RECONNECT_WIFI too high. Reseting to 5 + #undef RETRY_TIMES_RECONNECT_WIFI + #define RETRY_TIMES_RECONNECT_WIFI 5 + #endif +#endif + +#ifndef RESET_IF_CONFIG_TIMEOUT + #define RESET_IF_CONFIG_TIMEOUT true +#endif + +#ifndef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 10 +#else + // Force range of user-defined TIMES_BEFORE_RESET between 2-100 + #if (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET < 2) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too low. Reseting to 2 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 2 + #elif (CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET > 100) + #warning CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET too high. Resetting to 100 + #undef CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET + #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET 100 + #endif +#endif + + void run() + { + static int retryTimes = 0; + static bool wifiDisconnectedOnce = false; + + // Lost connection in running. Give chance to reconfig. + // Check WiFi status every 5s and update status + // Check twice to be sure wifi disconnected is real + static unsigned long checkstatus_timeout = 0; + #define WIFI_STATUS_CHECK_INTERVAL 5000L + + //// New DRD //// + // Call the double reset detector loop method every so often, + // so that it can recognise when the timeout expires. + // You can also call drd.stop() when you wish to no longer + // consider the next reset as a double reset. + drd->loop(); + //// New DRD //// + + if ( !configuration_mode && (millis() > checkstatus_timeout) ) + { + if (WiFi.status() == WL_CONNECTED) + { + wifi_connected = true; + } + else + { + if (wifiDisconnectedOnce) + { + wifiDisconnectedOnce = false; + wifi_connected = false; + WN_LOGERROR(F("r:Check&WLost")); + } + else + { + wifiDisconnectedOnce = true; + } + } + + checkstatus_timeout = millis() + WIFI_STATUS_CHECK_INTERVAL; + } + + // Lost connection in running. Give chance to reconfig. + if ( !wifi_connected ) + { + // If configTimeout but user hasn't connected to configWeb => try to reconnect WiFi + // But if user has connected to configWeb, stay there until done, then reset hardware + if ( configuration_mode && ( configTimeout == 0 || millis() < configTimeout ) ) + { + retryTimes = 0; + + if (server) + { + //WN_LOGDEBUG(F("r:handleClient")); + server->handleClient(); + } + + return; + } + else + { +#if RESET_IF_CONFIG_TIMEOUT + // If we're here but still in configuration_mode, permit running TIMES_BEFORE_RESET times before reset hardware + // to permit user another chance to config. + if ( configuration_mode && (configTimeout != 0) ) + { + if (++retryTimes <= CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET) + { + WN_LOGERROR1(F("r:WLost&TOut.ConW.Retry#"), retryTimes); + } + else + { + resetFunc(); //call reset + } + } +#endif + + // Not in config mode, try reconnecting before forcing to config mode + if ( !wifi_connected ) + { + WN_LOGERROR(F("r:WLost.ReconW")); + + if (connectMultiWiFi(RETRY_TIMES_RECONNECT_WIFI)) + { + WN_LOGERROR(F("r:WOK")); + } + } + } + } + else if (configuration_mode) + { + configuration_mode = false; + WN_LOGERROR(F("r:gotWBack")); + } + } + + ////////////////////////////////////////////// + + void setHostname() + { + if (RFC952_hostname[0] != 0) + { +#if USE_WIFI101 + WiFi.hostname(RFC952_hostname); +#elif USE_WIFI_NINA + WiFi.setHostname(RFC952_hostname); +#endif + } + } + + ////////////////////////////////////////////// + + void setConfigPortalIP(IPAddress portalIP = IPAddress(192, 168, 4, 1)) + { + portal_apIP = portalIP; + } + + ////////////////////////////////////////////// + + #define MIN_WIFI_CHANNEL 1 + #define MAX_WIFI_CHANNEL 11 // Channel 13 is flaky, because of bad number 13 ;-) + + int setConfigPortalChannel(int channel = 1) + { + // If channel < MIN_WIFI_CHANNEL - 1 or channel > MAX_WIFI_CHANNEL => channel = 1 + // If channel == 0 => will use random channel from MIN_WIFI_CHANNEL to MAX_WIFI_CHANNEL + // If (MIN_WIFI_CHANNEL <= channel <= MAX_WIFI_CHANNEL) => use it + if ( (channel < MIN_WIFI_CHANNEL - 1) || (channel > MAX_WIFI_CHANNEL) ) + AP_channel = 1; + else if ( (channel >= MIN_WIFI_CHANNEL - 1) && (channel <= MAX_WIFI_CHANNEL) ) + AP_channel = channel; + + return AP_channel; + } + + ////////////////////////////////////////////// + + void setConfigPortal(String ssid = "", String pass = "") + { + portal_ssid = ssid; + portal_pass = pass; + } + + ////////////////////////////////////////////// + + void setSTAStaticIPConfig(IPAddress ip) + { + static_IP = ip; + } + + ////////////////////////////////////////////// + + String getWiFiSSID(uint8_t index) + { + if (index >= NUM_WIFI_CREDENTIALS) + return String(""); + + if (!hadConfigData) + getConfigData(); + + return (String(WIFININA_config.WiFi_Creds[index].wifi_ssid)); + } + + ////////////////////////////////////////////// + + String getWiFiPW(uint8_t index) + { + if (index >= NUM_WIFI_CREDENTIALS) + return String(""); + + if (!hadConfigData) + getConfigData(); + + return (String(WIFININA_config.WiFi_Creds[index].wifi_pw)); + } + + ////////////////////////////////////////////// + + bool getWiFiStatus() + { + return wifi_connected; + } + + ////////////////////////////////////////////// + + WiFiNINA_Configuration* getFullConfigData(WiFiNINA_Configuration *configData) + { + if (!hadConfigData) + getConfigData(); + + // Check if NULL pointer + if (configData) + memcpy(configData, &WIFININA_config, sizeof(WiFiNINA_Configuration)); + + return (configData); + } + + ////////////////////////////////////////////// + + String localIP() + { + ipAddress = IPAddressToString(WiFi.localIP()); + + return ipAddress; + } + + ////////////////////////////////////////////// + + void clearConfigData() + { + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + } +#endif + + saveConfigData(); + } + + ////////////////////////////////////////////// + + bool isConfigDataValid() + { + return hadConfigData; + } + + ////////////////////////////////////////////// + + // Forced CP => Flag = 0xBEEFBEEF. Else => No forced CP + // Flag to be stored at (EEPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // to avoid corruption to current data + //#define FORCED_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xDEADBEEF) + //#define FORCED_PERS_CONFIG_PORTAL_FLAG_DATA ( (uint32_t) 0xBEEFDEAD) + + const uint32_t FORCED_CONFIG_PORTAL_FLAG_DATA = 0xDEADBEEF; + const uint32_t FORCED_PERS_CONFIG_PORTAL_FLAG_DATA = 0xBEEFDEAD; + + #define FORCED_CONFIG_PORTAL_FLAG_DATA_SIZE 4 + + void resetAndEnterConfigPortal() + { + persForcedConfigPortal = false; + + setForcedCP(false); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// + + // This will keep CP forever, until you successfully enter CP, and Save data to clear the flag. + void resetAndEnterConfigPortalPersistent() + { + persForcedConfigPortal = true; + + setForcedCP(true); + + // Delay then reset the ESP8266 after save data + delay(1000); + resetFunc(); + } + + ////////////////////////////////////////////// + + void resetFunc() + { + delay(1000); + // Restart for nRF52 + NVIC_SystemReset(); + } + + ////////////////////////////////////// + + // Add customs headers from v1.1.0 + + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + +#if USING_CUSTOMS_STYLE + //sets a custom style, such as color + // ""; + void setCustomsStyle(const char* CustomsStyle = WIFININA_HTML_HEAD_STYLE) + { + WIFININA_HTML_HEAD_CUSTOMS_STYLE = CustomsStyle; + WN_LOGDEBUG1(F("Set CustomsStyle to : "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + } + + const char* getCustomsStyle() + { + WN_LOGDEBUG1(F("Get CustomsStyle = "), WIFININA_HTML_HEAD_CUSTOMS_STYLE); + return WIFININA_HTML_HEAD_CUSTOMS_STYLE; + } +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + //sets a custom element to add to head, like a new style tag + void setCustomsHeadElement(const char* CustomsHeadElement = NULL) + { + _CustomsHeadElement = CustomsHeadElement; + WN_LOGDEBUG1(F("Set CustomsHeadElement to : "), _CustomsHeadElement); + } + + const char* getCustomsHeadElement() + { + WN_LOGDEBUG1(F("Get CustomsHeadElement = "), _CustomsHeadElement); + return _CustomsHeadElement; + } +#endif + +#if USING_CORS_FEATURE + void setCORSHeader(const char* CORSHeaders = NULL) + { + _CORS_Header = CORSHeaders; + + WN_LOGDEBUG1(F("Set CORS Header to : "), _CORS_Header); + } + + const char* getCORSHeader() + { + WN_LOGDEBUG1(F("Get CORS Header = "), _CORS_Header); + return _CORS_Header; + } +#endif + + ////////////////////////////////////// + + + private: + String ipAddress = "0.0.0.0"; + + WiFiWebServer* server = NULL; + + bool configuration_mode = false; + + unsigned long configTimeout; + bool hadConfigData = false; + + bool isForcedConfigPortal = false; + bool persForcedConfigPortal = false; + + WiFiNINA_Configuration WIFININA_config; + + uint16_t totalDataSize = 0; + + String macAddress = ""; + bool wifi_connected = false; + + IPAddress portal_apIP = IPAddress(192, 168, 4, 1); + int AP_channel = 10; + + String portal_ssid = ""; + String portal_pass = ""; + + IPAddress static_IP = IPAddress(0, 0, 0, 0); + + ///////////////////////////////////// + + // Add customs headers from v1.1.0 + +#if USING_CUSTOMS_STYLE + const char* WIFININA_HTML_HEAD_CUSTOMS_STYLE = NULL; +#endif + +#if USING_CUSTOMS_HEAD_ELEMENT + const char* _CustomsHeadElement = NULL; +#endif + +#if USING_CORS_FEATURE + const char* _CORS_Header = WM_HTTP_CORS_ALLOW_ALL; //"*"; +#endif + + ////////////////////////////////////// + + #define RFC952_HOSTNAME_MAXLEN 24 + char RFC952_hostname[RFC952_HOSTNAME_MAXLEN + 1]; + + char* getRFC952_hostname(const char* iHostname) + { + memset(RFC952_hostname, 0, sizeof(RFC952_hostname)); + + size_t len = ( RFC952_HOSTNAME_MAXLEN < strlen(iHostname) ) ? RFC952_HOSTNAME_MAXLEN : strlen(iHostname); + + size_t j = 0; + + for (size_t i = 0; i < len - 1; i++) + { + if ( isalnum(iHostname[i]) || iHostname[i] == '-' ) + { + RFC952_hostname[j] = iHostname[i]; + j++; + } + } + // no '-' as last char + if ( isalnum(iHostname[len - 1]) || (iHostname[len - 1] != '-') ) + RFC952_hostname[j] = iHostname[len - 1]; + + return RFC952_hostname; + } + + ////////////////////////////////////////////// + + void displayConfigData(WiFiNINA_Configuration configData) + { + WN_LOGERROR5(F("Hdr="), configData.header, F(",SSID="), configData.WiFi_Creds[0].wifi_ssid, + F(",PW="), configData.WiFi_Creds[0].wifi_pw); + WN_LOGERROR3(F("SSID1="), configData.WiFi_Creds[1].wifi_ssid, F(",PW1="), configData.WiFi_Creds[1].wifi_pw); + WN_LOGERROR1(F("BName="), configData.board_name); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + WN_LOGERROR5("i=", i, ",id=", myMenuItems[i].id, ",data=", myMenuItems[i].pdata); + } +#endif + } + + ////////////////////////////////////////////// + + void displayWiFiData() + { + WN_LOGERROR3(F("SSID="), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); + WN_LOGERROR1(F("IP="), localIP() ); + } + +#define WIFININA_BOARD_TYPE "WIFININA" +#define WM_NO_CONFIG "blank" + + int calcChecksum() + { + int checkSum = 0; + for (uint16_t index = 0; index < (sizeof(WIFININA_config) - sizeof(WIFININA_config.checkSum)); index++) + { + checkSum += * ( ( (byte*) &WIFININA_config ) + index); + } + + return checkSum; + } + +// Use LittleFS/InternalFS for nRF52 +#define CONFIG_FILENAME ("/wm_config.dat") +#define CONFIG_FILENAME_BACKUP ("/wm_config.bak") + +#define CREDENTIALS_FILENAME ("/wm_cred.dat") +#define CREDENTIALS_FILENAME_BACKUP ("/wm_cred.bak") + +#define CONFIG_PORTAL_FILENAME ("/wm_cp.dat") +#define CONFIG_PORTAL_FILENAME_BACKUP ("/wm_cp.bak") + + ////////////////////////////////////////////// + + void saveForcedCP(uint32_t value) + { + file.open(CONFIG_PORTAL_FILENAME, FILE_O_WRITE); + //File file = FileFS.open(CONFIG_PORTAL_FILENAME, "w"); + + WN_LOGERROR(F("SaveCPFile ")); + + if (file) + { + file.seek(0); + file.write((uint8_t*) &value, sizeof(value)); + //file.write((uint8_t*) &value, sizeof(value)); + + file.close(); + WN_LOGERROR(F("OK")); + } + else + { + WN_LOGERROR(F("failed")); + } + + // Trying open redundant CP file + file.open(CONFIG_PORTAL_FILENAME_BACKUP, FILE_O_WRITE); + //file = FileFS.open(CONFIG_PORTAL_FILENAME_BACKUP, "w"); + + WN_LOGERROR(F("SaveBkUpCPFile ")); + + if (file) + { + file.seek(0); + file.write((uint8_t*) &value, sizeof(value)); + //file.write((uint8_t*) &value, sizeof(value)); + file.close(); + WN_LOGERROR(F("OK")); + } + else + { + WN_LOGERROR(F("failed")); + } + } + + ////////////////////////////////////////////// + + void setForcedCP(bool isPersistent) + { + uint32_t readForcedConfigPortalFlag = isPersistent? FORCED_PERS_CONFIG_PORTAL_FLAG_DATA : FORCED_CONFIG_PORTAL_FLAG_DATA; + + WN_LOGERROR(isPersistent ? F("setForcedCP Persistent") : F("setForcedCP non-Persistent")); + + saveForcedCP(readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + + void clearForcedCP() + { + uint32_t readForcedConfigPortalFlag = 0; + + WN_LOGERROR(F("clearForcedCP")); + + saveForcedCP(readForcedConfigPortalFlag); + } + + ////////////////////////////////////////////// + + bool isForcedCP() + { + uint32_t readForcedConfigPortalFlag; + + WN_LOGDEBUG(F("Check if isForcedCP")); + + file.open(CONFIG_PORTAL_FILENAME, FILE_O_READ); + //File file = FileFS.open(CONFIG_PORTAL_FILENAME, "r"); + WN_LOGDEBUG(F("LoadCPFile ")); + + if (!file) + { + WN_LOGDEBUG(F("failed")); + + // Trying open redundant config file + file.open(CONFIG_PORTAL_FILENAME_BACKUP, FILE_O_READ); + //file = FileFS.open(CONFIG_PORTAL_FILENAME_BACKUP, "r"); + WN_LOGDEBUG(F("LoadBkUpCPFile ")); + + if (!file) + { + WN_LOGDEBUG(F("failed")); + return false; + } + } + + file.seek(0); + file.read((char *) &readForcedConfigPortalFlag, sizeof(readForcedConfigPortalFlag)); + //file.readBytes((char *) &readForcedConfigPortalFlag, sizeof(readForcedConfigPortalFlag)); + + file.close(); + WN_LOGDEBUG(F("OK")); + + + // Return true if forced CP (0xDEADBEEF read at offset EPROM_START + DRD_FLAG_DATA_SIZE + CONFIG_DATA_SIZE) + // => set flag noForcedConfigPortal = false + if (readForcedConfigPortalFlag == FORCED_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = false; + return true; + } + else if (readForcedConfigPortalFlag == FORCED_PERS_CONFIG_PORTAL_FLAG_DATA) + { + persForcedConfigPortal = true; + return true; + } + else + { + return false; + } + } + + ////////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMETERS + + bool checkDynamicData() + { + int checkSum = 0; + int readCheckSum; + char* readBuffer; + + file.open(CREDENTIALS_FILENAME, FILE_O_READ); + WN_LOGDEBUG(F("LoadCredFile ")); + + if (!file) + { + WN_LOGDEBUG(F("failed")); + + // Trying open redundant config file + //file(CREDENTIALS_FILENAME_BACKUP, FILE_O_READ); + file.open(CREDENTIALS_FILENAME_BACKUP, FILE_O_READ); + WN_LOGDEBUG(F("LoadBkUpCredFile ")); + + if (!file) + { + WN_LOGDEBUG(F("failed")); + return false; + } + } + + // Find the longest pdata, then dynamically allocate buffer. Remember to free when done + // This is used to store tempo data to calculate checksum to see of data is valid + // We dont like to destroy myMenuItems[i].pdata with invalid data + + uint16_t maxBufferLength = 0; + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + if (myMenuItems[i].maxlen > maxBufferLength) + maxBufferLength = myMenuItems[i].maxlen; + } + + if (maxBufferLength > 0) + { + readBuffer = new char[ maxBufferLength + 1 ]; + + // check to see NULL => stop and return false + if (readBuffer == NULL) + { + WN_LOGDEBUG(F("ChkCrR: Error can't allocate buffer.")); + return false; + } + else + { + WN_LOGDEBUG1(F("ChkCrR: Buffer allocated, Sz="), maxBufferLength + 1); + } + } + else + { + WN_LOGDEBUG(F("ChkCrR: maxBufferLength = 0.")); + return false; + } + + uint16_t offset = 0; + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + char* _pointer = readBuffer; + + // Actual size of pdata is [maxlen + 1] + memset(readBuffer, 0, myMenuItems[i].maxlen + 1); + + // Redundant, but to be sure correct position + file.seek(offset); + file.read(_pointer, myMenuItems[i].maxlen); + + offset += myMenuItems[i].maxlen; + + WN_LOGDEBUG3(F("ChkCrR:pdata="), readBuffer, F(",len="), myMenuItems[i].maxlen); + + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) + { + checkSum += *_pointer; + } + } + + file.read((char *) &readCheckSum, sizeof(readCheckSum)); + + WN_LOGDEBUG(F("OK")); + file.close(); + + WN_LOGDEBUG3(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + + // Free buffer + if (readBuffer != NULL) + { + free(readBuffer); + WN_LOGDEBUG(F("Buffer freed")); + } + + if ( checkSum != readCheckSum) + { + return false; + } + + return true; + } + + ////////////////////////////////////////////// + + bool loadDynamicData() + { + int checkSum = 0; + int readCheckSum; + totalDataSize = sizeof(WIFININA_config) + sizeof(readCheckSum); + + file.open(CREDENTIALS_FILENAME, FILE_O_READ); + WN_LOGDEBUG(F("LoadCredFile ")); + + if (!file) + { + WN_LOGDEBUG(F("failed")); + + // Trying open redundant config file + file.open(CREDENTIALS_FILENAME_BACKUP, FILE_O_READ); + WN_LOGDEBUG(F("LoadBkUpCredFile ")); + + if (!file) + { + WN_LOGDEBUG(F("failed")); + return false; + } + } + + uint16_t offset = 0; + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + char* _pointer = myMenuItems[i].pdata; + totalDataSize += myMenuItems[i].maxlen; + + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + + // Redundant, but to be sure correct position + file.seek(offset); + file.read(_pointer, myMenuItems[i].maxlen); + + offset += myMenuItems[i].maxlen; + + WN_LOGDEBUG3(F("CrR:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) + { + checkSum += *_pointer; + } + } + + file.read((char *) &readCheckSum, sizeof(readCheckSum)); + + WN_LOGDEBUG(F("OK")); + file.close(); + + WN_LOGDEBUG3(F("CrCCsum=0x"), String(checkSum, HEX), F(",CrRCsum=0x"), String(readCheckSum, HEX)); + + if ( checkSum != readCheckSum) + { + return false; + } + + return true; + } + + ////////////////////////////////////////////// + + void saveDynamicData() + { + int checkSum = 0; + + file.open(CREDENTIALS_FILENAME, FILE_O_WRITE); + WN_LOGDEBUG(F("SaveCredFile ")); + + uint16_t offset = 0; + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + char* _pointer = myMenuItems[i].pdata; + + WN_LOGDEBUG3(F("CW1:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + + if (file) + { + // Redundant, but to be sure correct position + file.seek(offset); + file.write((uint8_t*) _pointer, myMenuItems[i].maxlen); + + offset += myMenuItems[i].maxlen; + } + else + { + WN_LOGDEBUG(F("failed")); + } + + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) + { + checkSum += *_pointer; + } + } + + if (file) + { + file.write((uint8_t*) &checkSum, sizeof(checkSum)); + file.close(); + WN_LOGDEBUG(F("OK")); + } + else + { + WN_LOGDEBUG(F("failed")); + } + + WN_LOGDEBUG1(F("CrWCSum=0x"), String(checkSum, HEX)); + + // Trying open redundant Auth file + file.open(CREDENTIALS_FILENAME_BACKUP, FILE_O_WRITE); + WN_LOGDEBUG(F("SaveBkUpCredFile ")); + + offset = 0; + + for (int i = 0; i < NUM_MENU_ITEMS; i++) + { + char* _pointer = myMenuItems[i].pdata; + + WN_LOGDEBUG3(F("CW2:pdata="), myMenuItems[i].pdata, F(",len="), myMenuItems[i].maxlen); + + if (file) + { + file.seek(offset); + file.write((uint8_t*) _pointer, myMenuItems[i].maxlen); + + // Redundant, but to be sure correct position + offset += myMenuItems[i].maxlen; + } + else + { + WN_LOGDEBUG(F("failed")); + } + + for (uint16_t j = 0; j < myMenuItems[i].maxlen; j++,_pointer++) + { + checkSum += *_pointer; + } + } + + if (file) + { + file.write((uint8_t*) &checkSum, sizeof(checkSum)); + file.close(); + WN_LOGDEBUG(F("OK")); + } + else + { + WN_LOGDEBUG(F("failed")); + } + } +#endif + + ////////////////////////////////////////////// + + void NULLTerminateConfig() + { + //#define HEADER_MAX_LEN 16 + //#define SERVER_MAX_LEN 32 + //#define TOKEN_MAX_LEN 36 + + // NULL Terminating to be sure + WIFININA_config.header[HEADER_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[0].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_ssid[SSID_MAX_LEN - 1] = 0; + WIFININA_config.WiFi_Creds[1].wifi_pw [PASS_MAX_LEN - 1] = 0; + WIFININA_config.board_name[BOARD_NAME_MAX_LEN - 1] = 0; + } + + ////////////////////////////////////////////// + + void loadConfigData() + { + WN_LOGDEBUG(F("LoadCfgFile ")); + + // file existed + file.open(CONFIG_FILENAME, FILE_O_READ); + if (!file) + { + WN_LOGDEBUG(F("failed")); + + // Trying open redundant config file + file.open(CONFIG_FILENAME_BACKUP, FILE_O_READ); + WN_LOGDEBUG(F("LoadBkUpCfgFile ")); + + if (!file) + { + WN_LOGDEBUG(F("failed")); + return; + } + } + + file.seek(0); + file.read((char *) &WIFININA_config, sizeof(WIFININA_config)); + + WN_LOGDEBUG(F("OK")); + file.close(); + } + + ////////////////////////////////////////////// + + void saveConfigData() + { + WN_LOGDEBUG(F("SaveCfgFile ")); + + int calChecksum = calcChecksum(); + WIFININA_config.checkSum = calChecksum; + WN_LOGDEBUG1(F("WCSum=0x"), String(calChecksum, HEX)); + + file.open(CONFIG_FILENAME, FILE_O_WRITE); + + if (file) + { + file.seek(0); + file.write((uint8_t*) &WIFININA_config, sizeof(WIFININA_config)); + + file.close(); + WN_LOGDEBUG(F("OK")); + } + else + { + WN_LOGDEBUG(F("failed")); + } + + WN_LOGDEBUG(F("SaveBkUpCfgFile ")); + + // Trying open redundant Auth file + file.open(CONFIG_FILENAME_BACKUP, FILE_O_WRITE); + + if (file) + { + file.seek(0); + file.write((uint8_t *) &WIFININA_config, sizeof(WIFININA_config)); + + file.close(); + WN_LOGDEBUG(F("OK")); + } + else + { + WN_LOGDEBUG(F("failed")); + } + +#if USE_DYNAMIC_PARAMETERS + saveDynamicData(); +#endif + } + + ////////////////////////////////////////////// + + // New from v1.0.5 + void loadAndSaveDefaultConfigData() + { + // Load Default Config Data from Sketch + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); + + // Including config and dynamic data, and assume valid + saveConfigData(); + + WN_LOGDEBUG(F("======= Start Loaded Config Data =======")); + displayConfigData(WIFININA_config); + } + + ////////////////////////////////////////////// + + // Return false if init new EEPROM or SPIFFS. No more need trying to connect. Go directly to config mode + bool getConfigData() + { + bool dynamicDataValid = true; + int calChecksum; + + hadConfigData = false; + + // Initialize Internal File System + if (!InternalFS.begin()) + { + WN_LOGERROR(F("InternalFS failed")); + return false; + } + + // Use new LOAD_DEFAULT_CONFIG_DATA logic + if (LOAD_DEFAULT_CONFIG_DATA) + { + // Load Config Data from Sketch + loadAndSaveDefaultConfigData(); + + // Don't need Config Portal anymore + return true; + } + else + { + // Load stored config data from LittleFS + loadConfigData(); + + // Verify ChkSum + calChecksum = calcChecksum(); + + WN_LOGERROR3(F("CCSum=0x"), String(calChecksum, HEX), + F(",RCSum=0x"), String(WIFININA_config.checkSum, HEX)); + +#if USE_DYNAMIC_PARAMETERS + // Load stored dynamic data from LittleFS + dynamicDataValid = checkDynamicData(); +#endif + + // If checksum = 0 => LittleFS has been cleared (by uploading new FW, etc) => force to CP + // If bad checksum = 0 => force to CP + if ( (calChecksum != 0) && (calChecksum == WIFININA_config.checkSum) ) + { + if (dynamicDataValid) + { + #if USE_DYNAMIC_PARAMETERS + loadDynamicData(); + + #if ( BLYNK_WM_DEBUG > 2) + WN_LOGERROR(F("Valid Stored Dynamic Data")); + #endif + #endif + + WN_LOGERROR(F("======= Start Stored Config Data =======")); + displayConfigData(WIFININA_config); + + // Don't need Config Portal anymore + return true; + } + else + { + // Invalid Stored config data => Config Portal + WN_LOGERROR(F("Invalid Stored Dynamic Data. Load default from Sketch")); + + // Load Default Config Data from Sketch, better than just "blank" + loadAndSaveDefaultConfigData(); + + // Need Config Portal here as data can be just dummy + // Even if you don't open CP, you're OK on next boot if your default config data is valid + return false; + } + } + } + + if ( (strncmp(WIFININA_config.header, WIFININA_BOARD_TYPE, strlen(WIFININA_BOARD_TYPE)) != 0) || + (calChecksum != WIFININA_config.checkSum) || !dynamicDataValid || + ( (calChecksum == 0) && (WIFININA_config.checkSum == 0) ) ) + { + // Including Credentials CSum + WN_LOGERROR1(F("InitCfgFile,sz="), sizeof(WIFININA_config)); + + // doesn't have any configuration + if (LOAD_DEFAULT_CONFIG_DATA) + { + memcpy(&WIFININA_config, &defaultConfig, sizeof(WIFININA_config)); + } + else + { + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + } +#endif + + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG); + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG); + strcpy(WIFININA_config.board_name, WM_NO_CONFIG); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + strncpy(myMenuItems[i].pdata, WM_NO_CONFIG, myMenuItems[i].maxlen); + } +#endif + } + + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + WN_LOGDEBUG3(F("g:myMenuItems["), i, F("]="), myMenuItems[i].pdata ); + } +#endif + + // Don't need + WIFININA_config.checkSum = 0; + + saveConfigData(); + + return false; + } + else if ( !strncmp(WIFININA_config.WiFi_Creds[0].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[0].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_ssid, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strncmp(WIFININA_config.WiFi_Creds[1].wifi_pw, WM_NO_CONFIG, strlen(WM_NO_CONFIG) ) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_ssid) || + !strlen(WIFININA_config.WiFi_Creds[0].wifi_pw) || + !strlen(WIFININA_config.WiFi_Creds[1].wifi_pw) ) + { + // If SSID, PW ="nothing", stay in config mode forever until having config Data. + return false; + } + else + { + displayConfigData(WIFININA_config); + } + + return true; + } + + ////////////////////////////////////////////// + + // New connection logic from v1.0.5 + bool connectMultiWiFi(int retry_time) + { + int sleep_time = 250; + int index = 0; + uint8_t status; + + static int lastConnectedIndex = 255; + + WN_LOGDEBUG(F("ConMultiWifi")); + + if (static_IP != IPAddress(0, 0, 0, 0)) + { + WN_LOGDEBUG(F("UseStatIP")); + WiFi.config(static_IP); + } + + if (lastConnectedIndex != 255) + { + index = (lastConnectedIndex + 1) % NUM_WIFI_CREDENTIALS; + WN_LOGDEBUG3(F("Using index="), index, F(", lastConnectedIndex="), lastConnectedIndex); + } + + WN_LOGDEBUG3(F("con2WF:SSID="), WIFININA_config.WiFi_Creds[index].wifi_ssid, + F(",PW="), WIFININA_config.WiFi_Creds[index].wifi_pw); + + while ( !wifi_connected && ( 0 < retry_time ) ) + { + WN_LOGDEBUG1(F("Remaining retry_time="), retry_time); + + status = WiFi.begin(WIFININA_config.WiFi_Creds[index].wifi_ssid, WIFININA_config.WiFi_Creds[index].wifi_pw); + + // Need restart WiFi at beginning of each cycle + if (status == WL_CONNECTED) + { + wifi_connected = true; + lastConnectedIndex = index; + WN_LOGDEBUG1(F("WOK, lastConnectedIndex="), lastConnectedIndex); + + break; + } + else + { + delay(sleep_time); + retry_time--; + } + } + + if (retry_time <= 0) + { + WN_LOGDEBUG3(F("Failed using index="), index, F(", retry_time="), retry_time); + } + + if (wifi_connected) + { + WN_LOGDEBUG(F("con2WF:OK")); + displayWiFiData(); + } + else + { + WN_LOGDEBUG(F("con2WF:failed")); + // Can't connect, so try another index next time. Faking this index is OK and lost + lastConnectedIndex = index; + } + + return wifi_connected; + } + + ////////////////////////////////////////////// + + // NEW + void createHTML(String& root_html_template) + { + String pitem; + + root_html_template = WIFININA_HTML_HEAD_START; + + #if USING_CUSTOMS_STYLE + // Using Customs style when not NULL + if (WIFININA_HTML_HEAD_CUSTOMS_STYLE) + root_html_template += WIFININA_HTML_HEAD_CUSTOMS_STYLE; + else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #else + root_html_template += WIFININA_HTML_HEAD_STYLE; + #endif + + #if USING_CUSTOMS_HEAD_ELEMENT + if (_CustomsHeadElement) + root_html_template += _CustomsHeadElement; + #endif + + root_html_template += String(WIFININA_HTML_HEAD_END) + WIFININA_FLDSET_START; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + pitem = String(WIFININA_HTML_PARAM); + + pitem.replace("{b}", myMenuItems[i].displayName); + pitem.replace("{v}", myMenuItems[i].id); + pitem.replace("{i}", myMenuItems[i].id); + + root_html_template += pitem; + } + + root_html_template += String(WIFININA_FLDSET_END) + WIFININA_HTML_BUTTON + WIFININA_HTML_SCRIPT; + + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + pitem = String(WIFININA_HTML_SCRIPT_ITEM); + + pitem.replace("{d}", myMenuItems[i].id); + + root_html_template += pitem; + } + + root_html_template += String(WIFININA_HTML_SCRIPT_END) + WIFININA_HTML_END; + + return; + } + + ////////////////////////////////////////////// + + void serverSendHeaders() + { + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CACHE_CONTROL:"), WM_HTTP_CACHE_CONTROL, "=", WM_HTTP_NO_STORE); + server->sendHeader(WM_HTTP_CACHE_CONTROL, WM_HTTP_NO_STORE); + +#if USING_CORS_FEATURE + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_CORS:"), WM_HTTP_CORS, " : ", _CORS_Header); + server->sendHeader(WM_HTTP_CORS, _CORS_Header); +#endif + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_PRAGMA:"), WM_HTTP_PRAGMA, " : ", WM_HTTP_NO_CACHE); + server->sendHeader(WM_HTTP_PRAGMA, WM_HTTP_NO_CACHE); + + WN_LOGDEBUG3(F("serverSendHeaders:WM_HTTP_EXPIRES:"), WM_HTTP_EXPIRES, " : ", "-1"); + server->sendHeader(WM_HTTP_EXPIRES, "-1"); + } + + ////////////////////////////////////////////// + + void handleRequest() + { + if (server) + { + String key = server->arg("key"); + String value = server->arg("value"); + + static int number_items_Updated = 0; + + if (key == "" && value == "") + { + // New from v1.1.0 + serverSendHeaders(); + ////// + + String result; + createHTML(result); + + // Reset configTimeout to stay here until finished. + configTimeout = 0; + + if ( RFC952_hostname[0] != 0 ) + { + // Replace only if Hostname is valid + result.replace("SAMD_WM_NINA_Lite", RFC952_hostname); + } + else if ( WIFININA_config.board_name[0] != 0 ) + { + // Or replace only if board_name is valid. Otherwise, keep intact + result.replace("SAMD_WM_NINA_Lite", WIFININA_config.board_name); + } + + result.replace("[[id]]", WIFININA_config.WiFi_Creds[0].wifi_ssid); + result.replace("[[pw]]", WIFININA_config.WiFi_Creds[0].wifi_pw); + result.replace("[[id1]]", WIFININA_config.WiFi_Creds[1].wifi_ssid); + result.replace("[[pw1]]", WIFININA_config.WiFi_Creds[1].wifi_pw); + result.replace("[[nm]]", WIFININA_config.board_name); + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + String toChange = String("[[") + myMenuItems[i].id + "]]"; + result.replace(toChange, myMenuItems[i].pdata); + } +#endif + + + WN_LOGDEBUG1(F("h:HTML page size:"), result.length()); + WN_LOGDEBUG1(F("h:HTML="), result); + + server->send(200, "text/html", result); + + return; + } + + if (number_items_Updated == 0) + { + memset(&WIFININA_config, 0, sizeof(WIFININA_config)); + strcpy(WIFININA_config.header, WIFININA_BOARD_TYPE); + } + +#if USE_DYNAMIC_PARAMETERS + if (!menuItemUpdated) + { + // Don't need to free + menuItemUpdated = new bool[NUM_MENU_ITEMS]; + + if (menuItemUpdated) + { + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + // To flag item is not yet updated + menuItemUpdated[i] = false; + } + + WN_LOGDEBUG1(F("h: Init menuItemUpdated :" ), NUM_MENU_ITEMS); + } + else + { + WN_LOGERROR(F("h: Error can't alloc memory for menuItemUpdated" )); + } + } +#endif + + static bool id_Updated = false; + static bool pw_Updated = false; + static bool id1_Updated = false; + static bool pw1_Updated = false; + static bool nm_Updated = false; + + if (!id_Updated && (key == String("id"))) + { + WN_LOGDEBUG(F("h:repl id")); + id_Updated = true; + + number_items_Updated++; + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str()); + else + strncpy(WIFININA_config.WiFi_Creds[0].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_ssid) - 1); + } + else if (!pw_Updated && (key == String("pw"))) + { + WN_LOGDEBUG(F("h:repl pw")); + pw_Updated = true; + + number_items_Updated++; + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str()); + else + strncpy(WIFININA_config.WiFi_Creds[0].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[0].wifi_pw) - 1); + } + else if (!id1_Updated && (key == String("id1"))) + { + WN_LOGDEBUG(F("h:repl id1")); + id1_Updated = true; + + number_items_Updated++; + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str()); + else + strncpy(WIFININA_config.WiFi_Creds[1].wifi_ssid, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_ssid) - 1); + } + else if (!pw1_Updated && (key == String("pw1"))) + { + WN_LOGDEBUG(F("h:repl pw1")); + pw1_Updated = true; + + number_items_Updated++; + if (strlen(value.c_str()) < sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1) + strcpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str()); + else + strncpy(WIFININA_config.WiFi_Creds[1].wifi_pw, value.c_str(), sizeof(WIFININA_config.WiFi_Creds[1].wifi_pw) - 1); + } + else if (!nm_Updated && (key == String("nm"))) + { + WN_LOGDEBUG(F("h:repl nm")); + nm_Updated = true; + + number_items_Updated++; + if (strlen(value.c_str()) < sizeof(WIFININA_config.board_name) - 1) + strcpy(WIFININA_config.board_name, value.c_str()); + else + strncpy(WIFININA_config.board_name, value.c_str(), sizeof(WIFININA_config.board_name) - 1); + } + else + { + +#if USE_DYNAMIC_PARAMETERS + for (uint16_t i = 0; i < NUM_MENU_ITEMS; i++) + { + if ( !menuItemUpdated[i] && (key == myMenuItems[i].id) ) + { + WN_LOGDEBUG3(F("h:"), myMenuItems[i].id, F("="), value.c_str() ); + + menuItemUpdated[i] = true; + + number_items_Updated++; + + // Actual size of pdata is [maxlen + 1] + memset(myMenuItems[i].pdata, 0, myMenuItems[i].maxlen + 1); + + if ((int) strlen(value.c_str()) < myMenuItems[i].maxlen) + strcpy(myMenuItems[i].pdata, value.c_str()); + else + strncpy(myMenuItems[i].pdata, value.c_str(), myMenuItems[i].maxlen); + + break; + } + } +#endif + } + + WN_LOGDEBUG1(F("h:items updated ="), number_items_Updated); + WN_LOGDEBUG3(F("h:key ="), key, ", value =", value); + + server->send(200, "text/html", "OK"); + +#if USE_DYNAMIC_PARAMETERS + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS + NUM_MENU_ITEMS) +#else + if (number_items_Updated == NUM_CONFIGURABLE_ITEMS) +#endif + { + WN_LOGDEBUG(F("h:UpdLittleFS")); + + saveConfigData(); + + WN_LOGDEBUG(F("h:Rst")); + + // TO DO : what command to reset + // Delay then reset the board after save data + delay(1000); + resetFunc(); //call reset + } + } // if (server) + } + + ////////////////////////////////////////////// + +#ifndef CONFIG_TIMEOUT + #warning Default CONFIG_TIMEOUT = 60s + #define CONFIG_TIMEOUT 60000L +#endif + + void startConfigurationMode() + { + WiFi.config(portal_apIP); + + if ( (portal_ssid == "") || portal_pass == "" ) + { + String randomNum = String(random(0xFFFFFF), HEX); + randomNum.toUpperCase(); + + portal_ssid = "WIFININA_" + randomNum; + portal_pass = "MyWIFININA_" + randomNum; + } + + // start access point, AP only, channel 10 + + uint16_t channel; + + // Use random channel if AP_channel == 0 + if (AP_channel == 0) + channel = (millis() % MAX_WIFI_CHANNEL) + 1; + else + channel = AP_channel; + + WN_LOGERROR3(F("SSID="), portal_ssid, F(",PW="), portal_pass); + WN_LOGERROR3(F("IP="), portal_apIP, F(",CH="), channel); + +#if USE_ESP_AT_SHIELD + // start access point, AP only,default channel 10 + WiFi.beginAP(portal_ssid.c_str(), channel, portal_pass.c_str(), ENC_TYPE_WPA2_PSK, true); +#else + // start access point, AP only,default channel 10 + WiFi.beginAP(portal_ssid.c_str(), portal_pass.c_str(), channel); +#endif + + + if (!server) + { + server = new WiFiWebServer; + } + + //See https://stackoverflow.com/questions/39803135/c-unresolved-overloaded-function-type?rq=1 + + if (server) + { + server->on("/", [this](){ handleRequest(); }); + server->begin(); + } + + // If there is no saved config Data, stay in config mode forever until having config Data. + // or SSID, PW, Server,Token ="nothing" + if (hadConfigData) + { + configTimeout = millis() + CONFIG_TIMEOUT; + + WN_LOGDEBUG3(F("s:millis() = "), millis(), F(", configTimeout = "), configTimeout); + } + else + { + configTimeout = 0; + + WN_LOGDEBUG(F("s:configTimeout = 0")); + } + + configuration_mode = true; + } +}; + + +#endif //WiFiManager_NINA_Lite_nRF52_h