From 4ff114642ec49e42ac3091d09e0c576c4e3732a8 Mon Sep 17 00:00:00 2001 From: Magnus Persson Date: Sun, 9 Jan 2022 23:12:40 +0100 Subject: [PATCH] Added wifmanager --- .../ESP_DoubleResetDetector.h | 368 +++ lib/ESP_WiFiManager/ESP_WiFiManager-Impl.h | 2122 ++++++++++++++++ lib/ESP_WiFiManager/ESP_WiFiManager.h | 728 ++++++ lib/ESP_WiFiManager/ESP_WiFiManager_Debug.h | 127 + lib/ESP_WiFiManager/utils/TZ.h | 2150 +++++++++++++++++ platformio.ini | 11 +- src/main.cpp | 40 +- src/wifi.cpp | 195 +- src/wifi.hpp | 25 +- 9 files changed, 5659 insertions(+), 107 deletions(-) create mode 100644 lib/ESP_DoubleResetDetector/ESP_DoubleResetDetector.h create mode 100644 lib/ESP_WiFiManager/ESP_WiFiManager-Impl.h create mode 100644 lib/ESP_WiFiManager/ESP_WiFiManager.h create mode 100644 lib/ESP_WiFiManager/ESP_WiFiManager_Debug.h create mode 100644 lib/ESP_WiFiManager/utils/TZ.h diff --git a/lib/ESP_DoubleResetDetector/ESP_DoubleResetDetector.h b/lib/ESP_DoubleResetDetector/ESP_DoubleResetDetector.h new file mode 100644 index 0000000..6f049f5 --- /dev/null +++ b/lib/ESP_DoubleResetDetector/ESP_DoubleResetDetector.h @@ -0,0 +1,368 @@ +/**************************************************************************************************************************** + ESP_DoubleResetDetector.h + For ESP8266 / ESP32 boards + + ESP_DoubleResetDetector is a library for the ESP8266/Arduino platform + to enable trigger configure mode by resetting ESP32 / ESP8266 twice. + + Forked from DataCute https://github.com/datacute/DoubleResetDetector + + Built by Khoi Hoang https://github.com/khoih-prog/ESP_DoubleResetDetector + Licensed under MIT license + Version: 1.2.1 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 15/12/2019 Initial coding + 1.0.1 K Hoang 30/12/2019 Now can use EEPROM or SPIFFS for both ESP8266 and ESP32. RTC still OK for ESP8266 + 1.0.2 K Hoang 10/04/2020 Fix bug by left-over cpp file and in example. + 1.0.3 K Hoang 13/05/2020 Update to use LittleFS for ESP8266 core 2.7.1+ + 1.1.0 K Hoang 04/12/2020 Add support to LittleFS for ESP32 using LITTLEFS Library + 1.1.1 K Hoang 28/12/2020 Suppress all possible compiler warnings + 1.1.2 K Hoang 10/10/2021 Update `platform.ini` and `library.json` + 1.2.0 K Hoang 26/11/2021 Auto detect ESP32 core and use either built-in LittleFS or LITTLEFS library + 1.2.1 K Hoang 26/11/2021 Fix compile error for ESP32 core v1.0.5- +*****************************************************************************************************************************/ + +#pragma once + +#ifndef ESP_DoubleResetDetector_H +#define ESP_DoubleResetDetector_H + +#if defined(ARDUINO) && (ARDUINO >= 100) + #include +#else + #include +#endif + +#define ESP_DOUBLE_RESET_DETECTOR_VERSION "ESP_DoubleResetDetector v1.2.1" +#define ESP_DOUBLERESETDETECTOR_VERSION ESP_DOUBLE_RESET_DETECTOR_VERSION + +//#define ESP_DRD_USE_EEPROM false +//#define ESP_DRD_USE_LITTLEFS false +//#define ESP_DRD_USE_SPIFFS false +//#define ESP8266_DRD_USE_RTC false //true + +#ifdef ESP32 + #if (!ESP_DRD_USE_EEPROM && !ESP_DRD_USE_SPIFFS && !ESP_DRD_USE_LITTLEFS) + #warning Neither EEPROM, SPIFFS nor LittleFS selected. Default to EEPROM + #ifdef ESP_DRD_USE_EEPROM + #undef ESP_DRD_USE_EEPROM + #define ESP_DRD_USE_EEPROM true + #endif + #endif +#endif + +#ifdef ESP8266 + #if (!ESP8266_DRD_USE_RTC && !ESP_DRD_USE_EEPROM && !ESP_DRD_USE_SPIFFS && !ESP_DRD_USE_LITTLEFS) + #warning Neither RTC, EEPROM, LITTLEFS nor SPIFFS selected. Default to EEPROM + #ifdef ESP_DRD_USE_EEPROM + #undef ESP_DRD_USE_EEPROM + #define ESP_DRD_USE_EEPROM true + #endif + #endif +#endif + +//default to use EEPROM, otherwise, use LITTLEFS (higher priority), then SPIFFS +#if ESP_DRD_USE_EEPROM + #include + + #define FLAG_DATA_SIZE 4 + + #ifndef EEPROM_SIZE + #define EEPROM_SIZE 512 + #endif + + #ifndef EEPROM_START + #define EEPROM_START 256 + #endif + +#elif ( ESP_DRD_USE_LITTLEFS || ESP_DRD_USE_SPIFFS ) + +#include + +#ifdef ESP32 + + #if ESP_DRD_USE_LITTLEFS + // Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h + //#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) ) //(ESP_ARDUINO_VERSION_MAJOR >= 2) + #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) + #warning Using ESP32 Core 1.0.6 or 2.0.0+ + // The library has been merged into esp32 core from release 1.0.6 + #include + + #define FileFS LittleFS + #define FS_Name "LittleFS" + #else + #warning Using ESP32 Core 1.0.5-. You must install LITTLEFS library + // The library has been merged into esp32 core from release 1.0.6 + #include // https://github.com/lorol/LITTLEFS + + #define FileFS LITTLEFS + #define FS_Name "LittleFS" + #endif + #else + #include "SPIFFS.h" + // ESP32 core 1.0.4 still uses SPIFFS + #define FileFS SPIFFS + #endif + +#else + // From ESP8266 core 2.7.1 + #include + + #if ESP_DRD_USE_LITTLEFS + #define FileFS LittleFS + #else + #define FileFS SPIFFS + #endif + +#endif // #if ESP_DRD_USE_EEPROM + + + +#define DRD_FILENAME "/drd.dat" + +#endif //#if ESP_DRD_USE_EEPROM + +#ifndef DOUBLERESETDETECTOR_DEBUG +#define DOUBLERESETDETECTOR_DEBUG false +#endif + +#define DOUBLERESETDETECTOR_FLAG_SET 0xD0D01234 +#define DOUBLERESETDETECTOR_FLAG_CLEAR 0xD0D04321 + +class DoubleResetDetector +{ + public: + DoubleResetDetector(int timeout, int address) + { +#if ESP_DRD_USE_EEPROM +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.printf("EEPROM size = %d, start = %d\n", EEPROM_SIZE, EEPROM_START); +#endif + + EEPROM.begin(EEPROM_SIZE); +#elif ( ESP_DRD_USE_LITTLEFS || ESP_DRD_USE_SPIFFS ) + // LittleFS / SPIFFS code + if (!FileFS.begin()) + { +#if (DOUBLERESETDETECTOR_DEBUG) + +#if ESP_DRD_USE_LITTLEFS + Serial.println("LittleFS failed!. Please use SPIFFS or EEPROM."); +#else + Serial.println("SPIFFS failed!. Please use LittleFS or EEPROM."); +#endif + +#endif + } +#else +#ifdef ESP8266 + //RTC only for ESP8266 +#endif +#endif + + this->timeout = timeout * 1000; + this->address = address; + doubleResetDetected = false; + waitingForDoubleReset = false; + }; + + bool detectDoubleReset() + { + doubleResetDetected = detectRecentlyResetFlag(); + + if (doubleResetDetected) + { +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.println("doubleResetDetected"); +#endif + + clearRecentlyResetFlag(); + } + else + { +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.println("No doubleResetDetected"); +#endif + + setRecentlyResetFlag(); + waitingForDoubleReset = true; + } + + return doubleResetDetected; + + }; + + void loop() + { + if (waitingForDoubleReset && millis() > timeout) + { +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.println("Stop doubleResetDetecting"); +#endif + + stop(); + } + }; + + void stop() + { + clearRecentlyResetFlag(); + waitingForDoubleReset = false; + }; + + bool doubleResetDetected; + + + private: + uint32_t DOUBLERESETDETECTOR_FLAG; + unsigned long timeout; + int address; + bool waitingForDoubleReset; + + bool detectRecentlyResetFlag() + { +#if (ESP_DRD_USE_EEPROM) + EEPROM.get(EEPROM_START, DOUBLERESETDETECTOR_FLAG); + doubleResetDetectorFlag = DOUBLERESETDETECTOR_FLAG; + +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.printf("EEPROM Flag read = 0x%X\n", DOUBLERESETDETECTOR_FLAG); +#endif +#elif ( ESP_DRD_USE_LITTLEFS || ESP_DRD_USE_SPIFFS ) + // LittleFS / SPIFFS code + if (FileFS.exists(DRD_FILENAME)) + { + // if config file exists, load + File file = FileFS.open(DRD_FILENAME, "r"); + + if (!file) + { +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.println("Loading config file failed"); +#endif + } + + file.readBytes((char *) &DOUBLERESETDETECTOR_FLAG, sizeof(DOUBLERESETDETECTOR_FLAG)); + doubleResetDetectorFlag = DOUBLERESETDETECTOR_FLAG; + +#if (DOUBLERESETDETECTOR_DEBUG) + +#if ESP_DRD_USE_LITTLEFS + Serial.printf("LittleFS Flag read = 0x%X\n", DOUBLERESETDETECTOR_FLAG); +#else + Serial.printf("SPIFFS Flag read = 0x%X\n", DOUBLERESETDETECTOR_FLAG); +#endif + +#endif + + file.close(); + } +#else +#ifdef ESP8266 + //RTC only for ESP8266 + ESP.rtcUserMemoryRead(address, &doubleResetDetectorFlag, sizeof(doubleResetDetectorFlag)); +#endif +#endif + + doubleResetDetected = (doubleResetDetectorFlag == DOUBLERESETDETECTOR_FLAG_SET); + return doubleResetDetected; + }; + + void setRecentlyResetFlag() + { + doubleResetDetectorFlag = DOUBLERESETDETECTOR_FLAG_SET; + + DOUBLERESETDETECTOR_FLAG = DOUBLERESETDETECTOR_FLAG_SET; + +#if (ESP_DRD_USE_EEPROM) + EEPROM.put(EEPROM_START, DOUBLERESETDETECTOR_FLAG); + EEPROM.commit(); + +#if (DOUBLERESETDETECTOR_DEBUG) + delay(1000); + EEPROM.get(EEPROM_START, DOUBLERESETDETECTOR_FLAG); + + Serial.printf("SetFlag write = 0x%X\n", DOUBLERESETDETECTOR_FLAG); +#endif +#elif ( ESP_DRD_USE_LITTLEFS || ESP_DRD_USE_SPIFFS ) + // LittleFS / SPIFFS code + File file = FileFS.open(DRD_FILENAME, "w"); +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.println("Saving config file..."); +#endif + + if (file) + { + file.write((uint8_t *) &DOUBLERESETDETECTOR_FLAG, sizeof(DOUBLERESETDETECTOR_FLAG)); + file.close(); +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.println("Saving config file OK"); +#endif + } + else + { +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.println("Saving config file failed"); +#endif + } +#else +#ifdef ESP8266 + //RTC only for ESP8266 + ESP.rtcUserMemoryWrite(address, &doubleResetDetectorFlag, sizeof(doubleResetDetectorFlag)); +#endif +#endif + }; + + + void clearRecentlyResetFlag() + { + doubleResetDetectorFlag = DOUBLERESETDETECTOR_FLAG_CLEAR; + DOUBLERESETDETECTOR_FLAG = DOUBLERESETDETECTOR_FLAG_CLEAR; + +#if (ESP_DRD_USE_EEPROM) + //DOUBLERESETDETECTOR_FLAG = DOUBLERESETDETECTOR_FLAG_CLEAR; + EEPROM.put(EEPROM_START, DOUBLERESETDETECTOR_FLAG); + EEPROM.commit(); + +#if (DOUBLERESETDETECTOR_DEBUG) + delay(1000); + EEPROM.get(EEPROM_START, DOUBLERESETDETECTOR_FLAG); + + Serial.printf("ClearFlag write = 0x%X\n", DOUBLERESETDETECTOR_FLAG); +#endif +#elif ( ESP_DRD_USE_LITTLEFS || ESP_DRD_USE_SPIFFS ) + // LittleFS / SPIFFS code + File file = FileFS.open(DRD_FILENAME, "w"); +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.println("Saving config file..."); +#endif + + if (file) + { + file.write((uint8_t *) &DOUBLERESETDETECTOR_FLAG, sizeof(DOUBLERESETDETECTOR_FLAG)); + file.close(); +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.println("Saving config file OK"); +#endif + } + else + { +#if (DOUBLERESETDETECTOR_DEBUG) + Serial.println("Saving config file failed"); +#endif + } + +#else +#ifdef ESP8266 + //RTC only for ESP8266 + ESP.rtcUserMemoryWrite(address, &doubleResetDetectorFlag, sizeof(doubleResetDetectorFlag)); +#endif +#endif + }; + + uint32_t doubleResetDetectorFlag; +}; +#endif // ESP_DoubleResetDetector_H diff --git a/lib/ESP_WiFiManager/ESP_WiFiManager-Impl.h b/lib/ESP_WiFiManager/ESP_WiFiManager-Impl.h new file mode 100644 index 0000000..328a4a2 --- /dev/null +++ b/lib/ESP_WiFiManager/ESP_WiFiManager-Impl.h @@ -0,0 +1,2122 @@ +/**************************************************************************************************************************** + ESP_WiFiManager-Impl.h + For ESP8266 / ESP32 boards + + ESP_WiFiManager is a library for the ESP8266/Arduino platform + (https://github.com/esp8266/Arduino) to enable easy + configuration and reconfiguration of WiFi credentials using a Captive Portal + inspired by: + http://www.esp8266.com/viewtopic.php?f=29&t=2520 + https://github.com/chriscook8/esp-arduino-apboot + https://github.com/esp8266/Arduino/blob/master/libraries/DNSServer/examples/CaptivePortalAdvanced/ + + Modified from Tzapu https://github.com/tzapu/WiFiManager + and from Ken Taylor https://github.com/kentaylor + + Built by Khoi Hoang https://github.com/khoih-prog/ESP_WiFiManager + Licensed under MIT license + + Version: 1.8.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 07/10/2019 Initial coding + 1.0.1 K Hoang 13/12/2019 Fix bug. Add features. Add support for ESP32 + 1.0.2 K Hoang 19/12/2019 Fix bug thatkeeps ConfigPortal in endless loop if Portal/Router SSID or Password is NULL. + 1.0.3 K Hoang 05/01/2020 Option not displaying AvailablePages in Info page. Enhance README.md. Modify examples + 1.0.4 K Hoang 07/01/2020 Add RFC952 setHostname feature. + 1.0.5 K Hoang 15/01/2020 Add configurable DNS feature. Thanks to @Amorphous of https://community.blynk.cc + 1.0.6 K Hoang 03/02/2020 Add support for ArduinoJson version 6.0.0+ ( tested with v6.14.1 ) + 1.0.7 K Hoang 13/04/2020 Reduce start time, fix SPIFFS bug in examples, update README.md + 1.0.8 K Hoang 10/06/2020 Fix STAstaticIP issue. Restructure code. Add LittleFS support for ESP8266 core 2.7.1+ + 1.0.9 K Hoang 29/07/2020 Fix ESP32 STAstaticIP bug. Permit changing from DHCP <-> static IP using Config Portal. + Add, enhance examples (fix MDNS for ESP32) + 1.0.10 K Hoang 08/08/2020 Add more features to Config Portal. Use random WiFi AP channel to avoid conflict. + 1.0.11 K Hoang 17/08/2020 Add CORS feature. Fix bug in softAP, autoConnect, resetSettings. + 1.1.0 K Hoang 28/08/2020 Add MultiWiFi feature to autoconnect to best WiFi at runtime + 1.1.1 K Hoang 30/08/2020 Add setCORSHeader function to allow flexible CORS. Fix typo and minor improvement. + 1.1.2 K Hoang 17/08/2020 Fix bug. Add example. + 1.2.0 K Hoang 09/10/2020 Restore cpp code besides Impl.h code to use if linker error. Fix bug. + 1.3.0 K Hoang 04/12/2020 Add LittleFS support to ESP32 using LITTLEFS Library + 1.4.1 K Hoang 22/12/2020 Fix staticIP not saved. Add functions. Add complex examples. Sync with ESPAsync_WiFiManager + 1.4.2 K Hoang 14/01/2021 Fix examples' bug not using saved WiFi Credentials after losing all WiFi connections. + 1.4.3 K Hoang 23/01/2021 Fix examples' bug not saving Static IP in certain cases. + 1.5.0 K Hoang 12/02/2021 Add support to new ESP32-S2 + 1.5.1 K Hoang 26/03/2021 Fix compiler error if setting Compiler Warnings to All. Retest with esp32 core v1.0.6 + 1.5.2 K Hoang 08/04/2021 Fix example misleading messages. + 1.5.3 K Hoang 13/04/2021 Add dnsServer error message. + 1.6.0 K Hoang 20/04/2021 Add support to new ESP32-C3 using SPIFFS or EEPROM + 1.6.1 K Hoang 25/04/2021 Fix MultiWiFi bug. Fix captive-portal bug if CP AP address is not default 192.168.4.1 + 1.7.0 K Hoang 06/05/2021 Set _timezoneName. Add support to new ESP32-S2 (METRO_ESP32S2, FUNHOUSE_ESP32S2, etc.) + 1.7.1 K Hoang 08/05/2021 Fix Json bug. Fix timezoneName not displayed in Info page. + 1.7.2 K Hoang 08/05/2021 Fix warnings with ESP8266 core v3.0.0 + 1.7.3 K Hoang 29/07/2021 Fix MultiWiFi connection issue with ESP32 core v2.0.0-rc1+ + 1.7.4 K Hoang 13/08/2021 Add WiFi scanning of hidden SSIDs + 1.7.5 K Hoang 10/10/2021 Update `platform.ini` and `library.json` + 1.7.6 K Hoang 26/11/2021 Auto detect ESP32 core and use either built-in LittleFS or LITTLEFS library + 1.7.7 K Hoang 26/11/2021 Fix compile error for ESP32 core v1.0.5- + 1.7.8 K Hoang 30/11/2021 Fix bug to permit using HTTP port different from 80. Fix bug + 1.8.0 K Hoang 29/12/2021 Fix `multiple-definitions` linker error and weird bug related to src_cpp + *****************************************************************************************************************************/ + +#pragma once + +#ifndef ESP_WiFiManager_Impl_h +#define ESP_WiFiManager_Impl_h + + +////////////////////////////////////////// + +ESP_WMParameter::ESP_WMParameter(const char *custom) +{ + _WMParam_data._id = NULL; + _WMParam_data._placeholder = NULL; + _WMParam_data._length = 0; + _WMParam_data._value = NULL; + _WMParam_data._labelPlacement = WFM_LABEL_BEFORE; + + _customHTML = custom; +} + +////////////////////////////////////////// + +ESP_WMParameter::ESP_WMParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom, int labelPlacement) +{ + init(id, placeholder, defaultValue, length, custom, labelPlacement); +} + +////////////////////////////////////////// +// New in v1.4.0 +ESP_WMParameter::ESP_WMParameter(const WMParam_Data& WMParam_data) +{ + init(WMParam_data._id, WMParam_data._placeholder, WMParam_data._value, WMParam_data._length, "", WMParam_data._labelPlacement); +} +////// +////////////////////////////////////////// + +void ESP_WMParameter::init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom, int labelPlacement) +{ + _WMParam_data._id = id; + _WMParam_data._placeholder = placeholder; + _WMParam_data._length = length; + _WMParam_data._labelPlacement = labelPlacement; + + _WMParam_data._value = new char[_WMParam_data._length + 1]; + + if (_WMParam_data._value != NULL) + { + memset(_WMParam_data._value, 0, _WMParam_data._length + 1); + + if (defaultValue != NULL) + { + strncpy(_WMParam_data._value, defaultValue, _WMParam_data._length); + } + } + + _customHTML = custom; +} + +////////////////////////////////////////// + +ESP_WMParameter::~ESP_WMParameter() +{ + if (_WMParam_data._value != NULL) + { + delete[] _WMParam_data._value; + } +} + +////////////////////////////////////////// +// New in v1.4.0 +// Using Struct to get/set whole data at once +void ESP_WMParameter::setWMParam_Data(const WMParam_Data& WMParam_data) +{ + LOGINFO(F("setWMParam_Data")); + + memcpy(&_WMParam_data, &WMParam_data, sizeof(_WMParam_data)); +} + +////////////////////////////////////////// + +void ESP_WMParameter::getWMParam_Data(WMParam_Data &WMParam_data) +{ + LOGINFO(F("getWMParam_Data")); + + memcpy(&WMParam_data, &_WMParam_data, sizeof(WMParam_data)); +} +////// + +////////////////////////////////////////// + +const char* ESP_WMParameter::getValue() +{ + return _WMParam_data._value; +} + +////////////////////////////////////////// + +const char* ESP_WMParameter::getID() +{ + return _WMParam_data._id; +} + +////////////////////////////////////////// + +const char* ESP_WMParameter::getPlaceholder() +{ + return _WMParam_data._placeholder; +} + +////////////////////////////////////////// + +int ESP_WMParameter::getValueLength() +{ + return _WMParam_data._length; +} + +////////////////////////////////////////// + +int ESP_WMParameter::getLabelPlacement() +{ + return _WMParam_data._labelPlacement; +} + +////////////////////////////////////////// + +const char* ESP_WMParameter::getCustomHTML() +{ + return _customHTML; +} + +////////////////////////////////////////// + +/** + [getParameters description] + @access public +*/ +ESP_WMParameter** ESP_WiFiManager::getParameters() +{ + return _params; +} + +/** + [getParametersCount description] + @access public +*/ +int ESP_WiFiManager::getParametersCount() +{ + return _paramsCount; +} + +////////////////////////////////////////// + +char* ESP_WiFiManager::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; +} + +////////////////////////////////////////// + +ESP_WiFiManager::ESP_WiFiManager(const char *iHostname) +{ +#if USE_DYNAMIC_PARAMS + _max_params = WIFI_MANAGER_MAX_PARAMS; + _params = (ESP_WMParameter**)malloc(_max_params * sizeof(ESP_WMParameter*)); +#endif + + //WiFi not yet started here, must call WiFi.mode(WIFI_STA) and modify function WiFiGenericClass::mode(wifi_mode_t m) !!! + + WiFi.mode(WIFI_STA); + + if (iHostname[0] == 0) + { +#ifdef ESP8266 + String _hostname = "ESP8266-" + String(ESP.getChipId(), HEX); +#else //ESP32 + String _hostname = "ESP32-" + String((uint32_t)ESP.getEfuseMac(), HEX); +#endif + _hostname.toUpperCase(); + + getRFC952_hostname(_hostname.c_str()); + + } + else + { + // Prepare and store the hostname only not NULL + getRFC952_hostname(iHostname); + } + + LOGWARN1(F("RFC925 Hostname ="), RFC952_hostname); + + setHostname(); + + networkIndices = NULL; +} + +////////////////////////////////////////// + +ESP_WiFiManager::~ESP_WiFiManager() +{ +#if USE_DYNAMIC_PARAMS + if (_params != NULL) + { + LOGINFO(F("freeing allocated params!")); + + free(_params); + } +#endif + + if (networkIndices) + { + free(networkIndices); //indices array no longer required so free memory + } +} + +////////////////////////////////////////// + +#if USE_DYNAMIC_PARAMS +bool ESP_WiFiManager::addParameter(ESP_WMParameter *p) +#else +void ESP_WiFiManager::addParameter(ESP_WMParameter *p) +#endif +{ +#if USE_DYNAMIC_PARAMS + + if (_paramsCount == _max_params) + { + // rezise the params array + _max_params += WIFI_MANAGER_MAX_PARAMS; + + LOGINFO1(F("Increasing _max_params to:"), _max_params); + + ESP_WMParameter** new_params = (ESP_WMParameter**)realloc(_params, _max_params * sizeof(ESP_WMParameter*)); + + if (new_params != NULL) + { + _params = new_params; + } + else + { + LOGINFO(F("ERROR: failed to realloc params, size not increased!")); + + return false; + } + } + + _params[_paramsCount] = p; + _paramsCount++; + + LOGINFO1(F("Adding parameter"), p->getID()); + + return true; + +#else + + // Danger here. Better to use Tzapu way here + if (_paramsCount < (WIFI_MANAGER_MAX_PARAMS)) + { + _params[_paramsCount] = p; + _paramsCount++; + + LOGINFO1(F("Adding parameter"), p->getID()); + } + else + { + LOGINFO("Can't add parameter. Full"); + } + +#endif +} + +////////////////////////////////////////// + +void ESP_WiFiManager::setupConfigPortal() +{ + stopConfigPortal = false; //Signal not to close config portal + + /*This library assumes autoconnect is set to 1. It usually is + but just in case check the setting and turn on autoconnect if it is off. + Some useful discussion at https://github.com/esp8266/Arduino/issues/1615*/ + if (WiFi.getAutoConnect() == 0) + WiFi.setAutoConnect(1); + + dnsServer.reset(new DNSServer()); + +#ifdef ESP8266 + server.reset(new ESP8266WebServer(HTTP_PORT_TO_USE)); +#else //ESP32 + server.reset(new WebServer(HTTP_PORT_TO_USE)); +#endif + + // optional soft ip config + // Must be put here before dns server start to take care of the non-default ConfigPortal AP IP. + // Check (https://github.com/khoih-prog/ESP_WiFiManager/issues/58) + if (_WiFi_AP_IPconfig._ap_static_ip) + { + LOGWARN3(F("Custom AP IP/GW/Subnet = "), _WiFi_AP_IPconfig._ap_static_ip, _WiFi_AP_IPconfig._ap_static_gw, _WiFi_AP_IPconfig._ap_static_sn); + + WiFi.softAPConfig(_WiFi_AP_IPconfig._ap_static_ip, _WiFi_AP_IPconfig._ap_static_gw, _WiFi_AP_IPconfig._ap_static_sn); + } + + /* Setup the DNS server redirecting all the domains to the apIP */ + if (dnsServer) + { + dnsServer->setErrorReplyCode(DNSReplyCode::NoError); + + // DNSServer started with "*" domain name, all DNS requests will be passsed to WiFi.softAPIP() + if (! dnsServer->start(DNS_PORT, "*", WiFi.softAPIP())) + { + // No socket available + LOGERROR(F("Can't start DNS Server. No available socket")); + } + } + else + { + // No space available + LOGERROR(F("Can't initiate DNS Server. No enough space")); + } + + _configPortalStart = millis(); + + LOGWARN1(F("Configuring AP SSID ="), _apName); + + if (_apPassword != NULL) + { + if (strlen(_apPassword) < 8 || strlen(_apPassword) > 63) + { + // fail passphrase to short or long! + LOGERROR(F("Invalid AccessPoint password. Ignoring")); + + _apPassword = NULL; + } + LOGWARN1(F("AP PWD ="), _apPassword); + } + + + // KH, new from v1.0.10 to enable dynamic/random channel + static int channel; + + // Use random channel if _WiFiAPChannel == 0 + if (_WiFiAPChannel == 0) + channel = (_configPortalStart % MAX_WIFI_CHANNEL) + 1; + else + channel = _WiFiAPChannel; + + if (_apPassword != NULL) + { + LOGWARN1(F("AP Channel ="), channel); + + //WiFi.softAP(_apName, _apPassword);//password option + WiFi.softAP(_apName, _apPassword, channel); + } + else + { + // Can't use channel here + WiFi.softAP(_apName); + } + ////// + + delay(500); // Without delay I've seen the IP address blank + + LOGWARN1(F("AP IP address ="), WiFi.softAPIP()); + + /* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */ + server->on("/", std::bind(&ESP_WiFiManager::handleRoot, this)); + server->on("/wifi", std::bind(&ESP_WiFiManager::handleWifi, this)); + server->on("/wifisave", std::bind(&ESP_WiFiManager::handleWifiSave, this)); + server->on("/close", std::bind(&ESP_WiFiManager::handleServerClose, this)); + server->on("/i", std::bind(&ESP_WiFiManager::handleInfo, this)); + server->on("/r", std::bind(&ESP_WiFiManager::handleReset, this)); + server->on("/state", std::bind(&ESP_WiFiManager::handleState, this)); + server->on("/scan", std::bind(&ESP_WiFiManager::handleScan, this)); + server->onNotFound(std::bind(&ESP_WiFiManager::handleNotFound, this)); + server->begin(); // Web server start + + LOGWARN(F("HTTP server started")); +} + +////////////////////////////////////////// + +bool ESP_WiFiManager::autoConnect() +{ +#ifdef ESP8266 + String ssid = "ESP_" + String(ESP.getChipId()); +#else //ESP32 + String ssid = "ESP_" + String((uint32_t)ESP.getEfuseMac()); +#endif + + return autoConnect(ssid.c_str(), NULL); +} + +/* This is not very useful as there has been an assumption that device has to be + told to connect but Wifi already does it's best to connect in background. Calling this + method will block until WiFi connects. Sketch can avoid + blocking call then use (WiFi.status()==WL_CONNECTED) test to see if connected yet. + See some discussion at https://github.com/tzapu/WiFiManager/issues/68 +*/ + +// New in v1.0.11 +// To permit autoConnect() to use STA static IP or DHCP IP. +#ifndef AUTOCONNECT_NO_INVALIDATE + #define AUTOCONNECT_NO_INVALIDATE true +#endif + +////////////////////////////////////////// + +bool ESP_WiFiManager::autoConnect(char const *apName, char const *apPassword) +{ +#if AUTOCONNECT_NO_INVALIDATE + LOGINFO(F("\nAutoConnect using previously saved SSID/PW, but keep previous settings")); + // Connect to previously saved SSID/PW, but keep previous settings + connectWifi(); +#else + LOGINFO(F("\nAutoConnect using previously saved SSID/PW, but invalidate previous settings")); + // Connect to previously saved SSID/PW, but invalidate previous settings + connectWifi(WiFi_SSID(), WiFi_Pass()); +#endif + + unsigned long startedAt = millis(); + + while (millis() - startedAt < 10000) + { + //delay(100); + delay(200); + + if (WiFi.status() == WL_CONNECTED) + { + float waited = (millis() - startedAt); + + LOGWARN1(F("Connected after waiting (s) :"), waited / 1000); + LOGWARN1(F("Local ip ="), WiFi.localIP()); + + return true; + } + } + + return startConfigPortal(apName, apPassword); +} + +////////////////////////////////////////// + +bool ESP_WiFiManager::startConfigPortal() +{ +#ifdef ESP8266 + String ssid = "ESP_" + String(ESP.getChipId()); +#else //ESP32 + String ssid = "ESP_" + String((uint32_t)ESP.getEfuseMac()); +#endif + ssid.toUpperCase(); + + return startConfigPortal(ssid.c_str(), NULL); +} + +////////////////////////////////////////// + +bool ESP_WiFiManager::startConfigPortal(char const *apName, char const *apPassword) +{ + //setup AP + int connRes = WiFi.waitForConnectResult(); + + LOGINFO("WiFi.waitForConnectResult Done"); + + if (connRes == WL_CONNECTED) + { + LOGINFO("SET AP_STA"); + + WiFi.mode(WIFI_AP_STA); //Dual mode works fine if it is connected to WiFi + } + else + { + LOGINFO("SET AP"); + + WiFi.mode(WIFI_AP); // Dual mode becomes flaky if not connected to a WiFi network. + // When ESP8266 station is trying to find a target AP, it will scan on every channel, + // that means ESP8266 station is changing its channel to scan. This makes the channel of ESP8266 softAP keep changing too.. + // So the connection may break. From http://bbs.espressif.com/viewtopic.php?t=671#p2531 + } + + _apName = apName; + _apPassword = apPassword; + + //notify we entered AP mode + if (_apcallback != NULL) + { + LOGINFO("_apcallback"); + + _apcallback(this); + } + + connect = false; + + setupConfigPortal(); + + bool TimedOut = true; + + LOGINFO("startConfigPortal : Enter loop"); + + while (_configPortalTimeout == 0 || millis() < _configPortalStart + _configPortalTimeout) + { + //DNS + dnsServer->processNextRequest(); + //HTTP + server->handleClient(); + +#if ( USING_ESP32_S2 || USING_ESP32_C3 ) + // Fix ESP32-S2 issue with WebServer (https://github.com/espressif/arduino-esp32/issues/4348) + delay(1); +#endif + + if (connect) + { + TimedOut = false; + delay(2000); + + LOGERROR(F("Connecting to new AP")); + + // using user-provided _ssid, _pass in place of system-stored ssid and pass + if (connectWifi(_ssid, _pass) != WL_CONNECTED) + { + LOGERROR(F("Failed to connect")); + + WiFi.mode(WIFI_AP); // Dual mode becomes flaky if not connected to a WiFi network. + } + else + { + //notify that configuration has changed and any optional parameters should be saved + if (_savecallback != NULL) + { + //todo: check if any custom parameters actually exist, and check if they really changed maybe + _savecallback(); + } + break; + } + + if (_shouldBreakAfterConfig) + { + //flag set to exit after config after trying to connect + //notify that configuration has changed and any optional parameters should be saved + if (_savecallback != NULL) + { + //todo: check if any custom parameters actually exist, and check if they really changed maybe + _savecallback(); + } + + break; + } + } + + if (stopConfigPortal) + { + LOGERROR("Stop ConfigPortal"); //KH + + stopConfigPortal = false; + break; + } + + yield(); + } + + WiFi.mode(WIFI_STA); + + if (TimedOut) + { + setHostname(); + + // New v1.0.8 to fix static IP when CP not entered or timed-out + setWifiStaticIP(); + + WiFi.begin(); + int connRes = waitForConnectResult(); + + LOGERROR1("Timed out connection result:", getStatus(connRes)); + } + + server->stop(); + server.reset(); + dnsServer->stop(); + dnsServer.reset(); + + return WiFi.status() == WL_CONNECTED; +} + +////////////////////////////////////////// + +void ESP_WiFiManager::setWifiStaticIP() +{ +#if USE_CONFIGURABLE_DNS + if (_WiFi_STA_IPconfig._sta_static_ip) + { + LOGWARN(F("Custom STA IP/GW/Subnet")); + + //***** Added section for DNS config option ***** + if (_WiFi_STA_IPconfig._sta_static_dns1 && _WiFi_STA_IPconfig._sta_static_dns2) + { + LOGWARN(F("DNS1 and DNS2 set")); + + WiFi.config(_WiFi_STA_IPconfig._sta_static_ip, _WiFi_STA_IPconfig._sta_static_gw, _WiFi_STA_IPconfig._sta_static_sn, _WiFi_STA_IPconfig._sta_static_dns1, _WiFi_STA_IPconfig._sta_static_dns2); + } + else if (_WiFi_STA_IPconfig._sta_static_dns1) + { + LOGWARN(F("Only DNS1 set")); + + WiFi.config(_WiFi_STA_IPconfig._sta_static_ip, _WiFi_STA_IPconfig._sta_static_gw, _WiFi_STA_IPconfig._sta_static_sn, _WiFi_STA_IPconfig._sta_static_dns1); + } + else + { + LOGWARN(F("No DNS server set")); + + WiFi.config(_WiFi_STA_IPconfig._sta_static_ip, _WiFi_STA_IPconfig._sta_static_gw, _WiFi_STA_IPconfig._sta_static_sn); + } + //***** End added section for DNS config option ***** + + LOGINFO1(F("setWifiStaticIP IP ="), WiFi.localIP()); + } + else + { + LOGWARN(F("Can't use Custom STA IP/GW/Subnet")); + } +#else + // check if we've got static_ip settings, if we do, use those. + if (_WiFi_STA_IPconfig._sta_static_ip) + { + WiFi.config(_WiFi_STA_IPconfig._sta_static_ip, _WiFi_STA_IPconfig._sta_static_gw, _WiFi_STA_IPconfig._sta_static_sn); + + LOGWARN1(F("Custom STA IP/GW/Subnet : "), WiFi.localIP()); + } +#endif +} + +////////////////////////////////////////// + +// New from v1.1.0 +int ESP_WiFiManager::reconnectWifi() +{ + int connectResult; + + // using user-provided _ssid, _pass in place of system-stored ssid and pass + if ( ( connectResult = connectWifi(_ssid, _pass) ) != WL_CONNECTED) + { + LOGERROR1(F("Failed to connect to"), _ssid); + + if ( ( connectResult = connectWifi(_ssid1, _pass1) ) != WL_CONNECTED) + { + LOGERROR1(F("Failed to connect to"), _ssid1); + + } + else + LOGERROR1(F("Connected to"), _ssid1); + } + else + LOGERROR1(F("Connected to"), _ssid); + + return connectResult; +} + +////////////////////////////////////////// + +int ESP_WiFiManager::connectWifi(const String& ssid, const String& pass) +{ + //KH, from v1.0.10. + // Add option if didn't input/update SSID/PW => Use the previous saved Credentials. + // But update the Static/DHCP options if changed. + if ( (ssid != "") || ( (ssid == "") && (WiFi_SSID() != "") ) ) + { + //fix for auto connect racing issue. Move up from v1.1.0 to avoid resetSettings() + if (WiFi.status() == WL_CONNECTED) + { + LOGWARN(F("Already connected. Bailing out.")); + return WL_CONNECTED; + } + + if (ssid != "") + resetSettings(); + +#ifdef ESP8266 + setWifiStaticIP(); +#endif + + WiFi.mode(WIFI_AP_STA); //It will start in station mode if it was previously in AP mode. + + setHostname(); + + // KH, Fix ESP32 staticIP after exiting CP, from v1.0.9 +#ifdef ESP32 + setWifiStaticIP(); +#endif + + if (ssid != "") + { + // Start Wifi with new values. + LOGWARN(F("Connect to new WiFi using new IP parameters")); + + WiFi.begin(ssid.c_str(), pass.c_str()); + } + else + { + // Start Wifi with old values. + LOGWARN(F("Connect to previous WiFi using new IP parameters")); + + WiFi.begin(); + } + } + else if (WiFi_SSID() == "") + { + LOGWARN(F("No saved credentials")); + } + + int connRes = waitForConnectResult(); + LOGWARN1("Connection result: ", getStatus(connRes)); + + //not connected, WPS enabled, no pass - first attempt + if (_tryWPS && connRes != WL_CONNECTED && pass == "") + { + startWPS(); + //should be connected at the end of WPS + connRes = waitForConnectResult(); + } + + return connRes; +} + +////////////////////////////////////////// + +uint8_t ESP_WiFiManager::waitForConnectResult() +{ + if (_connectTimeout == 0) + { + unsigned long startedAt = millis(); + + // In ESP8266, WiFi.waitForConnectResult() @return wl_status_t (0-255) or -1 on timeout !!! + // In ESP32, WiFi.waitForConnectResult() @return wl_status_t (0-255) + // So, using int for connRes to be safe + //int connRes = WiFi.waitForConnectResult(); + WiFi.waitForConnectResult(); + + float waited = (millis() - startedAt); + + LOGWARN1(F("Connected after waiting (s) :"), waited / 1000); + LOGWARN1(F("Local ip ="), WiFi.localIP()); + + // Fix bug from v1.1.0+, connRes is sometimes not correct. + //return connRes; + return WiFi.status(); + } + else + { + LOGERROR(F("Waiting WiFi connection with time out")); + unsigned long start = millis(); + bool keepConnecting = true; + uint8_t status; + + while (keepConnecting) + { + status = WiFi.status(); + if (millis() > start + _connectTimeout) + { + keepConnecting = false; + LOGERROR(F("Connection timed out")); + } + + if (status == WL_CONNECTED || status == WL_CONNECT_FAILED) + { + keepConnecting = false; + } + delay(100); + } + return status; + } +} + +////////////////////////////////////////// + +void ESP_WiFiManager::startWPS() +{ +#ifdef ESP8266 + LOGINFO("START WPS"); + WiFi.beginWPSConfig(); + LOGINFO("END WPS"); +#else //ESP32 + // TODO + LOGINFO("ESP32 WPS TODO"); +#endif +} + +////////////////////////////////////////// + +//Convenient for debugging but wasteful of program space. +//Remove if short of space +const char* ESP_WiFiManager::getStatus(int status) +{ + switch (status) + { + case WL_IDLE_STATUS: + return "WL_IDLE_STATUS"; + case WL_NO_SSID_AVAIL: + return "WL_NO_SSID_AVAIL"; + case WL_CONNECTED: + return "WL_CONNECTED"; + case WL_CONNECT_FAILED: + return "WL_CONNECT_FAILED"; + case WL_DISCONNECTED: + return "WL_DISCONNECTED"; + default: + return "UNKNOWN"; + } +} + +////////////////////////////////////////// + +String ESP_WiFiManager::getConfigPortalSSID() +{ + return _apName; +} + +////////////////////////////////////////// + +String ESP_WiFiManager::getConfigPortalPW() +{ + return _apPassword; +} + +////////////////////////////////////////// + +void ESP_WiFiManager::resetSettings() +{ + LOGINFO(F("Previous settings invalidated")); + +#ifdef ESP8266 + WiFi.disconnect(true); +#else + WiFi.disconnect(true, true); + // New in v1.0.11 + // Temporary fix for issue of not clearing WiFi SSID/PW from flash of ESP32 + // See https://github.com/khoih-prog/ESP_WiFiManager/issues/25 and https://github.com/espressif/arduino-esp32/issues/400 + WiFi.begin("0","0"); + ////// +#endif + + delay(200); + return; +} + +////////////////////////////////////////// + +void ESP_WiFiManager::setTimeout(unsigned long seconds) +{ + setConfigPortalTimeout(seconds); +} + +////////////////////////////////////////// + +void ESP_WiFiManager::setConfigPortalTimeout(unsigned long seconds) +{ + _configPortalTimeout = seconds * 1000; +} + +////////////////////////////////////////// + +void ESP_WiFiManager::setConnectTimeout(unsigned long seconds) +{ + _connectTimeout = seconds * 1000; +} + +////////////////////////////////////////// + +void ESP_WiFiManager::setDebugOutput(bool debug) +{ + _debug = debug; +} + +////////////////////////////////////////// + +// KH, new from v1.0.10 to enable dynamic/random channel +int ESP_WiFiManager::setConfigPortalChannel(int channel) +{ + // 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) ) + _WiFiAPChannel = 1; + else if ( (channel >= MIN_WIFI_CHANNEL - 1) && (channel <= MAX_WIFI_CHANNEL) ) + _WiFiAPChannel = channel; + + return _WiFiAPChannel; +} + +////////////////////////////////////////// + +void ESP_WiFiManager::setAPStaticIPConfig(const IPAddress& ip, const IPAddress& gw, const IPAddress& sn) +{ + LOGINFO(F("setAPStaticIPConfig")); + _WiFi_AP_IPconfig._ap_static_ip = ip; + _WiFi_AP_IPconfig._ap_static_gw = gw; + _WiFi_AP_IPconfig._ap_static_sn = sn; +} + +////////////////////////////////////////// + +// New in v1.4.0 +void ESP_WiFiManager::setAPStaticIPConfig(const WiFi_AP_IPConfig& WM_AP_IPconfig) +{ + LOGINFO(F("setAPStaticIPConfig")); + + memcpy((void*) &_WiFi_AP_IPconfig, &WM_AP_IPconfig, sizeof(_WiFi_AP_IPconfig)); +} + +////////////////////////////////////////// + +void ESP_WiFiManager::getAPStaticIPConfig(WiFi_AP_IPConfig &WM_AP_IPconfig) +{ + LOGINFO(F("getAPStaticIPConfig")); + + memcpy((void*) &WM_AP_IPconfig, &_WiFi_AP_IPconfig, sizeof(WM_AP_IPconfig)); +} +////// +////////////////////////////////////////// + +void ESP_WiFiManager::setSTAStaticIPConfig(const IPAddress& ip, const IPAddress& gw, const IPAddress& sn) +{ + LOGINFO(F("setSTAStaticIPConfig")); + _WiFi_STA_IPconfig._sta_static_ip = ip; + _WiFi_STA_IPconfig._sta_static_gw = gw; + _WiFi_STA_IPconfig._sta_static_sn = sn; +} + +////////////////////////////////////////// +// New in v1.4.0 + +void ESP_WiFiManager::setSTAStaticIPConfig(const WiFi_STA_IPConfig& WM_STA_IPconfig) +{ + LOGINFO(F("setSTAStaticIPConfig")); + + memcpy((void*) &_WiFi_STA_IPconfig, &WM_STA_IPconfig, sizeof(_WiFi_STA_IPconfig)); +} + +////////////////////////////////////////// + +void ESP_WiFiManager::getSTAStaticIPConfig(WiFi_STA_IPConfig &WM_STA_IPconfig) +{ + LOGINFO(F("getSTAStaticIPConfig")); + + memcpy((void*) &WM_STA_IPconfig, &_WiFi_STA_IPconfig, sizeof(WM_STA_IPconfig)); +} +////// +////////////////////////////////////////// + +#if USE_CONFIGURABLE_DNS +void ESP_WiFiManager::setSTAStaticIPConfig(const IPAddress& ip, const IPAddress& gw, const IPAddress& sn, + const IPAddress& dns_address_1, const IPAddress& dns_address_2) +{ + LOGINFO(F("setSTAStaticIPConfig for USE_CONFIGURABLE_DNS")); + _WiFi_STA_IPconfig._sta_static_ip = ip; + _WiFi_STA_IPconfig._sta_static_gw = gw; + _WiFi_STA_IPconfig._sta_static_sn = sn; + _WiFi_STA_IPconfig._sta_static_dns1 = dns_address_1; //***** Added argument ***** + _WiFi_STA_IPconfig._sta_static_dns2 = dns_address_2; //***** Added argument ***** +} +#endif + +////////////////////////////////////////// + +void ESP_WiFiManager::setMinimumSignalQuality(int quality) +{ + _minimumQuality = quality; +} + +////////////////////////////////////////// + +void ESP_WiFiManager::setBreakAfterConfig(bool shouldBreak) +{ + _shouldBreakAfterConfig = shouldBreak; +} + +////////////////////////////////////////// + +void ESP_WiFiManager::reportStatus(String &page) +{ + page += FPSTR(WM_HTTP_SCRIPT_NTP_MSG); + + if (WiFi_SSID() != "") + { + page += F("Configured to connect to access point "); + page += WiFi_SSID(); + + if (WiFi.status() == WL_CONNECTED) + { + page += F(" and currently connected on IP "); + page += WiFi.localIP().toString(); + page += F(""); + } + else + { + page += F(" but not currently connected to network."); + } + } + else + { + page += F("No network currently configured."); + } +} + +////////////////////////////////////////// + +/** Handle root or redirect to captive portal */ +void ESP_WiFiManager::handleRoot() +{ + LOGDEBUG(F("Handle root")); + + // Disable _configPortalTimeout when someone accessing Portal to give some time to config + _configPortalTimeout = 0; //KH + + if (captivePortal()) + { + // If caprive portal redirect instead of displaying the error page. + return; + } + + server->sendHeader(FPSTR(WM_HTTP_CACHE_CONTROL), FPSTR(WM_HTTP_NO_STORE)); + +#if USING_CORS_FEATURE + // New from v1.1.1, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + server->sendHeader(FPSTR(WM_HTTP_CORS), _CORS_Header); +#endif + + server->sendHeader(FPSTR(WM_HTTP_PRAGMA), FPSTR(WM_HTTP_NO_CACHE)); + server->sendHeader(FPSTR(WM_HTTP_EXPIRES), "-1"); + + String page = FPSTR(WM_HTTP_HEAD_START); + + page.replace("{v}", "Options"); + page += FPSTR(WM_HTTP_SCRIPT); + page += FPSTR(WM_HTTP_SCRIPT_NTP); + page += FPSTR(WM_HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(WM_HTTP_HEAD_END); + page += "

"; + page += _apName; + + if (WiFi_SSID() != "") + { + if (WiFi.status() == WL_CONNECTED) + { + page += " on "; + page += WiFi_SSID(); + } + else + { + page += " on "; + page += WiFi_SSID(); + page += ""; + } + } + + page += "

"; + page += FPSTR(WM_HTTP_PORTAL_OPTIONS); + page += F("
"); + reportStatus(page); + page += F("
"); + page += FPSTR(WM_HTTP_END); + + server->send(200, "text/html", page); + +} + +////////////////////////////////////////// + +/** Wifi config page handler */ +void ESP_WiFiManager::handleWifi() +{ + LOGDEBUG(F("Handle WiFi")); + + // Disable _configPortalTimeout when someone accessing Portal to give some time to config + _configPortalTimeout = 0; //KH + + server->sendHeader(FPSTR(WM_HTTP_CACHE_CONTROL), FPSTR(WM_HTTP_NO_STORE)); + +#if USING_CORS_FEATURE + // New from v1.1.1, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + server->sendHeader(FPSTR(WM_HTTP_CORS), _CORS_Header); +#endif + + server->sendHeader(FPSTR(WM_HTTP_PRAGMA), FPSTR(WM_HTTP_NO_CACHE)); + server->sendHeader(FPSTR(WM_HTTP_EXPIRES), "-1"); + + String page = FPSTR(WM_HTTP_HEAD_START); + + page.replace("{v}", "Config ESP"); + page += FPSTR(WM_HTTP_SCRIPT); + page += FPSTR(WM_HTTP_SCRIPT_NTP); + page += FPSTR(WM_HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(WM_HTTP_HEAD_END); + page += F("

Configuration

"); + + // KH, New, v1.0.6+ + numberOfNetworks = scanWifiNetworks(&networkIndices); + + //Print list of WiFi networks that were found in earlier scan + if (numberOfNetworks == 0) + { + page += F("No network found. Refresh to scan again."); + } + else + { + // From v1.0.10 + page += FPSTR(WM_FLDSET_START); + ////// + + //display networks in page + for (int i = 0; i < numberOfNetworks; i++) + { + if (networkIndices[i] == -1) + continue; // skip dups and those that are below the required quality + + LOGDEBUG1(F("Index ="), i); + LOGDEBUG1(F("SSID ="), WiFi.SSID(networkIndices[i])); + LOGDEBUG1(F("RSSI ="), WiFi.RSSI(networkIndices[i])); + + int quality = getRSSIasQuality(WiFi.RSSI(networkIndices[i])); + + String item = FPSTR(WM_HTTP_ITEM); + String rssiQ; + rssiQ += quality; + item.replace("{v}", WiFi.SSID(networkIndices[i])); + item.replace("{r}", rssiQ); + +#ifdef ESP8266 + if (WiFi.encryptionType(networkIndices[i]) != ENC_TYPE_NONE) +#else //ESP32 + if (WiFi.encryptionType(networkIndices[i]) != WIFI_AUTH_OPEN) +#endif + { + item.replace("{i}", "l"); + } + else + { + item.replace("{i}", ""); + } + + //LOGDEBUG(item); + page += item; + delay(0); + } + + // From v1.0.10 + page += FPSTR(WM_FLDSET_END); + ////// + + page += "
"; + } + + page += FPSTR(WM_HTTP_FORM_START); + char parLength[2]; + + page += FPSTR(WM_FLDSET_START); + + // add the extra parameters to the form + for (int i = 0; i < _paramsCount; i++) + { + if (_params[i] == NULL) + { + break; + } + + String pitem; + switch (_params[i]->getLabelPlacement()) + { + case WFM_LABEL_BEFORE: + pitem = FPSTR(WM_HTTP_FORM_LABEL_BEFORE); + break; + case WFM_LABEL_AFTER: + pitem = FPSTR(WM_HTTP_FORM_LABEL_AFTER); + break; + default: + // WFM_NO_LABEL + pitem = FPSTR(WM_HTTP_FORM_PARAM); + break; + } + + if (_params[i]->getID() != NULL) + { + pitem.replace("{i}", _params[i]->getID()); + pitem.replace("{n}", _params[i]->getID()); + pitem.replace("{p}", _params[i]->getPlaceholder()); + snprintf(parLength, 2, "%d", _params[i]->getValueLength()); + pitem.replace("{l}", parLength); + pitem.replace("{v}", _params[i]->getValue()); + pitem.replace("{c}", _params[i]->getCustomHTML()); + } + else + { + pitem = _params[i]->getCustomHTML(); + } + + page += pitem; + } + + // From v1.0.10 + if (_paramsCount > 0) + { + page += FPSTR(WM_FLDSET_END); + } + ////// + + if (_params[0] != NULL) + { + page += "
"; + } + + LOGDEBUG1(F("Static IP ="), _WiFi_STA_IPconfig._sta_static_ip.toString()); + + // KH, Comment out in v1.0.9 to permit changing from DHCP to static IP, or vice versa + // and add staticIP label in CP + + // From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used. + // You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa + // You have to explicitly specify false to disable the feature. + +#if !USE_STATIC_IP_CONFIG_IN_CP + if (_WiFi_STA_IPconfig._sta_static_ip) +#endif + { + // From v1.0.10 + page += FPSTR(WM_FLDSET_START); + ////// + + String item = FPSTR(WM_HTTP_FORM_LABEL); + item += FPSTR(WM_HTTP_FORM_PARAM); + item.replace("{i}", "ip"); + item.replace("{n}", "ip"); + item.replace("{p}", "Static IP"); + item.replace("{l}", "15"); + item.replace("{v}", _WiFi_STA_IPconfig._sta_static_ip.toString()); + + page += item; + + item = FPSTR(WM_HTTP_FORM_LABEL); + item += FPSTR(WM_HTTP_FORM_PARAM); + item.replace("{i}", "gw"); + item.replace("{n}", "gw"); + item.replace("{p}", "Gateway IP"); + item.replace("{l}", "15"); + item.replace("{v}", _WiFi_STA_IPconfig._sta_static_gw.toString()); + + page += item; + + item = FPSTR(WM_HTTP_FORM_LABEL); + item += FPSTR(WM_HTTP_FORM_PARAM); + item.replace("{i}", "sn"); + item.replace("{n}", "sn"); + item.replace("{p}", "Subnet"); + item.replace("{l}", "15"); + item.replace("{v}", _WiFi_STA_IPconfig._sta_static_sn.toString()); + + #if USE_CONFIGURABLE_DNS + //***** Added for DNS address options ***** + page += item; + + item = FPSTR(WM_HTTP_FORM_LABEL); + item += FPSTR(WM_HTTP_FORM_PARAM); + item.replace("{i}", "dns1"); + item.replace("{n}", "dns1"); + item.replace("{p}", "DNS1 IP"); + item.replace("{l}", "15"); + item.replace("{v}", _WiFi_STA_IPconfig._sta_static_dns1.toString()); + + page += item; + + item = FPSTR(WM_HTTP_FORM_LABEL); + item += FPSTR(WM_HTTP_FORM_PARAM); + item.replace("{i}", "dns2"); + item.replace("{n}", "dns2"); + item.replace("{p}", "DNS2 IP"); + item.replace("{l}", "15"); + item.replace("{v}", _WiFi_STA_IPconfig._sta_static_dns2.toString()); + //***** End added for DNS address options ***** + #endif + + page += item; + + // From v1.0.10 + page += FPSTR(WM_FLDSET_END); + ////// + + page += "
"; + } + + page += FPSTR(WM_HTTP_SCRIPT_NTP_HIDDEN); + + page += FPSTR(WM_HTTP_FORM_END); + + page += FPSTR(WM_HTTP_END); + + server->send(200, "text/html", page); + + LOGDEBUG(F("Sent config page")); +} + +////////////////////////////////////////// + +/** Handle the WLAN save form and redirect to WLAN config page again */ +void ESP_WiFiManager::handleWifiSave() +{ + LOGDEBUG(F("WiFi save")); + + //SAVE/connect here + _ssid = server->arg("s").c_str(); + _pass = server->arg("p").c_str(); + + // New from v1.1.0 + _ssid1 = server->arg("s1").c_str(); + _pass1 = server->arg("p1").c_str(); + + /////////////////////// + +#if USE_ESP_WIFIMANAGER_NTP + + if (server->arg("timezone") != "") + { + _timezoneName = server->arg("timezone"); + LOGDEBUG1(F("TZ name ="), _timezoneName); + } + else + { + LOGDEBUG(F("No TZ arg")); + } + +#endif + /////////////////////// + + //parameters + for (int i = 0; i < _paramsCount; i++) + { + if (_params[i] == NULL) + { + break; + } + + //read parameter + String value = server->arg(_params[i]->getID()).c_str(); + + //store it in array + // New in v1.4.0 + value.toCharArray(_params[i]->_WMParam_data._value, _params[i]->_WMParam_data._length); + ////// + + LOGDEBUG2(F("Parameter and value :"), _params[i]->getID(), value); + } + + if (server->arg("ip") != "") + { + String ip = server->arg("ip"); + optionalIPFromString(&_WiFi_STA_IPconfig._sta_static_ip, ip.c_str()); + + LOGDEBUG1(F("New Static IP ="), _WiFi_STA_IPconfig._sta_static_ip.toString()); + } + + if (server->arg("gw") != "") + { + String gw = server->arg("gw"); + optionalIPFromString(&_WiFi_STA_IPconfig._sta_static_gw, gw.c_str()); + + LOGDEBUG1(F("New Static Gateway ="), _WiFi_STA_IPconfig._sta_static_gw.toString()); + } + + if (server->arg("sn") != "") + { + String sn = server->arg("sn"); + optionalIPFromString(&_WiFi_STA_IPconfig._sta_static_sn, sn.c_str()); + + LOGDEBUG1(F("New Static Netmask ="), _WiFi_STA_IPconfig._sta_static_sn.toString()); + } + +#if USE_CONFIGURABLE_DNS + //***** Added for DNS Options ***** + if (server->arg("dns1") != "") + { + String dns1 = server->arg("dns1"); + optionalIPFromString(&_WiFi_STA_IPconfig._sta_static_dns1, dns1.c_str()); + + LOGDEBUG1(F("New Static DNS1 ="), _WiFi_STA_IPconfig._sta_static_dns1.toString()); + } + + if (server->arg("dns2") != "") + { + String dns2 = server->arg("dns2"); + optionalIPFromString(&_WiFi_STA_IPconfig._sta_static_dns2, dns2.c_str()); + + LOGDEBUG1(F("New Static DNS2 ="), _WiFi_STA_IPconfig._sta_static_dns2.toString()); + } + //***** End added for DNS Options ***** +#endif + + String page = FPSTR(WM_HTTP_HEAD_START); + + page.replace("{v}", "Credentials Saved"); + page += FPSTR(WM_HTTP_SCRIPT); + page += FPSTR(WM_HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(WM_HTTP_HEAD_END); + page += FPSTR(WM_HTTP_SAVED); + page.replace("{v}", _apName); + page.replace("{x}", _ssid); + + // KH, update from v1.1.0 + page.replace("{x1}", _ssid1); + ////// + + page += FPSTR(WM_HTTP_END); + + server->send(200, "text/html", page); + + LOGDEBUG(F("Sent wifi save page")); + + connect = true; //signal ready to connect/reset + + // Restore when Press Save WiFi + _configPortalTimeout = DEFAULT_PORTAL_TIMEOUT; +} + +////////////////////////////////////////// + +/** Handle shut down the server page */ +void ESP_WiFiManager::handleServerClose() +{ + LOGDEBUG(F("Server Close")); + + server->sendHeader(FPSTR(WM_HTTP_CACHE_CONTROL), FPSTR(WM_HTTP_NO_STORE)); + +#if USING_CORS_FEATURE + // New from v1.1.1, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + server->sendHeader(FPSTR(WM_HTTP_CORS), _CORS_Header); +#endif + + server->sendHeader(FPSTR(WM_HTTP_PRAGMA), FPSTR(WM_HTTP_NO_CACHE)); + server->sendHeader(FPSTR(WM_HTTP_EXPIRES), "-1"); + + String page = FPSTR(WM_HTTP_HEAD_START); + + page.replace("{v}", "Close Server"); + page += FPSTR(WM_HTTP_SCRIPT); + page += FPSTR(WM_HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(WM_HTTP_HEAD_END); + page += F("
"); + page += F("My network is "); + page += WiFi_SSID(); + page += F("
"); + page += F("IP address is "); + page += WiFi.localIP().toString(); + page += F("

"); + page += F("Portal closed...

"); + + //page += F("Push button on device to restart configuration server!"); + + page += FPSTR(WM_HTTP_END); + + server->send(200, "text/html", page); + + stopConfigPortal = true; //signal ready to shutdown config portal + + LOGDEBUG(F("Sent server close page")); + + // Restore when Press Save WiFi + _configPortalTimeout = DEFAULT_PORTAL_TIMEOUT; +} + +////////////////////////////////////////// + +/** Handle the info page */ +void ESP_WiFiManager::handleInfo() +{ + LOGDEBUG(F("Info")); + + // Disable _configPortalTimeout when someone accessing Portal to give some time to config + _configPortalTimeout = 0; //KH + + server->sendHeader(FPSTR(WM_HTTP_CACHE_CONTROL), FPSTR(WM_HTTP_NO_STORE)); + +#if USING_CORS_FEATURE + // New from v1.1.1, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + server->sendHeader(FPSTR(WM_HTTP_CORS), _CORS_Header); +#endif + + server->sendHeader(FPSTR(WM_HTTP_PRAGMA), FPSTR(WM_HTTP_NO_CACHE)); + server->sendHeader(FPSTR(WM_HTTP_EXPIRES), "-1"); + + String page = FPSTR(WM_HTTP_HEAD_START); + + page.replace("{v}", "Info"); + page += FPSTR(WM_HTTP_SCRIPT); + page += FPSTR(WM_HTTP_SCRIPT_NTP); + page += FPSTR(WM_HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(WM_HTTP_HEAD_END); + + page += F("

WiFi Information

"); + + reportStatus(page); + + page += FPSTR(WM_FLDSET_START); + + page += F("

Device Data

"); + page += F(""); + page += F(""); + page += F(""); + page += F(""); + page += F(""); + page += F(""); + page += F(""); + + page += F(""); + + page += F(""); + + page += F(""); + page += F("
NameValue
Chip ID"); + +#ifdef ESP8266 + page += String(ESP.getChipId(), HEX); //ESP.getChipId(); +#else //ESP32 + page += String((uint32_t)ESP.getEfuseMac(), HEX); //ESP.getChipId(); +#endif + + page += F("
Flash Chip ID"); + +#ifdef ESP8266 + page += String(ESP.getFlashChipId(), HEX); //ESP.getFlashChipId(); +#else //ESP32 + // TODO + page += F("TODO"); +#endif + + page += F("
IDE Flash Size"); + page += ESP.getFlashChipSize(); + page += F(" bytes
Real Flash Size"); + +#ifdef ESP8266 + page += ESP.getFlashChipRealSize(); +#else //ESP32 + // TODO + page += F("TODO"); +#endif + + page += F(" bytes
Access Point IP"); + page += WiFi.softAPIP().toString(); + page += F("
Access Point MAC"); + page += WiFi.softAPmacAddress(); + page += F("
SSID"); + page += WiFi_SSID(); + page += F("
Station IP"); + page += WiFi.localIP().toString(); + page += F("
Station MAC"); + page += WiFi.macAddress(); + page += F("
"); + + page += FPSTR(WM_FLDSET_END); + +#if USE_AVAILABLE_PAGES + page += FPSTR(WM_FLDSET_START); + + page += FPSTR(WM_HTTP_AVAILABLE_PAGES); + + page += FPSTR(WM_FLDSET_END); +#endif + + page += F("

More information about ESP_WiFiManager at"); + page += F("

https://github.com/khoih-prog/ESP_WiFiManager"); + page += FPSTR(WM_HTTP_END); + + server->send(200, "text/html", page); + + LOGDEBUG(F("Sent info page")); +} + +////////////////////////////////////////// + +/** Handle the state page */ +void ESP_WiFiManager::handleState() +{ + LOGDEBUG(F("State - json")); + + server->sendHeader(FPSTR(WM_HTTP_CACHE_CONTROL), FPSTR(WM_HTTP_NO_STORE)); + +#if USING_CORS_FEATURE + // New from v1.1.1, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + server->sendHeader(FPSTR(WM_HTTP_CORS), _CORS_Header); +#endif + + server->sendHeader(FPSTR(WM_HTTP_PRAGMA), FPSTR(WM_HTTP_NO_CACHE)); + server->sendHeader(FPSTR(WM_HTTP_EXPIRES), "-1"); + + String page = F("{\"Soft_AP_IP\":\""); + + page += WiFi.softAPIP().toString(); + page += F("\",\"Soft_AP_MAC\":\""); + page += WiFi.softAPmacAddress(); + page += F("\",\"Station_IP\":\""); + page += WiFi.localIP().toString(); + page += F("\",\"Station_MAC\":\""); + page += WiFi.macAddress(); + page += F("\","); + + if (WiFi.psk() != "") + { + page += F("\"Password\":true,"); + } + else + { + page += F("\"Password\":false,"); + } + + page += F("\"SSID\":\""); + page += WiFi_SSID(); + page += F("\"}"); + + server->send(200, "application/json", page); + + LOGDEBUG(F("Sent state page in json format")); +} + +////////////////////////////////////////// + +/** Handle the scan page */ +void ESP_WiFiManager::handleScan() +{ + LOGDEBUG(F("Scan")); + + // Disable _configPortalTimeout when someone accessing Portal to give some time to config + _configPortalTimeout = 0; //KH + + LOGDEBUG(F("State-Json")); + + server->sendHeader(FPSTR(WM_HTTP_CACHE_CONTROL), FPSTR(WM_HTTP_NO_STORE)); + +#if USING_CORS_FEATURE + // New from v1.1.1, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" + server->sendHeader(FPSTR(WM_HTTP_CORS), _CORS_Header); +#endif + + server->sendHeader(FPSTR(WM_HTTP_PRAGMA), FPSTR(WM_HTTP_NO_CACHE)); + server->sendHeader(FPSTR(WM_HTTP_EXPIRES), "-1"); + + int n; + int *indices; + + //Space for indices array allocated on heap in scanWifiNetworks + //and should be freed when indices no longer required. + + n = scanWifiNetworks(&indices); + LOGDEBUG(F("In handleScan, scanWifiNetworks done")); + String page = F("{\"Access_Points\":["); + + //display networks in page + for (int i = 0; i < n; i++) + { + if (indices[i] == -1) + continue; // skip duplicates and those that are below the required quality + + if (i != 0) + page += F(", "); + + LOGDEBUG1(F("Index ="), i); + LOGDEBUG1(F("SSID ="), WiFi.SSID(indices[i])); + LOGDEBUG1(F("RSSI ="), WiFi.RSSI(indices[i])); + + int quality = getRSSIasQuality(WiFi.RSSI(indices[i])); + String item = FPSTR(JSON_ITEM); + String rssiQ; + + rssiQ += quality; + item.replace("{v}", WiFi.SSID(indices[i])); + item.replace("{r}", rssiQ); + +#ifdef ESP8266 + if (WiFi.encryptionType(indices[i]) != ENC_TYPE_NONE) +#else //ESP32 + if (WiFi.encryptionType(indices[i]) != WIFI_AUTH_OPEN) +#endif + { + item.replace("{i}", "true"); + } + else + { + item.replace("{i}", "false"); + } + //LOGDEBUG(item); + page += item; + delay(0); + } + + if (indices) + { + free(indices); //indices array no longer required so free memory + } + + page += F("]}"); + + server->send(200, "application/json", page); + + LOGDEBUG(F("Sent WiFiScan Data in Json format")); +} + +////////////////////////////////////////// + +/** Handle the reset page */ +void ESP_WiFiManager::handleReset() +{ + LOGDEBUG(F("Reset")); + + server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server->sendHeader("Pragma", "no-cache"); + server->sendHeader("Expires", "-1"); + + String page = FPSTR(WM_HTTP_HEAD_START); + + page.replace("{v}", "WiFi Information"); + page += FPSTR(WM_HTTP_SCRIPT); + page += FPSTR(WM_HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(WM_HTTP_HEAD_END); + page += F("Resetting"); + page += FPSTR(WM_HTTP_END); + + server->send(200, "text/html", page); + + LOGDEBUG(F("Sent reset page")); + delay(5000); + + // New in v1.0.11 + // Temporary fix for issue of not clearing WiFi SSID/PW from flash of ESP32 + // See https://github.com/khoih-prog/ESP_WiFiManager/issues/25 and https://github.com/espressif/arduino-esp32/issues/400 + resetSettings(); + //WiFi.disconnect(true); // Wipe out WiFi credentials. + ////// + +#ifdef ESP8266 + ESP.reset(); +#else //ESP32 + ESP.restart(); +#endif + + delay(2000); +} + +////////////////////////////////////////// + +void ESP_WiFiManager::handleNotFound() +{ + if (captivePortal()) + { + // If caprive 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("Cache-Control", "no-cache, no-store, must-revalidate"); + server->sendHeader("Pragma", "no-cache"); + server->sendHeader("Expires", "-1"); + + server->send(404, "text/plain", message); +} + +////////////////////////////////////////// + +/** + HTTPD redirector + 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 ESP_WiFiManager::captivePortal() +{ + LOGDEBUG1(F("captivePortal: hostHeader = "), server->hostHeader()); + + if (!isIp(server->hostHeader())) + { + LOGINFO1(F("Request redirected to captive portal : "), server->client().localIP()); + + server->sendHeader(F("Location"), (String)F("http://") + toStringIp(server->client().localIP()), true); + server->send(302, FPSTR(WM_HTTP_HEAD_CT2), ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. + server->client().stop(); // Stop is needed because we sent no content length + + return true; + } + return false; +} + +////////////////////////////////////////// + +//start up config portal callback +void ESP_WiFiManager::setAPCallback(void(*func)(ESP_WiFiManager* myWiFiManager)) +{ + _apcallback = func; +} + +////////////////////////////////////////// + +//start up save config callback +void ESP_WiFiManager::setSaveConfigCallback(void(*func)()) +{ + _savecallback = func; +} + +////////////////////////////////////////// + +//sets a custom element to add to head, like a new style tag +void ESP_WiFiManager::setCustomHeadElement(const char* element) { + _customHeadElement = element; +} + +//if this is true, remove duplicated Access Points - defaut true +void ESP_WiFiManager::setRemoveDuplicateAPs(bool removeDuplicates) +{ + _removeDuplicateAPs = removeDuplicates; +} + +////////////////////////////////////////// + +//Scan for WiFiNetworks in range and sort by signal strength +//space for indices array allocated on the heap and should be freed when no longer required +int ESP_WiFiManager::scanWifiNetworks(int **indicesptr) +{ + LOGDEBUG(F("Scanning Network")); + + int n = WiFi.scanNetworks(false, true); + + LOGDEBUG1(F("scanWifiNetworks: Done, Scanned Networks n ="), n); + + //KH, Terrible bug here. WiFi.scanNetworks() returns n < 0 => malloc( negative == very big ) => crash!!! + //In .../esp32/libraries/WiFi/src/WiFiType.h + //#define WIFI_SCAN_RUNNING (-1) + //#define WIFI_SCAN_FAILED (-2) + //if (n == 0) + if (n <= 0) + { + LOGDEBUG(F("No network found")); + return (0); + } + else + { + // Allocate space off the heap for indices array. + // This space should be freed when no longer required. + int* indices = (int *)malloc(n * sizeof(int)); + + if (indices == NULL) + { + LOGDEBUG(F("ERROR: Out of memory")); + *indicesptr = NULL; + return (0); + } + + *indicesptr = indices; + + //sort networks + for (int i = 0; i < n; i++) + { + indices[i] = i; + } + + LOGDEBUG(F("Sorting")); + + // RSSI SORT + // old sort + for (int i = 0; i < n; i++) + { + for (int j = i + 1; j < n; j++) + { + if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) + { + std::swap(indices[i], indices[j]); + } + } + } + + LOGDEBUG(F("Removing Dup")); + + // remove duplicates ( must be RSSI sorted ) + if (_removeDuplicateAPs) + { + String cssid; + for (int i = 0; i < n; i++) + { + if (indices[i] == -1) + continue; + + cssid = WiFi.SSID(indices[i]); + for (int j = i + 1; j < n; j++) + { + if (cssid == WiFi.SSID(indices[j])) + { + LOGDEBUG1("DUP AP:", WiFi.SSID(indices[j])); + indices[j] = -1; // set dup aps to index -1 + } + } + } + } + + for (int i = 0; i < n; i++) + { + if (indices[i] == -1) + continue; // skip dups + + int quality = getRSSIasQuality(WiFi.RSSI(indices[i])); + + if (!(_minimumQuality == -1 || _minimumQuality < quality)) + { + indices[i] = -1; + LOGDEBUG(F("Skipping low quality")); + } + } + +#if (DEBUG_WIFIMGR > 2) + for (int i = 0; i < n; i++) + { + if (indices[i] == -1) + continue; // skip dups + else + Serial.println(WiFi.SSID(indices[i])); + } +#endif + + return (n); + } +} + +////////////////////////////////////////// + +int ESP_WiFiManager::getRSSIasQuality(int RSSI) +{ + int quality = 0; + + if (RSSI <= -100) + { + quality = 0; + } + else if (RSSI >= -50) + { + quality = 100; + } + else + { + quality = 2 * (RSSI + 100); + } + + return quality; +} + +////////////////////////////////////////// + +/** Is this an IP? */ +bool ESP_WiFiManager::isIp(const String& str) +{ + for (unsigned int i = 0; i < str.length(); i++) + { + int c = str.charAt(i); + + if (c != '.' && c != ':' && (c < '0' || c > '9')) + { + return false; + } + } + return true; +} + +////////////////////////////////////////// + +/** IP to String? */ +String ESP_WiFiManager::toStringIp(const IPAddress& ip) +{ + String res = ""; + for (int i = 0; i < 3; i++) + { + res += String((ip >> (8 * i)) & 0xFF) + "."; + } + + res += String(((ip >> 8 * 3)) & 0xFF); + + return res; +} + +////////////////////////////////////////// + +#ifdef ESP32 +// We can't use WiFi.SSID() in ESP32 as it's only valid after connected. +// SSID and Password stored in ESP32 wifi_ap_record_t and wifi_config_t are also cleared in reboot +// Have to create a new function to store in EEPROM/SPIFFS for this purpose + +String ESP_WiFiManager::getStoredWiFiSSID() +{ + if (WiFi.getMode() == WIFI_MODE_NULL) + { + return String(); + } + + wifi_ap_record_t info; + + if (!esp_wifi_sta_get_ap_info(&info)) + { + return String(reinterpret_cast(info.ssid)); + } + else + { + wifi_config_t conf; + esp_wifi_get_config(WIFI_IF_STA, &conf); + return String(reinterpret_cast(conf.sta.ssid)); + } + + return String(); +} + +////////////////////////////////////////// + +String ESP_WiFiManager::getStoredWiFiPass() +{ + if (WiFi.getMode() == WIFI_MODE_NULL) + { + return String(); + } + + wifi_config_t conf; + esp_wifi_get_config(WIFI_IF_STA, &conf); + + return String(reinterpret_cast(conf.sta.password)); +} +#endif + + +#endif //ESP_WiFiManager_Impl_h diff --git a/lib/ESP_WiFiManager/ESP_WiFiManager.h b/lib/ESP_WiFiManager/ESP_WiFiManager.h new file mode 100644 index 0000000..cd7f5aa --- /dev/null +++ b/lib/ESP_WiFiManager/ESP_WiFiManager.h @@ -0,0 +1,728 @@ +/**************************************************************************************************************************** + ESP_WiFiManager.h + For ESP8266 / ESP32 boards + + ESP_WiFiManager is a library for the ESP8266/Arduino platform + (https://github.com/esp8266/Arduino) to enable easy + configuration and reconfiguration of WiFi credentials using a Captive Portal + inspired by: + http://www.esp8266.com/viewtopic.php?f=29&t=2520 + https://github.com/chriscook8/esp-arduino-apboot + https://github.com/esp8266/Arduino/blob/master/libraries/DNSServer/examples/CaptivePortalAdvanced/ + + Modified from Tzapu https://github.com/tzapu/WiFiManager + and from Ken Taylor https://github.com/kentaylor + + Built by Khoi Hoang https://github.com/khoih-prog/ESP_WiFiManager + Licensed under MIT license + + Version: 1.8.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 07/10/2019 Initial coding + 1.0.1 K Hoang 13/12/2019 Fix bug. Add features. Add support for ESP32 + 1.0.2 K Hoang 19/12/2019 Fix bug thatkeeps ConfigPortal in endless loop if Portal/Router SSID or Password is NULL. + 1.0.3 K Hoang 05/01/2020 Option not displaying AvailablePages in Info page. Enhance README.md. Modify examples + 1.0.4 K Hoang 07/01/2020 Add RFC952 setHostname feature. + 1.0.5 K Hoang 15/01/2020 Add configurable DNS feature. Thanks to @Amorphous of https://community.blynk.cc + 1.0.6 K Hoang 03/02/2020 Add support for ArduinoJson version 6.0.0+ ( tested with v6.14.1 ) + 1.0.7 K Hoang 13/04/2020 Reduce start time, fix SPIFFS bug in examples, update README.md + 1.0.8 K Hoang 10/06/2020 Fix STAstaticIP issue. Restructure code. Add LittleFS support for ESP8266 core 2.7.1+ + 1.0.9 K Hoang 29/07/2020 Fix ESP32 STAstaticIP bug. Permit changing from DHCP <-> static IP using Config Portal. + Add, enhance examples (fix MDNS for ESP32) + 1.0.10 K Hoang 08/08/2020 Add more features to Config Portal. Use random WiFi AP channel to avoid conflict. + 1.0.11 K Hoang 17/08/2020 Add CORS feature. Fix bug in softAP, autoConnect, resetSettings. + 1.1.0 K Hoang 28/08/2020 Add MultiWiFi feature to autoconnect to best WiFi at runtime + 1.1.1 K Hoang 30/08/2020 Add setCORSHeader function to allow flexible CORS. Fix typo and minor improvement. + 1.1.2 K Hoang 17/08/2020 Fix bug. Add example. + 1.2.0 K Hoang 09/10/2020 Restore cpp code besides Impl.h code to use if linker error. Fix bug. + 1.3.0 K Hoang 04/12/2020 Add LittleFS support to ESP32 using LITTLEFS Library + 1.4.1 K Hoang 22/12/2020 Fix staticIP not saved. Add functions. Add complex examples. Sync with ESPAsync_WiFiManager + 1.4.2 K Hoang 14/01/2021 Fix examples' bug not using saved WiFi Credentials after losing all WiFi connections. + 1.4.3 K Hoang 23/01/2021 Fix examples' bug not saving Static IP in certain cases. + 1.5.0 K Hoang 12/02/2021 Add support to new ESP32-S2 + 1.5.1 K Hoang 26/03/2021 Fix compiler error if setting Compiler Warnings to All. Retest with esp32 core v1.0.6 + 1.5.2 K Hoang 08/04/2021 Fix example misleading messages. + 1.5.3 K Hoang 13/04/2021 Add dnsServer error message. + 1.6.0 K Hoang 20/04/2021 Add support to new ESP32-C3 using SPIFFS or EEPROM + 1.6.1 K Hoang 25/04/2021 Fix MultiWiFi bug. Fix captive-portal bug if CP AP address is not default 192.168.4.1 + 1.7.0 K Hoang 06/05/2021 Set _timezoneName. Add support to new ESP32-S2 (METRO_ESP32S2, FUNHOUSE_ESP32S2, etc.) + 1.7.1 K Hoang 08/05/2021 Fix Json bug. Fix timezoneName not displayed in Info page. + 1.7.2 K Hoang 08/05/2021 Fix warnings with ESP8266 core v3.0.0 + 1.7.3 K Hoang 29/07/2021 Fix MultiWiFi connection issue with ESP32 core v2.0.0-rc1+ + 1.7.4 K Hoang 13/08/2021 Add WiFi scanning of hidden SSIDs + 1.7.5 K Hoang 10/10/2021 Update `platform.ini` and `library.json` + 1.7.6 K Hoang 26/11/2021 Auto detect ESP32 core and use either built-in LittleFS or LITTLEFS library + 1.7.7 K Hoang 26/11/2021 Fix compile error for ESP32 core v1.0.5- + 1.7.8 K Hoang 30/11/2021 Fix bug to permit using HTTP port different from 80. Fix bug + 1.8.0 K Hoang 29/12/2021 Fix `multiple-definitions` linker error and weird bug related to src_cpp + *****************************************************************************************************************************/ + +#pragma once + +#ifndef ESP_WiFiManager_h +#define ESP_WiFiManager_h + +#if !( defined(ESP8266) || defined(ESP32) ) + #error This code is intended to run on the ESP8266 or ESP32 platform! Please check your Tools->Board setting. +#elif ( ARDUINO_ESP32S2_DEV || ARDUINO_FEATHERS2 || ARDUINO_ESP32S2_THING_PLUS || ARDUINO_MICROS2 || \ + ARDUINO_METRO_ESP32S2 || ARDUINO_MAGTAG29_ESP32S2 || ARDUINO_FUNHOUSE_ESP32S2 || \ + ARDUINO_ADAFRUIT_FEATHER_ESP32S2_NOPSRAM ) + #warning Using ESP32_S2. To follow library instructions to install esp32-s2 core and WebServer Patch + #warning You have to select HUGE APP or 1.9-2.0 MB APP to be able to run Config Portal. Must use PSRAM + #define USING_ESP32_S2 true +#elif ( ARDUINO_ESP32C3_DEV ) + #warning Using ESP32_C3. To follow library instructions to install esp32-c3 core. Only SPIFFS and EEPROM OK. + #warning You have to select Flash size 2MB and Minimal APP (1.3MB + 700KB) for some boards + #define USING_ESP32_C3 true +#endif + +#define ESP_WIFIMANAGER_VERSION "ESP_WiFiManager v1.8.0" + +#define ESP_WIFIMANAGER_VERSION_MAJOR 1 +#define ESP_WIFIMANAGER_VERSION_MINOR 8 +#define ESP_WIFIMANAGER_VERSION_PATCH 0 + +#define ESP_WIFIMANAGER_VERSION_INT 1008000 + +#include "ESP_WiFiManager_Debug.h" + +#if ( defined(HTTP_PORT) && (HTTP_PORT < 65536) && (HTTP_PORT > 0) ) + #if (_WIFIMGR_LOGLEVEL_ > 2) + #warning Using custom HTTP_PORT + #endif + + #define HTTP_PORT_TO_USE HTTP_PORT +#else + #if (_WIFIMGR_LOGLEVEL_ > 2) + #warning Using default HTTP_PORT = 80 + #endif + + #define HTTP_PORT_TO_USE 80 +#endif + +//KH, for ESP32 +#ifdef ESP8266 + #include + #include +#else //ESP32 + #include + #include +#endif + +#include +#include +#undef min +#undef max +#include + +//KH, for ESP32 +#ifdef ESP8266 + extern "C" + { + #include "user_interface.h" + } + + #define ESP_getChipId() (ESP.getChipId()) +#else //ESP32 + #include + #define ESP_getChipId() ((uint32_t)ESP.getEfuseMac()) +#endif + +// New in v1.4.0 +typedef struct +{ + IPAddress _ap_static_ip; + IPAddress _ap_static_gw; + IPAddress _ap_static_sn; + +} WiFi_AP_IPConfig; + +// Thanks to @Amorphous for the feature and code +// (https://community.blynk.cc/t/esp-wifimanager-for-esp32-and-esp8266/42257/13) +// To enable to configure from sketch +#if !defined(USE_CONFIGURABLE_DNS) + #define USE_CONFIGURABLE_DNS false +#endif + +typedef struct +{ + IPAddress _sta_static_ip; + IPAddress _sta_static_gw; + IPAddress _sta_static_sn; + IPAddress _sta_static_dns1; + IPAddress _sta_static_dns2; +} WiFi_STA_IPConfig; +////// + +#define WFM_LABEL_BEFORE 1 +#define WFM_LABEL_AFTER 2 +#define WFM_NO_LABEL 0 + +/** Handle CORS in pages */ +// Default false for using only whenever necessary to avoid security issue when using CORS (Cross-Origin Resource Sharing) +#ifndef USING_CORS_FEATURE + // Contributed by AlesSt (https://github.com/AlesSt) to solve AJAX CORS protection problem of API redirects on client side + // See more in https://github.com/khoih-prog/ESP_WiFiManager/issues/27 and https://en.wikipedia.org/wiki/Cross-origin_resource_sharing + #define USING_CORS_FEATURE false +#endif + +//KH +//Mofidy HTTP_HEAD to WM_HTTP_HEAD_START to avoid conflict in Arduino esp8266 core 2.6.0+ +const char WM_HTTP_200[] PROGMEM = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"; +const char WM_HTTP_HEAD_START[] PROGMEM = "{v}"; + +// KH, update from v1.0.10 +const char WM_HTTP_STYLE[] PROGMEM = ""; +////// + +// KH, update from v1.1.0 +const char WM_HTTP_SCRIPT[] PROGMEM = ""; +////// + +// From v1.0.9 to permit disable or configure NTP from sketch +#ifndef USE_ESP_WIFIMANAGER_NTP + // From v1.0.6 to enable NTP config + #define USE_ESP_WIFIMANAGER_NTP true +#endif + +#if USE_ESP_WIFIMANAGER_NTP + +#include "utils/TZ.h" + +const char WM_HTTP_SCRIPT_NTP_MSG[] PROGMEM = "

Your Timezone is :

"; +const char WM_HTTP_SCRIPT_NTP_HIDDEN[] PROGMEM = "

"; + +#if ESP8266 + #if !(USE_CLOUDFLARE_NTP) + #undef USE_CLOUDFLARE_NTP + #define USE_CLOUDFLARE_NTP true + #warning Forcing USE_CLOUDFLARE_NTP for ESP8266 as low memory can cause blank page + #endif +#endif + +// To permit disable or configure NTP from sketch +#ifndef USE_CLOUDFLARE_NTP + #define USE_CLOUDFLARE_NTP false +#endif + +#if USE_CLOUDFLARE_NTP +const char WM_HTTP_SCRIPT_NTP[] PROGMEM = ""; +#else +const char WM_HTTP_SCRIPT_NTP[] PROGMEM = ""; +#endif + +#else + const char WM_HTTP_SCRIPT_NTP_MSG[] PROGMEM = ""; + const char WM_HTTP_SCRIPT_NTP_HIDDEN[] PROGMEM = ""; + const char WM_HTTP_SCRIPT_NTP[] PROGMEM = ""; +#endif + +// KH, update from v1.0.10 +const char WM_HTTP_HEAD_END[] PROGMEM = "
"; + +const char WM_FLDSET_START[] PROGMEM = "
"; +const char WM_FLDSET_END[] PROGMEM = "
"; +////// + +const char WM_HTTP_PORTAL_OPTIONS[] PROGMEM = "



"; +const char WM_HTTP_ITEM[] PROGMEM = "
{v} {r}%
"; +const char JSON_ITEM[] PROGMEM = "{\"SSID\":\"{v}\", \"Encryption\":{i}, \"Quality\":\"{r}\"}"; + +// KH, update from v1.1.0 +//const char WM_HTTP_FORM_START[] PROGMEM = "
"; +//const char WM_HTTP_FORM_START[] PROGMEM = "
"; +////// + +// KH, add from v1.0.10 +const char WM_HTTP_FORM_LABEL_BEFORE[] PROGMEM = "
"; +const char WM_HTTP_FORM_LABEL_AFTER[] PROGMEM = "
"; +////// + +const char WM_HTTP_FORM_LABEL[] PROGMEM = ""; +const char WM_HTTP_FORM_PARAM[] PROGMEM = ""; + +const char WM_HTTP_FORM_END[] PROGMEM = "
"; + +// KH, update from v1.1.0 +const char WM_HTTP_SAVED[] PROGMEM = "
Credentials Saved
Try connecting ESP to the {x}/{x1} network. Wait around 10 seconds then check if it's OK.

The {v} AP will run on the same WiFi channel of the {x}/{x1} AP. You may have to manually reconnect to the {v} AP.

"; +////// + +const char WM_HTTP_END[] PROGMEM = "
"; + +//KH, from v1.1.0 +const char WM_HTTP_HEAD_CL[] PROGMEM = "Content-Length"; +const char WM_HTTP_HEAD_CT[] PROGMEM = "text/html"; +const char WM_HTTP_HEAD_CT2[] PROGMEM = "text/plain"; + +//KH Add repeatedly used const +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 = "*"; + +#if USE_AVAILABLE_PAGES +const char WM_HTTP_AVAILABLE_PAGES[] PROGMEM = "

Available Pages

PageFunction
/Menu page.
/wifiShow WiFi scan results and enter WiFi configuration.
/wifisaveSave WiFi configuration information and configure device. Needs variables supplied.
/closeClose the configuration server and configuration WiFi network.
/iThis page.
/rDelete WiFi configuration and reboot. ESP device will not reconnect to a network until new WiFi configuration data is entered.
/stateCurrent device state in JSON format. Interface for programmatic WiFi configuration.
/scanRun a WiFi scan and return results in JSON format. Interface for programmatic WiFi configuration.
"; +#else +const char WM_HTTP_AVAILABLE_PAGES[] PROGMEM = ""; +#endif + +//KH +#define WIFI_MANAGER_MAX_PARAMS 20 + +///////////////////////////////////////////////////////////////////////////// +// New in v1.4.0 +typedef struct +{ + const char *_id; + const char *_placeholder; + char *_value; + int _length; + int _labelPlacement; + +} WMParam_Data; +////// + +class ESP_WMParameter +{ + public: + ESP_WMParameter(const char *custom); + ESP_WMParameter(const char *id, const char *placeholder, const char *defaultValue, int length, + const char *custom = "", int labelPlacement = WFM_LABEL_BEFORE); + + // New in v1.4.0 + ESP_WMParameter(const WMParam_Data& WMParam_data); + ////// + + ~ESP_WMParameter(); + + // New in v1.4.0 + void setWMParam_Data(const WMParam_Data& WMParam_data); + void getWMParam_Data(WMParam_Data &WMParam_data); + ////// + + const char *getID(); + const char *getValue(); + const char *getPlaceholder(); + int getValueLength(); + int getLabelPlacement(); + const char *getCustomHTML(); + + private: + + WMParam_Data _WMParam_data; + + const char *_customHTML; + + void init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom, int labelPlacement); + + friend class ESP_WiFiManager; +}; + +#define USE_DYNAMIC_PARAMS true +#define DEFAULT_PORTAL_TIMEOUT 60000L + +// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used. +// You have to explicitly specify false to disable the feature. +#ifndef USE_STATIC_IP_CONFIG_IN_CP + #define USE_STATIC_IP_CONFIG_IN_CP true +#endif + +class ESP_WiFiManager +{ + public: + + ESP_WiFiManager(const char *iHostname = ""); + + ~ESP_WiFiManager(); + + // Update feature from v1.0.11. Can use with STA staticIP now + bool autoConnect(); + bool autoConnect(char const *apName, char const *apPassword = NULL); + ////// + + //if you want to start the config portal + bool startConfigPortal(); + bool startConfigPortal(char const *apName, char const *apPassword = NULL); + + // get the AP name of the config portal, so it can be used in the callback + String getConfigPortalSSID(); + // get the AP password of the config portal, so it can be used in the callback + String getConfigPortalPW(); + + void resetSettings(); + + //sets timeout before webserver loop ends and exits even if there has been no setup. + //usefully for devices that failed to connect at some point and got stuck in a webserver loop + //in seconds setConfigPortalTimeout is a new name for setTimeout + void setConfigPortalTimeout(unsigned long seconds); + void setTimeout(unsigned long seconds); + + //sets timeout for which to attempt connecting, usefull if you get a lot of failed connects + void setConnectTimeout(unsigned long seconds); + + + void setDebugOutput(bool debug); + //defaults to not showing anything under 8% signal quality if called + void setMinimumSignalQuality(int quality = 8); + + // KH, new from v1.0.10 to enable dynamic/random channel + int setConfigPortalChannel(int channel = 1); + ////// + + //sets a custom ip /gateway /subnet configuration + void setAPStaticIPConfig(const IPAddress& ip, const IPAddress& gw, const IPAddress& sn); + + // New in v1.4.0 + void setAPStaticIPConfig(const WiFi_AP_IPConfig& WM_AP_IPconfig); + void getAPStaticIPConfig(WiFi_AP_IPConfig &WM_AP_IPconfig); + ////// + + //sets config for a static IP + void setSTAStaticIPConfig(const IPAddress& ip, const IPAddress& gw, const IPAddress& sn); + + // New in v1.4.0 + void setSTAStaticIPConfig(const WiFi_STA_IPConfig& WM_STA_IPconfig); + void getSTAStaticIPConfig(WiFi_STA_IPConfig &WM_STA_IPconfig); + ////// + +#if USE_CONFIGURABLE_DNS + void setSTAStaticIPConfig(const IPAddress& ip, const IPAddress& gw, const IPAddress& sn, + const IPAddress& dns_address_1, const IPAddress& dns_address_2); +#endif + + //called when AP mode and config portal is started + void setAPCallback(void(*func)(ESP_WiFiManager*)); + //called when settings have been changed and connection was successful + void setSaveConfigCallback(void(*func)()); + +#if USE_DYNAMIC_PARAMS + //adds a custom parameter + bool addParameter(ESP_WMParameter *p); +#else + //adds a custom parameter + void addParameter(ESP_WMParameter *p); +#endif + + //if this is set, it will exit after config, even if connection is unsucessful. + void setBreakAfterConfig(bool shouldBreak); + //if this is set, try WPS setup when starting (this will delay config portal for up to 2 mins) + //TODO + //if this is set, customise style + void setCustomHeadElement(const char* element); + //if this is true, remove duplicated Access Points - defaut true + void setRemoveDuplicateAPs(bool removeDuplicates); + //Scan for WiFiNetworks in range and sort by signal strength + //space for indices array allocated on the heap and should be freed when no longer required + int scanWifiNetworks(int **indicesptr); + + // return SSID of router in STA mode got from config portal. NULL if no user's input //KH + String getSSID() + { + return _ssid; + } + + // return password of router in STA mode got from config portal. NULL if no user's input //KH + String getPW() + { + return _pass; + } + + // New from v1.1.0 + // return SSID of router in STA mode got from config portal. NULL if no user's input //KH + String getSSID1() + { + return _ssid1; + } + + // return password of router in STA mode got from config portal. NULL if no user's input //KH + String getPW1() + { + return _pass1; + } + + #define MAX_WIFI_CREDENTIALS 2 + + String getSSID(uint8_t index) + { + if (index == 0) + return _ssid; + else if (index == 1) + return _ssid1; + else + return String(""); + } + + String getPW(uint8_t index) + { + if (index == 0) + return _pass; + else if (index == 1) + return _pass1; + else + return String(""); + } + ////// + + // New from v1.1.1, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" +#if USING_CORS_FEATURE + void setCORSHeader(const char* CORSHeaders) + { + _CORS_Header = CORSHeaders; + + LOGWARN1(F("Set CORS Header to : "), _CORS_Header); + } + + const char* getCORSHeader() + { + return _CORS_Header; + } +#endif + + //returns the list of Parameters + ESP_WMParameter** getParameters(); + // returns the Parameters Count + int getParametersCount(); + + const char* getStatus(int status); + +#ifdef ESP32 + String getStoredWiFiSSID(); + String getStoredWiFiPass(); +#endif + + String WiFi_SSID() + { +#ifdef ESP8266 + return WiFi.SSID(); +#else + return getStoredWiFiSSID(); +#endif + } + + String WiFi_Pass() + { +#ifdef ESP8266 + return WiFi.psk(); +#else + return getStoredWiFiPass(); +#endif + } + + void setHostname() + { + if (RFC952_hostname[0] != 0) + { +#if ESP8266 + WiFi.hostname(RFC952_hostname); +#else + + // Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h + //#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) ) //(ESP_ARDUINO_VERSION_MAJOR >= 2) + #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) + WiFi.setHostname(RFC952_hostname); + #else + // Still have bug in ESP32_S2 for old core. If using WiFi.setHostname() => WiFi.localIP() always = 255.255.255.255 + if ( String(ARDUINO_BOARD) != "ESP32S2_DEV" ) + { + // See https://github.com/espressif/arduino-esp32/issues/2537 + WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); + WiFi.setHostname(RFC952_hostname); + } + #endif +#endif + } + } + +#if USE_ESP_WIFIMANAGER_NTP + + String getTimezoneName() + { + return _timezoneName; + } + + void setTimezoneName(const String& inTimezoneName) + { + _timezoneName = inTimezoneName; + } + ////// + + //See: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + // EST5EDT,M3.2.0,M11.1.0 (for America/New_York) + // EST5EDT is the name of the time zone + // EST is the abbreviation used when DST is off + // 6 hours is the time difference from GMT + // EDT is the abbreviation used when DST is on + // ,M3 is the third month + // .2 is the second occurrence of the day in the month + // .0 is Sunday + // ,M11 is the eleventh month + // .1 is the first occurrence of the day in the month + // .0 is Sunday + + const char * getTZ(const char * timezoneName) + { + //const char TZ_NAME[][TIMEZONE_MAX_LEN] + for (uint16_t index = 0; index < sizeof(TZ_NAME) / TIMEZONE_MAX_LEN; index++) + { + if ( !strncmp(timezoneName, (TZ_NAME[index]), strlen((TZ_NAME[index])) ) ) + { + yield(); + return (ESP_TZ_NAME[index]); + } + } + + return ""; + } + + + const char * getTZ(const String& timezoneName) + { + return getTZ(timezoneName.c_str()); + } + + +#endif + + private: + std::unique_ptr dnsServer; + + //KH, for ESP32 +#ifdef ESP8266 + std::unique_ptr server; +#else //ESP32 + std::unique_ptr server; +#endif + +#define RFC952_HOSTNAME_MAXLEN 24 + char RFC952_hostname[RFC952_HOSTNAME_MAXLEN + 1]; + + char* getRFC952_hostname(const char* iHostname); + + void setupConfigPortal(); + void startWPS(); + //const char* getStatus(int status); + + const char* _apName = "no-net"; + const char* _apPassword = NULL; + + String _ssid = ""; + String _pass = ""; + + // New from v1.1.0 + String _ssid1 = ""; + String _pass1 = ""; + ////// + +#if USE_ESP_WIFIMANAGER_NTP + // Timezone info + String _timezoneName = ""; +#endif + + unsigned long _configPortalTimeout = 0; + + unsigned long _connectTimeout = 0; + unsigned long _configPortalStart = 0; + + int numberOfNetworks; + int *networkIndices; + + // KH, new from v1.0.10 to enable dynamic/random channel + // default to channel 1 + #define MIN_WIFI_CHANNEL 1 + #define MAX_WIFI_CHANNEL 11 // Channel 12,13 is flaky, because of bad number 13 ;-) + + int _WiFiAPChannel = 1; + ////// + + // New in v1.4.0 + WiFi_AP_IPConfig _WiFi_AP_IPconfig; + + WiFi_STA_IPConfig _WiFi_STA_IPconfig = { IPAddress(0, 0, 0, 0), IPAddress(192, 168, 2, 1), IPAddress(255, 255, 255, 0), + IPAddress(192, 168, 2, 1), IPAddress(8, 8, 8, 8) }; + ////// + + int _paramsCount = 0; + int _minimumQuality = -1; + bool _removeDuplicateAPs = true; + bool _shouldBreakAfterConfig = false; + bool _tryWPS = false; + + const char* _customHeadElement = ""; + + int status = WL_IDLE_STATUS; + + // New from v1.1.0, for configure CORS Header, default to WM_HTTP_CORS_ALLOW_ALL = "*" +#if USING_CORS_FEATURE + const char* _CORS_Header = WM_HTTP_CORS_ALLOW_ALL; //"*"; +#endif + ////// + + // New v1.0.8 + void setWifiStaticIP(); + + // New v1.1.0 + int reconnectWifi(); + ////// + + // New v1.0.11 + int connectWifi(const String& ssid = "", const String& pass = ""); + ////// + + uint8_t waitForConnectResult(); + + void handleRoot(); + void handleWifi(); + void handleWifiSave(); + void handleServerClose(); + void handleInfo(); + void handleState(); + void handleScan(); + void handleReset(); + void handleNotFound(); + bool captivePortal(); + + void reportStatus(String &page); + + // DNS server + const byte DNS_PORT = 53; + + //helpers + int getRSSIasQuality(int RSSI); + bool isIp(const String& str); + String toStringIp(const IPAddress& ip); + + bool connect; + bool stopConfigPortal = false; + + bool _debug = false; //true; + + void(*_apcallback) (ESP_WiFiManager*) = NULL; + void(*_savecallback)() = NULL; + +#if USE_DYNAMIC_PARAMS + int _max_params; + ESP_WMParameter** _params; +#else + ESP_WMParameter* _params[WIFI_MANAGER_MAX_PARAMS]; +#endif + + template + void DEBUG_WM(Generic text); + + template + auto optionalIPFromString(T *obj, const char *s) -> decltype(obj->fromString(s)) { + return obj->fromString(s); + } + auto optionalIPFromString(...) -> bool { + LOGINFO("NO fromString METHOD ON IPAddress, you need ESP8266 core 2.1.0 or newer for Custom IP configuration to work."); + return false; + } +}; + +#endif // ESP_WiFiManager_h + diff --git a/lib/ESP_WiFiManager/ESP_WiFiManager_Debug.h b/lib/ESP_WiFiManager/ESP_WiFiManager_Debug.h new file mode 100644 index 0000000..c60454b --- /dev/null +++ b/lib/ESP_WiFiManager/ESP_WiFiManager_Debug.h @@ -0,0 +1,127 @@ +/**************************************************************************************************************************** + ESP_WiFiManager_Debug.h + For ESP8266 / ESP32 boards + + ESP_WiFiManager is a library for the ESP8266/Arduino platform + (https://github.com/esp8266/Arduino) to enable easy + configuration and reconfiguration of WiFi credentials using a Captive Portal + inspired by: + http://www.esp8266.com/viewtopic.php?f=29&t=2520 + https://github.com/chriscook8/esp-arduino-apboot + https://github.com/esp8266/Arduino/blob/master/libraries/DNSServer/examples/CaptivePortalAdvanced/ + + Modified from Tzapu https://github.com/tzapu/WiFiManager + and from Ken Taylor https://github.com/kentaylor + + Built by Khoi Hoang https://github.com/khoih-prog/ESP_WiFiManager + Licensed under MIT license + + Version: 1.8.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.0 K Hoang 07/10/2019 Initial coding + 1.0.1 K Hoang 13/12/2019 Fix bug. Add features. Add support for ESP32 + 1.0.2 K Hoang 19/12/2019 Fix bug thatkeeps ConfigPortal in endless loop if Portal/Router SSID or Password is NULL. + 1.0.3 K Hoang 05/01/2020 Option not displaying AvailablePages in Info page. Enhance README.md. Modify examples + 1.0.4 K Hoang 07/01/2020 Add RFC952 setHostname feature. + 1.0.5 K Hoang 15/01/2020 Add configurable DNS feature. Thanks to @Amorphous of https://community.blynk.cc + 1.0.6 K Hoang 03/02/2020 Add support for ArduinoJson version 6.0.0+ ( tested with v6.14.1 ) + 1.0.7 K Hoang 13/04/2020 Reduce start time, fix SPIFFS bug in examples, update README.md + 1.0.8 K Hoang 10/06/2020 Fix STAstaticIP issue. Restructure code. Add LittleFS support for ESP8266 core 2.7.1+ + 1.0.9 K Hoang 29/07/2020 Fix ESP32 STAstaticIP bug. Permit changing from DHCP <-> static IP using Config Portal. + Add, enhance examples (fix MDNS for ESP32) + 1.0.10 K Hoang 08/08/2020 Add more features to Config Portal. Use random WiFi AP channel to avoid conflict. + 1.0.11 K Hoang 17/08/2020 Add CORS feature. Fix bug in softAP, autoConnect, resetSettings. + 1.1.0 K Hoang 28/08/2020 Add MultiWiFi feature to autoconnect to best WiFi at runtime + 1.1.1 K Hoang 30/08/2020 Add setCORSHeader function to allow flexible CORS. Fix typo and minor improvement. + 1.1.2 K Hoang 17/08/2020 Fix bug. Add example. + 1.2.0 K Hoang 09/10/2020 Restore cpp code besides Impl.h code to use if linker error. Fix bug. + 1.3.0 K Hoang 04/12/2020 Add LittleFS support to ESP32 using LITTLEFS Library + 1.4.1 K Hoang 22/12/2020 Fix staticIP not saved. Add functions. Add complex examples. Sync with ESPAsync_WiFiManager + 1.4.2 K Hoang 14/01/2021 Fix examples' bug not using saved WiFi Credentials after losing all WiFi connections. + 1.4.3 K Hoang 23/01/2021 Fix examples' bug not saving Static IP in certain cases. + 1.5.0 K Hoang 12/02/2021 Add support to new ESP32-S2 + 1.5.1 K Hoang 26/03/2021 Fix compiler error if setting Compiler Warnings to All. Retest with esp32 core v1.0.6 + 1.5.2 K Hoang 08/04/2021 Fix example misleading messages. + 1.5.3 K Hoang 13/04/2021 Add dnsServer error message. + 1.6.0 K Hoang 20/04/2021 Add support to new ESP32-C3 using SPIFFS or EEPROM + 1.6.1 K Hoang 25/04/2021 Fix MultiWiFi bug. Fix captive-portal bug if CP AP address is not default 192.168.4.1 + 1.7.0 K Hoang 06/05/2021 Set _timezoneName. Add support to new ESP32-S2 (METRO_ESP32S2, FUNHOUSE_ESP32S2, etc.) + 1.7.1 K Hoang 08/05/2021 Fix Json bug. Fix timezoneName not displayed in Info page. + 1.7.2 K Hoang 08/05/2021 Fix warnings with ESP8266 core v3.0.0 + 1.7.3 K Hoang 29/07/2021 Fix MultiWiFi connection issue with ESP32 core v2.0.0-rc1+ + 1.7.4 K Hoang 13/08/2021 Add WiFi scanning of hidden SSIDs + 1.7.5 K Hoang 10/10/2021 Update `platform.ini` and `library.json` + 1.7.6 K Hoang 26/11/2021 Auto detect ESP32 core and use either built-in LittleFS or LITTLEFS library + 1.7.7 K Hoang 26/11/2021 Fix compile error for ESP32 core v1.0.5- + 1.7.8 K Hoang 30/11/2021 Fix bug to permit using HTTP port different from 80. Fix bug + 1.8.0 K Hoang 29/12/2021 Fix `multiple-definitions` linker error and weird bug related to src_cpp + *****************************************************************************************************************************/ + +#pragma once + +#ifndef ESP_WiFiManager_Debug_H +#define ESP_WiFiManager_Debug_H + +#ifdef WIFIMGR_DEBUG_PORT + #define WM_DBG_PORT WIFIMGR_DEBUG_PORT +#else + #define WM_DBG_PORT Serial +#endif + +// Change _WIFIMGR_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 _WIFIMGR_LOGLEVEL_ + #define _WIFIMGR_LOGLEVEL_ 0 +#endif + +const char WM_MARK[] = "[WM] "; +const char WM_SP[] = " "; + +#define WM_PRINT WM_DBG_PORT.print +#define WM_PRINTLN WM_DBG_PORT.println + +#define WM_PRINT_MARK WM_PRINT(WM_MARK) +#define WM_PRINT_SP WM_PRINT(WM_SP) + +//////////////////////////////////////////////////// + +#define LOGERROR(x) if(_WIFIMGR_LOGLEVEL_>0) { WM_PRINT_MARK; WM_PRINTLN(x); } +#define LOGERROR0(x) if(_WIFIMGR_LOGLEVEL_>0) { WM_PRINT(x); } +#define LOGERROR1(x,y) if(_WIFIMGR_LOGLEVEL_>0) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINTLN(y); } +#define LOGERROR2(x,y,z) if(_WIFIMGR_LOGLEVEL_>0) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINTLN(z); } +#define LOGERROR3(x,y,z,w) if(_WIFIMGR_LOGLEVEL_>0) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINT(z); WM_PRINT_SP; WM_PRINTLN(w); } + +//////////////////////////////////////////////////// + +#define LOGWARN(x) if(_WIFIMGR_LOGLEVEL_>1) { WM_PRINT_MARK; WM_PRINTLN(x); } +#define LOGWARN0(x) if(_WIFIMGR_LOGLEVEL_>1) { WM_PRINT(x); } +#define LOGWARN1(x,y) if(_WIFIMGR_LOGLEVEL_>1) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINTLN(y); } +#define LOGWARN2(x,y,z) if(_WIFIMGR_LOGLEVEL_>1) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINTLN(z); } +#define LOGWARN3(x,y,z,w) if(_WIFIMGR_LOGLEVEL_>1) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINT(z); WM_PRINT_SP; WM_PRINTLN(w); } + +//////////////////////////////////////////////////// + +#define LOGINFO(x) if(_WIFIMGR_LOGLEVEL_>2) { WM_PRINT_MARK; WM_PRINTLN(x); } +#define LOGINFO0(x) if(_WIFIMGR_LOGLEVEL_>2) { WM_PRINT(x); } +#define LOGINFO1(x,y) if(_WIFIMGR_LOGLEVEL_>2) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINTLN(y); } +#define LOGINFO2(x,y,z) if(_WIFIMGR_LOGLEVEL_>2) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINTLN(z); } +#define LOGINFO3(x,y,z,w) if(_WIFIMGR_LOGLEVEL_>2) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINT(z); WM_PRINT_SP; WM_PRINTLN(w); } + +//////////////////////////////////////////////////// + +#define LOGDEBUG(x) if(_WIFIMGR_LOGLEVEL_>3) { WM_PRINT_MARK; WM_PRINTLN(x); } +#define LOGDEBUG0(x) if(_WIFIMGR_LOGLEVEL_>3) { WM_PRINT(x); } +#define LOGDEBUG1(x,y) if(_WIFIMGR_LOGLEVEL_>3) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINTLN(y); } +#define LOGDEBUG2(x,y,z) if(_WIFIMGR_LOGLEVEL_>3) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINTLN(z); } +#define LOGDEBUG3(x,y,z,w) if(_WIFIMGR_LOGLEVEL_>3) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINT(z); WM_PRINT_SP; WM_PRINTLN(w); } + +//////////////////////////////////////////////////// + +#endif //ESP_WiFiManager_Debug_H diff --git a/lib/ESP_WiFiManager/utils/TZ.h b/lib/ESP_WiFiManager/utils/TZ.h new file mode 100644 index 0000000..223b9be --- /dev/null +++ b/lib/ESP_WiFiManager/utils/TZ.h @@ -0,0 +1,2150 @@ + +// autogenerated from https://raw.githubusercontent.com/nayarsystems/posix_tz_db/master/zones.csv +// by script /tools/TZupdate.sh +// Thu Nov 12 04:07:03 UTC 2020 +// +// This database is autogenerated from IANA timezone database +// https://raw.githubusercontent.com/nayarsystems/posix_tz_db/master/zones.csv +// (using https://www.iana.org/time-zones) +// and can be updated on demand in this repository +// or by yourself using the above script + +#ifndef TZDB_H +#define TZDB_H + +//See: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html +// EST5EDT,M3.2.0,M11.1.0 (for America/New_York) +// EST5EDT is the name of the time zone +// EST is the abbreviation used when DST is off +// 6 hours is the time difference from GMT +// EDT is the abbreviation used when DST is on +// ,M3 is the third month +// .2 is the second occurrence of the day in the month +// .0 is Sunday +// ,M11 is the eleventh month +// .1 is the first occurrence of the day in the month +// .0 is Sunday + + +#if !defined(USING_AFRICA) + #define USING_AFRICA false +#endif + +#if !defined(USING_AMERICA) + #define USING_AMERICA true +#endif + +#if !defined(USING_ANTARCTICA) + #define USING_ANTARCTICA false +#endif + +#if !defined(USING_ASIA) + #define USING_ASIA false +#endif + +#if !defined(USING_ATLANTIC) + #define USING_ATLANTIC false +#endif + +#if !defined(USING_AUSTRALIA) + #define USING_AUSTRALIA true +#endif + +#if !defined(USING_EUROPE) + #define USING_EUROPE false +#endif + +#if !defined(USING_INDIAN) + #define USING_INDIAN false +#endif + +#if !defined(USING_PACIFIC) + #define USING_PACIFIC false +#endif + +#if !defined(USING_ETC_GMT) + #define USING_ETC_GMT false +#endif + + + + +//////////////////////////////////////////////////// + +#if 1 + +#define TZ_Africa_Abidjan ("GMT0") +#define TZ_Africa_Accra ("GMT0") +#define TZ_Africa_Addis_Ababa ("EAT-3") +#define TZ_Africa_Algiers ("CET-1") +#define TZ_Africa_Asmara ("EAT-3") +#define TZ_Africa_Bamako ("GMT0") +#define TZ_Africa_Bangui ("WAT-1") +#define TZ_Africa_Banjul ("GMT0") +#define TZ_Africa_Bissau ("GMT0") +#define TZ_Africa_Blantyre ("CAT-2") +#define TZ_Africa_Brazzaville ("WAT-1") +#define TZ_Africa_Bujumbura ("CAT-2") +#define TZ_Africa_Cairo ("EET-2") +#define TZ_Africa_Casablanca ("<+01>-1") +#define TZ_Africa_Ceuta ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Africa_Conakry ("GMT0") +#define TZ_Africa_Dakar ("GMT0") +#define TZ_Africa_Dar_es_Salaam ("EAT-3") +#define TZ_Africa_Djibouti ("EAT-3") +#define TZ_Africa_Douala ("WAT-1") +#define TZ_Africa_El_Aaiun ("<+01>-1") +#define TZ_Africa_Freetown ("GMT0") +#define TZ_Africa_Gaborone ("CAT-2") +#define TZ_Africa_Harare ("CAT-2") +#define TZ_Africa_Johannesburg ("SAST-2") +#define TZ_Africa_Juba ("EAT-3") +#define TZ_Africa_Kampala ("EAT-3") +#define TZ_Africa_Khartoum ("CAT-2") +#define TZ_Africa_Kigali ("CAT-2") +#define TZ_Africa_Kinshasa ("WAT-1") +#define TZ_Africa_Lagos ("WAT-1") +#define TZ_Africa_Libreville ("WAT-1") +#define TZ_Africa_Lome ("GMT0") +#define TZ_Africa_Luanda ("WAT-1") +#define TZ_Africa_Lubumbashi ("CAT-2") +#define TZ_Africa_Lusaka ("CAT-2") +#define TZ_Africa_Malabo ("WAT-1") +#define TZ_Africa_Maputo ("CAT-2") +#define TZ_Africa_Maseru ("SAST-2") +#define TZ_Africa_Mbabane ("SAST-2") +#define TZ_Africa_Mogadishu ("EAT-3") +#define TZ_Africa_Monrovia ("GMT0") +#define TZ_Africa_Nairobi ("EAT-3") +#define TZ_Africa_Ndjamena ("WAT-1") +#define TZ_Africa_Niamey ("WAT-1") +#define TZ_Africa_Nouakchott ("GMT0") +#define TZ_Africa_Ouagadougou ("GMT0") +#define TZ_Africa_PortomNovo ("WAT-1") +#define TZ_Africa_Sao_Tome ("GMT0") +#define TZ_Africa_Tripoli ("EET-2") +#define TZ_Africa_Tunis ("CET-1") +#define TZ_Africa_Windhoek ("CAT-2") +#define TZ_America_Adak ("HST10HDT,M3.2.0,M11.1.0") +#define TZ_America_Anchorage ("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_Anguilla ("AST4") +#define TZ_America_Antigua ("AST4") +#define TZ_America_Araguaina ("<-03>3") +#define TZ_America_Argentina_Buenos_Aires ("<-03>3") +#define TZ_America_Argentina_Catamarca ("<-03>3") +#define TZ_America_Argentina_Cordoba ("<-03>3") +#define TZ_America_Argentina_Jujuy ("<-03>3") +#define TZ_America_Argentina_La_Rioja ("<-03>3") +#define TZ_America_Argentina_Mendoza ("<-03>3") +#define TZ_America_Argentina_Rio_Gallegos ("<-03>3") +#define TZ_America_Argentina_Salta ("<-03>3") +#define TZ_America_Argentina_San_Juan ("<-03>3") +#define TZ_America_Argentina_San_Luis ("<-03>3") +#define TZ_America_Argentina_Tucuman ("<-03>3") +#define TZ_America_Argentina_Ushuaia ("<-03>3") +#define TZ_America_Aruba ("AST4") +#define TZ_America_Asuncion ("<-04>4<-03>,M10.1.0/0,M3.4.0/0") +#define TZ_America_Atikokan ("EST5") +#define TZ_America_Bahia ("<-03>3") +#define TZ_America_Bahia_Banderas ("CST6CDT,M4.1.0,M10.5.0") +#define TZ_America_Barbados ("AST4") +#define TZ_America_Belem ("<-03>3") +#define TZ_America_Belize ("CST6") +#define TZ_America_BlancmSablon ("AST4") +#define TZ_America_Boa_Vista ("<-04>4") +#define TZ_America_Bogota ("<-05>5") +#define TZ_America_Boise ("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Cambridge_Bay ("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Campo_Grande ("<-04>4") +#define TZ_America_Cancun ("EST5") +#define TZ_America_Caracas ("<-04>4") +#define TZ_America_Cayenne ("<-03>3") +#define TZ_America_Cayman ("EST5") +#define TZ_America_Chicago ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Chihuahua ("MST7MDT,M4.1.0,M10.5.0") +#define TZ_America_Costa_Rica ("CST6") +#define TZ_America_Creston ("MST7") +#define TZ_America_Cuiaba ("<-04>4") +#define TZ_America_Curacao ("AST4") +#define TZ_America_Danmarkshavn ("GMT0") +#define TZ_America_Dawson ("MST7") +#define TZ_America_Dawson_Creek ("MST7") +#define TZ_America_Denver ("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Detroit ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Dominica ("AST4") +#define TZ_America_Edmonton ("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Eirunepe ("<-05>5") +#define TZ_America_El_Salvador ("CST6") +#define TZ_America_Fortaleza ("<-03>3") +#define TZ_America_Fort_Nelson ("MST7") +#define TZ_America_Glace_Bay ("AST4ADT,M3.2.0,M11.1.0") +#define TZ_America_Godthab ("<-03>3<-02>,M3.5.0/-2,M10.5.0/-1") +#define TZ_America_Goose_Bay ("AST4ADT,M3.2.0,M11.1.0") +#define TZ_America_Grand_Turk ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Grenada ("AST4") +#define TZ_America_Guadeloupe ("AST4") +#define TZ_America_Guatemala ("CST6") +#define TZ_America_Guayaquil ("<-05>5") +#define TZ_America_Guyana ("<-04>4") +#define TZ_America_Halifax ("AST4ADT,M3.2.0,M11.1.0") +#define TZ_America_Havana ("CST5CDT,M3.2.0/0,M11.1.0/1") +#define TZ_America_Hermosillo ("MST7") +#define TZ_America_Indiana_Indianapolis ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Knox ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Marengo ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Petersburg ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Tell_City ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Vevay ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Vincennes ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Winamac ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Inuvik ("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Iqaluit ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Jamaica ("EST5") +#define TZ_America_Juneau ("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_Kentucky_Louisville ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Kentucky_Monticello ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Kralendijk ("AST4") +#define TZ_America_La_Paz ("<-04>4") +#define TZ_America_Lima ("<-05>5") +#define TZ_America_Los_Angeles ("PST8PDT,M3.2.0,M11.1.0") +#define TZ_America_Lower_Princes ("AST4") +#define TZ_America_Maceio ("<-03>3") +#define TZ_America_Managua ("CST6") +#define TZ_America_Manaus ("<-04>4") +#define TZ_America_Marigot ("AST4") +#define TZ_America_Martinique ("AST4") +#define TZ_America_Matamoros ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Mazatlan ("MST7MDT,M4.1.0,M10.5.0") +#define TZ_America_Menominee ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Merida ("CST6CDT,M4.1.0,M10.5.0") +#define TZ_America_Metlakatla ("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_Mexico_City ("CST6CDT,M4.1.0,M10.5.0") +#define TZ_America_Miquelon ("<-03>3<-02>,M3.2.0,M11.1.0") +#define TZ_America_Moncton ("AST4ADT,M3.2.0,M11.1.0") +#define TZ_America_Monterrey ("CST6CDT,M4.1.0,M10.5.0") +#define TZ_America_Montevideo ("<-03>3") +#define TZ_America_Montreal ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Montserrat ("AST4") +#define TZ_America_Nassau ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_New_York ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Nipigon ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Nome ("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_Noronha ("<-02>2") +#define TZ_America_North_Dakota_Beulah ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_North_Dakota_Center ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_North_Dakota_New_Salem ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Ojinaga ("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Panama ("EST5") +#define TZ_America_Pangnirtung ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Paramaribo ("<-03>3") +#define TZ_America_Phoenix ("MST7") +#define TZ_America_PortmaumPrince ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Port_of_Spain ("AST4") +#define TZ_America_Porto_Velho ("<-04>4") +#define TZ_America_Puerto_Rico ("AST4") +#define TZ_America_Punta_Arenas ("<-03>3") +#define TZ_America_Rainy_River ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Rankin_Inlet ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Recife ("<-03>3") +#define TZ_America_Regina ("CST6") +#define TZ_America_Resolute ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Rio_Branco ("<-05>5") +#define TZ_America_Santarem ("<-03>3") +#define TZ_America_Santiago ("<-04>4<-03>,M9.1.6/24,M4.1.6/24") +#define TZ_America_Santo_Domingo ("AST4") +#define TZ_America_Sao_Paulo ("<-03>3") +#define TZ_America_Scoresbysund ("<-01>1<+00>,M3.5.0/0,M10.5.0/1") +#define TZ_America_Sitka ("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_St_Barthelemy ("AST4") +#define TZ_America_St_Johns ("NST3:30NDT,M3.2.0,M11.1.0") +#define TZ_America_St_Kitts ("AST4") +#define TZ_America_St_Lucia ("AST4") +#define TZ_America_St_Thomas ("AST4") +#define TZ_America_St_Vincent ("AST4") +#define TZ_America_Swift_Current ("CST6") +#define TZ_America_Tegucigalpa ("CST6") +#define TZ_America_Thule ("AST4ADT,M3.2.0,M11.1.0") +#define TZ_America_Thunder_Bay ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Tijuana ("PST8PDT,M3.2.0,M11.1.0") +#define TZ_America_Toronto ("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Tortola ("AST4") +#define TZ_America_Vancouver ("PST8PDT,M3.2.0,M11.1.0") +#define TZ_America_Whitehorse ("MST7") +#define TZ_America_Winnipeg ("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Yakutat ("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_Yellowknife ("MST7MDT,M3.2.0,M11.1.0") +#define TZ_Antarctica_Casey ("<+11>-11") +#define TZ_Antarctica_Davis ("<+07>-7") +#define TZ_Antarctica_DumontDUrville ("<+10>-10") +#define TZ_Antarctica_Macquarie ("AEST-10AEDT,M10.1.0,M4.1.0/3") +#define TZ_Antarctica_Mawson ("<+05>-5") +#define TZ_Antarctica_McMurdo ("NZST-12NZDT,M9.5.0,M4.1.0/3") +#define TZ_Antarctica_Palmer ("<-03>3") +#define TZ_Antarctica_Rothera ("<-03>3") +#define TZ_Antarctica_Syowa ("<+03>-3") +#define TZ_Antarctica_Troll ("<+00>0<+02>-2,M3.5.0/1,M10.5.0/3") +#define TZ_Antarctica_Vostok ("<+06>-6") +#define TZ_Arctic_Longyearbyen ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Asia_Aden ("<+03>-3") +#define TZ_Asia_Almaty ("<+06>-6") +#define TZ_Asia_Amman ("EET-2EEST,M3.5.4/24,M10.5.5/1") +#define TZ_Asia_Anadyr ("<+12>-12") +#define TZ_Asia_Aqtau ("<+05>-5") +#define TZ_Asia_Aqtobe ("<+05>-5") +#define TZ_Asia_Ashgabat ("<+05>-5") +#define TZ_Asia_Atyrau ("<+05>-5") +#define TZ_Asia_Baghdad ("<+03>-3") +#define TZ_Asia_Bahrain ("<+03>-3") +#define TZ_Asia_Baku ("<+04>-4") +#define TZ_Asia_Bangkok ("<+07>-7") +#define TZ_Asia_Barnaul ("<+07>-7") +#define TZ_Asia_Beirut ("EET-2EEST,M3.5.0/0,M10.5.0/0") +#define TZ_Asia_Bishkek ("<+06>-6") +#define TZ_Asia_Brunei ("<+08>-8") +#define TZ_Asia_Chita ("<+09>-9") +#define TZ_Asia_Choibalsan ("<+08>-8") +#define TZ_Asia_Colombo ("<+0530>-5:30") +#define TZ_Asia_Damascus ("EET-2EEST,M3.5.5/0,M10.5.5/0") +#define TZ_Asia_Dhaka ("<+06>-6") +#define TZ_Asia_Dili ("<+09>-9") +#define TZ_Asia_Dubai ("<+04>-4") +#define TZ_Asia_Dushanbe ("<+05>-5") +#define TZ_Asia_Famagusta ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Asia_Gaza ("EET-2EEST,M3.4.4/48,M10.4.4/49") +#define TZ_Asia_Hebron ("EET-2EEST,M3.4.4/48,M10.4.4/49") +#define TZ_Asia_Ho_Chi_Minh ("<+07>-7") +#define TZ_Asia_Hong_Kong ("HKT-8") +#define TZ_Asia_Hovd ("<+07>-7") +#define TZ_Asia_Irkutsk ("<+08>-8") +#define TZ_Asia_Jakarta ("WIB-7") +#define TZ_Asia_Jayapura ("WIT-9") +#define TZ_Asia_Jerusalem ("IST-2IDT,M3.4.4/26,M10.5.0") +#define TZ_Asia_Kabul ("<+0430>-4:30") +#define TZ_Asia_Kamchatka ("<+12>-12") +#define TZ_Asia_Karachi ("PKT-5") +#define TZ_Asia_Kathmandu ("<+0545>-5:45") +#define TZ_Asia_Khandyga ("<+09>-9") +#define TZ_Asia_Kolkata ("IST-5:30") +#define TZ_Asia_Krasnoyarsk ("<+07>-7") +#define TZ_Asia_Kuala_Lumpur ("<+08>-8") +#define TZ_Asia_Kuching ("<+08>-8") +#define TZ_Asia_Kuwait ("<+03>-3") +#define TZ_Asia_Macau ("CST-8") +#define TZ_Asia_Magadan ("<+11>-11") +#define TZ_Asia_Makassar ("WITA-8") +#define TZ_Asia_Manila ("PST-8") +#define TZ_Asia_Muscat ("<+04>-4") +#define TZ_Asia_Nicosia ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Asia_Novokuznetsk ("<+07>-7") +#define TZ_Asia_Novosibirsk ("<+07>-7") +#define TZ_Asia_Omsk ("<+06>-6") +#define TZ_Asia_Oral ("<+05>-5") +#define TZ_Asia_Phnom_Penh ("<+07>-7") +#define TZ_Asia_Pontianak ("WIB-7") +#define TZ_Asia_Pyongyang ("KST-9") +#define TZ_Asia_Qatar ("<+03>-3") +#define TZ_Asia_Qyzylorda ("<+05>-5") +#define TZ_Asia_Riyadh ("<+03>-3") +#define TZ_Asia_Sakhalin ("<+11>-11") +#define TZ_Asia_Samarkand ("<+05>-5") +#define TZ_Asia_Seoul ("KST-9") +#define TZ_Asia_Shanghai ("CST-8") +#define TZ_Asia_Singapore ("<+08>-8") +#define TZ_Asia_Srednekolymsk ("<+11>-11") +#define TZ_Asia_Taipei ("CST-8") +#define TZ_Asia_Tashkent ("<+05>-5") +#define TZ_Asia_Tbilisi ("<+04>-4") +#define TZ_Asia_Tehran ("<+0330>-3:30<+0430>,J79/24,J263/24") +#define TZ_Asia_Thimphu ("<+06>-6") +#define TZ_Asia_Tokyo ("JST-9") +#define TZ_Asia_Tomsk ("<+07>-7") +#define TZ_Asia_Ulaanbaatar ("<+08>-8") +#define TZ_Asia_Urumqi ("<+06>-6") +#define TZ_Asia_UstmNera ("<+10>-10") +#define TZ_Asia_Vientiane ("<+07>-7") +#define TZ_Asia_Vladivostok ("<+10>-10") +#define TZ_Asia_Yakutsk ("<+09>-9") +#define TZ_Asia_Yangon ("<+0630>-6:30") +#define TZ_Asia_Yekaterinburg ("<+05>-5") +#define TZ_Asia_Yerevan ("<+04>-4") +#define TZ_Atlantic_Azores ("<-01>1<+00>,M3.5.0/0,M10.5.0/1") +#define TZ_Atlantic_Bermuda ("AST4ADT,M3.2.0,M11.1.0") +#define TZ_Atlantic_Canary ("WET0WEST,M3.5.0/1,M10.5.0") +#define TZ_Atlantic_Cape_Verde ("<-01>1") +#define TZ_Atlantic_Faroe ("WET0WEST,M3.5.0/1,M10.5.0") +#define TZ_Atlantic_Madeira ("WET0WEST,M3.5.0/1,M10.5.0") +#define TZ_Atlantic_Reykjavik ("GMT0") +#define TZ_Atlantic_South_Georgia ("<-02>2") +#define TZ_Atlantic_Stanley ("<-03>3") +#define TZ_Atlantic_St_Helena ("GMT0") +#define TZ_Australia_Adelaide ("ACST-9:30ACDT,M10.1.0,M4.1.0/3") +#define TZ_Australia_Brisbane ("AEST-10") +#define TZ_Australia_Broken_Hill ("ACST-9:30ACDT,M10.1.0,M4.1.0/3") +#define TZ_Australia_Currie ("AEST-10AEDT,M10.1.0,M4.1.0/3") +#define TZ_Australia_Darwin ("ACST-9:30") +#define TZ_Australia_Eucla ("<+0845>-8:45") +#define TZ_Australia_Hobart ("AEST-10AEDT,M10.1.0,M4.1.0/3") +#define TZ_Australia_Lindeman ("AEST-10") +#define TZ_Australia_Lord_Howe ("<+1030>-10:30<+11>-11,M10.1.0,M4.1.0") +#define TZ_Australia_Melbourne ("AEST-10AEDT,M10.1.0,M4.1.0/3") +#define TZ_Australia_Perth ("AWST-8") +#define TZ_Australia_Sydney ("AEST-10AEDT,M10.1.0,M4.1.0/3") +#define TZ_Europe_Amsterdam ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Andorra ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Astrakhan ("<+04>-4") +#define TZ_Europe_Athens ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Belgrade ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Berlin ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Bratislava ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Brussels ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Bucharest ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Budapest ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Busingen ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Chisinau ("EET-2EEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Copenhagen ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Dublin ("IST-1GMT0,M10.5.0,M3.5.0/1") +#define TZ_Europe_Gibraltar ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Guernsey ("GMT0BST,M3.5.0/1,M10.5.0") +#define TZ_Europe_Helsinki ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Isle_of_Man ("GMT0BST,M3.5.0/1,M10.5.0") +#define TZ_Europe_Istanbul ("<+03>-3") +#define TZ_Europe_Jersey ("GMT0BST,M3.5.0/1,M10.5.0") +#define TZ_Europe_Kaliningrad ("EET-2") +#define TZ_Europe_Kiev ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Kirov ("<+03>-3") +#define TZ_Europe_Lisbon ("WET0WEST,M3.5.0/1,M10.5.0") +#define TZ_Europe_Ljubljana ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_London ("GMT0BST,M3.5.0/1,M10.5.0") +#define TZ_Europe_Luxembourg ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Madrid ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Malta ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Mariehamn ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Minsk ("<+03>-3") +#define TZ_Europe_Monaco ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Moscow ("MSK-3") +#define TZ_Europe_Oslo ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Paris ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Podgorica ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Prague ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Riga ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Rome ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Samara ("<+04>-4") +#define TZ_Europe_San_Marino ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Sarajevo ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Saratov ("<+04>-4") +#define TZ_Europe_Simferopol ("MSK-3") +#define TZ_Europe_Skopje ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Sofia ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Stockholm ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Tallinn ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Tirane ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Ulyanovsk ("<+04>-4") +#define TZ_Europe_Uzhgorod ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Vaduz ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Vatican ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Vienna ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Vilnius ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Volgograd ("<+04>-4") +#define TZ_Europe_Warsaw ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Zagreb ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Zaporozhye ("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Zurich ("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Indian_Antananarivo ("EAT-3") +#define TZ_Indian_Chagos ("<+06>-6") +#define TZ_Indian_Christmas ("<+07>-7") +#define TZ_Indian_Cocos ("<+0630>-6:30") +#define TZ_Indian_Comoro ("EAT-3") +#define TZ_Indian_Kerguelen ("<+05>-5") +#define TZ_Indian_Mahe ("<+04>-4") +#define TZ_Indian_Maldives ("<+05>-5") +#define TZ_Indian_Mauritius ("<+04>-4") +#define TZ_Indian_Mayotte ("EAT-3") +#define TZ_Indian_Reunion ("<+04>-4") +#define TZ_Pacific_Apia ("<+13>-13<+14>,M9.5.0/3,M4.1.0/4") +#define TZ_Pacific_Auckland ("NZST-12NZDT,M9.5.0,M4.1.0/3") +#define TZ_Pacific_Bougainville ("<+11>-11") +#define TZ_Pacific_Chatham ("<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45") +#define TZ_Pacific_Chuuk ("<+10>-10") +#define TZ_Pacific_Easter ("<-06>6<-05>,M9.1.6/22,M4.1.6/22") +#define TZ_Pacific_Efate ("<+11>-11") +#define TZ_Pacific_Enderbury ("<+13>-13") +#define TZ_Pacific_Fakaofo ("<+13>-13") +#define TZ_Pacific_Fiji ("<+12>-12<+13>,M11.2.0,M1.2.3/99") +#define TZ_Pacific_Funafuti ("<+12>-12") +#define TZ_Pacific_Galapagos ("<-06>6") +#define TZ_Pacific_Gambier ("<-09>9") +#define TZ_Pacific_Guadalcanal ("<+11>-11") +#define TZ_Pacific_Guam ("ChST-10") +#define TZ_Pacific_Honolulu ("HST10") +#define TZ_Pacific_Kiritimati ("<+14>-14") +#define TZ_Pacific_Kosrae ("<+11>-11") +#define TZ_Pacific_Kwajalein ("<+12>-12") +#define TZ_Pacific_Majuro ("<+12>-12") +#define TZ_Pacific_Marquesas ("<-0930>9:30") +#define TZ_Pacific_Midway ("SST11") +#define TZ_Pacific_Nauru ("<+12>-12") +#define TZ_Pacific_Niue ("<-11>11") +#define TZ_Pacific_Norfolk ("<+11>-11<+12>,M10.1.0,M4.1.0/3") +#define TZ_Pacific_Noumea ("<+11>-11") +#define TZ_Pacific_Pago_Pago ("SST11") +#define TZ_Pacific_Palau ("<+09>-9") +#define TZ_Pacific_Pitcairn ("<-08>8") +#define TZ_Pacific_Pohnpei ("<+11>-11") +#define TZ_Pacific_Port_Moresby ("<+10>-10") +#define TZ_Pacific_Rarotonga ("<-10>10") +#define TZ_Pacific_Saipan ("ChST-10") +#define TZ_Pacific_Tahiti ("<-10>10") +#define TZ_Pacific_Tarawa ("<+12>-12") +#define TZ_Pacific_Tongatapu ("<+13>-13") +#define TZ_Pacific_Wake ("<+12>-12") +#define TZ_Pacific_Wallis ("<+12>-12") +#define TZ_Etc_GMT ("GMT0") +#define TZ_Etc_GMTm0 ("GMT0") +#define TZ_Etc_GMTm1 ("<+01>-1") +#define TZ_Etc_GMTm2 ("<+02>-2") +#define TZ_Etc_GMTm3 ("<+03>-3") +#define TZ_Etc_GMTm4 ("<+04>-4") +#define TZ_Etc_GMTm5 ("<+05>-5") +#define TZ_Etc_GMTm6 ("<+06>-6") +#define TZ_Etc_GMTm7 ("<+07>-7") +#define TZ_Etc_GMTm8 ("<+08>-8") +#define TZ_Etc_GMTm9 ("<+09>-9") +#define TZ_Etc_GMTm10 ("<+10>-10") +#define TZ_Etc_GMTm11 ("<+11>-11") +#define TZ_Etc_GMTm12 ("<+12>-12") +#define TZ_Etc_GMTm13 ("<+13>-13") +#define TZ_Etc_GMTm14 ("<+14>-14") +#define TZ_Etc_GMT0 ("GMT0") +#define TZ_Etc_GMTp0 ("GMT0") +#define TZ_Etc_GMTp1 ("<-01>1") +#define TZ_Etc_GMTp2 ("<-02>2") +#define TZ_Etc_GMTp3 ("<-03>3") +#define TZ_Etc_GMTp4 ("<-04>4") +#define TZ_Etc_GMTp5 ("<-05>5") +#define TZ_Etc_GMTp6 ("<-06>6") +#define TZ_Etc_GMTp7 ("<-07>7") +#define TZ_Etc_GMTp8 ("<-08>8") +#define TZ_Etc_GMTp9 ("<-09>9") +#define TZ_Etc_GMTp10 ("<-10>10") +#define TZ_Etc_GMTp11 ("<-11>11") +#define TZ_Etc_GMTp12 ("<-12>12") +#define TZ_Etc_UCT ("UTC0") +#define TZ_Etc_UTC ("UTC0") +#define TZ_Etc_Greenwich ("GMT0") +#define TZ_Etc_Universal ("UTC0") +#define TZ_Etc_Zulu ("UTC0") + + +#else + + +#define TZ_Africa_Abidjan PSTR("GMT0") +#define TZ_Africa_Accra PSTR("GMT0") +#define TZ_Africa_Addis_Ababa PSTR("EAT-3") +#define TZ_Africa_Algiers PSTR("CET-1") +#define TZ_Africa_Asmara PSTR("EAT-3") +#define TZ_Africa_Bamako PSTR("GMT0") +#define TZ_Africa_Bangui PSTR("WAT-1") +#define TZ_Africa_Banjul PSTR("GMT0") +#define TZ_Africa_Bissau PSTR("GMT0") +#define TZ_Africa_Blantyre PSTR("CAT-2") +#define TZ_Africa_Brazzaville PSTR("WAT-1") +#define TZ_Africa_Bujumbura PSTR("CAT-2") +#define TZ_Africa_Cairo PSTR("EET-2") +#define TZ_Africa_Casablanca PSTR("<+01>-1") +#define TZ_Africa_Ceuta PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Africa_Conakry PSTR("GMT0") +#define TZ_Africa_Dakar PSTR("GMT0") +#define TZ_Africa_Dar_es_Salaam PSTR("EAT-3") +#define TZ_Africa_Djibouti PSTR("EAT-3") +#define TZ_Africa_Douala PSTR("WAT-1") +#define TZ_Africa_El_Aaiun PSTR("<+01>-1") +#define TZ_Africa_Freetown PSTR("GMT0") +#define TZ_Africa_Gaborone PSTR("CAT-2") +#define TZ_Africa_Harare PSTR("CAT-2") +#define TZ_Africa_Johannesburg PSTR("SAST-2") +#define TZ_Africa_Juba PSTR("EAT-3") +#define TZ_Africa_Kampala PSTR("EAT-3") +#define TZ_Africa_Khartoum PSTR("CAT-2") +#define TZ_Africa_Kigali PSTR("CAT-2") +#define TZ_Africa_Kinshasa PSTR("WAT-1") +#define TZ_Africa_Lagos PSTR("WAT-1") +#define TZ_Africa_Libreville PSTR("WAT-1") +#define TZ_Africa_Lome PSTR("GMT0") +#define TZ_Africa_Luanda PSTR("WAT-1") +#define TZ_Africa_Lubumbashi PSTR("CAT-2") +#define TZ_Africa_Lusaka PSTR("CAT-2") +#define TZ_Africa_Malabo PSTR("WAT-1") +#define TZ_Africa_Maputo PSTR("CAT-2") +#define TZ_Africa_Maseru PSTR("SAST-2") +#define TZ_Africa_Mbabane PSTR("SAST-2") +#define TZ_Africa_Mogadishu PSTR("EAT-3") +#define TZ_Africa_Monrovia PSTR("GMT0") +#define TZ_Africa_Nairobi PSTR("EAT-3") +#define TZ_Africa_Ndjamena PSTR("WAT-1") +#define TZ_Africa_Niamey PSTR("WAT-1") +#define TZ_Africa_Nouakchott PSTR("GMT0") +#define TZ_Africa_Ouagadougou PSTR("GMT0") +#define TZ_Africa_PortomNovo PSTR("WAT-1") +#define TZ_Africa_Sao_Tome PSTR("GMT0") +#define TZ_Africa_Tripoli PSTR("EET-2") +#define TZ_Africa_Tunis PSTR("CET-1") +#define TZ_Africa_Windhoek PSTR("CAT-2") +#define TZ_America_Adak PSTR("HST10HDT,M3.2.0,M11.1.0") +#define TZ_America_Anchorage PSTR("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_Anguilla PSTR("AST4") +#define TZ_America_Antigua PSTR("AST4") +#define TZ_America_Araguaina PSTR("<-03>3") +#define TZ_America_Argentina_Buenos_Aires PSTR("<-03>3") +#define TZ_America_Argentina_Catamarca PSTR("<-03>3") +#define TZ_America_Argentina_Cordoba PSTR("<-03>3") +#define TZ_America_Argentina_Jujuy PSTR("<-03>3") +#define TZ_America_Argentina_La_Rioja PSTR("<-03>3") +#define TZ_America_Argentina_Mendoza PSTR("<-03>3") +#define TZ_America_Argentina_Rio_Gallegos PSTR("<-03>3") +#define TZ_America_Argentina_Salta PSTR("<-03>3") +#define TZ_America_Argentina_San_Juan PSTR("<-03>3") +#define TZ_America_Argentina_San_Luis PSTR("<-03>3") +#define TZ_America_Argentina_Tucuman PSTR("<-03>3") +#define TZ_America_Argentina_Ushuaia PSTR("<-03>3") +#define TZ_America_Aruba PSTR("AST4") +#define TZ_America_Asuncion PSTR("<-04>4<-03>,M10.1.0/0,M3.4.0/0") +#define TZ_America_Atikokan PSTR("EST5") +#define TZ_America_Bahia PSTR("<-03>3") +#define TZ_America_Bahia_Banderas PSTR("CST6CDT,M4.1.0,M10.5.0") +#define TZ_America_Barbados PSTR("AST4") +#define TZ_America_Belem PSTR("<-03>3") +#define TZ_America_Belize PSTR("CST6") +#define TZ_America_BlancmSablon PSTR("AST4") +#define TZ_America_Boa_Vista PSTR("<-04>4") +#define TZ_America_Bogota PSTR("<-05>5") +#define TZ_America_Boise PSTR("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Cambridge_Bay PSTR("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Campo_Grande PSTR("<-04>4") +#define TZ_America_Cancun PSTR("EST5") +#define TZ_America_Caracas PSTR("<-04>4") +#define TZ_America_Cayenne PSTR("<-03>3") +#define TZ_America_Cayman PSTR("EST5") +#define TZ_America_Chicago PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Chihuahua PSTR("MST7MDT,M4.1.0,M10.5.0") +#define TZ_America_Costa_Rica PSTR("CST6") +#define TZ_America_Creston PSTR("MST7") +#define TZ_America_Cuiaba PSTR("<-04>4") +#define TZ_America_Curacao PSTR("AST4") +#define TZ_America_Danmarkshavn PSTR("GMT0") +#define TZ_America_Dawson PSTR("MST7") +#define TZ_America_Dawson_Creek PSTR("MST7") +#define TZ_America_Denver PSTR("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Detroit PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Dominica PSTR("AST4") +#define TZ_America_Edmonton PSTR("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Eirunepe PSTR("<-05>5") +#define TZ_America_El_Salvador PSTR("CST6") +#define TZ_America_Fortaleza PSTR("<-03>3") +#define TZ_America_Fort_Nelson PSTR("MST7") +#define TZ_America_Glace_Bay PSTR("AST4ADT,M3.2.0,M11.1.0") +#define TZ_America_Godthab PSTR("<-03>3<-02>,M3.5.0/-2,M10.5.0/-1") +#define TZ_America_Goose_Bay PSTR("AST4ADT,M3.2.0,M11.1.0") +#define TZ_America_Grand_Turk PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Grenada PSTR("AST4") +#define TZ_America_Guadeloupe PSTR("AST4") +#define TZ_America_Guatemala PSTR("CST6") +#define TZ_America_Guayaquil PSTR("<-05>5") +#define TZ_America_Guyana PSTR("<-04>4") +#define TZ_America_Halifax PSTR("AST4ADT,M3.2.0,M11.1.0") +#define TZ_America_Havana PSTR("CST5CDT,M3.2.0/0,M11.1.0/1") +#define TZ_America_Hermosillo PSTR("MST7") +#define TZ_America_Indiana_Indianapolis PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Knox PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Marengo PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Petersburg PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Tell_City PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Vevay PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Vincennes PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Indiana_Winamac PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Inuvik PSTR("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Iqaluit PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Jamaica PSTR("EST5") +#define TZ_America_Juneau PSTR("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_Kentucky_Louisville PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Kentucky_Monticello PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Kralendijk PSTR("AST4") +#define TZ_America_La_Paz PSTR("<-04>4") +#define TZ_America_Lima PSTR("<-05>5") +#define TZ_America_Los_Angeles PSTR("PST8PDT,M3.2.0,M11.1.0") +#define TZ_America_Lower_Princes PSTR("AST4") +#define TZ_America_Maceio PSTR("<-03>3") +#define TZ_America_Managua PSTR("CST6") +#define TZ_America_Manaus PSTR("<-04>4") +#define TZ_America_Marigot PSTR("AST4") +#define TZ_America_Martinique PSTR("AST4") +#define TZ_America_Matamoros PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Mazatlan PSTR("MST7MDT,M4.1.0,M10.5.0") +#define TZ_America_Menominee PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Merida PSTR("CST6CDT,M4.1.0,M10.5.0") +#define TZ_America_Metlakatla PSTR("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_Mexico_City PSTR("CST6CDT,M4.1.0,M10.5.0") +#define TZ_America_Miquelon PSTR("<-03>3<-02>,M3.2.0,M11.1.0") +#define TZ_America_Moncton PSTR("AST4ADT,M3.2.0,M11.1.0") +#define TZ_America_Monterrey PSTR("CST6CDT,M4.1.0,M10.5.0") +#define TZ_America_Montevideo PSTR("<-03>3") +#define TZ_America_Montreal PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Montserrat PSTR("AST4") +#define TZ_America_Nassau PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_New_York PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Nipigon PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Nome PSTR("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_Noronha PSTR("<-02>2") +#define TZ_America_North_Dakota_Beulah PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_North_Dakota_Center PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_North_Dakota_New_Salem PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Ojinaga PSTR("MST7MDT,M3.2.0,M11.1.0") +#define TZ_America_Panama PSTR("EST5") +#define TZ_America_Pangnirtung PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Paramaribo PSTR("<-03>3") +#define TZ_America_Phoenix PSTR("MST7") +#define TZ_America_PortmaumPrince PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Port_of_Spain PSTR("AST4") +#define TZ_America_Porto_Velho PSTR("<-04>4") +#define TZ_America_Puerto_Rico PSTR("AST4") +#define TZ_America_Punta_Arenas PSTR("<-03>3") +#define TZ_America_Rainy_River PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Rankin_Inlet PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Recife PSTR("<-03>3") +#define TZ_America_Regina PSTR("CST6") +#define TZ_America_Resolute PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Rio_Branco PSTR("<-05>5") +#define TZ_America_Santarem PSTR("<-03>3") +#define TZ_America_Santiago PSTR("<-04>4<-03>,M9.1.6/24,M4.1.6/24") +#define TZ_America_Santo_Domingo PSTR("AST4") +#define TZ_America_Sao_Paulo PSTR("<-03>3") +#define TZ_America_Scoresbysund PSTR("<-01>1<+00>,M3.5.0/0,M10.5.0/1") +#define TZ_America_Sitka PSTR("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_St_Barthelemy PSTR("AST4") +#define TZ_America_St_Johns PSTR("NST3:30NDT,M3.2.0,M11.1.0") +#define TZ_America_St_Kitts PSTR("AST4") +#define TZ_America_St_Lucia PSTR("AST4") +#define TZ_America_St_Thomas PSTR("AST4") +#define TZ_America_St_Vincent PSTR("AST4") +#define TZ_America_Swift_Current PSTR("CST6") +#define TZ_America_Tegucigalpa PSTR("CST6") +#define TZ_America_Thule PSTR("AST4ADT,M3.2.0,M11.1.0") +#define TZ_America_Thunder_Bay PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Tijuana PSTR("PST8PDT,M3.2.0,M11.1.0") +#define TZ_America_Toronto PSTR("EST5EDT,M3.2.0,M11.1.0") +#define TZ_America_Tortola PSTR("AST4") +#define TZ_America_Vancouver PSTR("PST8PDT,M3.2.0,M11.1.0") +#define TZ_America_Whitehorse PSTR("MST7") +#define TZ_America_Winnipeg PSTR("CST6CDT,M3.2.0,M11.1.0") +#define TZ_America_Yakutat PSTR("AKST9AKDT,M3.2.0,M11.1.0") +#define TZ_America_Yellowknife PSTR("MST7MDT,M3.2.0,M11.1.0") +#define TZ_Antarctica_Casey PSTR("<+11>-11") +#define TZ_Antarctica_Davis PSTR("<+07>-7") +#define TZ_Antarctica_DumontDUrville PSTR("<+10>-10") +#define TZ_Antarctica_Macquarie PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") +#define TZ_Antarctica_Mawson PSTR("<+05>-5") +#define TZ_Antarctica_McMurdo PSTR("NZST-12NZDT,M9.5.0,M4.1.0/3") +#define TZ_Antarctica_Palmer PSTR("<-03>3") +#define TZ_Antarctica_Rothera PSTR("<-03>3") +#define TZ_Antarctica_Syowa PSTR("<+03>-3") +#define TZ_Antarctica_Troll PSTR("<+00>0<+02>-2,M3.5.0/1,M10.5.0/3") +#define TZ_Antarctica_Vostok PSTR("<+06>-6") +#define TZ_Arctic_Longyearbyen PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Asia_Aden PSTR("<+03>-3") +#define TZ_Asia_Almaty PSTR("<+06>-6") +#define TZ_Asia_Amman PSTR("EET-2EEST,M3.5.4/24,M10.5.5/1") +#define TZ_Asia_Anadyr PSTR("<+12>-12") +#define TZ_Asia_Aqtau PSTR("<+05>-5") +#define TZ_Asia_Aqtobe PSTR("<+05>-5") +#define TZ_Asia_Ashgabat PSTR("<+05>-5") +#define TZ_Asia_Atyrau PSTR("<+05>-5") +#define TZ_Asia_Baghdad PSTR("<+03>-3") +#define TZ_Asia_Bahrain PSTR("<+03>-3") +#define TZ_Asia_Baku PSTR("<+04>-4") +#define TZ_Asia_Bangkok PSTR("<+07>-7") +#define TZ_Asia_Barnaul PSTR("<+07>-7") +#define TZ_Asia_Beirut PSTR("EET-2EEST,M3.5.0/0,M10.5.0/0") +#define TZ_Asia_Bishkek PSTR("<+06>-6") +#define TZ_Asia_Brunei PSTR("<+08>-8") +#define TZ_Asia_Chita PSTR("<+09>-9") +#define TZ_Asia_Choibalsan PSTR("<+08>-8") +#define TZ_Asia_Colombo PSTR("<+0530>-5:30") +#define TZ_Asia_Damascus PSTR("EET-2EEST,M3.5.5/0,M10.5.5/0") +#define TZ_Asia_Dhaka PSTR("<+06>-6") +#define TZ_Asia_Dili PSTR("<+09>-9") +#define TZ_Asia_Dubai PSTR("<+04>-4") +#define TZ_Asia_Dushanbe PSTR("<+05>-5") +#define TZ_Asia_Famagusta PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Asia_Gaza PSTR("EET-2EEST,M3.4.4/48,M10.4.4/49") +#define TZ_Asia_Hebron PSTR("EET-2EEST,M3.4.4/48,M10.4.4/49") +#define TZ_Asia_Ho_Chi_Minh PSTR("<+07>-7") +#define TZ_Asia_Hong_Kong PSTR("HKT-8") +#define TZ_Asia_Hovd PSTR("<+07>-7") +#define TZ_Asia_Irkutsk PSTR("<+08>-8") +#define TZ_Asia_Jakarta PSTR("WIB-7") +#define TZ_Asia_Jayapura PSTR("WIT-9") +#define TZ_Asia_Jerusalem PSTR("IST-2IDT,M3.4.4/26,M10.5.0") +#define TZ_Asia_Kabul PSTR("<+0430>-4:30") +#define TZ_Asia_Kamchatka PSTR("<+12>-12") +#define TZ_Asia_Karachi PSTR("PKT-5") +#define TZ_Asia_Kathmandu PSTR("<+0545>-5:45") +#define TZ_Asia_Khandyga PSTR("<+09>-9") +#define TZ_Asia_Kolkata PSTR("IST-5:30") +#define TZ_Asia_Krasnoyarsk PSTR("<+07>-7") +#define TZ_Asia_Kuala_Lumpur PSTR("<+08>-8") +#define TZ_Asia_Kuching PSTR("<+08>-8") +#define TZ_Asia_Kuwait PSTR("<+03>-3") +#define TZ_Asia_Macau PSTR("CST-8") +#define TZ_Asia_Magadan PSTR("<+11>-11") +#define TZ_Asia_Makassar PSTR("WITA-8") +#define TZ_Asia_Manila PSTR("PST-8") +#define TZ_Asia_Muscat PSTR("<+04>-4") +#define TZ_Asia_Nicosia PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Asia_Novokuznetsk PSTR("<+07>-7") +#define TZ_Asia_Novosibirsk PSTR("<+07>-7") +#define TZ_Asia_Omsk PSTR("<+06>-6") +#define TZ_Asia_Oral PSTR("<+05>-5") +#define TZ_Asia_Phnom_Penh PSTR("<+07>-7") +#define TZ_Asia_Pontianak PSTR("WIB-7") +#define TZ_Asia_Pyongyang PSTR("KST-9") +#define TZ_Asia_Qatar PSTR("<+03>-3") +#define TZ_Asia_Qyzylorda PSTR("<+05>-5") +#define TZ_Asia_Riyadh PSTR("<+03>-3") +#define TZ_Asia_Sakhalin PSTR("<+11>-11") +#define TZ_Asia_Samarkand PSTR("<+05>-5") +#define TZ_Asia_Seoul PSTR("KST-9") +#define TZ_Asia_Shanghai PSTR("CST-8") +#define TZ_Asia_Singapore PSTR("<+08>-8") +#define TZ_Asia_Srednekolymsk PSTR("<+11>-11") +#define TZ_Asia_Taipei PSTR("CST-8") +#define TZ_Asia_Tashkent PSTR("<+05>-5") +#define TZ_Asia_Tbilisi PSTR("<+04>-4") +#define TZ_Asia_Tehran PSTR("<+0330>-3:30<+0430>,J79/24,J263/24") +#define TZ_Asia_Thimphu PSTR("<+06>-6") +#define TZ_Asia_Tokyo PSTR("JST-9") +#define TZ_Asia_Tomsk PSTR("<+07>-7") +#define TZ_Asia_Ulaanbaatar PSTR("<+08>-8") +#define TZ_Asia_Urumqi PSTR("<+06>-6") +#define TZ_Asia_UstmNera PSTR("<+10>-10") +#define TZ_Asia_Vientiane PSTR("<+07>-7") +#define TZ_Asia_Vladivostok PSTR("<+10>-10") +#define TZ_Asia_Yakutsk PSTR("<+09>-9") +#define TZ_Asia_Yangon PSTR("<+0630>-6:30") +#define TZ_Asia_Yekaterinburg PSTR("<+05>-5") +#define TZ_Asia_Yerevan PSTR("<+04>-4") +#define TZ_Atlantic_Azores PSTR("<-01>1<+00>,M3.5.0/0,M10.5.0/1") +#define TZ_Atlantic_Bermuda PSTR("AST4ADT,M3.2.0,M11.1.0") +#define TZ_Atlantic_Canary PSTR("WET0WEST,M3.5.0/1,M10.5.0") +#define TZ_Atlantic_Cape_Verde PSTR("<-01>1") +#define TZ_Atlantic_Faroe PSTR("WET0WEST,M3.5.0/1,M10.5.0") +#define TZ_Atlantic_Madeira PSTR("WET0WEST,M3.5.0/1,M10.5.0") +#define TZ_Atlantic_Reykjavik PSTR("GMT0") +#define TZ_Atlantic_South_Georgia PSTR("<-02>2") +#define TZ_Atlantic_Stanley PSTR("<-03>3") +#define TZ_Atlantic_St_Helena PSTR("GMT0") +#define TZ_Australia_Adelaide PSTR("ACST-9:30ACDT,M10.1.0,M4.1.0/3") +#define TZ_Australia_Brisbane PSTR("AEST-10") +#define TZ_Australia_Broken_Hill PSTR("ACST-9:30ACDT,M10.1.0,M4.1.0/3") +#define TZ_Australia_Currie PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") +#define TZ_Australia_Darwin PSTR("ACST-9:30") +#define TZ_Australia_Eucla PSTR("<+0845>-8:45") +#define TZ_Australia_Hobart PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") +#define TZ_Australia_Lindeman PSTR("AEST-10") +#define TZ_Australia_Lord_Howe PSTR("<+1030>-10:30<+11>-11,M10.1.0,M4.1.0") +#define TZ_Australia_Melbourne PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") +#define TZ_Australia_Perth PSTR("AWST-8") +#define TZ_Australia_Sydney PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") +#define TZ_Europe_Amsterdam PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Andorra PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Astrakhan PSTR("<+04>-4") +#define TZ_Europe_Athens PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Belgrade PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Berlin PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Bratislava PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Brussels PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Bucharest PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Budapest PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Busingen PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Chisinau PSTR("EET-2EEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Copenhagen PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Dublin PSTR("IST-1GMT0,M10.5.0,M3.5.0/1") +#define TZ_Europe_Gibraltar PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Guernsey PSTR("GMT0BST,M3.5.0/1,M10.5.0") +#define TZ_Europe_Helsinki PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Isle_of_Man PSTR("GMT0BST,M3.5.0/1,M10.5.0") +#define TZ_Europe_Istanbul PSTR("<+03>-3") +#define TZ_Europe_Jersey PSTR("GMT0BST,M3.5.0/1,M10.5.0") +#define TZ_Europe_Kaliningrad PSTR("EET-2") +#define TZ_Europe_Kiev PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Kirov PSTR("<+03>-3") +#define TZ_Europe_Lisbon PSTR("WET0WEST,M3.5.0/1,M10.5.0") +#define TZ_Europe_Ljubljana PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_London PSTR("GMT0BST,M3.5.0/1,M10.5.0") +#define TZ_Europe_Luxembourg PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Madrid PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Malta PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Mariehamn PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Minsk PSTR("<+03>-3") +#define TZ_Europe_Monaco PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Moscow PSTR("MSK-3") +#define TZ_Europe_Oslo PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Paris PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Podgorica PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Prague PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Riga PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Rome PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Samara PSTR("<+04>-4") +#define TZ_Europe_San_Marino PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Sarajevo PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Saratov PSTR("<+04>-4") +#define TZ_Europe_Simferopol PSTR("MSK-3") +#define TZ_Europe_Skopje PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Sofia PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Stockholm PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Tallinn PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Tirane PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Ulyanovsk PSTR("<+04>-4") +#define TZ_Europe_Uzhgorod PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Vaduz PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Vatican PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Vienna PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Vilnius PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Volgograd PSTR("<+04>-4") +#define TZ_Europe_Warsaw PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Zagreb PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Europe_Zaporozhye PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") +#define TZ_Europe_Zurich PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#define TZ_Indian_Antananarivo PSTR("EAT-3") +#define TZ_Indian_Chagos PSTR("<+06>-6") +#define TZ_Indian_Christmas PSTR("<+07>-7") +#define TZ_Indian_Cocos PSTR("<+0630>-6:30") +#define TZ_Indian_Comoro PSTR("EAT-3") +#define TZ_Indian_Kerguelen PSTR("<+05>-5") +#define TZ_Indian_Mahe PSTR("<+04>-4") +#define TZ_Indian_Maldives PSTR("<+05>-5") +#define TZ_Indian_Mauritius PSTR("<+04>-4") +#define TZ_Indian_Mayotte PSTR("EAT-3") +#define TZ_Indian_Reunion PSTR("<+04>-4") +#define TZ_Pacific_Apia PSTR("<+13>-13<+14>,M9.5.0/3,M4.1.0/4") +#define TZ_Pacific_Auckland PSTR("NZST-12NZDT,M9.5.0,M4.1.0/3") +#define TZ_Pacific_Bougainville PSTR("<+11>-11") +#define TZ_Pacific_Chatham PSTR("<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45") +#define TZ_Pacific_Chuuk PSTR("<+10>-10") +#define TZ_Pacific_Easter PSTR("<-06>6<-05>,M9.1.6/22,M4.1.6/22") +#define TZ_Pacific_Efate PSTR("<+11>-11") +#define TZ_Pacific_Enderbury PSTR("<+13>-13") +#define TZ_Pacific_Fakaofo PSTR("<+13>-13") +#define TZ_Pacific_Fiji PSTR("<+12>-12<+13>,M11.2.0,M1.2.3/99") +#define TZ_Pacific_Funafuti PSTR("<+12>-12") +#define TZ_Pacific_Galapagos PSTR("<-06>6") +#define TZ_Pacific_Gambier PSTR("<-09>9") +#define TZ_Pacific_Guadalcanal PSTR("<+11>-11") +#define TZ_Pacific_Guam PSTR("ChST-10") +#define TZ_Pacific_Honolulu PSTR("HST10") +#define TZ_Pacific_Kiritimati PSTR("<+14>-14") +#define TZ_Pacific_Kosrae PSTR("<+11>-11") +#define TZ_Pacific_Kwajalein PSTR("<+12>-12") +#define TZ_Pacific_Majuro PSTR("<+12>-12") +#define TZ_Pacific_Marquesas PSTR("<-0930>9:30") +#define TZ_Pacific_Midway PSTR("SST11") +#define TZ_Pacific_Nauru PSTR("<+12>-12") +#define TZ_Pacific_Niue PSTR("<-11>11") +#define TZ_Pacific_Norfolk PSTR("<+11>-11<+12>,M10.1.0,M4.1.0/3") +#define TZ_Pacific_Noumea PSTR("<+11>-11") +#define TZ_Pacific_Pago_Pago PSTR("SST11") +#define TZ_Pacific_Palau PSTR("<+09>-9") +#define TZ_Pacific_Pitcairn PSTR("<-08>8") +#define TZ_Pacific_Pohnpei PSTR("<+11>-11") +#define TZ_Pacific_Port_Moresby PSTR("<+10>-10") +#define TZ_Pacific_Rarotonga PSTR("<-10>10") +#define TZ_Pacific_Saipan PSTR("ChST-10") +#define TZ_Pacific_Tahiti PSTR("<-10>10") +#define TZ_Pacific_Tarawa PSTR("<+12>-12") +#define TZ_Pacific_Tongatapu PSTR("<+13>-13") +#define TZ_Pacific_Wake PSTR("<+12>-12") +#define TZ_Pacific_Wallis PSTR("<+12>-12") +#define TZ_Etc_GMT PSTR("GMT0") +#define TZ_Etc_GMTm0 PSTR("GMT0") +#define TZ_Etc_GMTm1 PSTR("<+01>-1") +#define TZ_Etc_GMTm2 PSTR("<+02>-2") +#define TZ_Etc_GMTm3 PSTR("<+03>-3") +#define TZ_Etc_GMTm4 PSTR("<+04>-4") +#define TZ_Etc_GMTm5 PSTR("<+05>-5") +#define TZ_Etc_GMTm6 PSTR("<+06>-6") +#define TZ_Etc_GMTm7 PSTR("<+07>-7") +#define TZ_Etc_GMTm8 PSTR("<+08>-8") +#define TZ_Etc_GMTm9 PSTR("<+09>-9") +#define TZ_Etc_GMTm10 PSTR("<+10>-10") +#define TZ_Etc_GMTm11 PSTR("<+11>-11") +#define TZ_Etc_GMTm12 PSTR("<+12>-12") +#define TZ_Etc_GMTm13 PSTR("<+13>-13") +#define TZ_Etc_GMTm14 PSTR("<+14>-14") +#define TZ_Etc_GMT0 PSTR("GMT0") +#define TZ_Etc_GMTp0 PSTR("GMT0") +#define TZ_Etc_GMTp1 PSTR("<-01>1") +#define TZ_Etc_GMTp2 PSTR("<-02>2") +#define TZ_Etc_GMTp3 PSTR("<-03>3") +#define TZ_Etc_GMTp4 PSTR("<-04>4") +#define TZ_Etc_GMTp5 PSTR("<-05>5") +#define TZ_Etc_GMTp6 PSTR("<-06>6") +#define TZ_Etc_GMTp7 PSTR("<-07>7") +#define TZ_Etc_GMTp8 PSTR("<-08>8") +#define TZ_Etc_GMTp9 PSTR("<-09>9") +#define TZ_Etc_GMTp10 PSTR("<-10>10") +#define TZ_Etc_GMTp11 PSTR("<-11>11") +#define TZ_Etc_GMTp12 PSTR("<-12>12") +#define TZ_Etc_UCT PSTR("UTC0") +#define TZ_Etc_UTC PSTR("UTC0") +#define TZ_Etc_Greenwich PSTR("GMT0") +#define TZ_Etc_Universal PSTR("UTC0") +#define TZ_Etc_Zulu PSTR("UTC0") +#endif + +//////////////////////////////////////////////////////////// + +#define TIMEZONE_MAX_LEN 50 + +#if 1 + +const char TZ_NAME[][TIMEZONE_MAX_LEN] /*PROGMEM*/ = +{ +#if USING_AFRICA + "Africa/Abidjan", //PSTR("GMT0") + "Africa/Accra", //PSTR("GMT0") + "Africa/Addis_Ababa", //PSTR("EAT-3") + "Africa/Algiers", //PSTR("CET-1") + "Africa/Asmara", //PSTR("EAT-3") + "Africa/Bamako", //PSTR("GMT0") + "Africa/Bangui", //PSTR("WAT-1") + "Africa/Banjul", //PSTR("GMT0") + "Africa/Bissau", //PSTR("GMT0") + "Africa/Blantyre", //PSTR("CAT-2") + "Africa/Brazzaville", //PSTR("WAT-1") + "Africa/Bujumbura", //PSTR("CAT-2") + "Africa/Cairo", //PSTR("EET-2") + "Africa/Casablanca", //PSTR("<+01>-1") + "Africa/Ceuta", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Africa/Conakry", //PSTR("GMT0") + "Africa/Dakar", //PSTR("GMT0") + "Africa/Dar_es_Salaam", //PSTR("EAT-3") + "Africa/Djibouti", //PSTR("EAT-3") + "Africa/Douala", //PSTR("WAT-1") + "Africa/El_Aaiun", //PSTR("<+01>-1") + "Africa/Freetown", //PSTR("GMT0") + "Africa/Gaborone", //PSTR("CAT-2") + "Africa/Harare", //PSTR("CAT-2") + "Africa/Johannesburg", //PSTR("SAST-2") + "Africa/Juba", //PSTR("EAT-3") + "Africa/Kampala", //PSTR("EAT-3") + "Africa/Khartoum", //PSTR("CAT-2") + "Africa/Kigali", //PSTR("CAT-2") + "Africa/Kinshasa", //PSTR("WAT-1") + "Africa/Lagos", //PSTR("WAT-1") + "Africa/Libreville", //PSTR("WAT-1") + "Africa/Lome", //PSTR("GMT0") + "Africa/Luanda", //PSTR("WAT-1") + "Africa/Lubumbashi", //PSTR("CAT-2") + "Africa/Lusaka", //PSTR("CAT-2") + "Africa/Malabo", //PSTR("WAT-1") + "Africa/Maputo", //PSTR("CAT-2") + "Africa/Maseru", //PSTR("SAST-2") + "Africa/Mbabane", //PSTR("SAST-2") + "Africa/Mogadishu", //PSTR("EAT-3") + "Africa/Monrovia", //PSTR("GMT0") + "Africa/Nairobi", //PSTR("EAT-3") + "Africa/Ndjamena", //PSTR("WAT-1") + "Africa/Niamey", //PSTR("WAT-1") + "Africa/Nouakchott", //PSTR("GMT0") + "Africa/Ouagadougou", //PSTR("GMT0") + "Africa/PortomNovo", //PSTR("WAT-1") + "Africa/Sao_Tome", //PSTR("GMT0") + "Africa/Tripoli", //PSTR("EET-2") + "Africa/Tunis", //PSTR("CET-1") + "Africa/Windhoek", //PSTR("CAT-2") +#endif + + +#if USING_AMERICA + "America/Adak", //PSTR("HST10HDT",M3.2.0",M11.1.0") + "America/Anchorage", //PSTR("AKST9AKDT",M3.2.0",M11.1.0") + "America/Anguilla", //PSTR("AST4") + "America/Antigua", //PSTR("AST4") + "America/Araguaina", //PSTR("<-03>3") + "America/Argentina/Buenos_Aires", //PSTR("<-03>3") + "America/Argentina/Catamarca", //PSTR("<-03>3") + "America/Argentina/Cordoba", //PSTR("<-03>3") + "America/Argentina/Jujuy", //PSTR("<-03>3") + "America/Argentina/La_Rioja", //PSTR("<-03>3") + "America/Argentina/Mendoza", //PSTR("<-03>3") + "America/Argentina/Rio_Gallegos", //PSTR("<-03>3") + "America/Argentina/Salta", //PSTR("<-03>3") + "America/Argentina/San_Juan", //PSTR("<-03>3") + "America/Argentina/San_Luis", //PSTR("<-03>3") + "America/Argentina/Tucuman", //PSTR("<-03>3") + "America/Argentina/Ushuaia", //PSTR("<-03>3") + "America/Aruba", //PSTR("AST4") + "America/Asuncion", //PSTR("<-04>4<-03>",M10.1.0/0",M3.4.0/0") + "America/Atikokan", //PSTR("EST5") + "America/Bahia", //PSTR("<-03>3") + "America/Bahia_Banderas", //PSTR("CST6CDT",M4.1.0",M10.5.0") + "America/Barbados", //PSTR("AST4") + "America/Belem", //PSTR("<-03>3") + "America/Belize", //PSTR("CST6") + "America/BlancmSablon", //PSTR("AST4") + "America/Boa_Vista", //PSTR("<-04>4") + "America/Bogota", //PSTR("<-05>5") + "America/Boise", //PSTR("MST7MDT",M3.2.0",M11.1.0") + "America/Cambridge_Bay", //PSTR("MST7MDT",M3.2.0",M11.1.0") + "America/Campo_Grande", //PSTR("<-04>4") + "America/Cancun", //PSTR("EST5") + "America/Caracas", //PSTR("<-04>4") + "America/Cayenne", //PSTR("<-03>3") + "America/Cayman", //PSTR("EST5") + "America/Chicago", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/Chihuahua", //PSTR("MST7MDT",M4.1.0",M10.5.0") + "America/Costa_Rica", //PSTR("CST6") + "America/Creston", //PSTR("MST7") + "America/Cuiaba", //PSTR("<-04>4") + "America/Curacao", //PSTR("AST4") + "America/Danmarkshavn", //PSTR("GMT0") + "America/Dawson", //PSTR("MST7") + "America/Dawson_Creek", //PSTR("MST7") + "America/Denver", //PSTR("MST7MDT",M3.2.0",M11.1.0") + "America/Detroit", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Dominica", //PSTR("AST4") + "America/Edmonton", //PSTR("MST7MDT",M3.2.0",M11.1.0") + "America/Eirunepe", //PSTR("<-05>5") + "America/El_Salvador", //PSTR("CST6") + "America/Fortaleza", //PSTR("<-03>3") + "America/Fort_Nelson", //PSTR("MST7") + "America/Glace_Bay", //PSTR("AST4ADT",M3.2.0",M11.1.0") + "America/Godthab", //PSTR("<-03>3<-02>",M3.5.0/-2",M10.5.0/-1") + "America/Goose_Bay", //PSTR("AST4ADT",M3.2.0",M11.1.0") + "America/Grand_Turk", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Grenada", //PSTR("AST4") + "America/Guadeloupe", //PSTR("AST4") + "America/Guatemala", //PSTR("CST6") + "America/Guayaquil", //PSTR("<-05>5") + "America/Guyana", //PSTR("<-04>4") + "America/Halifax", //PSTR("AST4ADT",M3.2.0",M11.1.0") + "America/Havana", //PSTR("CST5CDT",M3.2.0/0",M11.1.0/1") + "America/Hermosillo", //PSTR("MST7") + "America/Indiana_Indianapolis", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Indiana_Knox", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/Indiana_Marengo", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Indiana_Petersburg", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Indiana_Tell_City", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/Indiana_Vevay", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Indiana_Vincennes", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Indiana_Winamac", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Inuvik", //PSTR("MST7MDT",M3.2.0",M11.1.0") + "America/Iqaluit", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Jamaica", //PSTR("EST5") + "America/Juneau", //PSTR("AKST9AKDT",M3.2.0",M11.1.0") + "America/Kentucky_Louisville", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Kentucky_Monticello", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Kralendijk", //PSTR("AST4") + "America/La_Paz", //PSTR("<-04>4") + "America/Lima", //PSTR("<-05>5") + "America/Los_Angeles", //PSTR("PST8PDT",M3.2.0",M11.1.0") + "America/Lower_Princes", //PSTR("AST4") + "America/Maceio", //PSTR("<-03>3") + "America/Managua", //PSTR("CST6") + "America/Manaus", //PSTR("<-04>4") + "America/Marigot", //PSTR("AST4") + "America/Martinique", //PSTR("AST4") + "America/Matamoros", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/Mazatlan", //PSTR("MST7MDT",M4.1.0",M10.5.0") + "America/Menominee", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/Merida", //PSTR("CST6CDT",M4.1.0",M10.5.0") + "America/Metlakatla", //PSTR("AKST9AKDT",M3.2.0",M11.1.0") + "America/Mexico_City", //PSTR("CST6CDT",M4.1.0",M10.5.0") + "America/Miquelon", //PSTR("<-03>3<-02>",M3.2.0",M11.1.0") + "America/Moncton", //PSTR("AST4ADT",M3.2.0",M11.1.0") + "America/Monterrey", //PSTR("CST6CDT",M4.1.0",M10.5.0") + "America/Montevideo", //PSTR("<-03>3") + "America/Montreal", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Montserrat", //PSTR("AST4") + "America/Nassau", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/New_York", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Nipigon", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Nome", //PSTR("AKST9AKDT",M3.2.0",M11.1.0") + "America/Noronha", //PSTR("<-02>2") + "America/North_Dakota_Beulah", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/North_Dakota_Center", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/North_Dakota_New_Salem", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/Ojinaga", //PSTR("MST7MDT",M3.2.0",M11.1.0") + "America/Panama", //PSTR("EST5") + "America/Pangnirtung", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Paramaribo", //PSTR("<-03>3") + "America/Phoenix", //PSTR("MST7") + "America/PortmaumPrince", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Port_of_Spain", //PSTR("AST4") + "America/Porto_Velho", //PSTR("<-04>4") + "America/Puerto_Rico", //PSTR("AST4") + "America/Punta_Arenas", //PSTR("<-03>3") + "America/Rainy_River", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/Rankin_Inlet", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/Recife", //PSTR("<-03>3") + "America/Regina", //PSTR("CST6") + "America/Resolute", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/Rio_Branco", //PSTR("<-05>5") + "America/Santarem", //PSTR("<-03>3") + "America/Santiago", //PSTR("<-04>4<-03>",M9.1.6/24",M4.1.6/24") + "America/Santo_Domingo", //PSTR("AST4") + "America/Sao_Paulo", //PSTR("<-03>3") + "America/Scoresbysund", //PSTR("<-01>1<+00>",M3.5.0/0",M10.5.0/1") + "America/Sitka", //PSTR("AKST9AKDT",M3.2.0",M11.1.0") + "America/St_Barthelemy", //PSTR("AST4") + "America/St_Johns", //PSTR("NST3:30NDT",M3.2.0",M11.1.0") + "America/St_Kitts", //PSTR("AST4") + "America/St_Lucia", //PSTR("AST4") + "America/St_Thomas", //PSTR("AST4") + "America/St_Vincent", //PSTR("AST4") + "America/Swift_Current", //PSTR("CST6") + "America/Tegucigalpa", //PSTR("CST6") + "America/Thule", //PSTR("AST4ADT",M3.2.0",M11.1.0") + "America/Thunder_Bay", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Tijuana", //PSTR("PST8PDT",M3.2.0",M11.1.0") + "America/Toronto", //PSTR("EST5EDT",M3.2.0",M11.1.0") + "America/Tortola", //PSTR("AST4") + "America/Vancouver", //PSTR("PST8PDT",M3.2.0",M11.1.0") + "America/Whitehorse", //PSTR("MST7") + "America/Winnipeg", //PSTR("CST6CDT",M3.2.0",M11.1.0") + "America/Yakutat", //PSTR("AKST9AKDT",M3.2.0",M11.1.0") + "America/Yellowknife", //PSTR("MST7MDT",M3.2.0",M11.1.0") +#endif + +#if USING_ANTARCTICA + "Antarctica/Casey", //PSTR("<+11>-11") + "Antarctica/Davis", //PSTR("<+07>-7") + "Antarctica/DumontDUrville", //PSTR("<+10>-10") + "Antarctica/Macquarie", //PSTR("AEST-10AEDT",M10.1.0",M4.1.0/3") + "Antarctica/Mawson", //PSTR("<+05>-5") + "Antarctica/McMurdo", //PSTR("NZST-12NZDT",M9.5.0",M4.1.0/3") + "Antarctica/Palmer", //PSTR("<-03>3") + "Antarctica/Rothera", //PSTR("<-03>3") + "Antarctica/Syowa", //PSTR("<+03>-3") + "Antarctica/Troll", //PSTR("<+00>0<+02>-2",M3.5.0/1",M10.5.0/3") + "Antarctica/Vostok", //PSTR("<+06>-6") + "Arctic/Longyearbyen", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") +#endif + +#if USING_ASIA + "Asia/Aden", //PSTR("<+03>-3") + "Asia/Almaty", //PSTR("<+06>-6") + "Asia/Amman", //PSTR("EET-2EEST",M3.5.4/24",M10.5.5/1") + "Asia/Anadyr", //PSTR("<+12>-12") + "Asia/Aqtau", //PSTR("<+05>-5") + "Asia/Aqtobe", //PSTR("<+05>-5") + "Asia/Ashgabat", //PSTR("<+05>-5") + "Asia/Atyrau", //PSTR("<+05>-5") + "Asia/Baghdad", //PSTR("<+03>-3") + "Asia/Bahrain", //PSTR("<+03>-3") + "Asia/Baku", //PSTR("<+04>-4") + "Asia/Bangkok", //PSTR("<+07>-7") + "Asia/Barnaul", //PSTR("<+07>-7") + "Asia/Beirut", //PSTR("EET-2EEST",M3.5.0/0",M10.5.0/0") + "Asia/Bishkek", //PSTR("<+06>-6") + "Asia/Brunei", //PSTR("<+08>-8") + "Asia/Chita", //PSTR("<+09>-9") + "Asia/Choibalsan", //PSTR("<+08>-8") + "Asia/Colombo", //PSTR("<+0530>-5:30") + "Asia/Damascus", //PSTR("EET-2EEST",M3.5.5/0",M10.5.5/0") + "Asia/Dhaka", //PSTR("<+06>-6") + "Asia/Dili", //PSTR("<+09>-9") + "Asia/Dubai", //PSTR("<+04>-4") + "Asia/Dushanbe", //PSTR("<+05>-5") + "Asia/Famagusta", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Asia/Gaza", //PSTR("EET-2EEST",M3.4.4/48",M10.4.4/49") + "Asia/Hebron", //PSTR("EET-2EEST",M3.4.4/48",M10.4.4/49") + "Asia/Ho_Chi_Minh", //PSTR("<+07>-7") + "Asia/Hong_Kong", //PSTR("HKT-8") + "Asia/Hovd", //PSTR("<+07>-7") + "Asia/Irkutsk", //PSTR("<+08>-8") + "Asia/Jakarta", //PSTR("WIB-7") + "Asia/Jayapura", //PSTR("WIT-9") + "Asia/Jerusalem", //PSTR("IST-2IDT",M3.4.4/26",M10.5.0") + "Asia/Kabul", //PSTR("<+0430>-4:30") + "Asia/Kamchatka", //PSTR("<+12>-12") + "Asia/Karachi", //PSTR("PKT-5") + "Asia/Kathmandu", //PSTR("<+0545>-5:45") + "Asia/Khandyga", //PSTR("<+09>-9") + "Asia/Kolkata", //PSTR("IST-5:30") + "Asia/Krasnoyarsk", //PSTR("<+07>-7") + "Asia/Kuala_Lumpur", //PSTR("<+08>-8") + "Asia/Kuching", //PSTR("<+08>-8") + "Asia/Kuwait", //PSTR("<+03>-3") + "Asia/Macau", //PSTR("CST-8") + "Asia/Magadan", //PSTR("<+11>-11") + "Asia/Makassar", //PSTR("WITA-8") + "Asia/Manila", //PSTR("PST-8") + "Asia/Muscat", //PSTR("<+04>-4") + "Asia/Nicosia", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Asia/Novokuznetsk", //PSTR("<+07>-7") + "Asia/Novosibirsk", //PSTR("<+07>-7") + "Asia/Omsk", //PSTR("<+06>-6") + "Asia/Oral", //PSTR("<+05>-5") + "Asia/Phnom_Penh", //PSTR("<+07>-7") + "Asia/Pontianak", //PSTR("WIB-7") + "Asia/Pyongyang", //PSTR("KST-9") + "Asia/Qatar", //PSTR("<+03>-3") + "Asia/Qyzylorda", //PSTR("<+05>-5") + "Asia/Riyadh", //PSTR("<+03>-3") + "Asia/Sakhalin", //PSTR("<+11>-11") + "Asia/Samarkand", //PSTR("<+05>-5") + "Asia/Seoul", //PSTR("KST-9") + "Asia/Shanghai", //PSTR("CST-8") + "Asia/Singapore", //PSTR("<+08>-8") + "Asia/Srednekolymsk", //PSTR("<+11>-11") + "Asia/Taipei", //PSTR("CST-8") + "Asia/Tashkent", //PSTR("<+05>-5") + "Asia/Tbilisi", //PSTR("<+04>-4") + "Asia/Tehran", //PSTR("<+0330>-3:30<+0430>",J79/24",J263/24") + "Asia/Thimphu", //PSTR("<+06>-6") + "Asia/Tokyo", //PSTR("JST-9") + "Asia/Tomsk", //PSTR("<+07>-7") + "Asia/Ulaanbaatar", //PSTR("<+08>-8") + "Asia/Urumqi", //PSTR("<+06>-6") + "Asia/UstmNera", //PSTR("<+10>-10") + "Asia/Vientiane", //PSTR("<+07>-7") + "Asia/Vladivostok", //PSTR("<+10>-10") + "Asia/Yakutsk", //PSTR("<+09>-9") + "Asia/Yangon", //PSTR("<+0630>-6:30") + "Asia/Yekaterinburg", //PSTR("<+05>-5") + "Asia/Yerevan", //PSTR("<+04>-4") +#endif + + +#if USING_ATLANTIC + "Atlantic/Azores", //PSTR("<-01>1<+00>",M3.5.0/0",M10.5.0/1") + "Atlantic/Bermuda", //PSTR("AST4ADT",M3.2.0",M11.1.0") + "Atlantic/Canary", //PSTR("WET0WEST",M3.5.0/1",M10.5.0") + "Atlantic/Cape_Verde", //PSTR("<-01>1") + "Atlantic/Faroe", //PSTR("WET0WEST",M3.5.0/1",M10.5.0") + "Atlantic/Madeira", //PSTR("WET0WEST",M3.5.0/1",M10.5.0") + "Atlantic/Reykjavik", //PSTR("GMT0") + "Atlantic/South_Georgia", //PSTR("<-02>2") + "Atlantic/Stanley", //PSTR("<-03>3") + "Atlantic/St_Helena", //PSTR("GMT0") +#endif + +#if USING_AUSTRALIA + "Australia/Adelaide", //PSTR("ACST-9:30ACDT",M10.1.0",M4.1.0/3") + "Australia/Brisbane", //PSTR("AEST-10") + "Australia/Broken_Hill", //PSTR("ACST-9:30ACDT",M10.1.0",M4.1.0/3") + "Australia/Currie", //PSTR("AEST-10AEDT",M10.1.0",M4.1.0/3") + "Australia/Darwin", //PSTR("ACST-9:30") + "Australia/Eucla", //PSTR("<+0845>-8:45") + "Australia/Hobart", //PSTR("AEST-10AEDT",M10.1.0",M4.1.0/3") + "Australia/Lindeman", //PSTR("AEST-10") + "Australia/Lord_Howe", //PSTR("<+1030>-10:30<+11>-11",M10.1.0",M4.1.0") + "Australia/Melbourne", //PSTR("AEST-10AEDT",M10.1.0",M4.1.0/3") + "Australia/Perth", //PSTR("AWST-8") + "Australia/Sydney", //PSTR("AEST-10AEDT",M10.1.0",M4.1.0/3") +#endif + +#if USING_EUROPE + "Europe/Amsterdam", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Andorra", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Astrakhan", //PSTR("<+04>-4") + "Europe/Athens", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Belgrade", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Berlin", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Bratislava", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Brussels", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Bucharest", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Budapest", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Busingen", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Chisinau", //PSTR("EET-2EEST",M3.5.0",M10.5.0/3") + "Europe/Copenhagen", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Dublin", //PSTR("IST-1GMT0",M10.5.0",M3.5.0/1") + "Europe/Gibraltar", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Guernsey", //PSTR("GMT0BST",M3.5.0/1",M10.5.0") + "Europe/Helsinki", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Isle_of_Man", //PSTR("GMT0BST",M3.5.0/1",M10.5.0") + "Europe/Istanbul", //PSTR("<+03>-3") + "Europe/Jersey", //PSTR("GMT0BST",M3.5.0/1",M10.5.0") + "Europe/Kaliningrad", //PSTR("EET-2") + "Europe/Kiev", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Kirov", //PSTR("<+03>-3") + "Europe/Lisbon", //PSTR("WET0WEST",M3.5.0/1",M10.5.0") + "Europe/Ljubljana", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/London", //PSTR("GMT0BST",M3.5.0/1",M10.5.0") + "Europe/Luxembourg", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Madrid", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Malta", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Mariehamn", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Minsk", //PSTR("<+03>-3") + "Europe/Monaco", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Moscow", //PSTR("MSK-3") + "Europe/Oslo", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Paris", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Podgorica", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Prague", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Riga", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Rome", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Samara", //PSTR("<+04>-4") + "Europe/San_Marino", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Sarajevo", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Saratov", //PSTR("<+04>-4") + "Europe/Simferopol", //PSTR("MSK-3") + "Europe/Skopje", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Sofia", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Stockholm", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Tallinn", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Tirane", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Ulyanovsk", //PSTR("<+04>-4") + "Europe/Uzhgorod", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Vaduz", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Vatican", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Vienna", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Vilnius", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Volgograd", //PSTR("<+04>-4") + "Europe/Warsaw", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Zagreb", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") + "Europe/Zaporozhye", //PSTR("EET-2EEST",M3.5.0/3",M10.5.0/4") + "Europe/Zurich", //PSTR("CET-1CEST",M3.5.0",M10.5.0/3") +#endif + +#if USING_INDIAN + "Indian/Antananarivo", //PSTR("EAT-3") + "Indian/Chagos", //PSTR("<+06>-6") + "Indian/Christmas", //PSTR("<+07>-7") + "Indian/Cocos", //PSTR("<+0630>-6:30") + "Indian/Comoro", //PSTR("EAT-3") + "Indian/Kerguelen", //PSTR("<+05>-5") + "Indian/Mahe", //PSTR("<+04>-4") + "Indian/Maldives", //PSTR("<+05>-5") + "Indian/Mauritius", //PSTR("<+04>-4") + "Indian/Mayotte", //PSTR("EAT-3") + "Indian/Reunion", //PSTR("<+04>-4") +#endif + +#if USING_PACIFIC + "Pacific/Apia", //PSTR("<+13>-13<+14>",M9.5.0/3",M4.1.0/4") + "Pacific/Auckland", //PSTR("NZST-12NZDT",M9.5.0",M4.1.0/3") + "Pacific/Bougainville", //PSTR("<+11>-11") + "Pacific/Chatham", //PSTR("<+1245>-12:45<+1345>",M9.5.0/2:45",M4.1.0/3:45") + "Pacific/Chuuk", //PSTR("<+10>-10") + "Pacific/Easter", //PSTR("<-06>6<-05>",M9.1.6/22",M4.1.6/22") + "Pacific/Efate", //PSTR("<+11>-11") + "Pacific/Enderbury", //PSTR("<+13>-13") + "Pacific/Fakaofo", //PSTR("<+13>-13") + "Pacific/Fiji", //PSTR("<+12>-12<+13>",M11.2.0",M1.2.3/99") + "Pacific/Funafuti", //PSTR("<+12>-12") + "Pacific/Galapagos", //PSTR("<-06>6") + "Pacific/Gambier", //PSTR("<-09>9") + "Pacific/Guadalcanal", //PSTR("<+11>-11") + "Pacific/Guam", //PSTR("ChST-10") + "Pacific/Honolulu", //PSTR("HST10") + "Pacific/Kiritimati", //PSTR("<+14>-14") + "Pacific/Kosrae", //PSTR("<+11>-11") + "Pacific/Kwajalein", //PSTR("<+12>-12") + "Pacific/Majuro", //PSTR("<+12>-12") + "Pacific/Marquesas", //PSTR("<-0930>9:30") + "Pacific/Midway", //PSTR("SST11") + "Pacific/Nauru", //PSTR("<+12>-12") + "Pacific/Niue", //PSTR("<-11>11") + "Pacific/Norfolk", //PSTR("<+11>-11<+12>",M10.1.0",M4.1.0/3") + "Pacific/Noumea", //PSTR("<+11>-11") + "Pacific/Pago_Pago", //PSTR("SST11") + "Pacific/Palau", //PSTR("<+09>-9") + "Pacific/Pitcairn", //PSTR("<-08>8") + "Pacific/Pohnpei", //PSTR("<+11>-11") + "Pacific/Port_Moresby", //PSTR("<+10>-10") + "Pacific/Rarotonga", //PSTR("<-10>10") + "Pacific/Saipan", //PSTR("ChST-10") + "Pacific/Tahiti", //PSTR("<-10>10") + "Pacific/Tarawa", //PSTR("<+12>-12") + "Pacific/Tongatapu", //PSTR("<+13>-13") + "Pacific/Wake", //PSTR("<+12>-12") + "Pacific/Wallis", //PSTR("<+12>-12") +#endif + +#if USING_ETC_GMT + "Etc/GMT", //PSTR("GMT0") + "Etc/GMTm0", //PSTR("GMT0") + "Etc/GMTm1", //PSTR("<+01>-1") + "Etc/GMTm2", //PSTR("<+02>-2") + "Etc/GMTm3", //PSTR("<+03>-3") + "Etc/GMTm4", //PSTR("<+04>-4") + "Etc/GMTm5", //PSTR("<+05>-5") + "Etc/GMTm6", //PSTR("<+06>-6") + "Etc/GMTm7", //PSTR("<+07>-7") + "Etc/GMTm8", //PSTR("<+08>-8") + "Etc/GMTm9", //PSTR("<+09>-9") + "Etc/GMTm10", //PSTR("<+10>-10") + "Etc/GMTm11", //PSTR("<+11>-11") + "Etc/GMTm12", //PSTR("<+12>-12") + "Etc/GMTm13", //PSTR("<+13>-13") + "Etc/GMTm14", //PSTR("<+14>-14") + "Etc/GMT0", //PSTR("GMT0") + "Etc/GMTp0", //PSTR("GMT0") + "Etc/GMTp1", //PSTR("<-01>1") + "Etc/GMTp2", //PSTR("<-02>2") + "Etc/GMTp3", //PSTR("<-03>3") + "Etc/GMTp4", //PSTR("<-04>4") + "Etc/GMTp5", //PSTR("<-05>5") + "Etc/GMTp6", //PSTR("<-06>6") + "Etc/GMTp7", //PSTR("<-07>7") + "Etc/GMTp8", //PSTR("<-08>8") + "Etc/GMTp9", //PSTR("<-09>9") + "Etc/GMTp10", //PSTR("<-10>10") + "Etc/GMTp11", //PSTR("<-11>11") + "Etc/GMTp12", //PSTR("<-12>12") + "Etc/UCT", //PSTR("UTC0") + "Etc/UTC", //PSTR("UTC0") + "Etc/Greenwich", //PSTR("GMT0") + "Etc/Universal", //PSTR("UTC0") + "Etc/Zulu", //PSTR("UTC0") +#endif +}; + +//////////////////////////////////////////////////////////// + +const char ESP_TZ_NAME[][TIMEZONE_MAX_LEN] /*PROGMEM*/ = +{ +#if USING_AFRICA + TZ_Africa_Abidjan, //PSTR("GMT0") + TZ_Africa_Accra, //PSTR("GMT0") + TZ_Africa_Addis_Ababa, //PSTR("EAT-3") + TZ_Africa_Algiers, //PSTR("CET-1") + TZ_Africa_Asmara, //PSTR("EAT-3") + TZ_Africa_Bamako, //PSTR("GMT0") + TZ_Africa_Bangui, //PSTR("WAT-1") + TZ_Africa_Banjul, //PSTR("GMT0") + TZ_Africa_Bissau, //PSTR("GMT0") + TZ_Africa_Blantyre, //PSTR("CAT-2") + TZ_Africa_Brazzaville, //PSTR("WAT-1") + TZ_Africa_Bujumbura, //PSTR("CAT-2") + TZ_Africa_Cairo, //PSTR("EET-2") + TZ_Africa_Casablanca, //PSTR("<+01>-1") + TZ_Africa_Ceuta, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Africa_Conakry, //PSTR("GMT0") + TZ_Africa_Dakar, //PSTR("GMT0") + TZ_Africa_Dar_es_Salaam, //PSTR("EAT-3") + TZ_Africa_Djibouti, //PSTR("EAT-3") + TZ_Africa_Douala, //PSTR("WAT-1") + TZ_Africa_El_Aaiun, //PSTR("<+01>-1") + TZ_Africa_Freetown, //PSTR("GMT0") + TZ_Africa_Gaborone, //PSTR("CAT-2") + TZ_Africa_Harare, //PSTR("CAT-2") + TZ_Africa_Johannesburg, //PSTR("SAST-2") + TZ_Africa_Juba, //PSTR("EAT-3") + TZ_Africa_Kampala, //PSTR("EAT-3") + TZ_Africa_Khartoum, //PSTR("CAT-2") + TZ_Africa_Kigali, //PSTR("CAT-2") + TZ_Africa_Kinshasa, //PSTR("WAT-1") + TZ_Africa_Lagos, //PSTR("WAT-1") + TZ_Africa_Libreville, //PSTR("WAT-1") + TZ_Africa_Lome, //PSTR("GMT0") + TZ_Africa_Luanda, //PSTR("WAT-1") + TZ_Africa_Lubumbashi, //PSTR("CAT-2") + TZ_Africa_Lusaka, //PSTR("CAT-2") + TZ_Africa_Malabo, //PSTR("WAT-1") + TZ_Africa_Maputo, //PSTR("CAT-2") + TZ_Africa_Maseru, //PSTR("SAST-2") + TZ_Africa_Mbabane, //PSTR("SAST-2") + TZ_Africa_Mogadishu, //PSTR("EAT-3") + TZ_Africa_Monrovia, //PSTR("GMT0") + TZ_Africa_Nairobi, //PSTR("EAT-3") + TZ_Africa_Ndjamena, //PSTR("WAT-1") + TZ_Africa_Niamey, //PSTR("WAT-1") + TZ_Africa_Nouakchott, //PSTR("GMT0") + TZ_Africa_Ouagadougou, //PSTR("GMT0") + TZ_Africa_PortomNovo, //PSTR("WAT-1") + TZ_Africa_Sao_Tome, //PSTR("GMT0") + TZ_Africa_Tripoli, //PSTR("EET-2") + TZ_Africa_Tunis, //PSTR("CET-1") + TZ_Africa_Windhoek, //PSTR("CAT-2") +#endif + + +#if USING_AMERICA + TZ_America_Adak, //PSTR("HST10HDT,M3.2.0,M11.1.0") + TZ_America_Anchorage, //PSTR("AKST9AKDT,M3.2.0,M11.1.0") + TZ_America_Anguilla, //PSTR("AST4") + TZ_America_Antigua, //PSTR("AST4") + TZ_America_Araguaina, //PSTR("<-03>3") + TZ_America_Argentina_Buenos_Aires, //PSTR("<-03>3") + TZ_America_Argentina_Catamarca, //PSTR("<-03>3") + TZ_America_Argentina_Cordoba, //PSTR("<-03>3") + TZ_America_Argentina_Jujuy, //PSTR("<-03>3") + TZ_America_Argentina_La_Rioja, //PSTR("<-03>3") + TZ_America_Argentina_Mendoza, //PSTR("<-03>3") + TZ_America_Argentina_Rio_Gallegos, //PSTR("<-03>3") + TZ_America_Argentina_Salta, //PSTR("<-03>3") + TZ_America_Argentina_San_Juan, //PSTR("<-03>3") + TZ_America_Argentina_San_Luis, //PSTR("<-03>3") + TZ_America_Argentina_Tucuman, //PSTR("<-03>3") + TZ_America_Argentina_Ushuaia, //PSTR("<-03>3") + TZ_America_Aruba, //PSTR("AST4") + TZ_America_Asuncion, //PSTR("<-04>4<-03>,M10.1.0/0,M3.4.0/0") + TZ_America_Atikokan, //PSTR("EST5") + TZ_America_Bahia, //PSTR("<-03>3") + TZ_America_Bahia_Banderas, //PSTR("CST6CDT,M4.1.0,M10.5.0") + TZ_America_Barbados, //PSTR("AST4") + TZ_America_Belem, //PSTR("<-03>3") + TZ_America_Belize, //PSTR("CST6") + TZ_America_BlancmSablon, //PSTR("AST4") + TZ_America_Boa_Vista, //PSTR("<-04>4") + TZ_America_Bogota, //PSTR("<-05>5") + TZ_America_Boise, //PSTR("MST7MDT,M3.2.0,M11.1.0") + TZ_America_Cambridge_Bay, //PSTR("MST7MDT,M3.2.0,M11.1.0") + TZ_America_Campo_Grande, //PSTR("<-04>4") + TZ_America_Cancun, //PSTR("EST5") + TZ_America_Caracas, //PSTR("<-04>4") + TZ_America_Cayenne, //PSTR("<-03>3") + TZ_America_Cayman, //PSTR("EST5") + TZ_America_Chicago, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_Chihuahua, //PSTR("MST7MDT,M4.1.0,M10.5.0") + TZ_America_Costa_Rica, //PSTR("CST6") + TZ_America_Creston, //PSTR("MST7") + TZ_America_Cuiaba, //PSTR("<-04>4") + TZ_America_Curacao, //PSTR("AST4") + TZ_America_Danmarkshavn, //PSTR("GMT0") + TZ_America_Dawson, //PSTR("MST7") + TZ_America_Dawson_Creek, //PSTR("MST7") + TZ_America_Denver, //PSTR("MST7MDT,M3.2.0,M11.1.0") + TZ_America_Detroit, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Dominica, //PSTR("AST4") + TZ_America_Edmonton, //PSTR("MST7MDT,M3.2.0,M11.1.0") + TZ_America_Eirunepe, //PSTR("<-05>5") + TZ_America_El_Salvador, //PSTR("CST6") + TZ_America_Fortaleza, //PSTR("<-03>3") + TZ_America_Fort_Nelson, //PSTR("MST7") + TZ_America_Glace_Bay, //PSTR("AST4ADT,M3.2.0,M11.1.0") + TZ_America_Godthab, //PSTR("<-03>3<-02>,M3.5.0/-2,M10.5.0/-1") + TZ_America_Goose_Bay, //PSTR("AST4ADT,M3.2.0,M11.1.0") + TZ_America_Grand_Turk, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Grenada, //PSTR("AST4") + TZ_America_Guadeloupe, //PSTR("AST4") + TZ_America_Guatemala, //PSTR("CST6") + TZ_America_Guayaquil, //PSTR("<-05>5") + TZ_America_Guyana, //PSTR("<-04>4") + TZ_America_Halifax, //PSTR("AST4ADT,M3.2.0,M11.1.0") + TZ_America_Havana, //PSTR("CST5CDT,M3.2.0/0,M11.1.0/1") + TZ_America_Hermosillo, //PSTR("MST7") + TZ_America_Indiana_Indianapolis, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Indiana_Knox, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_Indiana_Marengo, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Indiana_Petersburg, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Indiana_Tell_City, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_Indiana_Vevay, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Indiana_Vincennes, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Indiana_Winamac, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Inuvik, //PSTR("MST7MDT,M3.2.0,M11.1.0") + TZ_America_Iqaluit, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Jamaica, //PSTR("EST5") + TZ_America_Juneau, //PSTR("AKST9AKDT,M3.2.0,M11.1.0") + TZ_America_Kentucky_Louisville, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Kentucky_Monticello, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Kralendijk, //PSTR("AST4") + TZ_America_La_Paz, //PSTR("<-04>4") + TZ_America_Lima, //PSTR("<-05>5") + TZ_America_Los_Angeles, //PSTR("PST8PDT,M3.2.0,M11.1.0") + TZ_America_Lower_Princes, //PSTR("AST4") + TZ_America_Maceio, //PSTR("<-03>3") + TZ_America_Managua, //PSTR("CST6") + TZ_America_Manaus, //PSTR("<-04>4") + TZ_America_Marigot, //PSTR("AST4") + TZ_America_Martinique, //PSTR("AST4") + TZ_America_Matamoros, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_Mazatlan, //PSTR("MST7MDT,M4.1.0,M10.5.0") + TZ_America_Menominee, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_Merida, //PSTR("CST6CDT,M4.1.0,M10.5.0") + TZ_America_Metlakatla, //PSTR("AKST9AKDT,M3.2.0,M11.1.0") + TZ_America_Mexico_City, //PSTR("CST6CDT,M4.1.0,M10.5.0") + TZ_America_Miquelon, //PSTR("<-03>3<-02>,M3.2.0,M11.1.0") + TZ_America_Moncton, //PSTR("AST4ADT,M3.2.0,M11.1.0") + TZ_America_Monterrey, //PSTR("CST6CDT,M4.1.0,M10.5.0") + TZ_America_Montevideo, //PSTR("<-03>3") + TZ_America_Montreal, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Montserrat, //PSTR("AST4") + TZ_America_Nassau, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_New_York, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Nipigon, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Nome, //PSTR("AKST9AKDT,M3.2.0,M11.1.0") + TZ_America_Noronha, //PSTR("<-02>2") + TZ_America_North_Dakota_Beulah, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_North_Dakota_Center, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_North_Dakota_New_Salem, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_Ojinaga, //PSTR("MST7MDT,M3.2.0,M11.1.0") + TZ_America_Panama, //PSTR("EST5") + TZ_America_Pangnirtung, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Paramaribo, //PSTR("<-03>3") + TZ_America_Phoenix, //PSTR("MST7") + TZ_America_PortmaumPrince, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Port_of_Spain, //PSTR("AST4") + TZ_America_Porto_Velho, //PSTR("<-04>4") + TZ_America_Puerto_Rico, //PSTR("AST4") + TZ_America_Punta_Arenas, //PSTR("<-03>3") + TZ_America_Rainy_River, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_Rankin_Inlet, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_Recife, //PSTR("<-03>3") + TZ_America_Regina, //PSTR("CST6") + TZ_America_Resolute, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_Rio_Branco, //PSTR("<-05>5") + TZ_America_Santarem, //PSTR("<-03>3") + TZ_America_Santiago, //PSTR("<-04>4<-03>,M9.1.6/24,M4.1.6/24") + TZ_America_Santo_Domingo, //PSTR("AST4") + TZ_America_Sao_Paulo, //PSTR("<-03>3") + TZ_America_Scoresbysund, //PSTR("<-01>1<+00>,M3.5.0/0,M10.5.0/1") + TZ_America_Sitka, //PSTR("AKST9AKDT,M3.2.0,M11.1.0") + TZ_America_St_Barthelemy, //PSTR("AST4") + TZ_America_St_Johns, //PSTR("NST3:30NDT,M3.2.0,M11.1.0") + TZ_America_St_Kitts, //PSTR("AST4") + TZ_America_St_Lucia, //PSTR("AST4") + TZ_America_St_Thomas, //PSTR("AST4") + TZ_America_St_Vincent, //PSTR("AST4") + TZ_America_Swift_Current, //PSTR("CST6") + TZ_America_Tegucigalpa, //PSTR("CST6") + TZ_America_Thule, //PSTR("AST4ADT,M3.2.0,M11.1.0") + TZ_America_Thunder_Bay, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Tijuana, //PSTR("PST8PDT,M3.2.0,M11.1.0") + TZ_America_Toronto, //PSTR("EST5EDT,M3.2.0,M11.1.0") + TZ_America_Tortola, //PSTR("AST4") + TZ_America_Vancouver, //PSTR("PST8PDT,M3.2.0,M11.1.0") + TZ_America_Whitehorse, //PSTR("MST7") + TZ_America_Winnipeg, //PSTR("CST6CDT,M3.2.0,M11.1.0") + TZ_America_Yakutat, //PSTR("AKST9AKDT,M3.2.0,M11.1.0") + TZ_America_Yellowknife, //PSTR("MST7MDT,M3.2.0,M11.1.0") +#endif + +#if USING_ANTARCTICA + TZ_Antarctica_Casey, //PSTR("<+11>-11") + TZ_Antarctica_Davis, //PSTR("<+07>-7") + TZ_Antarctica_DumontDUrville, //PSTR("<+10>-10") + TZ_Antarctica_Macquarie, //PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") + TZ_Antarctica_Mawson, //PSTR("<+05>-5") + TZ_Antarctica_McMurdo, //PSTR("NZST-12NZDT,M9.5.0,M4.1.0/3") + TZ_Antarctica_Palmer, //PSTR("<-03>3") + TZ_Antarctica_Rothera, //PSTR("<-03>3") + TZ_Antarctica_Syowa, //PSTR("<+03>-3") + TZ_Antarctica_Troll, //PSTR("<+00>0<+02>-2,M3.5.0/1,M10.5.0/3") + TZ_Antarctica_Vostok, //PSTR("<+06>-6") + TZ_Arctic_Longyearbyen, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#endif + + +#if USING_ASIA + TZ_Asia_Aden, //PSTR("<+03>-3") + TZ_Asia_Almaty, //PSTR("<+06>-6") + TZ_Asia_Amman, //PSTR("EET-2EEST,M3.5.4/24,M10.5.5/1") + TZ_Asia_Anadyr, //PSTR("<+12>-12") + TZ_Asia_Aqtau, //PSTR("<+05>-5") + TZ_Asia_Aqtobe, //PSTR("<+05>-5") + TZ_Asia_Ashgabat, //PSTR("<+05>-5") + TZ_Asia_Atyrau, //PSTR("<+05>-5") + TZ_Asia_Baghdad, //PSTR("<+03>-3") + TZ_Asia_Bahrain, //PSTR("<+03>-3") + TZ_Asia_Baku, //PSTR("<+04>-4") + TZ_Asia_Bangkok, //PSTR("<+07>-7") + TZ_Asia_Barnaul, //PSTR("<+07>-7") + TZ_Asia_Beirut, //PSTR("EET-2EEST,M3.5.0/0,M10.5.0/0") + TZ_Asia_Bishkek, //PSTR("<+06>-6") + TZ_Asia_Brunei, //PSTR("<+08>-8") + TZ_Asia_Chita, //PSTR("<+09>-9") + TZ_Asia_Choibalsan, //PSTR("<+08>-8") + TZ_Asia_Colombo, //PSTR("<+0530>-5:30") + TZ_Asia_Damascus, //PSTR("EET-2EEST,M3.5.5/0,M10.5.5/0") + TZ_Asia_Dhaka, //PSTR("<+06>-6") + TZ_Asia_Dili, //PSTR("<+09>-9") + TZ_Asia_Dubai, //PSTR("<+04>-4") + TZ_Asia_Dushanbe, //PSTR("<+05>-5") + TZ_Asia_Famagusta, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Asia_Gaza, //PSTR("EET-2EEST,M3.4.4/48,M10.4.4/49") + TZ_Asia_Hebron, //PSTR("EET-2EEST,M3.4.4/48,M10.4.4/49") + TZ_Asia_Ho_Chi_Minh, //PSTR("<+07>-7") + TZ_Asia_Hong_Kong, //PSTR("HKT-8") + TZ_Asia_Hovd, //PSTR("<+07>-7") + TZ_Asia_Irkutsk, //PSTR("<+08>-8") + TZ_Asia_Jakarta, //PSTR("WIB-7") + TZ_Asia_Jayapura, //PSTR("WIT-9") + TZ_Asia_Jerusalem, //PSTR("IST-2IDT,M3.4.4/26,M10.5.0") + TZ_Asia_Kabul, //PSTR("<+0430>-4:30") + TZ_Asia_Kamchatka, //PSTR("<+12>-12") + TZ_Asia_Karachi, //PSTR("PKT-5") + TZ_Asia_Kathmandu, //PSTR("<+0545>-5:45") + TZ_Asia_Khandyga, //PSTR("<+09>-9") + TZ_Asia_Kolkata, //PSTR("IST-5:30") + TZ_Asia_Krasnoyarsk, //PSTR("<+07>-7") + TZ_Asia_Kuala_Lumpur, //PSTR("<+08>-8") + TZ_Asia_Kuching, //PSTR("<+08>-8") + TZ_Asia_Kuwait, //PSTR("<+03>-3") + TZ_Asia_Macau, //PSTR("CST-8") + TZ_Asia_Magadan, //PSTR("<+11>-11") + TZ_Asia_Makassar, //PSTR("WITA-8") + TZ_Asia_Manila, //PSTR("PST-8") + TZ_Asia_Muscat, //PSTR("<+04>-4") + TZ_Asia_Nicosia, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Asia_Novokuznetsk, //PSTR("<+07>-7") + TZ_Asia_Novosibirsk, //PSTR("<+07>-7") + TZ_Asia_Omsk, //PSTR("<+06>-6") + TZ_Asia_Oral, //PSTR("<+05>-5") + TZ_Asia_Phnom_Penh, //PSTR("<+07>-7") + TZ_Asia_Pontianak, //PSTR("WIB-7") + TZ_Asia_Pyongyang, //PSTR("KST-9") + TZ_Asia_Qatar, //PSTR("<+03>-3") + TZ_Asia_Qyzylorda, //PSTR("<+05>-5") + TZ_Asia_Riyadh, //PSTR("<+03>-3") + TZ_Asia_Sakhalin, //PSTR("<+11>-11") + TZ_Asia_Samarkand, //PSTR("<+05>-5") + TZ_Asia_Seoul, //PSTR("KST-9") + TZ_Asia_Shanghai, //PSTR("CST-8") + TZ_Asia_Singapore, //PSTR("<+08>-8") + TZ_Asia_Srednekolymsk, //PSTR("<+11>-11") + TZ_Asia_Taipei, //PSTR("CST-8") + TZ_Asia_Tashkent, //PSTR("<+05>-5") + TZ_Asia_Tbilisi, //PSTR("<+04>-4") + TZ_Asia_Tehran, //PSTR("<+0330>-3:30<+0430>,J79/24,J263/24") + TZ_Asia_Thimphu, //PSTR("<+06>-6") + TZ_Asia_Tokyo, //PSTR("JST-9") + TZ_Asia_Tomsk, //PSTR("<+07>-7") + TZ_Asia_Ulaanbaatar, //PSTR("<+08>-8") + TZ_Asia_Urumqi, //PSTR("<+06>-6") + TZ_Asia_UstmNera, //PSTR("<+10>-10") + TZ_Asia_Vientiane, //PSTR("<+07>-7") + TZ_Asia_Vladivostok, //PSTR("<+10>-10") + TZ_Asia_Yakutsk, //PSTR("<+09>-9") + TZ_Asia_Yangon, //PSTR("<+0630>-6:30") + TZ_Asia_Yekaterinburg, //PSTR("<+05>-5") + TZ_Asia_Yerevan, //PSTR("<+04>-4") +#endif + +#if USING_ATLANTIC + TZ_Atlantic_Azores, //PSTR("<-01>1<+00>,M3.5.0/0,M10.5.0/1") + TZ_Atlantic_Bermuda, //PSTR("AST4ADT,M3.2.0,M11.1.0") + TZ_Atlantic_Canary, //PSTR("WET0WEST,M3.5.0/1,M10.5.0") + TZ_Atlantic_Cape_Verde, //PSTR("<-01>1") + TZ_Atlantic_Faroe, //PSTR("WET0WEST,M3.5.0/1,M10.5.0") + TZ_Atlantic_Madeira, //PSTR("WET0WEST,M3.5.0/1,M10.5.0") + TZ_Atlantic_Reykjavik, //PSTR("GMT0") + TZ_Atlantic_South_Georgia, //PSTR("<-02>2") + TZ_Atlantic_Stanley, //PSTR("<-03>3") + TZ_Atlantic_St_Helena, //PSTR("GMT0") +#endif + +#if USING_AUSTRALIA + TZ_Australia_Adelaide, //PSTR("ACST-9:30ACDT,M10.1.0,M4.1.0/3") + TZ_Australia_Brisbane, //PSTR("AEST-10") + TZ_Australia_Broken_Hill, //PSTR("ACST-9:30ACDT,M10.1.0,M4.1.0/3") + TZ_Australia_Currie, //PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") + TZ_Australia_Darwin, //PSTR("ACST-9:30") + TZ_Australia_Eucla, //PSTR("<+0845>-8:45") + TZ_Australia_Hobart, //PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") + TZ_Australia_Lindeman, //PSTR("AEST-10") + TZ_Australia_Lord_Howe, //PSTR("<+1030>-10:30<+11>-11,M10.1.0,M4.1.0") + TZ_Australia_Melbourne, //PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") + TZ_Australia_Perth, //PSTR("AWST-8") + TZ_Australia_Sydney, //PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") +#endif + +#if USING_EUROPE + TZ_Europe_Amsterdam, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Andorra, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Astrakhan, //PSTR("<+04>-4") + TZ_Europe_Athens, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Belgrade, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Berlin, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Bratislava, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Brussels, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Bucharest, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Budapest, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Busingen, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Chisinau, //PSTR("EET-2EEST,M3.5.0,M10.5.0/3") + TZ_Europe_Copenhagen, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Dublin, //PSTR("IST-1GMT0,M10.5.0,M3.5.0/1") + TZ_Europe_Gibraltar, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Guernsey, //PSTR("GMT0BST,M3.5.0/1,M10.5.0") + TZ_Europe_Helsinki, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Isle_of_Man, //PSTR("GMT0BST,M3.5.0/1,M10.5.0") + TZ_Europe_Istanbul, //PSTR("<+03>-3") + TZ_Europe_Jersey, //PSTR("GMT0BST,M3.5.0/1,M10.5.0") + TZ_Europe_Kaliningrad, //PSTR("EET-2") + TZ_Europe_Kiev, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Kirov, //PSTR("<+03>-3") + TZ_Europe_Lisbon, //PSTR("WET0WEST,M3.5.0/1,M10.5.0") + TZ_Europe_Ljubljana, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_London, //PSTR("GMT0BST,M3.5.0/1,M10.5.0") + TZ_Europe_Luxembourg, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Madrid, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Malta, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Mariehamn, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Minsk, //PSTR("<+03>-3") + TZ_Europe_Monaco, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Moscow, //PSTR("MSK-3") + TZ_Europe_Oslo, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Paris, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Podgorica, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Prague, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Riga, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Rome, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Samara, //PSTR("<+04>-4") + TZ_Europe_San_Marino, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Sarajevo, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Saratov, //PSTR("<+04>-4") + TZ_Europe_Simferopol, //PSTR("MSK-3") + TZ_Europe_Skopje, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Sofia, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Stockholm, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Tallinn, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Tirane, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Ulyanovsk, //PSTR("<+04>-4") + TZ_Europe_Uzhgorod, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Vaduz, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Vatican, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Vienna, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Vilnius, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Volgograd, //PSTR("<+04>-4") + TZ_Europe_Warsaw, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Zagreb, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Europe_Zaporozhye, //PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") + TZ_Europe_Zurich, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") +#endif + +#if USING_INDIAN + TZ_Indian_Antananarivo, //PSTR("EAT-3") + TZ_Indian_Chagos, //PSTR("<+06>-6") + TZ_Indian_Christmas, //PSTR("<+07>-7") + TZ_Indian_Cocos, //PSTR("<+0630>-6:30") + TZ_Indian_Comoro, //PSTR("EAT-3") + TZ_Indian_Kerguelen, //PSTR("<+05>-5") + TZ_Indian_Mahe, //PSTR("<+04>-4") + TZ_Indian_Maldives, //PSTR("<+05>-5") + TZ_Indian_Mauritius, //PSTR("<+04>-4") + TZ_Indian_Mayotte, //PSTR("EAT-3") + TZ_Indian_Reunion, //PSTR("<+04>-4") +#endif + + +#if USING_PACIFIC + TZ_Pacific_Apia, //PSTR("<+13>-13<+14>,M9.5.0/3,M4.1.0/4") + TZ_Pacific_Auckland, //PSTR("NZST-12NZDT,M9.5.0,M4.1.0/3") + TZ_Pacific_Bougainville, //PSTR("<+11>-11") + TZ_Pacific_Chatham, //PSTR("<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45") + TZ_Pacific_Chuuk, //PSTR("<+10>-10") + TZ_Pacific_Easter, //PSTR("<-06>6<-05>,M9.1.6/22,M4.1.6/22") + TZ_Pacific_Efate, //PSTR("<+11>-11") + TZ_Pacific_Enderbury, //PSTR("<+13>-13") + TZ_Pacific_Fakaofo, //PSTR("<+13>-13") + TZ_Pacific_Fiji, //PSTR("<+12>-12<+13>,M11.2.0,M1.2.3/99") + TZ_Pacific_Funafuti, //PSTR("<+12>-12") + TZ_Pacific_Galapagos, //PSTR("<-06>6") + TZ_Pacific_Gambier, //PSTR("<-09>9") + TZ_Pacific_Guadalcanal, //PSTR("<+11>-11") + TZ_Pacific_Guam, //PSTR("ChST-10") + TZ_Pacific_Honolulu, //PSTR("HST10") + TZ_Pacific_Kiritimati, //PSTR("<+14>-14") + TZ_Pacific_Kosrae, //PSTR("<+11>-11") + TZ_Pacific_Kwajalein, //PSTR("<+12>-12") + TZ_Pacific_Majuro, //PSTR("<+12>-12") + TZ_Pacific_Marquesas, //PSTR("<-0930>9:30") + TZ_Pacific_Midway, //PSTR("SST11") + TZ_Pacific_Nauru, //PSTR("<+12>-12") + TZ_Pacific_Niue, //PSTR("<-11>11") + TZ_Pacific_Norfolk, //PSTR("<+11>-11<+12>,M10.1.0,M4.1.0/3") + TZ_Pacific_Noumea, //PSTR("<+11>-11") + TZ_Pacific_Pago_Pago, //PSTR("SST11") + TZ_Pacific_Palau, //PSTR("<+09>-9") + TZ_Pacific_Pitcairn, //PSTR("<-08>8") + TZ_Pacific_Pohnpei, //PSTR("<+11>-11") + TZ_Pacific_Port_Moresby, //PSTR("<+10>-10") + TZ_Pacific_Rarotonga, //PSTR("<-10>10") + TZ_Pacific_Saipan, //PSTR("ChST-10") + TZ_Pacific_Tahiti, //PSTR("<-10>10") + TZ_Pacific_Tarawa, //PSTR("<+12>-12") + TZ_Pacific_Tongatapu, //PSTR("<+13>-13") + TZ_Pacific_Wake, //PSTR("<+12>-12") + TZ_Pacific_Wallis, //PSTR("<+12>-12") +#endif + +#if USING_ETC_GMT + TZ_Etc_GMT, //PSTR("GMT0") + TZ_Etc_GMTm0, //PSTR("GMT0") + TZ_Etc_GMTm1, //PSTR("<+01>-1") + TZ_Etc_GMTm2, //PSTR("<+02>-2") + TZ_Etc_GMTm3, //PSTR("<+03>-3") + TZ_Etc_GMTm4, //PSTR("<+04>-4") + TZ_Etc_GMTm5, //PSTR("<+05>-5") + TZ_Etc_GMTm6, //PSTR("<+06>-6") + TZ_Etc_GMTm7, //PSTR("<+07>-7") + TZ_Etc_GMTm8, //PSTR("<+08>-8") + TZ_Etc_GMTm9, //PSTR("<+09>-9") + TZ_Etc_GMTm10, //PSTR("<+10>-10") + TZ_Etc_GMTm11, //PSTR("<+11>-11") + TZ_Etc_GMTm12, //PSTR("<+12>-12") + TZ_Etc_GMTm13, //PSTR("<+13>-13") + TZ_Etc_GMTm14, //PSTR("<+14>-14") + TZ_Etc_GMT0, //PSTR("GMT0") + TZ_Etc_GMTp0, //PSTR("GMT0") + TZ_Etc_GMTp1, //PSTR("<-01>1") + TZ_Etc_GMTp2, //PSTR("<-02>2") + TZ_Etc_GMTp3, //PSTR("<-03>3") + TZ_Etc_GMTp4, //PSTR("<-04>4") + TZ_Etc_GMTp5, //PSTR("<-05>5") + TZ_Etc_GMTp6, //PSTR("<-06>6") + TZ_Etc_GMTp7, //PSTR("<-07>7") + TZ_Etc_GMTp8, //PSTR("<-08>8") + TZ_Etc_GMTp9, //PSTR("<-09>9") + TZ_Etc_GMTp10, //PSTR("<-10>10") + TZ_Etc_GMTp11, //PSTR("<-11>11") + TZ_Etc_GMTp12, //PSTR("<-12>12") + TZ_Etc_UCT, //PSTR("UTC0") + TZ_Etc_UTC, //PSTR("UTC0") + TZ_Etc_Greenwich, //PSTR("GMT0") + TZ_Etc_Universal, //PSTR("UTC0") + TZ_Etc_Zulu, //PSTR("UTC0") +#endif +}; + + + +#else +const char TZ_NAME[][TIMEZONE_MAX_LEN] = +{ + "Pacific/Pago_Pago", + "America/Adak", + "Pacific/Honolulu", + "Pacific/Marquesas", + "Pacific/Gambier", + "America/Anchorage", + "America/Los_Angeles", + "Pacific/Pitcairn", + "America/Phoenix", + "America/Denver", + "America/Guatemala", + "America/Chicago", + "Pacific/Easter", + "America/Bogota", + "America/New_York", + "America/Caracas", + "America/Halifax", + "America/Santo_Domingo", + "America/Santiago", + "America/St_Johns", + "America/Godthab", + "America/Argentina/Buenos_Aires", + "America/Montevideo", + "Etc/GMT+2", + "Atlantic/Azores", + "Atlantic/Cape_Verde", + "Etc/UTC", + "Europe/London", + "Europe/Berlin", + "Africa/Lagos", + "Africa/Windhoek", + "Asia/Beirut", + "Africa/Johannesburg", + "Asia/Baghdad", + "Europe/Moscow", + "Asia/Tehran", + "Asia/Dubai", + "Asia/Baku", + "Asia/Kabul", + "Asia/Yekaterinburg", + "Asia/Karachi", + "Asia/Kolkata", + "Asia/Kathmandu", + "Asia/Dhaka", + "Asia/Omsk", + "Asia/Krasnoyarsk", + "Asia/Jakarta", + "Asia/Shanghai", + "Asia/Irkutsk", + "Australia/Eucla", + "Asia/Yakutsk", + "Asia/Tokyo", + "Australia/Darwin", + "Australia/Adelaide", + "Australia/Brisbane", + "Asia/Vladivostok", + "Australia/Sydney", + "Australia/Lord_Howe", + "Asia/Kamchatka", + "Pacific/Noumea", + "Pacific/Norfolk", + "Pacific/Auckland", + "Pacific/Tarawa", + "Pacific/Chatham", + "Pacific/Tongatapu", + "Pacific/Apia", + "Pacific/Kiritimati", +}; + +//////////////////////////////////////////////////////////// + +const char ESP_TZ_NAME[][TIMEZONE_MAX_LEN] = +{ + TZ_Pacific_Pago_Pago, //PSTR("SST11") + TZ_America_Adak, //PSTR("HST10HDT,M3.2.0,M11.1.0") + TZ_Pacific_Honolulu, //PSTR("HST10") + TZ_Pacific_Marquesas, //PSTR("<-0930>9:30") + TZ_Pacific_Gambier, //PSTR("<-09>9") + TZ_America_Anchorage, //PSTR("AKST9AKDT,M3.2.0,M11.1.0") + TZ_America_Los_Angeles, //"PST8PDT,M3.2.0,M11.1.0", //"America/Los_Angeles", + TZ_Pacific_Pitcairn, //PSTR("<-08>8") + TZ_America_Phoenix, //PSTR("MST7") + TZ_America_Denver, //"MST7MDT,M3.2.0,M11.1.0", //"America/Denver", + TZ_America_Guatemala, //PSTR("CST6") + TZ_America_Chicago, //"CST6CDT,M3.2.0,M11.1.0", //"America/Chicago", + TZ_Pacific_Easter, //PSTR("<-06>6<-05>,M9.1.6/22,M4.1.6/22") + TZ_America_Bogota, //PSTR("<-05>5") + TZ_America_New_York, //"EST5EDT,M3.2.0,M11.1.0", //"America/New_York", + TZ_America_Caracas, //PSTR("<-04>4") + TZ_America_Halifax, //"AST4ADT,M3.2.0,M11.1.0", //"America/Halifax", + TZ_America_Santo_Domingo, //PSTR("AST4") + TZ_America_Santiago, //"<-04>4<-03>,M9.1.6/24,M4.1.6/24", //"America/Santiago", + TZ_America_St_Johns, //PSTR("NST3:30NDT,M3.2.0,M11.1.0") + TZ_America_Godthab, //"<-03>3<-02>,M3.5.0/-2,M10.5.0/-1", //"America/Godthab", + TZ_America_Argentina_Buenos_Aires, //PSTR("<-03>3") + TZ_America_Montevideo, //"<-03>3", //"America/Montevideo", + TZ_Etc_GMTp2, //PSTR("<-02>2") + TZ_Atlantic_Azores, //PSTR("<-01>1<+00>,M3.5.0/0,M10.5.0/1") + TZ_Atlantic_Cape_Verde, //PSTR("<-01>1") + TZ_Etc_UTC, //PSTR("UTC0") + TZ_Europe_London, //PSTR("GMT0BST,M3.5.0/1,M10.5.0") + TZ_Europe_Berlin, //PSTR("CET-1CEST,M3.5.0,M10.5.0/3") + TZ_Africa_Lagos, //PSTR("WAT-1") + TZ_Africa_Windhoek, //PSTR("CAT-2") + TZ_Asia_Beirut, //"EET-2EEST,M3.5.0/0,M10.5.0/0" //"Asia/Beirut", + TZ_Africa_Johannesburg, //"SAST-2", //"Africa/Johannesburg", + TZ_Asia_Baghdad, //"<+03>-3", //"Asia/Baghdad", + TZ_Europe_Moscow, //PSTR("MSK-3") + TZ_Asia_Tehran, //PSTR("<+0330>-3:30<+0430>,J79/24,J263/24") + TZ_Asia_Dubai, //"<+04>-4", //"Asia/Dubai", + TZ_Asia_Baku, //PSTR("<+04>-4") + TZ_Asia_Kabul, //PSTR("<+0430>-4:30") + TZ_Asia_Yekaterinburg, //PSTR("<+05>-5") + TZ_Asia_Karachi, //PSTR("PKT-5") + TZ_Asia_Kolkata, //PSTR("IST-5:30") + TZ_Asia_Kathmandu, //PSTR("<+0545>-5:45") + TZ_Asia_Dhaka, //"<+06>-6", //"Asia/Dhaka", + TZ_Asia_Omsk, //PSTR("<+06>-6") + TZ_Asia_Krasnoyarsk, //PSTR("<+07>-7") + TZ_Asia_Jakarta, //"WIB-7", //"Asia/Jakarta", + TZ_Asia_Shanghai, //"CST-8", //"Asia/Shanghai", + TZ_Asia_Irkutsk, //PSTR("<+08>-8") + TZ_Australia_Eucla, //PSTR("<+0845>-8:45") + TZ_Asia_Yakutsk, //PSTR("<+09>-9") + TZ_Asia_Tokyo, //"JST-9", //"Asia/Tokyo", + TZ_Australia_Darwin, //PSTR("ACST-9:30") + TZ_Australia_Adelaide, //PSTR("ACST-9:30ACDT,M10.1.0,M4.1.0/3") + TZ_Australia_Brisbane, //"AEST-10", //"Australia/Brisbane", + TZ_Asia_Vladivostok, //PSTR("<+10>-10") + TZ_Australia_Sydney, //PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") + TZ_Australia_Lord_Howe, //PSTR("<+1030>-10:30<+11>-11,M10.1.0,M4.1.0") + TZ_Asia_Kamchatka, //PSTR("<+12>-12") + TZ_Pacific_Noumea, //"<+11>-11", //"Pacific/Noumea", + TZ_Pacific_Norfolk, //PSTR("<+11>-11<+12>,M10.1.0,M4.1.0/3") + TZ_Pacific_Auckland, //"NZST-12NZDT,M9.5.0,M4.1.0/3", //"Pacific/Auckland", + TZ_Pacific_Tarawa, //"<+12>-12", //"Pacific/Tarawa", + TZ_Pacific_Chatham, //PSTR("<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45") + TZ_Pacific_Tongatapu, //PSTR("<+13>-13") + TZ_Pacific_Apia, //PSTR("<+13>-13<+14>,M9.5.0/3,M4.1.0/4") + TZ_Pacific_Kiritimati, //PSTR("<+14>-14") +}; +#endif + +#endif // TZDB_H diff --git a/platformio.ini b/platformio.ini index 3f4a18d..763c81f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,13 +15,12 @@ include_dir = lib [common_env_data] upload_speed = 921600 monitor_speed = 115200 -#platform = espressif8266 @ 2.6.3 platform = espressif8266 @ 3.2.0 framework = arduino board = d1_mini build_unflags = -#src_build_flags = -Wunused-variable -Wregister -Wchar-subscripts build_flags = + -Wl,-Map,output.map -D BAUD=${common_env_data.monitor_speed} -D ACTIVATE_OTA #-D USE_GYRO_TEMP # If this is enabled the DS18 will not be used, temp is read from the gyro. @@ -45,11 +44,11 @@ build_flags = -D CFG_APPVER="\"0.5.0\"" lib_deps = # Switched to forks for better version control. # Using local copy of this library - #https://github.com/mp-se/i2cdevlib # https://github.com/jrowberg/i2cdevlib.git + #https://github.com/jrowberg/i2cdevlib.git# + #https://github.com/khoih-prog/ESP_WiFiManager# + #https://github.com/khoih-prog/ESP_DoubleResetDetector# https://github.com/mp-se/tinyexpr # https://github.com/codeplea/tinyexpr https://github.com/mp-se/incbin # https://github.com/graphitemaster/incbin - https://github.com/mp-se/ESP_DoubleResetDetector#v1.2.1 # https://github.com/khoih-prog/ESP_DoubleResetDetector - https://github.com/mp-se/WiFiManager#2.0.5-beta # https://github.com/tzapu/WiFiManager https://github.com/mp-se/Arduino-Log#1.1.1 # https://github.com/thijse/Arduino-Log https://github.com/mp-se/ArduinoJson#v6.18.5 # https://github.com/bblanchon/ArduinoJson https://github.com/mp-se/OneWire#v2.3.6 # https://github.com/PaulStoffregen/OneWire @@ -68,7 +67,7 @@ extra_scripts = build_unflags = ${common_env_data.build_unflags} build_flags = - #-D PIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS + -D PIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS #-D SKIP_SLEEPMODE ${common_env_data.build_flags} -D COLLECT_PERFDATA # This option will collect runtime data for a few defined methods to measure time, dumped to serial and/or influxdb diff --git a/src/main.cpp b/src/main.cpp index 5d29c01..5c76816 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,13 +32,6 @@ SOFTWARE. #include #include -// Settings for double reset detector. -#define ESP_DRD_USE_LITTLEFS true -#define DRD_TIMEOUT 2 -#define DRD_ADDRESS 0 -#include -extern DoubleResetDetector *drd; // Declared in WifiManager_Lite - // Define constats for this program #ifdef DEACTIVATE_SLEEPMODE const int interval = 1000; // ms, time to wait between changes to output @@ -105,8 +98,6 @@ void setup() { LOG_PERF_START("main-setup"); runtimeMillis = millis(); - drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS); - bool dt = drd->detectDoubleReset(); #if LOG_LEVEL == 6 && !defined(MAIN_DISABLE_LOGGING) delay(3000); // Wait a few seconds when using debug version so that serial is // started. @@ -126,18 +117,15 @@ void setup() { ESP.wdtDisable(); ESP.wdtEnable(5000); // 5 seconds - if (dt) { - Log.notice(F("Main: Detected doubletap on reset. Reset reason=%s" CR), - ESP.getResetReason().c_str()); + // No stored config, move to portal + if( !myWifi.hasConfig() ) { + Log.notice(F("Main: No wifi configuration detected, entering wifi setup." CR)); + runMode = RunMode::wifiSetupMode; } -#ifdef SKIP_SLEEPMODE - // If we are running in debug more we skip this part. makes is hard to debug - // in case of crash/watchdog reset - dt = false; -#endif - - if( !myWifi.hasConfig() ) { + // Double reset, go to portal. + if( myWifi.isDoubleResetDetected() ) { + Log.notice(F("Main: Double reset detected, entering wifi setup." CR)); runMode = RunMode::wifiSetupMode; } @@ -145,7 +133,6 @@ void setup() { switch (runMode) { case RunMode::wifiSetupMode: myWifi.startPortal(); - Log.notice(F("Main: No wifi configuration detected, running in wifiSetupMode." CR)); break; default: @@ -274,7 +261,6 @@ void goToSleep(int sleepInterval) { sleepInterval, (millis() - runtimeMillis) / 1000, volt); LittleFS.end(); myGyro.enterSleep(); - drd->stop(); LOG_PERF_STOP("run-time"); LOG_PERF_PUSH(); delay(100); @@ -285,11 +271,12 @@ void goToSleep(int sleepInterval) { // Main loops // void loop() { - drd->loop(); +// myDRD->loop(); switch (runMode) { case RunMode::configurationMode: myWebServer.loop(); + myWifi.loop(); loopGravityOnInterval(); break; @@ -298,26 +285,31 @@ void loop() { // conserve battery. if (!myWifi.isConnected()) { // no connection to wifi Log.notice(F("MAIN: No connection to wifi established, sleeping for 60s." CR)); + myWifi.stopDoubleReset(); goToSleep(60); } - if( loopReadGravity() ) + if( loopReadGravity() ) { + myWifi.stopDoubleReset(); goToSleep(myConfig.getSleepInterval()); + } // If the sensor is moving and we are not getting a clear reading, we enter // sleep for a short time to conserve battery. if (((millis() - stableGyroMillis) > 10000L)) { // 10s since last stable gyro reading Log.notice(F("MAIN: Unable to get a stable reading for 10s, sleeping for 60s." CR)); + myWifi.stopDoubleReset(); goToSleep(60); } LOG_PERF_START("loop-gyro-read"); myGyro.read(); LOG_PERF_STOP("loop-gyro-read"); + myWifi.loop(); break; case RunMode::wifiSetupMode: - myWifi.portalLoop(); + myWifi.loop(); break; } } diff --git a/src/wifi.cpp b/src/wifi.cpp index ae4dfd3..ae2345d 100644 --- a/src/wifi.cpp +++ b/src/wifi.cpp @@ -21,12 +21,12 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include +#include +#include #include #include -#include +//#include #include -#include #include #include @@ -34,91 +34,153 @@ SOFTWARE. #include #include #include -#include -Wifi myWifi; +/* +// Configuration settings for WifiManager_Lite +#define ESP_WM_LITE_DEBUG_OUTPUT Serial +#define _ESP_WM_LITE_LOGLEVEL_ 3 +#define MULTIRESETDETECTOR_DEBUG true +#define USE_DYNAMIC_PARAMETERS false +#define CONFIG_TIMEOUT 120*1000 +#define USING_MRD false // We use DRD instead +#define REQUIRE_ONE_SET_SSID_PW true +#include +bool LOAD_DEFAULT_CONFIG_DATA = false; +ESP_WiFiManager_Lite* wifiManager = 0; +ESP_WM_LITE_Configuration defaultConfig; +*/ +// Settings for DRD +#define ESP_DRD_USE_LITTLEFS true +#define ESP_DRD_USE_SPIFFS false +#define ESP_DRD_USE_EEPROM false +#define DOUBLERESETDETECTOR_DEBUG true +#include +#define DRD_TIMEOUT 3 +#define DRD_ADDRESS 0 + +// Settings for WIFI Manager +/*#define USING_AFRICA false +#define USING_AMERICA true +#define USING_ANTARCTICA false +#define USING_ASIA false +#define USING_ATLANTIC false +#define USING_AUSTRALIA false +#define USING_EUROPE true +#define USING_INDIAN false +#define USING_PACIFIC false +#define USING_ETC_GMT false +#define USE_CLOUDFLARE_NTP false +#define CONFIG_FILENAME F("/wifi_cred.dat")*/ +#define USE_ESP_WIFIMANAGER_NTP false +#define USE_CLOUDFLARE_NTP false +#define USING_CORS_FEATURE false +#define NUM_WIFI_CREDENTIALS 1 +#define USE_STATIC_IP_CONFIG_IN_CP false +#include +const char WM_HTTP_FORM_START[] PROGMEM = "
"; +#include +ESP_WiFiManager* myWifiManager; +DoubleResetDetector* myDRD; + +WifiConnection myWifi; const char *userSSID = USER_SSID; -const char *userPWD = USER_SSID_PWD; +const char *userPWD = USER_SSID_PWD; + +const int PIN_LED = 2; + +// +// Constructor +// +WifiConnection::WifiConnection() { + myDRD = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS); +} // // Check if we have a valid wifi configuration // -bool Wifi::hasConfig() { +bool WifiConnection::hasConfig() { if (strlen(myConfig.getWifiSSID()) ) return true; if (strlen(userSSID) ) return true; - return false; } +// +// Check if the wifi is connected +// +bool WifiConnection::isConnected() { + return WiFi.status() == WL_CONNECTED; +} + +// +// Get the IP adress +// +String WifiConnection::getIPAddress() { + return WiFi.localIP().toString(); +} + +// +// Additional method to detect double reset. +// +bool WifiConnection::isDoubleResetDetected() { + if (myDRD->detectDoubleReset()) { + Log.notice(F("WIFI: Double reset has been detected." CR)); + return true; + } + return false; +} + +// +// Stop double reset detection +// +void WifiConnection::stopDoubleReset() { + myDRD->stop(); +} + // // Start the wifi manager // -bool Wifi::startPortal() { +void WifiConnection::startPortal() { Log.notice(F("WIFI: Starting Wifi config portal." CR)); - return true; + + pinMode(PIN_LED, OUTPUT); + digitalWrite(PIN_LED, LOW); + + myWifiManager = new ESP_WiFiManager(WIFI_MDNS); + myWifiManager->setMinimumSignalQuality(-1); + myWifiManager->setConfigPortalChannel(0); + myWifiManager->setConfigPortalTimeout(120); + + if (myWifiManager->startConfigPortal(WIFI_DEFAULT_SSID, WIFI_DEFAULT_PWD)) { + Log.notice(F("WIFI: Exited portal, connected to wifi." CR)); + myConfig.setWifiSSID(myWifiManager->getSSID()); + myConfig.setWifiPass(myWifiManager->getPW()); + myConfig.saveFile(); + } + else { + Log.notice(F("WIFI: Exited portal, no connection to wifi." CR)); Serial.println(F("Not connected to WiFi")); + } + + stopDoubleReset(); + delay(500); + ESP.reset(); } // // Call the wifi manager in loop // -void Wifi::portalLoop() { +void WifiConnection::loop() { + myDRD->loop(); } // // Connect to last known access point or create one if connection is not // working. // -// REMOVE bool Wifi::connect(bool showPortal) { -bool Wifi::connect() { - WiFi.persistent(true); - WiFi.mode(WIFI_STA); - -/* REMOVE - if (!strlen(myConfig.getWifiSSID())) { - Log.info( - F("WIFI: No SSID seams to be stored, forcing portal to start." CR)); - showPortal = true; - } else { - // Log.info(F("WIFI: Using SSID=%s and %s." CR), myConfig.getWifiSSID(), - // myConfig.getWifiPass()); Log.info(F("WIFI: Using SSID=%s and %s." CR), - // myConfig.getWifiSSID(), "*****"); - } - - if (strlen(userSSID) == 0 && showPortal) { -#if LOG_LEVEL == 6 - Log.verbose( - F("WIFI: Connecting to WIFI via connection manager (portal=%s)." CR), - showPortal ? "true" : "false"); -#endif - WiFiManager myWifiManager; - Log.notice(F("WIFI: Starting wifi portal." CR)); - myWifiManager.setDebugOutput(true); - myWifiManager.setClass("invert"); - myWifiManager.setConfigPortalTimeout(120); // Keep it open for 120 seconds - bool f = - myWifiManager.startConfigPortal(WIFI_DEFAULT_SSID, WIFI_DEFAULT_PWD); - if (f) { - // Log.notice(F("WIFI: Success got values from WIFI portal=%s,%s." CR), - // myWifiManager.getWiFiSSID(), myWifiManager.getWiFiPass() ); - Log.notice(F("WIFI: Success got values from WIFI portal=%s,%s." CR), - myWifiManager.getWiFiSSID(), "*****"); - myConfig.setWifiSSID(myWifiManager.getWiFiSSID()); - myConfig.setWifiPass(myWifiManager.getWiFiPass()); - myConfig.saveFile(); - } else { - Log.notice(F("WIFI: Failure from WIFI portal, rebooting." CR)); - delay(200); - ESP.reset(); - } - } -*/ - +bool WifiConnection::connect() { // Connect to wifi int i = 0; - // Log.notice(F("WIFI: Connecting to WIFI, mode=%d,persistent=%d,fhy=%d ." - // CR), WiFi.getMode(), WiFi.getPersistent(), WiFi.getPhyMode() ); WiFi.mode(WIFI_STA); if (strlen(userSSID)) { Log.notice(F("WIFI: Connecting to wifi using hardcoded settings %s." CR), @@ -140,21 +202,22 @@ bool Wifi::connect() { Log.error(F("WIFI: Failed to connect to wifi %d, aborting %s." CR), WiFi.status(), getIPAddress().c_str()); WiFi.disconnect(); - return connectedFlag; // Return to main that we have failed to connect. + Serial.print(CR); + return false; // Return to main that we have failed to connect. } } + Serial.print(CR); - connectedFlag = true; Log.notice(F("WIFI: Connected to wifi ip=%s." CR), getIPAddress().c_str()); Log.notice(F("WIFI: Using mDNS name %s." CR), myConfig.getMDNS()); - return connectedFlag; + return true; } // // This will erase the stored credentials and forcing the WIFI manager to AP // mode. // -bool Wifi::disconnect() { +bool WifiConnection::disconnect() { Log.notice(F("WIFI: Erasing stored WIFI credentials." CR)); // Erase WIFI credentials return WiFi.disconnect(true); @@ -165,7 +228,7 @@ bool Wifi::disconnect() { // // // -bool Wifi::updateFirmware() { +bool WifiConnection::updateFirmware() { if (!newFirmware) { Log.notice(F("WIFI: No newer version exist, skipping update." CR)); return false; @@ -200,7 +263,7 @@ bool Wifi::updateFirmware() { // // Download and save file // -void Wifi::downloadFile(const char *fname) { +void WifiConnection::downloadFile(const char *fname) { #if LOG_LEVEL == 6 Log.verbose(F("WIFI: Download file %s." CR), fname); #endif @@ -228,7 +291,7 @@ void Wifi::downloadFile(const char *fname) { // // Check what firmware version is available over OTA // -bool Wifi::checkFirmwareVersion() { +bool WifiConnection::checkFirmwareVersion() { #if LOG_LEVEL == 6 Log.verbose(F("WIFI: Checking if new version exist." CR)); #endif @@ -309,7 +372,7 @@ bool Wifi::checkFirmwareVersion() { // // Parse a version string in the format M.m.p (eg. 1.2.10) // -bool Wifi::parseFirmwareVersionString(int (&num)[3], const char *version) { +bool WifiConnection::parseFirmwareVersionString(int (&num)[3], const char *version) { #if LOG_LEVEL == 6 Log.verbose(F("WIFI: Parsing version number string %s." CR), version); #endif diff --git a/src/wifi.hpp b/src/wifi.hpp index ff09737..0334b6d 100644 --- a/src/wifi.hpp +++ b/src/wifi.hpp @@ -25,13 +25,13 @@ SOFTWARE. #define SRC_WIFI_HPP_ // Include -#include +//#include +#include // classes -class Wifi { +class WifiConnection { private: // WIFI - bool connectedFlag = false; // OTA bool newFirmware = false; @@ -40,13 +40,16 @@ class Wifi { public: // WIFI - bool connect(); - bool disconnect(); - bool isConnected() { return connectedFlag; } - bool hasConfig(); - String getIPAddress() { return WiFi.localIP().toString(); } - bool startPortal(); - void portalLoop(); + WifiConnection(); + bool connect(); + bool disconnect(); + bool isConnected(); + bool isDoubleResetDetected(); + void stopDoubleReset(); + bool hasConfig(); + String getIPAddress(); + void startPortal(); + void loop(); // OTA bool updateFirmware(); @@ -54,7 +57,7 @@ class Wifi { }; // Global instance created -extern Wifi myWifi; +extern WifiConnection myWifi; #endif // SRC_WIFI_HPP_