ropg / ezTime

ezTime — pronounced "Easy Time" — is a very easy to use Arduino time and date library that provides NTP network time lookups, extensive timezone support, formatted time and date strings, user events, millisecond precision and more.
MIT License
336 stars 93 forks source link

Ethernet not compatible with ETH library #72

Open dorkmatt opened 4 years ago

dorkmatt commented 4 years ago

Using wESP32 (wired ethernet port) with 1.8.10 Arduino IDE and ESP32 SDK 3.2.3, the ethernet portion seems to fail. This may be related to #56 or #52, as DNS never seems to get resolved (though my example shows DNS working correctly for an HTTP connection).

I believe this is due to the use of Ethernet.h library, while these boards use the ESP32 specific Eth.h. I've tried both with and without EZTIME_ETHERNET defined. Also tried both with and without a custom NTP server defined. My guess is the Ethernet.h library is still needed for the UDP packet crafting, but not necessarily for the link state detection?

Sample sketch:

#include <ETH.h>    // ESP32 ethernet
#include <ESPmDNS.h>
#include <ezTime.h>

/* Local variables */
#define HOSTNAME "clock"
String LOCAL_NTP_SERVER = "100.64.42.1";

/* Setup libraries */
Preferences preferences;
static bool eth_connected = false;

void WiFiEvent(WiFiEvent_t event)
{
  switch (event) {
    case SYSTEM_EVENT_ETH_START:
      Serial.println("ETH Started");
      ETH.setHostname(HOSTNAME);
      break;
    case SYSTEM_EVENT_ETH_CONNECTED:
      Serial.println("ETH Connected");
      break;
    case SYSTEM_EVENT_ETH_GOT_IP:
      Serial.print("ETH MAC: ");
      Serial.print(ETH.macAddress());
      Serial.print(", IPv4: ");
      Serial.print(ETH.localIP());
      if (ETH.fullDuplex()) {
        Serial.print(", FULL_DUPLEX");
      }
      Serial.print(", ");
      Serial.print(ETH.linkSpeed());
      Serial.println("Mbps");
      eth_connected = true;
      break;
    case SYSTEM_EVENT_ETH_DISCONNECTED:
      Serial.println("ETH Disconnected");
      eth_connected = false;
      break;
    case SYSTEM_EVENT_ETH_STOP:
      Serial.println("ETH Stopped");
      eth_connected = false;
      break;
    default:
      break;
  }
}

void setup()
{
  Serial.begin(115200);

  Serial.print("Compiled date: ");
  Serial.print(__DATE__);
  Serial.print(" ");
  Serial.println (__TIME__);

  Serial.print("Arduino: v");
  Serial.println(ARDUINO,DEC);

  Serial.print("ESP32 SDK: ");
  Serial.println(ESP.getSdkVersion());

  // Bring up wired ethernet port, disable WiFi & Bluetooth  
  WiFi.onEvent(WiFiEvent);
  ETH.begin();
  MDNS.begin(HOSTNAME);
  WiFi.mode(WIFI_OFF);
  btStop();

  Serial.print("ESP date: ");
  Serial.println(UTC.dateTime());

  setServer(LOCAL_NTP_SERVER);
  setDebug(DEBUG);
}

void loop()
{
  // events();
  if (eth_connected) {
    testClient("checkip.dyndns.org", 80);
    waitForSync(25);
    Serial.print("NTP date: ");
    Serial.println(UTC.dateTime());
  }
  delay(10000);
}

void testClient(const char * host, uint16_t port)
{
  Serial.print("\nconnecting to ");
  Serial.println(host);

  WiFiClient client;
  if (!client.connect(host, port)) {
    Serial.println("connection failed");
    return;
  }
  client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
  while (client.connected() && !client.available());
  while (client.available()) {
    Serial.write(client.read());
  }

  Serial.println("closing connection\n");
  client.stop();
}

Resulting serial messages:

23:36:58.160 -> entry 0x4008069c
23:36:58.381 -> Compiled date: Nov 30 2019 23:36:46
23:36:58.381 -> Arduino: v10810
23:36:58.381 -> ESP32 SDK: v3.2.3
23:36:58.381 -> ETH Started
23:36:58.381 -> ESP date: Thursday, 01-Jan-1970 00:00:00 UTC
23:36:58.381 -> 
23:36:58.381 -> ezTime debug level set to DEBUG
23:37:02.365 -> ETH Connected
23:37:06.380 -> ETH MAC: 80:7D:3A:FE:XX:XX, IPv4: 100.64.42.138, FULL_DUPLEX, 100Mbps
23:37:08.371 -> 
23:37:08.371 -> connecting to checkip.dyndns.org
23:37:08.737 -> HTTP/1.1 200 OK
23:37:08.737 -> Content-Type: text/html
23:37:08.737 -> Server: DynDNS-CheckIP/1.0.1
23:37:08.737 -> Connection: close
23:37:08.737 -> Cache-Control: no-cache
23:37:08.737 -> Pragma: no-cache
23:37:08.737 -> Content-Length: 107
23:37:08.737 -> 
23:37:08.737 -> <html><head><title>Current IP Check</title></head><body>Current IP Address: 135.x.x.x</body></html>
23:37:08.737 -> closing connection
23:37:08.737 -> 
23:37:08.737 -> Waiting for time sync
23:37:09.002 -> Querying 100.64.42.1 ...
dorkmatt commented 4 years ago

Note that using WiFi on the same board, same SDK/IDE, same 0.8.2 library version (stock ezTime.h defines) works fine (both local and remote NTP pool time sources).

Sample WiFi sketch

#include <ETH.h>    // ESP32 ethernet
#include <WiFi.h>
#include <ezTime.h> // https://github.com/ropg/ezTime

/* Local variables */
static bool USE_WIFI = true;
const char* ssid = "mynetworkname";
const char* pass = "mysecretpass";

String LOCAL_NTP_SERVER = "100.64.42.1";

void setup()
{
  if (USE_WIFI) {
    WiFi.begin(ssid, pass);

    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
  } else if (!USE_WIFI) {
    WiFi.onEvent(WiFiEvent);
    ETH.begin();
    WiFi.mode(WIFI_OFF);
    btStop();
  }

  // setServer(LOCAL_NTP_SERVER);
  setDebug(INFO);
  waitForSync(25);
}

void loop()
{
  events();

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("Network online");
    testClient("checkip.dyndns.org", 80);

    Serial.print("NTP date: ");
    Serial.println(UTC.dateTime());
  }

  delay(10000);
}

WiFi serial messages:

14:27:07.444 -> ESP date: Thursday, 01-Jan-1970 00:00:00 UTC
14:27:07.577 -> [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 0 - WIFI_READY
14:27:07.577 -> [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
14:27:07.743 -> [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 4 - STA_CONNECTED
14:27:07.743 -> [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 7 - STA_GOT_IP
14:27:07.743 -> [D][WiFiGeneric.cpp:381] _eventCallback(): STA IP: 100.64.41.31, MASK: 255.255.255.0, GW: 100.64.41.1
14:27:08.075 -> .
14:27:08.075 -> ezTime debug level set to INFO
14:27:08.075 -> Waiting for time sync
14:27:08.307 -> Querying pool.ntp.org ... success (round trip 319 ms)
14:27:08.639 -> Received time: Sunday, 01-Dec-19 22:27:08.732 UTC
14:27:08.639 -> Time is in sync
14:27:08.639 -> Network online
14:27:08.639 -> 
14:27:08.639 -> connecting to checkip.dyndns.org
14:27:11.624 -> HTTP/1.1 200 OK
14:27:11.624 -> Content-Type: text/html
14:27:11.624 -> Server: DynDNS-CheckIP/1.2.0
14:27:11.624 -> Connection: close
14:27:11.624 -> Cache-Control: no-cache
14:27:11.624 -> Pragma: no-cache
14:27:11.624 -> Content-Length: 107
14:27:11.624 -> 
14:27:11.624 -> <html><head><title>Current IP Check</title></head><body>Current IP Address: 135.x.x.x</body></html>
14:27:11.658 -> closing connection
dorkmatt commented 4 years ago

Compiling w/o EZTIME_ETHERNET results in the "No network" error.

Compiling w/ EZTIME_ETHERNET defined, it looks like the initial NTP query begins prior the network being ready (before DHCP lease is issued) and then blocks (never execs loop function).

Compiling w/o EZTIME_ETHERNET defined and commenting out EZTIME_ETHERNET conditional under queryNTP seems to make it work with the wired ethernet port. My guess this is due to a slight fluke that WiFi.status() == WL_CONNECTED when using the wired port.

MassiPi commented 3 years ago

hello i can't get the library to work with ethernet with an esp8266 with 3.0.0 core. how did you fix that? thanks

mattygsa commented 2 years ago

HI folks. I.ve been having these issues trying to get a LAN8720 working with my eztime.h enabled sketch. I've tried variations on the above suggestions and was wondering if anyone has any further advice. I've not managed to get eztime to successfully query the pool.ntp.org and return the UTC time. It seems to hung up at that point and never goes beyond.