mirror of https://github.com/lumapu/ahoy.git
				
				
			
			
			
				Browse Source
			
			
			
			
				
		* combined common network functions into class * seperated wifi station from AP modepull/1549/head
				 12 changed files with 540 additions and 25 deletions
			
			
		| @ -0,0 +1,82 @@ | |||
| //-----------------------------------------------------------------------------
 | |||
| // 2024 Ahoy, https://ahoydtu.de
 | |||
| // Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
 | |||
| //-----------------------------------------------------------------------------
 | |||
| 
 | |||
| #ifndef __AHOY_ETHERNET_H__ | |||
| #define __AHOY_ETHERNET_H__ | |||
| 
 | |||
| #include <functional> | |||
| #include <AsyncUDP.h> | |||
| #include <ETH.h> | |||
| #include "AhoyEthernetSpi.h" | |||
| #include "AhoyEthernet.h" | |||
| 
 | |||
| class AhoyEthernet : public AhoyNetwork { | |||
|     public: | |||
|         void begin() override { | |||
|             setupIp([this](IPAddress ip, IPAddress gateway, IPAddress mask, IPAddress dns1, IPAddress dns2) -> bool { | |||
|                 return ETH.config(ip, gateway, mask, dns1, dns2); | |||
|             }); | |||
|         } | |||
| 
 | |||
|         void tickNetworkLoop() override { | |||
|             switch(mState) { | |||
|                 case NetworkState::DISCONNECTED: | |||
|                     break; | |||
|             } | |||
|         } | |||
| 
 | |||
|     private: | |||
| 
 | |||
|         /*switch (event) {
 | |||
|             case ARDUINO_EVENT_ETH_START: | |||
|                 DPRINTLN(DBG_VERBOSE, F("ETH Started")); | |||
| 
 | |||
|                 if(String(mConfig->sys.deviceName) != "") | |||
|                     ETH.setHostname(mConfig->sys.deviceName); | |||
|                 else | |||
|                     ETH.setHostname(F("ESP32_W5500")); | |||
|                 break; | |||
| 
 | |||
|             case ARDUINO_EVENT_ETH_CONNECTED: | |||
|                 DPRINTLN(DBG_VERBOSE, F("ETH Connected")); | |||
|                 break; | |||
| 
 | |||
|             case ARDUINO_EVENT_ETH_GOT_IP: | |||
|                 if (!mEthConnected) { | |||
|                     welcome(ETH.localIP().toString(), F(" (Station)")); | |||
| 
 | |||
|                     mEthConnected = true; | |||
|                     mOnNetworkCB(true); | |||
|                 } | |||
| 
 | |||
|                 if (!MDNS.begin(mConfig->sys.deviceName)) { | |||
|                     DPRINTLN(DBG_ERROR, F("Error setting up MDNS responder!")); | |||
|                 } else { | |||
|                     DBGPRINT(F("mDNS established: ")); | |||
|                     DBGPRINT(mConfig->sys.deviceName); | |||
|                     DBGPRINTLN(F(".local")); | |||
|                 } | |||
|                 break; | |||
| 
 | |||
|             case ARDUINO_EVENT_ETH_DISCONNECTED: | |||
|                 DPRINTLN(DBG_INFO, F("ETH Disconnected")); | |||
|                 mEthConnected = false; | |||
|                 mUdp.close(); | |||
|                 mOnNetworkCB(false); | |||
|                 break; | |||
| 
 | |||
|             case ARDUINO_EVENT_ETH_STOP: | |||
|                 DPRINTLN(DBG_INFO, F("ETH Stopped")); | |||
|                 mEthConnected = false; | |||
|                 mUdp.close(); | |||
|                 mOnNetworkCB(false); | |||
|                 break; | |||
| 
 | |||
|             default: | |||
|                 break; | |||
|         }*/ | |||
| }; | |||
| 
 | |||
| #endif /*__AHOY_ETHERNET_H__*/ | |||
| @ -0,0 +1,194 @@ | |||
| //-----------------------------------------------------------------------------
 | |||
| // 2024 Ahoy, https://ahoydtu.de
 | |||
| // Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
 | |||
| //-----------------------------------------------------------------------------
 | |||
| 
 | |||
| #ifndef __AHOY_NETWORK_H__ | |||
| #define __AHOY_NETWORK_H__ | |||
| 
 | |||
| #include "AhoyNetworkHelper.h" | |||
| #include <WiFiUdp.h> | |||
| #include "../config/settings.h" | |||
| #include "../utils/helper.h" | |||
| 
 | |||
| #if defined(ESP32) | |||
| #include <ESPmDNS.h> | |||
| #else | |||
| #include <ESP8266mDNS.h> | |||
| #endif | |||
| 
 | |||
| #define NTP_PACKET_SIZE 48 | |||
| 
 | |||
| class AhoyNetwork { | |||
|     public: | |||
|         typedef std::function<void(bool)> OnNetworkCB; | |||
|         typedef std::function<void(bool)> OnTimeCB; | |||
| 
 | |||
|     public: | |||
|         void setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNetworkCB, OnTimeCB onTimeCB) { | |||
|             mConfig = config; | |||
|             mUtcTimestamp = utcTimestamp; | |||
|             mOnNetworkCB = onNetworkCB; | |||
|             mOnTimeCB = onTimeCB; | |||
| 
 | |||
|             #if defined(ESP32) | |||
|             WiFi.onEvent([this](WiFiEvent_t event) -> void { | |||
|                 this->OnEvent(event); | |||
|             }); | |||
|             #else | |||
|             wifiConnectHandler = WiFi.onStationModeConnected( | |||
|                 [this](const WiFiEventStationModeConnected& event) -> void { | |||
|                 OnEvent(SYSTEM_EVENT_STA_CONNECTED); | |||
|             }); | |||
|             wifiGotIPHandler = WiFi.onStationModeGotIP( | |||
|                 [this](const WiFiEventStationModeGotIP& event) -> void { | |||
|                 OnEvent(SYSTEM_EVENT_STA_GOT_IP); | |||
|             }); | |||
|             wifiDisconnectHandler = WiFi.onStationModeDisconnected( | |||
|                 [this](const WiFiEventStationModeDisconnected& event) -> void { | |||
|                 OnEvent(SYSTEM_EVENT_STA_DISCONNECTED); | |||
|             }); | |||
|             #endif | |||
|         } | |||
| 
 | |||
|         bool isConnected() const { | |||
|             return (mStatus == NetworkState.CONNECTED); | |||
|         } | |||
| 
 | |||
|         bool updateNtpTime(void) { | |||
|             if(CONNECTED != mStatus) | |||
|                 return; | |||
| 
 | |||
|             if (!mUdp.connected()) { | |||
|                 IPAddress timeServer; | |||
|                 if (!WiFi.hostByName(mConfig->ntp.addr, timeServer)) | |||
|                     return false; | |||
|                 if (!mUdp.connect(timeServer, mConfig->ntp.port)) | |||
|                     return false; | |||
|             } | |||
| 
 | |||
|             mUdp.onPacket([this](AsyncUDPPacket packet) { | |||
|                 this->handleNTPPacket(packet); | |||
|             }); | |||
|             sendNTPpacket(timeServer); | |||
| 
 | |||
|             return true; | |||
|         } | |||
| 
 | |||
|     public: | |||
|         virtual void begin() = 0; | |||
|         virtual void tickNetworkLoop() = 0; | |||
|         virtual void connectionEvent(WiFiStatus_t status) = 0; | |||
| 
 | |||
|     protected: | |||
|         void setupIp(void) { | |||
|             if(mConfig->sys.ip.ip[0] != 0) { | |||
|                 IPAddress ip(mConfig->sys.ip.ip); | |||
|                 IPAddress mask(mConfig->sys.ip.mask); | |||
|                 IPAddress dns1(mConfig->sys.ip.dns1); | |||
|                 IPAddress dns2(mConfig->sys.ip.dns2); | |||
|                 IPAddress gateway(mConfig->sys.ip.gateway); | |||
|                 if(!ETH.config(ip, gateway, mask, dns1, dns2)) | |||
|                     DPRINTLN(DBG_ERROR, F("failed to set static IP!")); | |||
|             } | |||
|         } | |||
| 
 | |||
|         void OnEvent(WiFiEvent_t event) { | |||
|             switch(event) { | |||
|                 case SYSTEM_EVENT_STA_CONNECTED: | |||
|                     [[fallthrough]]; | |||
|                 case ARDUINO_EVENT_ETH_CONNECTED: | |||
|                     if(NetworkState::CONNECTED != mStatus) { | |||
|                         mStatus = NetworkState::CONNECTED; | |||
|                         DPRINTLN(DBG_INFO, F("Network connected")); | |||
|                     } | |||
|                     break; | |||
| 
 | |||
|                 case SYSTEM_EVENT_STA_GOT_IP: | |||
|                     [[fallthrough]]; | |||
|                 case ARDUINO_EVENT_ETH_GOT_IP: | |||
|                     mStatus = NetworkState::GOT_IP; | |||
|                     break; | |||
| 
 | |||
|                 case ARDUINO_EVENT_WIFI_STA_LOST_IP: | |||
|                     [[fallthrough]]; | |||
|                 case ARDUINO_EVENT_WIFI_STA_STOP: | |||
|                     [[fallthrough]]; | |||
|                 case SYSTEM_EVENT_STA_DISCONNECTED: | |||
|                     [[fallthrough]]; | |||
|                 case ARDUINO_EVENT_ETH_STOP: | |||
|                     [[fallthrough]]; | |||
|                 case ARDUINO_EVENT_ETH_DISCONNECTED: | |||
|                     mStatus = NetworkState::DISCONNECTED; | |||
|                     break; | |||
| 
 | |||
|                 default: | |||
|                     break; | |||
|             } | |||
|         } | |||
| 
 | |||
|     private: | |||
|         void sendNTPpacket(IPAddress& address) { | |||
|             //DPRINTLN(DBG_VERBOSE, F("wifi::sendNTPpacket"));
 | |||
|             uint8_t buf[NTP_PACKET_SIZE]; | |||
|             memset(buf, 0, NTP_PACKET_SIZE); | |||
| 
 | |||
|             buf[0] = 0b11100011; // 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();
 | |||
|         } | |||
| 
 | |||
|         void handleNTPPacket(AsyncUDPPacket packet) { | |||
|             char buf[80]; | |||
| 
 | |||
|             memcpy(buf, packet.data(), sizeof(buf)); | |||
| 
 | |||
|             unsigned long highWord = word(buf[40], buf[41]); | |||
|             unsigned long lowWord = word(buf[42], buf[43]); | |||
| 
 | |||
|             // combine the four bytes (two words) into a long integer
 | |||
|             // this is NTP time (seconds since Jan 1 1900):
 | |||
|             unsigned long secsSince1900 = highWord << 16 | lowWord; | |||
| 
 | |||
|             *mUtcTimestamp = secsSince1900 - 2208988800UL; // UTC time
 | |||
|             DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(*mUtcTimestamp) + " UTC"); | |||
|             mOnTimeCB(true); | |||
|             mUdp.close(); | |||
|         } | |||
| 
 | |||
|     protected: | |||
|         enum class NetworkState : uint8_t { | |||
|             DISCONNECTED, | |||
|             CONNECTING, | |||
|             CONNECTED, | |||
|             IN_AP_MODE, | |||
|             GOT_IP, | |||
|             IN_STA_MODE, | |||
|             RESET, | |||
|             SCAN_READY | |||
|         }; | |||
| 
 | |||
|     protected: | |||
|         settings_t *mConfig = nullptr; | |||
|         uint32_t *mUtcTimestamp = nullptr; | |||
| 
 | |||
|         OnNetworkCB mOnNetworkCB; | |||
|         OnTimeCB mOnTimeCB; | |||
| 
 | |||
|         NetworkState mStatus = NetworkState.DISCONNECTED; | |||
| 
 | |||
|         WiFiUDP mUdp; // for time server
 | |||
|         DNSServer mDns; | |||
| }; | |||
| 
 | |||
| #endif /*__AHOY_NETWORK_H__*/ | |||
| @ -0,0 +1,29 @@ | |||
| //-----------------------------------------------------------------------------
 | |||
| // 2024 Ahoy, https://ahoydtu.de
 | |||
| // Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
 | |||
| //-----------------------------------------------------------------------------
 | |||
| 
 | |||
| #ifndef __AHOY_NETWORK_HELPER_H__ | |||
| #define __AHOY_NETWORK_HELPER_H__ | |||
| 
 | |||
| #include "../utils/dbg.h" | |||
| #include <Arduino.h> | |||
| #include <WiFiType.h> | |||
| #include <WiFi.h> | |||
| #include <DNSServer.h> | |||
| 
 | |||
| namespace ah { | |||
|     void welcome(String ip, String info) { | |||
|         DBGPRINTLN(F("\n\n-------------------")); | |||
|         DBGPRINTLN(F("Welcome to AHOY!")); | |||
|         DBGPRINT(F("\npoint your browser to http://")); | |||
|         DBGPRINT(ip); | |||
|         DBGPRINT(" ("); | |||
|         DBGPRINT(info); | |||
|         DBGPRINTLN(")"); | |||
|         DBGPRINTLN(F("to configure your device")); | |||
|         DBGPRINTLN(F("-------------------\n")); | |||
|     } | |||
| } | |||
| 
 | |||
| #endif /*__AHOY_NETWORK_HELPER_H__*/ | |||
| @ -0,0 +1,70 @@ | |||
| //-----------------------------------------------------------------------------
 | |||
| // 2024 Ahoy, https://ahoydtu.de
 | |||
| // Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
 | |||
| //-----------------------------------------------------------------------------
 | |||
| 
 | |||
| #ifndef __AHOY_WIFI_AP_H__ | |||
| #define __AHOY_WIFI_AP_H__ | |||
| 
 | |||
| #include "../utils/dbg.h" | |||
| #include <Arduino.h> | |||
| #include "../config/settings.h" | |||
| #include "AhoyNetworkHelper.h" | |||
| 
 | |||
| class AhoyWifiAp { | |||
|     public: | |||
|         AhoyWifiAp() : mIp(192, 168, 4, 1) {} | |||
| 
 | |||
|         void setup(cfgSys_t *cfg) { | |||
|             mCfg = cfg; | |||
|         } | |||
| 
 | |||
|         void tickLoop() { | |||
|             if(mEnabled) | |||
|                 mDns.processNextRequest(); | |||
|         } | |||
| 
 | |||
|         void enable() { | |||
|             ah::welcome(mIp.toString(), String(F("Password: ") + String(mCfg->apPwd))); | |||
|             if('\0' == mCfg->deviceName[0]) | |||
|                 snprintf(mCfg->deviceName, DEVNAME_LEN, "%s", DEF_DEVICE_NAME); | |||
|             WiFi.hostname(mCfg->deviceName); | |||
| 
 | |||
|             #if defined(ETHERNET) | |||
|             WiFi.mode(WIFI_AP); | |||
|             #else | |||
|             WiFi.mode(WIFI_AP_STA); | |||
|             #endif | |||
|             WiFi.softAPConfig(mIp, mIp, IPAddress(255, 255, 255, 0)); | |||
|             WiFi.softAP(WIFI_AP_SSID, mCfg->apPwd); | |||
| 
 | |||
|             mDns.start(53, "*", mIp); | |||
| 
 | |||
|             mEnabled = true; | |||
|             tickLoop(); | |||
|         } | |||
| 
 | |||
|         void disable() { | |||
|             mDns.stop(); | |||
|             WiFi.softAPdisconnect(); | |||
|             #if defined(ETHERNET) | |||
|             WiFi.mode(WIFI_OFF); | |||
|             #else | |||
|             WiFi.mode(WIFI_STA); | |||
|             #endif | |||
| 
 | |||
|             mEnabled = false; | |||
|         } | |||
| 
 | |||
|         bool getEnable() const { | |||
|             return mEnabled; | |||
|         } | |||
| 
 | |||
|     private: | |||
|         cfgSys_t *mCfg = nullptr; | |||
|         DNSServer mDns; | |||
|         IPAddress mIp; | |||
|         bool mEnabled = false; | |||
| }; | |||
| 
 | |||
| #endif /*__AHOY_WIFI_AP_H__*/ | |||
					Loading…
					
					
				
		Reference in new issue