From a5f975bbe4fe22135d58a29b25b2838564e691c0 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 14 Aug 2022 03:00:04 +0200 Subject: [PATCH] * moved wifi related stuff to extra class --- .gitignore | 1 + tools/esp8266/app.cpp | 317 ++++++----------------------------------- tools/esp8266/app.h | 95 ++++-------- tools/esp8266/config.h | 4 +- tools/esp8266/web.cpp | 2 +- tools/esp8266/wifi.cpp | 248 ++++++++++++++++++++++++++++++++ tools/esp8266/wifi.h | 55 +++++++ 7 files changed, 382 insertions(+), 340 deletions(-) create mode 100644 tools/esp8266/wifi.cpp create mode 100644 tools/esp8266/wifi.h diff --git a/.gitignore b/.gitignore index 89b7ea7f..da27a66d 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ tools/esp8266/binaries *.ipch tools/esp8266/.vscode/extensions.json .DS_Store +.vscode diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index a612e757..f580407b 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -4,18 +4,17 @@ //----------------------------------------------------------------------------- #include "app.h" - #include //----------------------------------------------------------------------------- app::app() { DPRINTLN(DBG_VERBOSE, F("app::app")); - mDns = new DNSServer(); - mUdp = new WiFiUDP(); mEep = new eep(); Serial.begin(115200); + mWifi = new wifi(this, &mSysConfig, &mConfig); + mWebInst = new web(this, &mSysConfig, &mConfig, mVersion); mWebInst->setup(); @@ -29,71 +28,24 @@ app::app() { //----------------------------------------------------------------------------- void app::setup(uint32_t timeout) { DPRINTLN(DBG_VERBOSE, F("app::setup")); - mWifiStationTimeout = timeout; mWifiSettingsValid = checkEEpCrc(ADDR_START, ADDR_WIFI_CRC, ADDR_WIFI_CRC); mSettingsValid = checkEEpCrc(ADDR_START_SETTINGS, ((ADDR_NEXT)-(ADDR_START_SETTINGS)), ADDR_SETTINGS_CRC); loadEEpconfig(); -#ifndef AP_ONLY - if(false == apActive) - apActive = setupStation(mWifiStationTimeout); - setupMqtt(); -#endif + mWifi->setup(timeout, mWifiSettingsValid); + #ifndef AP_ONLY + setupMqtt(); + #endif mSys->setup(&mConfig); - - if(!mWifiSettingsValid) { - DPRINTLN(DBG_WARN, F("your settings are not valid! check [IP]/setup")); - apActive = true; - mApLastTick = millis(); - mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); - setupAp(WIFI_AP_SSID, WIFI_AP_PWD); - } - else { - DPRINTLN(DBG_INFO, F("\n\n----------------------------------------")); - DPRINTLN(DBG_INFO, F("Welcome to AHOY!")); - DPRINT(DBG_INFO, F("\npoint your browser to http://")); - if(apActive) - DBGPRINTLN(F("192.168.1.1")); - else - DBGPRINTLN(WiFi.localIP()); - DPRINTLN(DBG_INFO, F("to configure your device")); - DPRINTLN(DBG_INFO, F("----------------------------------------\n")); - } } - //----------------------------------------------------------------------------- -void app::MainLoop(void) { - //DPRINTLN(DBG_VERBOSE, F("M")); - if(apActive) { - mDns->processNextRequest(); -#ifndef AP_ONLY - if(checkTicker(&mNextTryTs, (WIFI_AP_ACTIVE_TIME * 1000))) { - apActive = setupStation(mWifiStationTimeout); - if(apActive) { - if(strlen(WIFI_AP_PWD) < 8) - DPRINTLN(DBG_ERROR, F("password must be at least 8 characters long")); - mApLastTick = millis(); - mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); - setupAp(WIFI_AP_SSID, WIFI_AP_PWD); - } - } - else { - if(millis() - mApLastTick > 10000) { - uint8_t cnt = WiFi.softAPgetStationNum(); - if(cnt > 0) { - DPRINTLN(DBG_INFO, String(cnt) + F(" client connected, resetting AP timeout")); - mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); - } - mApLastTick = millis(); - DPRINTLN(DBG_INFO, F("AP will be closed in ") + String((mNextTryTs - mApLastTick) / 1000) + F(" seconds")); - } - } -#endif - } +void app::loop(void) { + DPRINTLN(DBG_VERBOSE, F("app::loop")); + bool apActive = mWifi->loop(); mWebInst->loop(); if(checkTicker(&mUptimeTicker, mUptimeInterval)) { @@ -102,32 +54,18 @@ void app::MainLoop(void) { mTimestamp++; else { if(!apActive) { - mTimestamp = getNtpTime(); + mTimestamp = mWifi->getNtpTime(); DPRINTLN(DBG_INFO, "[NTP]: " + getDateTimeStr(mTimestamp)); } } } - if((WiFi.status() != WL_CONNECTED) && wifiWasEstablished) { - if(!apActive) { - DPRINTLN(DBG_INFO, "[WiFi]: Connection Lost"); - setupStation(mWifiStationTimeout); - } - } -} -//----------------------------------------------------------------------------- -void app::loop(void) { - DPRINTLN(DBG_VERBOSE, F("app::loop")); - MainLoop(); mSys->Radio.loop(); yield(); if(checkTicker(&mRxTicker, 5)) { - //DPRINTLN(DBG_VERBOSE, F("app_loops =") + String(app_loops)); - app_loops=0; - bool rxRdy = mSys->Radio.switchRxCh(); if(!mSys->BufCtrl.empty()) { @@ -552,24 +490,6 @@ void app::cbMqtt(char* topic, byte* payload, unsigned int length) { } -//----------------------------------------------------------------------------- -/*void app::webapi(void) { // ToDo - DPRINTLN(DBG_VERBOSE, F("app::api")); - const size_t capacity = 200; // Use arduinojson.org/assistant to compute the capacity. - DynamicJsonDocument payload(capacity); - - // Parse JSON object - deserializeJson(payload, mWeb->arg("plain")); - // ToDo: error handling for payload - if (payload["tx_request"] == TX_REQ_INFO){ - mSys->InfoCmd = payload["cmd"]; - DPRINTLN(DBG_INFO, F("Will make tx-request 0x15 with subcmd ") + String(mSys->InfoCmd)); - } - mWeb->send ( 200, "text/json", "{success:true}" ); -}*/ - - - //----------------------------------------------------------------------------- String app::getStatistics(void) { String content = F("Receive success: ") + String(mRxSuccess) + "\n"; @@ -722,6 +642,12 @@ String app::getJson(void) { } +//----------------------------------------------------------------------------- +bool app::getWifiApActive(void) { + return mWifi->getApActive(); +} + + //----------------------------------------------------------------------------- void app::sendMqttDiscoveryConfig(void) { DPRINTLN(DBG_VERBOSE, F("app::sendMqttDiscoveryConfig")); @@ -799,83 +725,8 @@ const char* app::getFieldStateClass(uint8_t fieldId) { } -//----------------------------------------------------------------------------- -void app::setupAp(const char *ssid, const char *pwd) { - DPRINTLN(DBG_VERBOSE, F("app::setupAp")); - IPAddress apIp(192, 168, 1, 1); - - DPRINTLN(DBG_INFO, F("\n---------\nAP MODE\nSSID: ") - + String(ssid) + F("\nPWD: ") - + String(pwd) + F("\nActive for: ") - + String(WIFI_AP_ACTIVE_TIME) + F(" seconds") - + F("\n---------\n")); - DPRINTLN(DBG_DEBUG, String(mNextTryTs)); - - WiFi.mode(WIFI_AP); - WiFi.softAPConfig(apIp, apIp, IPAddress(255, 255, 255, 0)); - WiFi.softAP(ssid, pwd); - - mDns->start(53, "*", apIp); -} - - -//----------------------------------------------------------------------------- -bool app::setupStation(uint32_t timeout) { - DPRINTLN(DBG_VERBOSE, F("app::setupStation")); - int32_t cnt; - bool startAp = false; - - if(timeout >= 3) - cnt = (timeout - 3) / 2 * 10; - else { - timeout = 1; - cnt = 1; - } - - WiFi.mode(WIFI_STA); - WiFi.begin(mSysConfig.stationSsid, mSysConfig.stationPwd); - if(String(mSysConfig.deviceName) != "") - WiFi.hostname(mSysConfig.deviceName); - - delay(2000); - DPRINTLN(DBG_INFO, F("connect to network '") + String(mSysConfig.stationSsid) + F("' ...")); - while (WiFi.status() != WL_CONNECTED) { - delay(100); - if(cnt % 40 == 0) - Serial.println("."); - else - Serial.print("."); - - if(timeout > 0) { // limit == 0 -> no limit - if(--cnt <= 0) { - if(WiFi.status() != WL_CONNECTED) { - startAp = true; - WiFi.disconnect(); - } - delay(100); - break; - } - } - } - Serial.println("."); - - if(false == startAp) { - wifiWasEstablished = true; - } - - delay(1000); - - return startAp; -} - - //----------------------------------------------------------------------------- void app::resetSystem(void) { - mWifiStationTimeout = 10; - wifiWasEstablished = false; - mNextTryTs = 0; - mApLastTick = 0; - mUptimeSecs = 0; mUptimeTicker = 0xffffffff; mUptimeInterval = 1000; @@ -921,7 +772,7 @@ void app::loadDefaultConfig(void) { // wifi snprintf(mSysConfig.stationSsid, SSID_LEN, "%s", FB_WIFI_SSID); snprintf(mSysConfig.stationPwd, PWD_LEN, "%s", FB_WIFI_PWD); - apActive = false; + // nrf24 mConfig.sendInterval = SEND_INTERVAL; @@ -932,8 +783,8 @@ void app::loadDefaultConfig(void) { mConfig.amplifierPower = DEF_AMPLIFIERPOWER & 0x03; // ntp - snprintf(mConfig.ntpAddr, NTP_ADDR_LEN, "%s", NTP_SERVER_NAME); - mConfig.ntpPort = NTP_LOCAL_PORT; + snprintf(mConfig.ntpAddr, NTP_ADDR_LEN, "%s", DEF_NTP_SERVER_NAME); + mConfig.ntpPort = DEF_NTP_PORT; // mqtt snprintf(mConfig.mqtt.broker, MQTT_ADDR_LEN, "%s", DEF_MQTT_BROKER); @@ -993,6 +844,32 @@ void app::loadEEpconfig(void) { } +//----------------------------------------------------------------------------- +void app::saveValues(void) { + DPRINTLN(DBG_VERBOSE, F("app::saveValues")); + + mEep->write(ADDR_CFG_SYS, (uint8_t*)&mSysConfig, CFG_SYS_LEN); + mEep->write(ADDR_CFG, (uint8_t*)&mConfig, CFG_LEN); + Inverter<> *iv; + for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { + iv = mSys->getInverterByPos(i); + if(NULL != iv) { + mEep->write(ADDR_INV_ADDR + (i * 8), iv->serial.u64); + mEep->write(ADDR_INV_PWR_LIM + i * 2, iv->powerLimit[0]); + mEep->write(ADDR_INV_NAME + (i * MAX_NAME_LENGTH), iv->name, MAX_NAME_LENGTH); + // max channel power / name + for(uint8_t j = 0; j < 4; j++) { + mEep->write(ADDR_INV_CH_PWR + (i * 2 * 4) + (j*2), iv->chMaxPwr[j]); + mEep->write(ADDR_INV_CH_NAME + (i * 4 * MAX_NAME_LENGTH) + j * MAX_NAME_LENGTH, iv->chName[j], MAX_NAME_LENGTH); + } + } + } + + updateCrc(); + mEep->commit(); +} + + //----------------------------------------------------------------------------- void app::setupMqtt(void) { if(mSettingsValid) { @@ -1030,107 +907,3 @@ void app::setupMqtt(void) { } } } - - -//----------------------------------------------------------------------------- -void app::saveValues(void) { - DPRINTLN(DBG_VERBOSE, F("app::saveValues")); - - mEep->write(ADDR_CFG_SYS, (uint8_t*)&mSysConfig, CFG_SYS_LEN); - mEep->write(ADDR_CFG, (uint8_t*)&mConfig, CFG_LEN); - Inverter<> *iv; - for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { - iv = mSys->getInverterByPos(i); - if(NULL != iv) { - mEep->write(ADDR_INV_ADDR + (i * 8), iv->serial.u64); - mEep->write(ADDR_INV_PWR_LIM + i * 2, iv->powerLimit[0]); - mEep->write(ADDR_INV_NAME + (i * MAX_NAME_LENGTH), iv->name, MAX_NAME_LENGTH); - // max channel power / name - for(uint8_t j = 0; j < 4; j++) { - mEep->write(ADDR_INV_CH_PWR + (i * 2 * 4) + (j*2), iv->chMaxPwr[j]); - mEep->write(ADDR_INV_CH_NAME + (i * 4 * MAX_NAME_LENGTH) + j * MAX_NAME_LENGTH, iv->chName[j], MAX_NAME_LENGTH); - } - } - } - - updateCrc(); - mEep->commit(); -} - - -//----------------------------------------------------------------------------- -time_t app::getNtpTime(void) { - //DPRINTLN(DBG_VERBOSE, F("app::getNtpTime")); - time_t date = 0; - IPAddress timeServer; - uint8_t buf[NTP_PACKET_SIZE]; - uint8_t retry = 0; - - WiFi.hostByName(NTP_SERVER_NAME, timeServer); - mUdp->begin(NTP_LOCAL_PORT); - - - sendNTPpacket(timeServer); - - while(retry++ < 5) { - int wait = 150; - while(--wait) { - if(NTP_PACKET_SIZE <= mUdp->parsePacket()) { - uint64_t secsSince1900; - mUdp->read(buf, NTP_PACKET_SIZE); - secsSince1900 = (buf[40] << 24); - secsSince1900 |= (buf[41] << 16); - secsSince1900 |= (buf[42] << 8); - secsSince1900 |= (buf[43] ); - - date = secsSince1900 - 2208988800UL; // UTC time - date += (TIMEZONE + offsetDayLightSaving(date)) * 3600; - break; - } - else - delay(10); - } - } - - return date; -} - - -//----------------------------------------------------------------------------- -void app::sendNTPpacket(IPAddress& address) { - //DPRINTLN(DBG_VERBOSE, F("app::sendNTPpacket")); - uint8_t buf[NTP_PACKET_SIZE] = {0}; - - buf[0] = B11100011; // LI, Version, Mode - buf[1] = 0; // Stratum - buf[2] = 6; // Max Interval between messages in seconds - buf[3] = 0xEC; // Clock Precision - // bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset - buf[12] = 49; // four-byte reference ID identifying - buf[13] = 0x4E; - buf[14] = 49; - buf[15] = 52; - - mUdp->beginPacket(address, 123); // NTP request, port 123 - mUdp->write(buf, NTP_PACKET_SIZE); - mUdp->endPacket(); -} - - -//----------------------------------------------------------------------------- -// calculates the daylight saving time for middle Europe. Input: Unixtime in UTC -// from: https://forum.arduino.cc/index.php?topic=172044.msg1278536#msg1278536 -time_t app::offsetDayLightSaving (uint32_t local_t) { - //DPRINTLN(DBG_VERBOSE, F("app::offsetDayLightSaving")); - int m = month (local_t); - if(m < 3 || m > 10) return 0; // no DSL in Jan, Feb, Nov, Dez - if(m > 3 && m < 10) return 1; // DSL in Apr, May, Jun, Jul, Aug, Sep - int y = year (local_t); - int h = hour (local_t); - int hToday = (h + 24 * day(local_t)); - if((m == 3 && hToday >= (1 + TIMEZONE + 24 * (31 - (5 * y /4 + 4) % 7))) - || (m == 10 && hToday < (1 + TIMEZONE + 24 * (31 - (5 * y /4 + 1) % 7))) ) - return 1; - else - return 0; -} diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index e003adec..ef1737e3 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -9,13 +9,6 @@ #include "dbg.h" #include "Arduino.h" -#include -#include - -// NTP -#include -#include -#include #include #include @@ -28,6 +21,7 @@ #include "CircularBuffer.h" #include "hmSystem.h" #include "mqtt.h" +#include "wifi.h" #include "web.h" // hier läst sich das Verhalten der app in Bezug auf MQTT @@ -61,12 +55,8 @@ typedef struct { bool requested; } invPayload_t; -const byte mDnsPort = 53; - -/* NTP TIMESERVER CONFIG */ -#define NTP_PACKET_SIZE 48 -#define TIMEZONE 1 // Central European time +1 +class wifi; class web; class app { @@ -82,6 +72,7 @@ class app { String getStatistics(void); String getLiveData(void); String getJson(void); + bool getWifiApActive(void); uint8_t getIrqPin(void) { return mConfig.pinIrq; @@ -135,35 +126,34 @@ class app { mEep->commit(); } - uint8_t app_loops; + inline bool checkTicker(uint32_t *ticker, uint32_t interval) { + uint32_t mil = millis(); + if(mil >= *ticker) { + *ticker = mil + interval; + return true; + } + else if(mil < (*ticker - interval)) { + *ticker = mil + interval; + return true; + } + + return false; + } + HmSystemType *mSys; - ESP8266WebServer *mWeb; - bool apActive; - bool wifiWasEstablished; private: - void MainLoop(void); - void setupAp(const char *ssid, const char *pwd); - bool setupStation(uint32_t timeout); - void resetSystem(void); void loadDefaultConfig(void); void loadEEpconfig(void); void setupMqtt(void); - time_t getNtpTime(void); - void sendNTPpacket(IPAddress& address); - time_t offsetDayLightSaving (uint32_t local_t); - - uint32_t mUptimeTicker; - uint16_t mUptimeInterval; - uint32_t mUptimeSecs; - uint8_t mHeapStatCnt; - - DNSServer *mDns; - - WiFiUDP *mUdp; // for time server + bool buildPayload(uint8_t id); + void processPayload(bool retransmit); + void sendMqttDiscoveryConfig(void); + const char* getFieldDeviceClass(uint8_t fieldId); + const char* getFieldStateClass(uint8_t fieldId); inline uint16_t buildEEpCrc(uint32_t start, uint32_t length) { DPRINTLN(DBG_VERBOSE, F("main.h:buildEEpCrc")); @@ -206,21 +196,6 @@ class app { return (crcCheck == crcRd); } - inline bool checkTicker(uint32_t *ticker, uint32_t interval) { - //DPRINTLN(DBG_VERBOSE, F("c")); - uint32_t mil = millis(); - if(mil >= *ticker) { - *ticker = mil + interval; - return true; - } - else if(mil < (*ticker - interval)) { - *ticker = mil + interval; - return true; - } - - return false; - } - void stats(void) { DPRINTLN(DBG_VERBOSE, F("main.h:stats")); uint32_t free; @@ -232,32 +207,22 @@ class app { DPRINTLN(DBG_VERBOSE, F(" - frag: ") + String(frag)); } + + uint32_t mUptimeTicker; + uint16_t mUptimeInterval; + uint32_t mUptimeSecs; + uint8_t mHeapStatCnt; + + bool mWifiSettingsValid; bool mSettingsValid; eep *mEep; uint32_t mTimestamp; - uint32_t mWifiStationTimeout; - uint32_t mNextTryTs; - uint32_t mApLastTick; - - - bool buildPayload(uint8_t id); - void processPayload(bool retransmit); - - void showStatistics(void); - void showHoymiles(void); - void showLiveData(void); - void showJSON(void); - void webapi(void); - - - void sendMqttDiscoveryConfig(void); - const char* getFieldDeviceClass(uint8_t fieldId); - const char* getFieldStateClass(uint8_t fieldId); bool mShowRebootRequest; + wifi *mWifi; web *mWebInst; sysConfig_t mSysConfig; config_t mConfig; diff --git a/tools/esp8266/config.h b/tools/esp8266/config.h index b9af7f8e..a022528e 100644 --- a/tools/esp8266/config.h +++ b/tools/esp8266/config.h @@ -70,10 +70,10 @@ #define INACT_PWR_THRESH 3 // default ntp server uri -#define NTP_SERVER_NAME "pool.ntp.org" +#define DEF_NTP_SERVER_NAME "pool.ntp.org" // default ntp server port -#define NTP_LOCAL_PORT 8888 +#define DEF_NTP_PORT 8888 // default mqtt interval #define MQTT_INTERVAL 60 diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 9c4860c6..abac2515 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -158,7 +158,7 @@ void web::showSetup(void) { // -> the PWD will only be changed if it does not match the default "{PWD}" html.replace(F("{DEVICE}"), String(mSysCfg->deviceName)); html.replace(F("{VERSION}"), String(mVersion)); - if(mMain->apActive) + if(mMain->getWifiApActive()) html.replace("{IP}", String(F("http://192.168.1.1"))); else html.replace("{IP}", (F("http://") + String(WiFi.localIP().toString()))); diff --git a/tools/esp8266/wifi.cpp b/tools/esp8266/wifi.cpp new file mode 100644 index 00000000..f0cc8f84 --- /dev/null +++ b/tools/esp8266/wifi.cpp @@ -0,0 +1,248 @@ +//----------------------------------------------------------------------------- +// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778 +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#include "wifi.h" + + +// NTP CONFIG +#define NTP_PACKET_SIZE 48 +#define TIMEZONE 1 // Central European time +1 + + +//----------------------------------------------------------------------------- +wifi::wifi(app *main, sysConfig_t *sysCfg, config_t *config) { + mMain = main; + mSysCfg = sysCfg; + mConfig = config; + + mDns = new DNSServer(); + mUdp = new WiFiUDP(); + + mWifiStationTimeout = 10; + wifiWasEstablished = false; + mNextTryTs = 0; + mApLastTick = 0; + mApActive = false; +} + + +//----------------------------------------------------------------------------- +void wifi::setup(uint32_t timeout, bool settingValid) { + mWifiStationTimeout = timeout; + #ifndef AP_ONLY + if(false == mApActive) + mApActive = setupStation(mWifiStationTimeout); + #endif + + if(!settingValid) { + DPRINTLN(DBG_WARN, F("your settings are not valid! check [IP]/setup")); + mApActive = true; + mApLastTick = millis(); + mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); + setupAp(WIFI_AP_SSID, WIFI_AP_PWD); + } + else { + DPRINTLN(DBG_INFO, F("\n\n----------------------------------------")); + DPRINTLN(DBG_INFO, F("Welcome to AHOY!")); + DPRINT(DBG_INFO, F("\npoint your browser to http://")); + if(mApActive) + DBGPRINTLN(F("192.168.1.1")); + else + DBGPRINTLN(WiFi.localIP()); + DPRINTLN(DBG_INFO, F("to configure your device")); + DPRINTLN(DBG_INFO, F("----------------------------------------\n")); + } +} + + +//----------------------------------------------------------------------------- +bool wifi::loop(void) { + if(mApActive) { + mDns->processNextRequest(); +#ifndef AP_ONLY + if(mMain->checkTicker(&mNextTryTs, (WIFI_AP_ACTIVE_TIME * 1000))) { + mApActive = setupStation(mWifiStationTimeout); + if(mApActive) { + if(strlen(WIFI_AP_PWD) < 8) + DPRINTLN(DBG_ERROR, F("password must be at least 8 characters long")); + mApLastTick = millis(); + mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); + setupAp(WIFI_AP_SSID, WIFI_AP_PWD); + } + } + else { + if(millis() - mApLastTick > 10000) { + uint8_t cnt = WiFi.softAPgetStationNum(); + if(cnt > 0) { + DPRINTLN(DBG_INFO, String(cnt) + F(" client connected, resetting AP timeout")); + mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000)); + } + mApLastTick = millis(); + DPRINTLN(DBG_INFO, F("AP will be closed in ") + String((mNextTryTs - mApLastTick) / 1000) + F(" seconds")); + } + } +#endif + } + + if((WiFi.status() != WL_CONNECTED) && wifiWasEstablished) { + if(!mApActive) { + DPRINTLN(DBG_INFO, "[WiFi]: Connection Lost"); + mApActive = setupStation(mWifiStationTimeout); + } + } + + return mApActive; +} + + +//----------------------------------------------------------------------------- +void wifi::setupAp(const char *ssid, const char *pwd) { + DPRINTLN(DBG_VERBOSE, F("app::setupAp")); + IPAddress apIp(192, 168, 1, 1); + + DPRINTLN(DBG_INFO, F("\n---------\nAP MODE\nSSID: ") + + String(ssid) + F("\nPWD: ") + + String(pwd) + F("\nActive for: ") + + String(WIFI_AP_ACTIVE_TIME) + F(" seconds") + + F("\n---------\n")); + DPRINTLN(DBG_DEBUG, String(mNextTryTs)); + + WiFi.mode(WIFI_AP); + WiFi.softAPConfig(apIp, apIp, IPAddress(255, 255, 255, 0)); + WiFi.softAP(ssid, pwd); + + mDns->start(53, "*", apIp); +} + + +//----------------------------------------------------------------------------- +bool wifi::setupStation(uint32_t timeout) { + DPRINTLN(DBG_VERBOSE, F("app::setupStation")); + int32_t cnt; + bool startAp = false; + + if(timeout >= 3) + cnt = (timeout - 3) / 2 * 10; + else { + timeout = 1; + cnt = 1; + } + + WiFi.mode(WIFI_STA); + WiFi.begin(mSysCfg->stationSsid, mSysCfg->stationPwd); + if(String(mSysCfg->deviceName) != "") + WiFi.hostname(mSysCfg->deviceName); + + delay(2000); + DPRINTLN(DBG_INFO, F("connect to network '") + String(mSysCfg->stationSsid) + F("' ...")); + while (WiFi.status() != WL_CONNECTED) { + delay(100); + if(cnt % 40 == 0) + Serial.println("."); + else + Serial.print("."); + + if(timeout > 0) { // limit == 0 -> no limit + if(--cnt <= 0) { + if(WiFi.status() != WL_CONNECTED) { + startAp = true; + WiFi.disconnect(); + } + delay(100); + break; + } + } + } + Serial.println("."); + + if(false == startAp) + wifiWasEstablished = true; + + delay(1000); + return startAp; +} + + +//----------------------------------------------------------------------------- +bool wifi::getApActive(void) { + return mApActive; +} + +//----------------------------------------------------------------------------- +time_t wifi::getNtpTime(void) { + //DPRINTLN(DBG_VERBOSE, F("wifi::getNtpTime")); + time_t date = 0; + IPAddress timeServer; + uint8_t buf[NTP_PACKET_SIZE]; + uint8_t retry = 0; + + WiFi.hostByName(mConfig->ntpAddr, timeServer); + mUdp->begin(mConfig->ntpPort); + + + sendNTPpacket(timeServer); + + while(retry++ < 5) { + int wait = 150; + while(--wait) { + if(NTP_PACKET_SIZE <= mUdp->parsePacket()) { + uint64_t secsSince1900; + mUdp->read(buf, NTP_PACKET_SIZE); + secsSince1900 = (buf[40] << 24); + secsSince1900 |= (buf[41] << 16); + secsSince1900 |= (buf[42] << 8); + secsSince1900 |= (buf[43] ); + + date = secsSince1900 - 2208988800UL; // UTC time + date += (TIMEZONE + offsetDayLightSaving(date)) * 3600; + break; + } + else + delay(10); + } + } + + return date; +} + + +//----------------------------------------------------------------------------- +void wifi::sendNTPpacket(IPAddress& address) { + //DPRINTLN(DBG_VERBOSE, F("wifi::sendNTPpacket")); + uint8_t buf[NTP_PACKET_SIZE] = {0}; + + buf[0] = B11100011; // LI, Version, Mode + buf[1] = 0; // Stratum + buf[2] = 6; // Max Interval between messages in seconds + buf[3] = 0xEC; // Clock Precision + // bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset + buf[12] = 49; // four-byte reference ID identifying + buf[13] = 0x4E; + buf[14] = 49; + buf[15] = 52; + + mUdp->beginPacket(address, 123); // NTP request, port 123 + mUdp->write(buf, NTP_PACKET_SIZE); + mUdp->endPacket(); +} + + +//----------------------------------------------------------------------------- +// calculates the daylight saving time for middle Europe. Input: Unixtime in UTC +// from: https://forum.arduino.cc/index.php?topic=172044.msg1278536#msg1278536 +time_t wifi::offsetDayLightSaving (uint32_t local_t) { + //DPRINTLN(DBG_VERBOSE, F("wifi::offsetDayLightSaving")); + int m = month (local_t); + if(m < 3 || m > 10) return 0; // no DSL in Jan, Feb, Nov, Dez + if(m > 3 && m < 10) return 1; // DSL in Apr, May, Jun, Jul, Aug, Sep + int y = year (local_t); + int h = hour (local_t); + int hToday = (h + 24 * day(local_t)); + if((m == 3 && hToday >= (1 + TIMEZONE + 24 * (31 - (5 * y /4 + 4) % 7))) + || (m == 10 && hToday < (1 + TIMEZONE + 24 * (31 - (5 * y /4 + 1) % 7))) ) + return 1; + else + return 0; +} diff --git a/tools/esp8266/wifi.h b/tools/esp8266/wifi.h new file mode 100644 index 00000000..4a1bc32e --- /dev/null +++ b/tools/esp8266/wifi.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778 +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#ifndef __WIFI_H__ +#define __WIFI_H__ + +#include "dbg.h" +#include +#include + +// NTP +#include +#include +#include + +#include "defines.h" + +#include "app.h" + +class app; + +class wifi { + public: + wifi(app *main, sysConfig_t *sysCfg, config_t *config); + ~wifi() {} + + void setup(uint32_t timeout, bool settingValid); + bool loop(void); + void setupAp(const char *ssid, const char *pwd); + bool setupStation(uint32_t timeout); + bool getApActive(void); + time_t getNtpTime(void); + + private: + void sendNTPpacket(IPAddress& address); + time_t offsetDayLightSaving (uint32_t local_t); + + + config_t *mConfig; + sysConfig_t *mSysCfg; + app *mMain; + + DNSServer *mDns; + WiFiUDP *mUdp; // for time server + + uint32_t mWifiStationTimeout; + uint32_t mNextTryTs; + uint32_t mApLastTick; + bool mApActive; + bool wifiWasEstablished; +}; + +#endif /*__WIFI_H__*/