Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WiFi.getTime() function on WiFiS3 library doesn't work #206

Closed
tigoe opened this issue Dec 13, 2023 · 4 comments · Fixed by #394
Closed

WiFi.getTime() function on WiFiS3 library doesn't work #206

tigoe opened this issue Dec 13, 2023 · 4 comments · Fixed by #394
Assignees
Labels
conclusion: resolved Issue was resolved topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project

Comments

@tigoe
Copy link
Member

tigoe commented Dec 13, 2023

The getTime() function in the WiFiS2 library never gets the time via NTP.

Here's a test:

#include <WiFiS3.h>            // use this for the Uno R4 WiFi board
#include "arduino_secrets.h"  // put SECRET_SSID and SECRET_PASS here

// the epoch time, obtained from the network:
unsigned long epoch = 0;

void setup() {
  // initialize serial:
  Serial.begin(9600);
}

void loop() {
  // if not connected, attempt to connect:
  if (WiFi.status() != WL_CONNECTED) {
    connectToNetwork();
  }
}

void connectToNetwork() {
  Serial.print("Attempting to connect to network ");
  Serial.println(SECRET_SSID);
  // try to connect to the network:
  while (WiFi.status() != WL_CONNECTED) {
    //Connect to WPA / WPA2 network:
    WiFi.begin(SECRET_SSID, SECRET_PASS);
    delay(2000);
  }
  // print out the device's network status:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  // print the signal strength:
  Serial.print("Signal Strength: ");
  Serial.println(WiFi.RSSI());
  // get network time:
  getNetworkTime();
}

void getNetworkTime() {
  do {
    epoch = WiFi.getTime();
    delay(2000);
    Serial.println("NTP request attempt");
  } while (epoch <= 0);
}

When you run this on the Uno R4 WiFi, it'll compile, but you'll get an endless stream of "NTP request attempt" messages.

@tigoe tigoe added the type: imperfection Perceived defect in any part of project label Dec 13, 2023
@JAndrassy
Copy link
Contributor

unsigned long CWifi::getTime() {
return 0;
}

@per1234 per1234 added the topic: code Related to content of the project itself label Dec 13, 2023
@tigoe
Copy link
Member Author

tigoe commented Dec 13, 2023

I took the example from the WiFi libraries that Michael Margolis originally wrote, did some digging in the NTP RFC, and re-wrote it into a generic function. This should work with any of the WiFi libraries, and could also be submitted to Espressif as a pull request for the ESP32 library. I tested it there too. It requires the UDP library though:
#include <WiFiUdp.h>

// send an NTP request and wait for the result:
// Thanks to Michael Margolis for the original inspiration and RFC 5905 for the details. 
unsigned long getTime() {
  WiFiUDP Udp;
  Udp.begin(localPort);
  // NTP timestamp packet is 48 bytes:
  const int NTP_PACKET_SIZE = 48;
  // diff between NTP result and current UTC epoch is 70 years in seconds:
  const unsigned long SEVENTY_YEARS = 2208988800UL;
  // byte buffer for NTP packet:
  byte packetBuffer[NTP_PACKET_SIZE];
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // simplest NTP request needs only the leap indicator, NTP version, and mode.
  // see RFC5905: https://datatracker.ietf.org/doc/html/rfc5905
  packetBuffer[0] = 0b00100011;  // Leap indicator 0, version 4, mode 3
                                 // send request to pool.ntp.org, port 123:

  Udp.beginPacket("pool.ntp.org", 123);
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
  // wait for return packet:
  while (!Udp.parsePacket())
    ;
  // Parse the return packet:
  Udp.read(packetBuffer, NTP_PACKET_SIZE);
  //the timestamp  (32 bit integer) starts at byte 40
  // of the received packet:
  unsigned long result = 0;
  for (byte b = 40; b < 44; b++) {
    // shift the whole thing over 8 bits, and add the next byte:
    result = (result << 8) | packetBuffer[b];
  }
  // subtract the time since 1900:
  result = result - SEVENTY_YEARS;
  return result;
}

@JAndrassy
Copy link
Contributor

JAndrassy commented Dec 14, 2023

Espressif has NTP time in the SDK.

  configTime(gmtOffset_sec, daylightOffset_sec, "pool.ntp.org");
  time_t now = time(nullptr);
  while (now < SECS_YR_2000) {
    delay(100);
    now = time(nullptr);
  }

I plan to do the getTime implementations.

@paulvha
Copy link
Contributor

paulvha commented Feb 15, 2024

created a pull request to add gettime.
The user provide POSIX timezone & daylight saving information for the current location.
The output can be formatted according to the strftime()
Requires both the core and bridge to be updated. Also includes an example to demonstrate the usage.

regards,
Paul

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
conclusion: resolved Issue was resolved topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project
Projects
None yet
5 participants