mirror of https://github.com/lumapu/ahoy.git
				
				
			
				 7 changed files with 382 additions and 340 deletions
			
			
		| @ -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; | ||||
|  | } | ||||
| @ -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 <ESP8266WiFi.h> | ||||
|  | #include <ESP8266WebServer.h> | ||||
|  | 
 | ||||
|  | // NTP
 | ||||
|  | #include <WiFiUdp.h> | ||||
|  | #include <TimeLib.h> | ||||
|  | #include <DNSServer.h> | ||||
|  | 
 | ||||
|  | #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__*/ | ||||
					Loading…
					
					
				
		Reference in new issue