ESP8266: Get Date and Time from HTTP Header

Instead of sending NTP packets to remote time server as in a previous blog post the date and the time can also be extracted from any HTTP header returned after an HTTP GET request. Usually the HTTP header contains the date and the time from the router. This way the local network must not be left necessarily. For illustration purposes only a well-known URL is used in this example.

Components used

Adafruit Feather Huzzah
Monochrome OLED display

Wiring

Adafruit Feather Huzzah OLED Display
3,3 V 3,3 V
GND GND
SDA (4)  SDA
SCL (5)  SCL

Software

This Arduino sketch shows

  • how to connect to the WiFi network
  • how to perform an HTTP GET request on an URL (could be an IP address as well)
  • how to extract date and time from the HTTP response header
  • how to display date and time on an OLED display .

Code

#include <EEPROM.h>
#include <ESP8266WiFi.h>    // http://esp8266.github.io/Arduino/versions/2.0.0/doc/libraries.html
#include <WiFiClient.h>     // https://www.arduino.cc/en/Reference/WiFiClient

// OLED ESP_ssd1306_128x64_I2C
#include <ESP_SSD1306.h>    // Modification of Adafruit_SSD1306 for ESP8266 compatibility
#include <Adafruit_GFX.h>   // Needs a little change in original Adafruit library (See README.txt file)
#include <SPI.h>            // For SPI comm (needed for not getting compile error)
#include <Wire.h>           // For I2C comm, but needed for not getting compile error

boolean debug=true;

// WiFi connection data
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

const char* server = "www.google.de"; 	// an example URL
const int serverPort = 80;		// a port number
const char* resource = "/";       	// http resource

const unsigned long BAUD_RATE = 115200;	// serial connection speed
const unsigned long HTTP_TIMEOUT = 10000;   // max respone time from server

void initSerial();
void connectWiFi();
bool connect(const char* hostName, const int port);
void disconnect();
bool sendRequest(const char* host, const char* resource);
WiFiClient client;

#define OLED_RESET  16  // Pin 16 -RESET digital signal
ESP_SSD1306 display(OLED_RESET); // FOR I2C

void initOLEDDisplay();
void showDateAndTime();

bool findDateAndTimeInResponseHeaders();
String extractDayFromDateTimeString(String dateTime);
String extractMonthFromDateTimeString(String dateTime);
String extractYearFromDateTimeString(String dateTime);
String extractHourFromDateTimeString(String dateTime);
String extractMinuteFromDateTimeString(String dateTime);
String translateMonth(String monthStr);
String dateAndTime; // stores date and time from HTTP response header

unsigned long previousMillis = 0;
#define INTERVAL_MS 10000

void setup() {
  if( debug ) Serial.println("setup");
  initSerial();
  initOLEDDisplay();
  connectWiFi();
} // setup()

void loop() {

  unsigned long currentMillis = millis();
  // run every 10 seconds
  if (currentMillis - previousMillis >= INTERVAL_MS) {
    previousMillis = currentMillis;
	if( debug ) Serial.println("loop: get date and time");

	  if( connect(server, serverPort) ) {
		if( sendRequest(server, resource) ) {
		  if( findDateAndTimeInResponseHeaders() ) {
			if( debug ) {
			  Serial.print( "Date and Time from HTTP response header: " );
			  Serial.println( dateAndTime.c_str() );
			}
			showDateAndTime();
		  }
		}
		disconnect();
	  }
  }
} // loop()

// initialize serial port
void initSerial() {
  Serial.begin(BAUD_RATE);
  while (!Serial) {
    ;  // wait for serial port to initialize
  }
  if( debug ) Serial.println("Serial ready");
}

void initOLEDDisplay() {
  // SSD1306 Init
  display.begin(SSD1306_SWITCHCAPVCC);  // Switch OLED
  display.clearDisplay();
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();
}

// attempt to connect to WiFi
void connectWiFi() {
  WiFi.mode(WIFI_STA);
  // connect to the WiFi network
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    if( debug ) Serial.print(".");
  }
  if( debug ) {
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  }
}

// Open connection to the HTTP server
bool connect(const char* hostName, const int port) {
  if( debug ) {
    Serial.print("Connect to ");
    Serial.println(hostName);
  }
  bool ok = client.connect(hostName, port);
  if( debug ) Serial.println(ok ? "Connected" : "Connection Failed!");
  return ok;
}
/* example  curl -vv http://www.google.de
* About to connect() to www.google.de port 80 (#0)
*   Trying 172.217.17.227...
* Connected to www.google.de (172.217.17.227) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.google.de
> Accept: * / *
*/
/* example response:
< HTTP/1.1 200 OK
< Date: Sun, 29 May 2016 10:00:14 GMT */ // Send the HTTP GET request to the server bool sendRequest(const char* host, const char* resource) {      if( debug ) {         Serial.print("GET ");         Serial.println(resource);     }     client.print("GET ");     client.print(resource);     client.println(" HTTP/1.1");     client.print("Host: ");     client.println(host);     client.println("Accept: */*");     client.println("Connection: close");     client.println();     return true;  }  bool findDateAndTimeInResponseHeaders() {     // date and time string starts with Date: and ends with GMT     // example: Date: Sun, 29 May 2016 10:00:14 GMT     client.setTimeout(HTTP_TIMEOUT);     char header[85];     size_t length = client.readBytes(header, 85);     header[length] = 0;     String headerString = String(header);     int ds = headerString.indexOf("Date: ");     int de = headerString.indexOf("GMT");     dateAndTime = headerString.substring(ds+6, de);     // date and time: Sun, 29 May 2016 10:00:14     if( debug ) {       Serial.print("HTTP response header ");       Serial.println(headerString.c_str());       Serial.print("index start date ");       Serial.println(ds);       Serial.print("index end time ");       Serial.println(de);       Serial.println(  );       Serial.print("date and time: ");       Serial.println(dateAndTime.c_str());     }    return dateAndTime.length()&amp;gt;15;
}

// Close the connection with the HTTP server
void disconnect() {
  if( debug ) Serial.println("Disconnect from HTTP server");
  client.stop();
}

//-------- time+date code ----------
// example: Sun, 29 May 2016 10:00:14
String extractDayFromDateTimeString(String dateTime) {
  uint8_t firstSpace = dateTime.indexOf(' ');
  String dayStr = dateTime.substring(firstSpace+1, firstSpace+3);
  if( debug ) {
    Serial.print("Day: ");
    Serial.println(dayStr.c_str());
  }
  return dayStr;
}

String extractMonthFromDateTimeString(String dateTime) {
  uint8_t firstSpace = dateTime.indexOf(' ', 7);
  String monthStr = dateTime.substring(firstSpace+1, firstSpace+4);
  if( debug ) {
    Serial.print("Month: ");
    Serial.println(monthStr.c_str());
  }
  return monthStr;
}

String extractYearFromDateTimeString(String dateTime) {
  uint8_t firstSpace = dateTime.indexOf(' ', 10);
  String yearStr = dateTime.substring(firstSpace+1, firstSpace+5);
  if( debug ) {
    Serial.print("Year: ");
    Serial.println(yearStr.c_str());
  }
  return yearStr;
}

String extractHourFromDateTimeString(String dateTime) {
  uint8_t firstColon = dateTime.indexOf(':');
  String hourStr = dateTime.substring(firstColon, firstColon-2);
  if( debug ) {
    Serial.print("Hour (GMT): ");
    Serial.println(hourStr.c_str());
  }
  // adjust GMT time
  int h = hourStr.toInt();
  h += 2; // summertime
  //h += 1; // wintertime
  if( debug ) {
    Serial.print("Hour (adjusted for summertime): ");
    Serial.println(h);
  }
  return String(h);
}

String extractMinuteFromDateTimeString(String dateTime) {
  uint8_t secondColon = dateTime.lastIndexOf(':');
  String minuteStr = dateTime.substring(secondColon, secondColon-2);
  if( debug ) {
    Serial.print("Minute: ");
    Serial.println(minuteStr.c_str());
  }
  return minuteStr;
}

String extractDayFromCalendarDate(String date) {
  String dateStr = String(date);
  uint8_t firstDot = dateStr.indexOf('.');
  String dayStr = dateStr.substring(1, firstDot);
  if( debug ) {
    Serial.print("Day: ");
    Serial.println(dayStr.c_str());
  }
  return dayStr;
}

String translateMonth(String monthStr) {
  if(monthStr.equals(String("Jan"))) return String("01");
  if(monthStr.equals(String("Feb"))) return String("02");
  if(monthStr.equals(String("Mar"))) return String("03");
  if(monthStr.equals(String("Apr"))) return String("04");
  if(monthStr.equals(String("May"))) return String("05");
  if(monthStr.equals(String("Jun"))) return String("06");
  if(monthStr.equals(String("Jul"))) return String("07");
  if(monthStr.equals(String("Aug"))) return String("08");
  if(monthStr.equals(String("Sep"))) return String("09");
  if(monthStr.equals(String("Oct"))) return String("10");
  if(monthStr.equals(String("Nov"))) return String("11");
  if(monthStr.equals(String("Dec"))) return String("12");
}

void showDateAndTime() {
  display.clearDisplay();

  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  String date = extractDayFromDateTimeString(dateAndTime);
  date += ".";
  date += translateMonth(extractMonthFromDateTimeString(dateAndTime));
  date += ".";
  date += extractYearFromDateTimeString(dateAndTime);
  display.println(date.c_str());
  String timeStr = extractHourFromDateTimeString(dateAndTime);
  timeStr += ":";
  timeStr += extractMinuteFromDateTimeString(dateAndTime);
  display.setCursor(30, 35);
  display.println(timeStr.c_str());

  display.display();
}

Results

oled_blog
Date and time extracted from HTTP response header on OLED display
Advertisements

Ein Gedanke zu “ESP8266: Get Date and Time from HTTP Header

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s