Closed heinemannj closed 4 years ago
see SNTPTime.ino example it works only with AT Lobo builds
Hi Juraj, yes for sure - actually it works not with the official Espressif versions ... But I'm pretty sure you are able to implement ...
I have already a workarrounf by using
Cheers Joerg
the official AT firmware doesn't have a command to return time in epoch seconds. parsing the display format of AT+CIPSNTPTIME? is something I am not willing to code. It would make the library larger.
the AT 2 has AT+SYSTIMESTAMP?
. you could ask Espressif here to add it to 1.7.3 too
OK - Your view is fully understandable.
I have open an issue at Espressif: https://github.com/espressif/ESP8266_NONOS_SDK/issues/297
As a workarround
#include <WiFiEspAT.h>
#include <NTPClient.h>
#include <TimeLib.h>
// Baud rate for communication with Monitor Port
#define MONITOR_BAUD_RATE 115200 // Works reliable over USB
// Baud rate for communication with AT firmware
#define AT_BAUD_RATE 500000 // For Arduino Mega over Hardware Serial "500000" baud works good
//#define AT_BAUD_RATE 200000
//#define AT_BAUD_RATE 115200 // Over Hardware Serial AT Firmware's Default "115200" baud works reliably
// Serial port for communication with AT firmware
//#define SerialAT Serial1
//#define SerialAT Serial2
#define SerialAT Serial3
// Number of the LED pin
//#define LedPin LED_BUILTIN
#define LedPin 13
// Time server pool
// Offset in seconds - Can be changed later with setTimeOffset()
// Update interval in milliseconds - Can be changed using setUpdateInterval()
const char* ntpServer = "us.pool.ntp.org";
const long ntpTimeOffset = 3600;
const unsigned long ntpUpdateInterval = 3600000;
//=======================================================================
// LED blink
//=======================================================================
void blink(int interval) {
digitalWrite(LedPin, HIGH);
if (interval > 0) {
delay(interval);
digitalWrite(LedPin, LOW);
delay(interval);
} else {
digitalWrite(LedPin, LOW);
}
}
//=======================================================================
// Setup Wifi
//=======================================================================
IPAddress wifiIP;
uint8_t wifiMac[6];
char wifiMacStr[18];
char wifiHostname[33];
long wifiRssi;
void setup_wifi() {
// Initialize Serial port for communication with the WiFi module
SerialAT.begin(AT_BAUD_RATE);
WiFi.init(SerialAT);
// Check if Serial port for communication with the WiFi module is working
if (WiFi.status() == WL_NO_MODULE) {
Serial.println();
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true) {
blink(100);
}
}
// Disable ESP deep sleep mode
Serial.println("Sending AT deep sleep change (disable deep sleep) ...");
SerialAT.println("AT+SLEEP=0");
blink(500);
// Disable default automatic start of persistent AP
WiFi.endAP(true);
// Waiting for connection to Wifi network set with the SetupWiFiConnection sketch
Serial.println("Waiting for connection to WiFi");
while (WiFi.status() != WL_CONNECTED) {
blink(500);
Serial.print('.');
}
Serial.println();
Serial.println("Connected to WiFi network.");
// SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// Your WiFi shield's IP address:
wifiIP = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(wifiIP);
// Your WiFi shield's MAC address
WiFi.macAddress(wifiMac);
snprintf(wifiMacStr, sizeof(wifiMacStr), "%02X:%02X:%02X:%02X:%02X:%02X", wifiMac[5], wifiMac[4], wifiMac[3], wifiMac[2], wifiMac[1], wifiMac[0]);
Serial.print("MAC Address: ");
Serial.println(wifiMacStr);
// Your WiFi shield's hostname:
WiFi.hostname(wifiHostname);
Serial.print("Hostname: ");
Serial.println(wifiHostname);
// The received WiFi signal strength:
wifiRssi = WiFi.RSSI();
Serial.print("Signal Strength (RSSI): ");
Serial.print(wifiRssi);
Serial.println(" dBm");
}
//=======================================================================
// Setup (Main)
//=======================================================================
// For NTP client
WiFiUDP UDP;
NTPClient timeClient(UDP, ntpServer, ntpTimeOffset, ntpUpdateInterval);
void setup() {
// Initial LED state
pinMode(LedPin, OUTPUT);
digitalWrite(LedPin, LOW);
// Initialize Serial Monitor
Serial.begin(MONITOR_BAUD_RATE);
// Initialize WiFi
setup_wifi();
// Initialize NTP client
timeClient.begin();
setSyncProvider(&ntpSyncProvider);
}
//=======================================================================
// Synchronization with NTP server / Update localtime
//=======================================================================
time_t ntpSyncProvider() {
// Waiting for synchronization with NTP server
for (int i = 0; i < 5; i++) {
if (timeClient.forceUpdate()) {
return timeClient.getEpochTime();
} else {
blink(5);
}
}
return timeClient.getEpochTime();
}
//=======================================================================
// Loop (Main)
//=======================================================================
void loop() {
char buff[20];
sprintf(buff, "%02d-%02d-%02d %02d:%02d:%02d", year(), month(), day(), hour(), minute(), second());
Serial.println(buff);
delay(1000);
}
I ran into the same problem while using an ESP8285.
As a quick solution I hacked the functions sntpCfg() and sntpTime() in my EspAtDrv.cpp as shown below. To activate the new parts of code, the macro WIFIESP8285 has to be defined.
bool EspAtDrvClass::sntpCfg(int8_t timezone, const char* server1, const char* server2) {
maintain();
LOG_INFO_PRINT_PREFIX();
LOG_INFO_PRINTLN(F("SNTP config"));
#ifdef WIFIESP8285
timezone = 0; // The ESP8285 prints a timestamp including the timezone offset. We don't want to have this for our Unixtime.
#endif
cmd->print(F("AT+CIPSNTPCFG=1,"));
cmd->print(timezone);
cmd->print(",\"");
cmd->print(server1);
if (server2) {
cmd->print((FSH_P) QOUT_COMMA_QOUT);
cmd->print(server2);
}
cmd->print('"');
return sendCommand();
}
unsigned long EspAtDrvClass::sntpTime() {
maintain();
LOG_INFO_PRINT_PREFIX();
LOG_INFO_PRINTLN(F("SNTP time"));
#ifdef WIFIESP8285
// Output of AT+CIPSNTPTIME? is +CIPSNTPTIME:Sun Sep 26 13:24:51 2021
cmd->print(F("AT+CIPSNTPTIME?"));
if (!sendCommand(PSTR("+CIPSNTPTIME")))
return 0;
uint32_t y, m, d, hh, mm, ss; // We use 32 bits for all variables for easier calculations later.
// Name of Day (not used)
char* tok = strtok(buffer + strlen("+CIPSNTPTIME:"), " ");
// Month
tok = strtok(NULL, " ");
switch( *tok )
{
case 'J': // Jan, Jun, Jul
if( *(tok+1) == 'a' ) // Jan
{
m = 1;
}
else if( *(tok+2) == 'n' ) // Jun
{
m = 6;
}
else // Jul
{
m = 7;
}
break;
case 'F': // Feb
m = 2;
break;
case 'M': // Mar
m = 3;
break;
case 'A': // Apr
m = 8;
break;
case 'S': // Sep
m = 9;
break;
case 'O': // Oct
m = 10;
break;
case 'N': // Nov
m = 11;
break;
case 'D': // Dec
m = 12;
break;
default: // Error
m = 0;
break;
}
// Day
tok = strtok(NULL, " ");
d = strtoul(tok, NULL, 10);
// Time
tok = strtok(NULL, " ");
hh = 10 * (*(tok+0) - '0') + (*(tok+1) - '0');
mm = 10 * (*(tok+3) - '0') + (*(tok+4) - '0');
ss = 10 * (*(tok+6) - '0') + (*(tok+7) - '0');
// Year
tok = strtok(NULL, " ");
//yOff = strtoul(tok, NULL, 10) - 2000;
y = strtoul(tok, NULL, 10);
// Convert to Epoch
uint8_t daysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
uint32_t yday;
uint8_t i;
yday = d;
for (i = 1; i < m; i++)
yday += daysInMonth[i-1];
if(m > 2)
{
// Detect leap years
if( ((y % 4 == 0) && (y % 100!= 0)) || (y%400 == 0) )
{
yday++;
}
}
y = y - 1900;
yday = yday - 1; // The following formula uses "days since January 1 of the year".
// Formula from https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15
unsigned long res = ss + mm*60 + hh*3600 + yday*86400 + (y-70)*31536000 + ((y-69)/4)*86400 - ((y-1)/100)*86400 + ((y+299)/400)*86400;
#elif defined WIFIESPAT1
cmd->print(F("AT+SNTPTIME?")); // AT LoBo firmware command
if (!sendCommand(PSTR("+SNTPTIME")))
return 0;
char* tok = strtok(buffer + strlen("+SNTPTIME:"), ",");
unsigned long res = strtoul(tok, NULL, 10);
#else
cmd->print(F("AT+SYSTIMESTAMP?"));
if (!sendCommand(PSTR("+SYSTIMESTAMP")))
return 0;
unsigned long res = strtoul(buffer + strlen("+SYSTIMESTAMP:"), NULL, 10);
#endif
readOK();
return res;
}
The code is a first quick & dirty version and could - for sure - be optimized. Maybe this helps someone.
There is a important bug: case 'A': // Apr m = 8; break
Must be = 4 and miss Aug
I have modified EspAtDrv.cpp with the command sets by ESP8266 AT Firmware, officially launched by Espressif.
But I#m runnig into below issue:
// Initialize NTP client WiFi.sntp(ntpTimeZone, ntpServer);
15:23:49.265 -> esp INFO: SNTP config 15:23:49.265 -> esp> AT+CIPSNTPCFG=1,1,"192.168.178.1" ...sent 15:23:49.265 -> esp> OK ...matched
for (int i = 0; i < 5; i++) { setTime(WiFi.getTime()); }
15:23:49.265 -> esp INFO: SNTP time 15:23:49.265 -> esp> AT+CIPSNTPTIME? ...sent 15:23:49.265 -> esp> +CIPSNTPTIME:Thu Jan 01 00:00:00 1970 ...matched 15:23:49.265 -> esp> OK ...matched 15:23:49.265 -> esp INFO: SNTP time 15:23:49.265 -> esp> AT+CIPSNTPTIME? ...sent 15:23:49.299 -> esp> +CIPSNTPTIME:Thu Jan 01 00:00:00 1970 ...matched 15:23:49.299 -> esp> OK ...matched 15:23:49.299 -> esp INFO: SNTP time 15:23:49.299 -> esp> AT+CIPSNTPTIME? ...sent 15:23:49.299 -> esp> +CIPSNTPTIME:Thu Feb 06 15:23:50 2020 ...matched 15:23:49.299 -> esp> OK ...matched 15:23:49.299 -> esp INFO: SNTP time 15:23:49.299 -> esp> AT+CIPSNTPTIME? ...sent 15:23:49.299 -> esp> +CIPSNTPTIME:Thu Feb 06 15:23:50 2020 ...matched 15:23:49.335 -> esp> OK ...matched
Serial.println(WiFi.getTime()); Serial.println(now());
char buff[20]; sprintf(buff, "%02d-%02d-%02d %02d:%02d:%02d", year(), month(), day(), hour(), minute(), second()); Serial.println(buff);
15:32:05.210 -> 0 15:32:05.210 -> 0 15:32:05.210 -> 1970-00-00 00:00:00
Can you please adapt SNTP functions to the official commands? ESP8266 NonOS AT Bin V1.7.1