Solar powered outdoor weather sensor

To be independent of a plug socket for an outdoor weather sensor solar power looks a lot more promising than wind or water for power generation. 😉 Especially since simple solar panels for tinkering are available for little money in the meantime. Only shipping from China usually takes a couple of weeks.

Earlier this year I launched my personal outdoor weather sensor to collect weather data such as temperature, humidity and air pressure. So far this required a plug socket and a 5V power supply. For the future I plan to use a solar panel to load a rechargeable battery which will alternatively power the outdoor weather sensor. Well, at least, when outside temperatures allow. During wintertime the cold temperatures might shorten the life of the rechargeable battery. Therefore, in the cold season the 5V power supply can be used alternatively.

Components used

Outdoor weather sensor
5V solar panel
Lithium battery 3,7 V, 2500 mAh
Lithium battery charger
Step up power supply

Wiring

Starting from the solar panel the wires go to the input of the charger module. The charger is connected to the battery and the step up power supply. The output lines of the step up power supply are soldered to the outdoor weather sensor. The battery should be removable to switch easily to a conventional 5V power supply.

The following sketch roughly illustrates the setup:

sketch

Adjusting the Step Up power supply

The desired output voltage of the step up power supply is 5V in this case. It can be adjusted by turning the small screw while the outgoing lines of the charger modules are connected to a multimeter measuring the voltage.

Notes

To fully charge the rechargeable battery it should be very sunny! Charging takes a couple of hours depending on the size of the battery. Since it is a lithium battery the memory effect known from NiMh or NiCd rechargeable batteries can be neglected.

As soon as the outdoor weather sensor is powered by an electric 5V power supply the battery should be removed! (Mentioned just in case.)

Result

Summers sunlight is optimal for charging a lithium battery and driving the outdoor weather sensor. This works in parallel. Since the outdoor weather sensor will spend most of the time in deep sleep mode the battery should last a while! So far I did not measure how mich power is drawn by awaking the outdoor weather sensor from deep sleep, doing the measurements, sending the measured values via WiFi to the server and going back to sleep. Perhaps later…

Well, now it is time to find a weather-proof box for all of this!

 

 

ESP8266: Switch WiFi Connections using RFID

It took me some time to find an example for using RFID (Radio Frequency IDentification) on an Arduino. RFID is commonly used for identification, tracking, etc. . RFID senders (tags) are so small that they can be implanted. I heard rumours that some humans already started to wear RFID senders under their skin! Brave new world… Imagine to turn on the coffee machine contactless by pointing at it with the index finger. Such a thought gives me the creeps.

However, the example I describe here switches the WiFi connection only depending on the RFID tag discovered. Easily expandable for different purposes!

Components used

Adafruit Feather Huzzah
Monochrome OLED display
RFID-RC522 receiver + matching RFID tags

Wiring

Adafruit Feather Huzzah RFID-RC522 OLED Display
3,3 V 3,3 V  3,3 V
GND GND GND
SDA (4) SDA
SCL (5) SCL
2 (Arduino Uno: 10) SDA
SCK/14 (Arduino Uno: 11) SCK
MO/13  MOSI
MI/12 MISO
16 * (Arduino Uno: 9)  RST

For SDA and Reset two free IO pins should be used on the ESP8266 module. These two pins will be initialized during setup.

The wiring of the RFID receiver to the ESP8266 module is described here as well, including a wiring diagram.

Software

The RFID Arduino library https://github.com/miguelbalboa/rfid can be used. The library can be downloaded from the github repository. The download folder rfid-master should be renamed to rfidmaster and should be copied to the Arduino IDE’s library directory.

During compilation the rfid library issues a warning that it is incompatible with STM32F1 architecture. But this seems to have no influence, the software is working in the end.

Sample Sketch

In this example the WiFi connection will be switched depending on the RFID tag that was recognized. The tags that can be used are hard coded.

#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

#include <SPI.h>
#include <MFRC522.h>

// 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;

// Arduino Uno
//#define SS_PIN 10 // SDA an Pin 10
//#define RST_PIN 9 // RST an Pin 9

// ESP8266 (Adafruit Feather Huzzah)
#define RST_PIN 15 // RST-PIN for RC522 - RFID - SPI - Modul GPIO15
#define SS_PIN  2  // SDA-PIN for RC522 - RFID - SPI - Modul GPIO2 

MFRC522 mfrc522(SS_PIN, RST_PIN); // RFID-Empfänger benennen

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

void initSerial();
void connectWiFi(const char* ssid, const char* password);
void disconnectWifi();
WiFiClient client;

const char* ssid1 = "SSID1";
const char* password1 = "PASSWORD1";
const char* ssid2 = "SSID2";
const char* password2 = "PASSWORD2";

const char* RFIDTAG1 = "IDe7b5f653";
const char* RFIDTAG2 = "ID2e6432";

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

void initOLEDDisplay();
void showConnection(const char* ssid);

void setup() {

  initSerial();
  if( debug ) Serial.println("setup");

  initOLEDDisplay();

  // start SPI connection
  // initialize RFID receiver
  SPI.begin();
  mfrc522.PCD_Init();
}

void loop() {

  // RFID-TAG is close
  if ( ! mfrc522.PICC_IsNewCardPresent() ) {
    return; // gehe weiter...
  }

  // RFID-TAG was detected
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return; // gehe weiter...
  }

  String tag = "ID";
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    // UID of RFID-TAG is read, consists of 4 single blocks
    tag += String(mfrc522.uid.uidByte[i], HEX);
  }
  if( debug ) {
    Serial.print("ID of RFID-TAG: ");
    Serial.print(tag.c_str());
    Serial.println();
  }

  // decide what to do for a certain tag
  if( tag == RFIDTAG1 ) {
    disconnectWifi();
    connectWiFi(ssid1, password1);
  }
  if( tag == RFIDTAG2 ) {
    disconnectWifi();
    connectWiFi(ssid2, password2);
  }
}

// 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(const char* ssid, const char* password) {
  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());
  }
  if( WiFi.status() == WL_CONNECTED ) {
    showConnection(ssid);
  } else {
    showConnection("-");
  }
}

void disconnectWifi() {
  WiFi.disconnect();
}

void showConnection(const char* ssid) {
  display.clearDisplay();

  display.setTextSize(2);
  display.setTextColor(WHITE);

  display.setCursor(0, 0);
  display.println("SSID");

  display.setCursor(0, 15);
  display.println(ssid);

  display.display();
}

This is how the test setup looks like:
RFID switch

ESP8266: Uploading Weather Data to openweathermap.org

A couple of months ago I designed a small weather station to measure weather data such as temperature,  humidity and barometric pressure using an ESP8266 module and a couple of sensors. How this outdoor weather sensor is constructed is described in an older blog post.

openweathermap.org allows to connect a home made weather station to its network of weather stations around the world (currently >40.000). This may help to improve the data which is provided by openweathermap.org.

Uploading measured weather data is easily accomplished by performing an HTTP POST to http://openweathermap.org/data/post using basic authentication.

This manual describes how to upload weather data. Which weather details may be submitted in the post is illustrated in the table of the manual.

Prerequisites

An account for openweathermap.org is required. The username and password must be translatedinto BASE64 encoding. This online tool helps to transfer username:password for openweathermap.org into the required format.

The location of the weather station is required as GPS coordinates. The latitude and the longitude of the location of the weather station can be determined with google maps for example. All it needs is to click on the location on the map. The coordinates will be displayed in a small window below the adress.

Components used

Outdoor weather sensor

Source Code

The Arduino sketch for the outdoor weather sensor may be enhanced. For brevity I concentrate in this example on the additional functionality required to upload the weather data, not on their measurement.

#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

boolean debug=true;
// WiFi connection data
const char* ssid = "SSID";
const char* password = "PASSWORD";

const char* server = "openweathermap.org";
const int serverPort = 80;

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);
bool sendPost(const char* hostName, float temperature, float humidity, float pressure);
void displayResponse();
void disconnect();
WiFiClient client;

unsigned long previousMillis = 0;
#define INTERVAL_MS 60000

#define CredentialsBase64 "sOmECRYPticStRiNggg" // enter here the BASE64 encoded credentials in the form &amp;amp;amp;lt;username&amp;amp;amp;gt;:&amp;amp;amp;lt;password&amp;amp;amp;gt;
// https://www.base64encode.org/enc/credential/
const String stationName = "MyOwnWeatherStation"; // enter the station name (it will be displayed on openweathermap.org)
// use coordinates from google maps
const String lat = "xx.xxxxx"; // latitude
const String lng = "yy.yyyyy"; // longitude
const String alt = "5"; // altitude of the location in meters without decimals

void setup() {
  initSerial();
  connectWiFi();
}

void loop() {
  unsigned long currentMillis = millis();
  // run every minute
  if (currentMillis - previousMillis >= INTERVAL_MS) {
    previousMillis = currentMillis;
    if( debug ) Serial.println("loop: measure weather data");
    float temperature=14.6;
    float humidity=89.1;
    float pressure=1004.6;
    // TODO use measured data from sensors!

    if( connect(server, serverPort) ) {
      if( sendPost(server, temperature, humidity, pressure) ) {
        displayResponse();
      }
    }
    disconnect();
  }
}

// send the HTTP POST request to the server
bool sendPost(const char* hostName, float temperature, float humidity, float pressure) {
  if( debug ) {
    Serial.print("POST weather data to");
    Serial.println(hostName);
    Serial.print("t = ");
    Serial.println(temperature);
    Serial.print("h = ");
    Serial.println(humidity);
    Serial.print("p = ");
    Serial.println(pressure);
  }

  // construct packet
  String packet = "";
  packet += "temp=";
  packet += (int)temperature;
  packet += "&humidity=";
  packet += (int)humidity;
  packet += "&pressure=";
  packet += (int)pressure;
  packet += "&lat=";
  packet += lat;
  packet += "&long=";
  packet += lng;
  packet += "&alt=";
  packet += alt;
  packet += "&name=";
  packet += stationName;

  // construct POST request
  String cmd = "POST /data/post HTTP/1.1\n";
  cmd += "Host: ";
  cmd += hostName;
  cmd += "\n";
  cmd += "Content-Type: application/x-www-form-urlencoded\n";
  cmd += "Authorization: Basic ";
  cmd += CredentialsBase64;
  cmd += "\n";
  cmd += "Content-Length: ";
  cmd += packet.length();
  cmd += "\n";
  cmd += "Connection: close\n\n";
  cmd += packet;
  cmd += "\r\n\r\n";

  if( debug ) {
    Serial.print("packet: ");
    Serial.println(packet);
    Serial.print("cmd: ");
    Serial.println(cmd);
  }
  client.println(cmd);
  return true;
}

void displayResponse() {
  client.setTimeout(HTTP_TIMEOUT);
  char reply[400];
  size_t length = client.readBytes(reply, 400);
  reply[length] = 0;
  String replyString = String(reply);

  if( debug ) {
    Serial.print("HTTP response ");
    Serial.println(replyString.c_str());
  }
}

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

// attempt to connect to WiFi
void connectWiFi() {
  WiFi.mode(WIFI_STA);
  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;
}

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

Notes

The HTTP POST to upload weather data boils down to

POST /data/post HTTP/1.1
Host: openweathermap.org
Content-Type: application/x-www-form-urlencoded
Authorization: Basic sOmECRYPticStRiNggg
Content-Length: 80
Connection: close

temp=20&humidity=71&pressure=1011&lat=49.11&long=24.11&alt=200&name=StationName

The content length is the length of the string containing the measured weather data, the coordinates etc. . More weather parameters may be added – everything that is measurable can be interesting for the upload.

How to find the own Weather Station

Finding the data from the own weather station after the upload was a bit tricky. It looks like openweathermap.org is working on improvements for uploading weather data as I conclude from this support answer. At least the documentation for upploading data needs improvements.

The station ID is returned in the HTTP response to the post. This is easy to miss. If the upload of weather data was successful the response should look similar to this:

HTTP response header HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Sat, 20 Aug 2016 11:37:00 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
X-Powered-By: Fat-Free Framework (http://fatfree.sourceforge.net)
Pragma: no-cache
Cache-Control: no-cache, must-revalidate

{"message":"","cod":"200","id":987654321}

The ID can be used to observe the station using the URL http://openweathermap.org/station/987654321 .

To retrieve the weather data from this station in JSON format an HTTP GET request can be performed using this URL in a browser:

http://api.openweathermap.org/data/2.5/station?id=987654321&APPID=<YOURAPPID&gt; .

With some delay the uploaded data becomes visible in JSON format:

{
"station":
{"name":"MyOwnWeatherStation",
"type":5,"status":20,"user_id":0,"id":987654321,
"coord":{"lon":y.yyyy,"lat":xx.xxxx}},
"last":{"main":{"temp":290.15,"humidity":69,"pressure":1030},
"dt":1471791637},
"params":["temp","pressure","humidity"]
}

Inspirational Links

https://github.com/Benjamin3992/OpenWeatherDuino

http://openweathermap.org/stations

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