#include <WiFi.h>
#include <HTTPClient.h>
#include <Arduino_JSON.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <Adafruit_SSD1306.h>

// ICONS START

  // Array bytes of the Weather icons

  const unsigned char cloudy [] PROGMEM = {
    // 'cloudy', 60x53px
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xf0,
    0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0xf0,
    0xff, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0xff, 0xf0, 0xff, 0xff, 0xff, 0x80, 0x00, 0x1f, 0xff, 0xf0,
    0xff, 0xff, 0xff, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xf0,
    0xff, 0xff, 0xfe, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x07, 0xff, 0xf0,
    0xff, 0xff, 0xc0, 0x00, 0x00, 0x03, 0xff, 0xf0, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xf0,
    0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xf0,
    0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x07, 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0,
    0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0,
    0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0,
    0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x03, 0xf0,
    0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x07, 0xf0, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0,
    0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf0,
    0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0,
    0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0,
    0xfe, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0,
    0xfe, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0,
    0xfe, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0,
    0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0,
    0xff, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0,
    0xff, 0xe0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0
  };
  const unsigned char drizzle [] PROGMEM = {
    // 'drizzle', 59x55px
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xfc, 0x01, 0xff, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xc0, 0x00, 0x07, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xc0, 0x00, 0x07, 0xff, 0xff, 0xe0, 0xff, 0xfe, 0x07, 0xff, 0x80, 0xff, 0xff, 0xe0,
    0xff, 0xfc, 0x1f, 0xff, 0xe0, 0x7f, 0xff, 0xe0, 0xff, 0xf8, 0x3f, 0xff, 0xf8, 0x7f, 0xff, 0xe0,
    0xff, 0xf8, 0x3f, 0xff, 0xf8, 0x7f, 0xff, 0xe0, 0xff, 0xf0, 0x3f, 0xff, 0xfc, 0x7f, 0xff, 0xe0,
    0xff, 0xe0, 0x3f, 0xff, 0xfe, 0x01, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xe0,
    0xff, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xe0, 0xff, 0x81, 0xff, 0xff, 0xff, 0x00, 0x07, 0xe0,
    0xff, 0x81, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xe0, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xe0,
    0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xe0, 0xfe, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xe0,
    0xfc, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x60, 0xe0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x20,
    0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x20, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
    0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
    0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
    0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
    0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x20, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x20,
    0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x60, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x60,
    0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xe0,
    0xe0, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xe0, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0,
    0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0,
    0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xf1, 0xff, 0x1f, 0xfb, 0xff, 0x0f, 0xe0,
    0xff, 0x80, 0xfc, 0x0f, 0xe1, 0xfe, 0x0f, 0xe0, 0xff, 0x80, 0xfc, 0x0f, 0xc1, 0xfc, 0x0f, 0xe0,
    0xff, 0x01, 0xf8, 0x1f, 0x81, 0xf8, 0x0f, 0xe0, 0xfe, 0x03, 0xf0, 0x3f, 0x07, 0xe0, 0x3f, 0xe0,
    0xfc, 0x1f, 0xc3, 0xf8, 0x07, 0x80, 0xff, 0xe0, 0xfc, 0x7f, 0xc3, 0xf8, 0x1f, 0x81, 0xff, 0xe0,
    0xfc, 0x7f, 0xc3, 0xf8, 0x3f, 0x87, 0xff, 0xe0, 0xfc, 0xff, 0xc7, 0xfc, 0x7f, 0x8f, 0xff, 0xe0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0
  };
  const unsigned char rain [] PROGMEM = {
    // 'rain', 59x55px
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xf8, 0x00, 0x01, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xe0, 0x00, 0x00, 0x7f, 0xff, 0xe0, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x3f, 0xff, 0xe0,
    0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xe0,
    0xff, 0xff, 0x80, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0,
    0xff, 0xe0, 0x00, 0x00, 0x00, 0x07, 0xff, 0xe0, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0,
    0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0,
    0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0,
    0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0,
    0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0,
    0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0,
    0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0,
    0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0,
    0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0,
    0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xe0,
    0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0,
    0xff, 0xfe, 0x00, 0x00, 0x00, 0x03, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xe7, 0xfd, 0xff, 0x3f, 0xff, 0xe0, 0xff, 0xff, 0xe7, 0xf9, 0xff, 0x3f, 0xff, 0xe0,
    0xff, 0xff, 0xe1, 0xf8, 0xfe, 0x1f, 0xff, 0xe0, 0xff, 0xff, 0xc1, 0xf8, 0xfe, 0x1f, 0xff, 0xe0,
    0xff, 0xff, 0x87, 0xf1, 0xfc, 0x3f, 0xff, 0xe0, 0xff, 0xff, 0x07, 0xe1, 0xf0, 0x3f, 0xff, 0xe0,
    0xff, 0xff, 0x0f, 0xe3, 0xe0, 0x7f, 0xff, 0xe0, 0xff, 0xfe, 0x0f, 0xc3, 0xe0, 0x7f, 0xff, 0xe0,
    0xff, 0xfc, 0x1f, 0xc7, 0xc0, 0xff, 0xff, 0xe0, 0xff, 0xfe, 0x3f, 0xc7, 0xe1, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0
  };
  const unsigned char snow [] PROGMEM = {
    // 'snow(1)', 57x58px
    0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0x80,
    0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0x80,
    0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0x80,
    0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xb0, 0xff, 0xff, 0xff, 0x80,
    0xff, 0xe0, 0xff, 0x00, 0x07, 0xf0, 0x7f, 0x80, 0xff, 0xc0, 0xf3, 0x00, 0x0f, 0xf0, 0x7f, 0x80,
    0xff, 0xc0, 0xf3, 0x00, 0x0c, 0xf0, 0x3f, 0x80, 0xff, 0xc0, 0xe3, 0xc0, 0x1c, 0xf0, 0x3f, 0x80,
    0xff, 0xe0, 0x03, 0xe0, 0x3c, 0x60, 0x3f, 0x80, 0xff, 0xf0, 0x03, 0xf0, 0x7c, 0x00, 0x3f, 0x80,
    0xff, 0xfe, 0x03, 0xf0, 0xfc, 0x03, 0xff, 0x80, 0xff, 0xff, 0x03, 0xf0, 0xfc, 0x07, 0xff, 0x80,
    0xff, 0xfe, 0x01, 0xf0, 0xfc, 0x07, 0xff, 0x80, 0xff, 0xfc, 0x00, 0xf0, 0xfc, 0x03, 0xff, 0x80,
    0xff, 0xf0, 0x00, 0xf0, 0xf8, 0x00, 0xff, 0x80, 0xff, 0xf0, 0x00, 0x70, 0xf0, 0x00, 0xff, 0x80,
    0xff, 0xff, 0xf0, 0x30, 0xe0, 0x1f, 0xff, 0x80, 0xff, 0xef, 0xf8, 0x10, 0xe0, 0xff, 0xff, 0x80,
    0xff, 0xc3, 0xec, 0x00, 0x01, 0xfe, 0x7f, 0x80, 0xff, 0xe3, 0xfe, 0x00, 0x03, 0xfc, 0x7f, 0x80,
    0xff, 0xe1, 0xff, 0x00, 0x03, 0xfc, 0x7d, 0x80, 0xf8, 0xe0, 0x7f, 0x00, 0x07, 0xf0, 0xff, 0x80,
    0xf0, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0xf0, 0x80, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x60, 0x80,
    0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
    0xf0, 0xe0, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xe1, 0xfe, 0x00, 0x00, 0x00, 0x21, 0x80,
    0xff, 0xe3, 0xfc, 0x00, 0x0f, 0xf0, 0x77, 0x80, 0xff, 0xc3, 0xfc, 0x00, 0x0f, 0xf8, 0x7f, 0x80,
    0xff, 0xe7, 0xf8, 0x00, 0x07, 0xfc, 0x7f, 0x80, 0xff, 0xff, 0xf0, 0x30, 0x03, 0xfc, 0x7f, 0x80,
    0xff, 0xff, 0xf0, 0x70, 0xc3, 0xff, 0x7f, 0x80, 0xff, 0xf1, 0x80, 0xf0, 0xc1, 0xff, 0xff, 0x80,
    0xff, 0xf0, 0x01, 0xf0, 0xc0, 0x00, 0xff, 0x80, 0xff, 0xf0, 0x03, 0xe0, 0xe0, 0x01, 0xff, 0x80,
    0xff, 0xfe, 0x07, 0xe0, 0xf0, 0x03, 0xff, 0x80, 0xff, 0xfc, 0x07, 0xe0, 0xf8, 0x07, 0xff, 0x80,
    0xff, 0xfc, 0x07, 0xf0, 0xfc, 0x0f, 0xff, 0x80, 0xff, 0xf8, 0x03, 0xe0, 0x7c, 0x0f, 0xff, 0x80,
    0xff, 0xe0, 0x43, 0xe0, 0xfc, 0x00, 0xff, 0x80, 0xff, 0xc0, 0xe3, 0xc0, 0xfc, 0x40, 0x3f, 0x80,
    0xff, 0xc0, 0xe3, 0x00, 0x3c, 0x60, 0x7f, 0x80, 0xff, 0xc0, 0xf6, 0x00, 0x1c, 0xf0, 0x3f, 0x80,
    0xff, 0xe0, 0xfc, 0x21, 0x0d, 0xe0, 0x7f, 0x80, 0xff, 0xe0, 0xfc, 0x33, 0xcf, 0xf0, 0xff, 0x80,
    0xff, 0xff, 0xfb, 0xf3, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xe1, 0xfd, 0xff, 0xff, 0x80,
    0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x80,
    0xff, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x80,
    0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x80
  };
  // ICONS END

//SETUP DISPLAYS
  Adafruit_SSD1306 display1(128, 64, &Wire, -1);
  Adafruit_SSD1306 display2(128, 64, &Wire, -1);
  Adafruit_SH1107 display3 = Adafruit_SH1107(128, 128, &Wire, -1, 1000000, 100000);


//SETUP ACCESS POINT
  const char* ssid = "wifi_name";
  const char* password = "wifi_pass";

//SETUP SERVER NAMES
  const String weatherServerName = "http://api.weatherapi.com/v1/forecast.json?key=api_key&q=city&days=2&aqi=no&alerts=no";
  const String timeServerName = "https://timeapi.io/api/Time/current/zone?timeZone=Europe/Berlin";

int counter = 0;

// Select I2C BUS
void TCA9548A(uint8_t bus){
  Wire.beginTransmission(0x73);  // TCA9548A address
  Wire.write(1 << bus);          // send byte to select bus
  Wire.endTransmission();
  Serial.print(bus);
}

String httpGETRequest(const char* serverName) {
  WiFiClient client;
  HTTPClient http;
    
  // Your Domain name with URL path or IP address with path
  http.begin(client, serverName);
  
  // Send HTTP POST request
  int httpResponseCode = http.GET();
  
  String payload = "{}"; 
  
  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  http.end();

  return payload;
}

// WIDGETS
  void display3widget(int code_no)
  {
    if (code_no == 1072 || code_no == 1150 || code_no == 1153 || code_no == 1168 || code_no == 1171)
      display3.drawBitmap(0, 0, drizzle, 57, 54, SH110X_BLACK, SH110X_WHITE);
    else if (code_no == 1000)
      display3.fillCircle(30, 30, 20, SH110X_WHITE);  
    else if (code_no == 1066 || code_no == 1114 || code_no == 1210 || code_no ==  1213 || code_no == 1216 || code_no == 1219 || code_no == 1222 || code_no == 1225 || code_no == 1255 || code_no == 1279 || code_no == 1282)
      display3.drawBitmap(0, 0, snow, 57, 54, SH110X_BLACK, SH110X_WHITE);
    else if (code_no == 1003 || code_no == 1006 || code_no == 1009 || code_no == 1135 || code_no == 1147)
      display3.drawBitmap(0, 0, cloudy, 57, 54, SH110X_BLACK, SH110X_WHITE);
    else
      display3.drawBitmap(0, 0, rain, 57, 54, SH110X_BLACK, SH110X_WHITE);
  }

  void display1widget(int code_no)
  {
    if (code_no == 1072 || code_no == 1150 || code_no == 1153 || code_no == 1168 || code_no == 1171)
      display1.drawBitmap(0, 0, drizzle, 57, 50, SH110X_BLACK, SH110X_WHITE);
    else if (code_no == 1000)
      display1.fillCircle(30, 30, 15, SH110X_WHITE);  
    else if (code_no == 1066 || code_no == 1114 || code_no == 1210 || code_no ==  1213 || code_no == 1216 || code_no == 1219 || code_no == 1222 || code_no == 1225 || code_no == 1255 || code_no == 1279 || code_no == 1282)
      display1.drawBitmap(0, 0, snow, 57, 50, SH110X_BLACK, SH110X_WHITE);
    else if (code_no == 1003 || code_no == 1006 || code_no == 1009 || code_no == 1135 || code_no == 1147)
      display1.drawBitmap(0, 0, cloudy, 57, 50, SH110X_BLACK, SH110X_WHITE);
    else
      display1.drawBitmap(0, 0, rain, 57, 50, SH110X_BLACK, SH110X_WHITE);
  }

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

  // Connect to wifi
  delay(100);
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  delay(500);

  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
 
  Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.");

  // Start I2C communication with the Multiplexer
  Wire.begin();

  // Init OLED display on bus number 2 (display 1)
  TCA9548A(1);
  if(!display1.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  } 
  // Clear the buffer
  display1.clearDisplay();

  // Init OLED display on bus number 3
  TCA9548A(2);
  if(!display2.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  } 
  // Clear the buffer
  display2.clearDisplay();

  // Init OLED display on bus number 4
  TCA9548A(0);
  if(!display3.begin(0x3C, true)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  } 
  // Clear the buffer
  display3.clearDisplay();
}

void loop() {
  
  // Send an HTTP GET request
  // Check WiFi connection status
  if(WiFi.status()== WL_CONNECTED){    
    if(counter <= 0){

      Serial.println("Getting weather info:");
      // WEATHER START
      String jsonBuffer = httpGETRequest(weatherServerName.c_str());

      JSONVar myObject = JSON.parse(jsonBuffer);

      // JSON.typeof(jsonVar) can be used to get the type of the var
      if (JSON.typeof(myObject) == "undefined") {
        Serial.println("Parsing input failed!");
        display3.setTextSize(1);
        display3.setCursor(0, 32);
        display3.println("Please Wait.....");
        display3.println("");
        display3.print("Parsing failed!");
        display3.display();
        delay(1000);
        return;
      }

      TCA9548A(0);
      
      display3.clearDisplay();

      Serial.println(int(myObject["forecast"]["forecastday"][0]["day"]["avgtemp_c"]));
    
      display3widget(myObject["forecast"]["forecastday"][0]["day"]["condition"]["code"]);

      // Details displayed on the OLED
      display3.setCursor(64, 8);
      display3.setTextSize(2);
      display3.setTextColor(SH110X_WHITE);        // Draw white text
      display3.print(int(myObject["forecast"]["forecastday"][0]["day"]["avgtemp_c"]));
      display3.print("'C");

      display3.setTextSize(1);
      display3.setCursor(60, 42);
      display3.setTextColor(SH110X_WHITE);        // Draw white text
      String date = myObject["forecast"]["forecastday"][0]["date"];
      date.replace("\"", "");
      display3.print(date);

      display3.drawLine(0, 64, 128, 64, SH110X_WHITE);
    
      display3.setTextSize(1);
      display3.setCursor(0, 68);
      String desc = myObject["forecast"]["forecastday"][0]["day"]["condition"]["text"];
      desc.replace("\"", "");
      display3.print(desc);
      
      display3.setTextSize(1);
      display3.setCursor(0, 92);
      display3.print("Rain: ");
      display3.print(int(myObject["forecast"]["forecastday"][0]["day"]["daily_chance_of_rain"]));
      display3.print(" %");

      display3.setTextSize(1);
      display3.setCursor(0, 104);
      display3.print("Max: ");
      display3.print(int(myObject["forecast"]["forecastday"][0]["day"]["maxtemp_c"]));
      display3.print(" C | Min: ");
      display3.print(int(myObject["forecast"]["forecastday"][0]["day"]["mintemp_c"]));
      display3.print(" C");


      display3.setTextSize(1);
      display3.setCursor(0, 116);
      display3.print("Humidity: ");
      display3.print(int(myObject["forecast"]["forecastday"][0]["day"]["avghumidity"]));
      display3.print(" %");

      display3.display();

      delay(100);

      TCA9548A(1);

      display1.clearDisplay();
    
      display1widget(myObject["forecast"]["forecastday"][1]["day"]["condition"]["code"]);

      // Details displayed on the OLED
      display1.setCursor(64, 1);
      display1.setTextColor(WHITE);
      display1.setTextSize(2);
      display1.print(int(myObject["forecast"]["forecastday"][1]["day"]["avgtemp_c"]));
      display1.print("'C");


      display1.setTextSize(1);
      display1.setCursor(60, 25);
      display1.setTextColor(WHITE);
      String date2 = myObject["forecast"]["forecastday"][1]["date"];
      date2.replace("\"", "");
      display1.print(date2);

      display1.setTextSize(1);
      display1.setCursor(60, 38);
      display1.print("Rain: ");
      display1.print(int(myObject["forecast"]["forecastday"][1]["day"]["daily_chance_of_rain"]));
      display1.println(" %");
    
      display1.setTextSize(1);
      display1.setCursor(0, 52);
      String desc2 = myObject["forecast"]["forecastday"][1]["day"]["condition"]["text"];
      desc2.replace("\"", "");
      display1.print(desc2);

      display1.display();

      // WEATHER END
    } else if (counter > 6){
      counter = -1;
    }

    // TIME START
    Serial.println("Getting time info:");

    HTTPClient http;
    http.begin(timeServerName.c_str());

    int httpResponseCode = http.GET();
      
    if (httpResponseCode == 200) {
      String jsonBuffer2 = http.getString();

      JSONVar myObject2 = JSON.parse(jsonBuffer2);

      String checkTime = myObject2["time"];
      if (checkTime.indexOf("23:30") != -1) {
        delay (1000 * 60 * 5);
        esp_restart();
      }

      Serial.println("");

      Serial.println(myObject2);

      TCA9548A(2);
      display2.clearDisplay();
      display2.setTextSize(3);
      display2.setTextColor(WHITE);
      display2.setCursor(22, 2);
      // Display static text
      String ttt = myObject2["time"];
      ttt.replace("\"", "");
      display2.print(ttt);
      
      display2.setTextSize(2);
      display2.setTextColor(WHITE);
      display2.setCursor(18, 32);
      String day = myObject2["dayOfWeek"];
      day.replace("\"", "");
      display2.print(day);

      display2.setTextSize(1);
      display2.setTextColor(WHITE);
      display2.setCursor(32, 51);
      String dd = myObject2["date"];
      dd.replace("\"", "");
      display2.print(dd);

      display2.setTextSize(1);
      display2.setTextColor(WHITE);
      display2.setCursor(120, 56);
      display2.print(counter);

      display2.display(); 
    }
    else {
        Serial.print("Error code: ");
        Serial.println(httpResponseCode);
    }
      

    // Free resources
    http.end();


    // TIME END
  } else {
    Serial.println("WiFi Disconnected");
      display3.setTextSize(1);
      display3.setCursor(0, 32);
      display3.println("Please Wait.....");
      display3.println("");
      display3.print("Is internet available??");
      display3.display();
      delay(1000);
      return;
  }
  counter = counter + 1;
  delay(1000 * 10);
  
}

