mirror of https://github.com/lumapu/ahoy.git
lumapu
2 years ago
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