mirror of https://github.com/lumapu/ahoy.git
				
				
			
				 6 changed files with 316 additions and 7 deletions
			
			
		@ -0,0 +1,243 @@ | 
				
			|||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||
 | 
					// 2023 Ahoy, https://www.mikrocontroller.net/topic/525778
 | 
				
			||||
 | 
					// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
 | 
				
			||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#if defined(ETHERNET) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#if defined(ESP32) && defined(F) | 
				
			||||
 | 
					  #undef F | 
				
			||||
 | 
					  #define F(sl) (sl) | 
				
			||||
 | 
					#endif | 
				
			||||
 | 
					#include "ahoyeth.h" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||
 | 
					ahoyeth::ahoyeth() | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    // WiFi.onEvent(ESP32_W5500_event);
 | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||
 | 
					void ahoyeth::setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNetworkCB, OnTimeCB onTimeCB) { | 
				
			||||
 | 
					    mConfig = config; | 
				
			||||
 | 
					    mUtcTimestamp = utcTimestamp; | 
				
			||||
 | 
					    mOnNetworkCB = onNetworkCB; | 
				
			||||
 | 
					    mOnTimeCB = onTimeCB; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    DPRINTLN(DBG_INFO, F("[ETH]: Register for events...")); | 
				
			||||
 | 
					    Serial.flush(); | 
				
			||||
 | 
					    WiFi.onEvent([this](WiFiEvent_t event, arduino_event_info_t info) -> void { this->onEthernetEvent(event, info); }); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    DPRINTLN(DBG_INFO, F("[ETH]: begin...")); | 
				
			||||
 | 
					    Serial.flush(); | 
				
			||||
 | 
					    ETH.begin(ETH_MISO_GPIO, ETH_MOSI_GPIO, ETH_SCK_GPIO, ETH_CS_PIN, ETH_INT_GPIO, ETH_SPI_CLOCK_MHZ, ETH_SPI_HOST); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||
 | 
					bool ahoyeth::updateNtpTime(void) { | 
				
			||||
 | 
					    DPRINTLN(DBG_DEBUG, F(__FUNCTION__)); Serial.flush(); | 
				
			||||
 | 
					    Serial.printf("ETH.linkUp()=%s\n", ETH.linkUp() ? "up" : "down"); | 
				
			||||
 | 
					    Serial.print("ETH.localIP()="); | 
				
			||||
 | 
					    Serial.println(ETH.localIP()); | 
				
			||||
 | 
					    Serial.printf("Go on? %s\n", (!ETH.localIP()) ? "No..." : "Yes..."); | 
				
			||||
 | 
					    if (!ETH.localIP()) | 
				
			||||
 | 
					        return false; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    DPRINTLN(DBG_DEBUG, F("updateNtpTime: checking udp \"connection\"...")); Serial.flush(); | 
				
			||||
 | 
					    if (!mUdp.connected()) | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        DPRINTLN(DBG_DEBUG, F("updateNtpTime: About to (re)connect...")); Serial.flush(); | 
				
			||||
 | 
					        IPAddress timeServer; | 
				
			||||
 | 
					        if (!WiFi.hostByName(mConfig->ntp.addr, timeServer)) | 
				
			||||
 | 
					            return false; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        if (!mUdp.connect(timeServer, mConfig->ntp.port)) | 
				
			||||
 | 
					            return false; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        DPRINTLN(DBG_DEBUG, F("updateNtpTime: Connected...")); Serial.flush(); | 
				
			||||
 | 
					        mUdp.onPacket([this](AsyncUDPPacket packet) | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					            DPRINTLN(DBG_DEBUG, F("updateNtpTime: about to handle ntp packet...")); Serial.flush(); | 
				
			||||
 | 
					            this->handleNTPPacket(packet); | 
				
			||||
 | 
					        }); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    DPRINTLN(DBG_DEBUG, F("updateNtpTime: prepare packet...")); Serial.flush(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // set all bytes in the buffer to 0
 | 
				
			||||
 | 
					    memset(mUdpPacketBuffer, 0, NTP_PACKET_SIZE); | 
				
			||||
 | 
					    // Initialize values needed to form NTP request
 | 
				
			||||
 | 
					    // (see URL above for details on the packets)
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    mUdpPacketBuffer[0]   = 0b11100011;   // LI, Version, Mode
 | 
				
			||||
 | 
					    mUdpPacketBuffer[1]   = 0;     // Stratum, or type of clock
 | 
				
			||||
 | 
					    mUdpPacketBuffer[2]   = 6;     // Polling Interval
 | 
				
			||||
 | 
					    mUdpPacketBuffer[3]   = 0xEC;  // Peer Clock Precision
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // 8 bytes of zero for Root Delay & Root Dispersion
 | 
				
			||||
 | 
					    mUdpPacketBuffer[12]  = 49; | 
				
			||||
 | 
					    mUdpPacketBuffer[13]  = 0x4E; | 
				
			||||
 | 
					    mUdpPacketBuffer[14]  = 49; | 
				
			||||
 | 
					    mUdpPacketBuffer[15]  = 52; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    //Send unicast
 | 
				
			||||
 | 
					    DPRINTLN(DBG_DEBUG, F("updateNtpTime: send packet...")); Serial.flush(); | 
				
			||||
 | 
					    mUdp.write(mUdpPacketBuffer, sizeof(mUdpPacketBuffer)); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    return true; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||
 | 
					void ahoyeth::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); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||
 | 
					void ahoyeth::welcome(String ip, String mode) { | 
				
			||||
 | 
					    DBGPRINTLN(F("\n\n--------------------------------")); | 
				
			||||
 | 
					    DBGPRINTLN(F("Welcome to AHOY!")); | 
				
			||||
 | 
					    DBGPRINT(F("\npoint your browser to http://")); | 
				
			||||
 | 
					    DBGPRINT(ip); | 
				
			||||
 | 
					    DBGPRINTLN(mode); | 
				
			||||
 | 
					    DBGPRINTLN(F("to configure your device")); | 
				
			||||
 | 
					    DBGPRINTLN(F("--------------------------------\n")); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    AWS_LOG(F("[ETH]: Got event...")); | 
				
			||||
 | 
					    switch (event) | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					#if ( ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) && ( ARDUINO_ESP32_GIT_VER != 0x46d5afb1 ) ) | 
				
			||||
 | 
					    // For breaking core v2.0.0
 | 
				
			||||
 | 
					    // Why so strange to define a breaking enum arduino_event_id_t in WiFiGeneric.h
 | 
				
			||||
 | 
					    // compared to the old system_event_id_t, now in tools/sdk/esp32/include/esp_event/include/esp_event_legacy.h
 | 
				
			||||
 | 
					    // You can preserve the old enum order and just adding new items to do no harm
 | 
				
			||||
 | 
					    case ARDUINO_EVENT_ETH_START: | 
				
			||||
 | 
					        AWS_LOG(F("\nETH Started")); | 
				
			||||
 | 
					        //set eth hostname here
 | 
				
			||||
 | 
					        if(String(mConfig->sys.deviceName) != "") | 
				
			||||
 | 
					            ETH.setHostname(mConfig->sys.deviceName); | 
				
			||||
 | 
					        else | 
				
			||||
 | 
					            ETH.setHostname("ESP32_W5500"); | 
				
			||||
 | 
					        break; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    case ARDUINO_EVENT_ETH_CONNECTED: | 
				
			||||
 | 
					        AWS_LOG(F("ETH Connected")); | 
				
			||||
 | 
					        break; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    case ARDUINO_EVENT_ETH_GOT_IP: | 
				
			||||
 | 
					        if (!ESP32_W5500_eth_connected) | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					            AWS_LOG3(F("ETH MAC: "), ETH.macAddress(), F(", IPv4: "), ETH.localIP()); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            if (ETH.fullDuplex()) | 
				
			||||
 | 
					            { | 
				
			||||
 | 
					            AWS_LOG0(F("FULL_DUPLEX, ")); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            else | 
				
			||||
 | 
					            { | 
				
			||||
 | 
					                AWS_LOG0(F("HALF_DUPLEX, ")); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            AWS_LOG1(ETH.linkSpeed(), F("Mbps")); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            ESP32_W5500_eth_connected = true; | 
				
			||||
 | 
					            mOnNetworkCB(true); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					        break; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    case ARDUINO_EVENT_ETH_DISCONNECTED: | 
				
			||||
 | 
					      AWS_LOG("ETH Disconnected"); | 
				
			||||
 | 
					      ESP32_W5500_eth_connected = false; | 
				
			||||
 | 
					      mUdp.close(); | 
				
			||||
 | 
					      mOnNetworkCB(false); | 
				
			||||
 | 
					      break; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    case ARDUINO_EVENT_ETH_STOP: | 
				
			||||
 | 
					      AWS_LOG("\nETH Stopped"); | 
				
			||||
 | 
					      ESP32_W5500_eth_connected = false; | 
				
			||||
 | 
					      mUdp.close(); | 
				
			||||
 | 
					      mOnNetworkCB(false); | 
				
			||||
 | 
					      break; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#else | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // For old core v1.0.6-
 | 
				
			||||
 | 
					    // Core v2.0.0 defines a stupid enum arduino_event_id_t, breaking any code for ESP32_W5500 written for previous core
 | 
				
			||||
 | 
					    // Why so strange to define a breaking enum arduino_event_id_t in WiFiGeneric.h
 | 
				
			||||
 | 
					    // compared to the old system_event_id_t, now in tools/sdk/esp32/include/esp_event/include/esp_event_legacy.h
 | 
				
			||||
 | 
					    // You can preserve the old enum order and just adding new items to do no harm
 | 
				
			||||
 | 
					    case SYSTEM_EVENT_ETH_START: | 
				
			||||
 | 
					        AWS_LOG(F("\nETH Started")); | 
				
			||||
 | 
					        //set eth hostname here
 | 
				
			||||
 | 
					        if(String(mConfig->sys.deviceName) != "") | 
				
			||||
 | 
					            ETH.setHostname(mConfig->sys.deviceName); | 
				
			||||
 | 
					        else | 
				
			||||
 | 
					            ETH.setHostname("ESP32_W5500"); | 
				
			||||
 | 
					        break; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    case SYSTEM_EVENT_ETH_CONNECTED: | 
				
			||||
 | 
					        AWS_LOG(F("ETH Connected")); | 
				
			||||
 | 
					        break; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    case SYSTEM_EVENT_ETH_GOT_IP: | 
				
			||||
 | 
					        if (!ESP32_W5500_eth_connected) | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					            AWS_LOG3(F("ETH MAC: "), ETH.macAddress(), F(", IPv4: "), ETH.localIP()); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            if (ETH.fullDuplex()) | 
				
			||||
 | 
					            { | 
				
			||||
 | 
					                AWS_LOG0(F("FULL_DUPLEX, ")); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            else | 
				
			||||
 | 
					            { | 
				
			||||
 | 
					                AWS_LOG0(F("HALF_DUPLEX, ")); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            AWS_LOG1(ETH.linkSpeed(), F("Mbps")); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            ESP32_W5500_eth_connected = true; | 
				
			||||
 | 
					            mOnNetworkCB(true); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					        break; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    case SYSTEM_EVENT_ETH_DISCONNECTED: | 
				
			||||
 | 
					        AWS_LOG("ETH Disconnected"); | 
				
			||||
 | 
					        ESP32_W5500_eth_connected = false; | 
				
			||||
 | 
					        mUdp.close(); | 
				
			||||
 | 
					        mOnNetworkCB(false); | 
				
			||||
 | 
					        break; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    case SYSTEM_EVENT_ETH_STOP: | 
				
			||||
 | 
					        AWS_LOG("\nETH Stopped"); | 
				
			||||
 | 
					        ESP32_W5500_eth_connected = false; | 
				
			||||
 | 
					        mUdp.close(); | 
				
			||||
 | 
					        mOnNetworkCB(false); | 
				
			||||
 | 
					        break; | 
				
			||||
 | 
					#endif | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    default: | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					      break; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#endif /* defined(ETHERNET) */ | 
				
			||||
@ -0,0 +1,60 @@ | 
				
			|||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||
 | 
					// 2023 Ahoy, https://www.mikrocontroller.net/topic/525778
 | 
				
			||||
 | 
					// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
 | 
				
			||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#if defined(ETHERNET) | 
				
			||||
 | 
					#ifndef __AHOYETH_H__ | 
				
			||||
 | 
					#define __AHOYETH_H__ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include <functional> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include <Arduino.h> | 
				
			||||
 | 
					#include <AsyncUDP.h> | 
				
			||||
 | 
					#include <DNSServer.h> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include "../utils/dbg.h" | 
				
			||||
 | 
					#include "../config/config.h" | 
				
			||||
 | 
					#include "../config/settings.h" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include "AsyncWebServer_ESP32_W5500.h" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class app; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#define NTP_PACKET_SIZE 48 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class ahoyeth { | 
				
			||||
 | 
					    public: /* types */ | 
				
			||||
 | 
					        typedef std::function<void(bool)> OnNetworkCB; | 
				
			||||
 | 
					        typedef std::function<void(bool)> OnTimeCB; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    public: | 
				
			||||
 | 
					        ahoyeth(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        void setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNetworkCB, OnTimeCB onTimeCB); | 
				
			||||
 | 
					        bool updateNtpTime(void); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    private: | 
				
			||||
 | 
					        void setupEthernet(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        void handleNTPPacket(AsyncUDPPacket packet); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        void welcome(String ip, String mode); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        void onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    private: | 
				
			||||
 | 
					        settings_t *mConfig; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        uint32_t *mUtcTimestamp; | 
				
			||||
 | 
					        AsyncUDP mUdp; // for time server
 | 
				
			||||
 | 
					        byte mUdpPacketBuffer[NTP_PACKET_SIZE];   // buffer to hold incoming and outgoing packets
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        OnNetworkCB mOnNetworkCB; | 
				
			||||
 | 
					        OnTimeCB mOnTimeCB; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#endif /*__AHOYETH_H__*/ | 
				
			||||
 | 
					#endif /* defined(ETHERNET) */ | 
				
			||||
					Loading…
					
					
				
		Reference in new issue