No title

 #include <WiFi.h>

#include <WebServer.h>


#include <Adafruit_GFX.h>

#include <Adafruit_ST7735.h>

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_BME280.h>

#include <math.h>


// =====================================================

// ESP32-C3 SAFE PINS

// =====================================================

#define TFT_CS    7

#define TFT_RST   2

#define TFT_DC    3

#define TFT_SCLK  4

#define TFT_MOSI  6


// =====================================================

// BME280 I2C

// =====================================================

#define BME_SDA   8

#define BME_SCL   9


Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

Adafruit_BME280 bme;


// =====================================================

// WIFI HOTSPOT

// =====================================================

const char* AP_SSID = "ESP32-Weather";

const char* AP_PASSWORD = "12345678";


WebServer server(80);


// =====================================================

// COLORS

// =====================================================

#define BLACK          0x0000

#define WHITE          0xFFFF

#define BLUE           0x001F

#define YELLOW         0xFFE0

#define RED            0xF800

#define GREEN          0x07E0

#define CYAN           0x07FF

#define PINK           0xF81F

#define ORANGE         0xFD20

#define CLOUD          0xFFFF

#define LIGHT_PURPLE   0xB81F


// =====================================================

// DATE & TIME

// Mobile se automatically set hoga

// =====================================================

int hours   = 12;

int minutes = 0;

int seconds = 0;


int day   = 26;

int month = 9;

int year  = 2026;


int dayOfWeek = 6;


// =====================================================

// DAY NAMES

// =====================================================

const char* dayNames[] = {

  "Sunday",

  "Monday",

  "Tuesday",

  "Wednesday",

  "Thursday",

  "Friday",

  "Saturday"

};


// =====================================================

// TIMERS

// =====================================================

unsigned long lastSecond = 0;

unsigned long lastSensorUpdate = 0;


// =====================================================

// BME VALUES

// =====================================================

float temperature = 0.0;

float humidity = 0.0;

float pressure = 0.0;


// =====================================================

// TIME SYNC STATUS

// =====================================================

bool timeSynced = false;


// =====================================================

// SETUP

// =====================================================

void setup() {


  Serial.begin(115200);


  // =================================================

  // TFT SPI

  // =================================================

  SPI.begin(TFT_SCLK, -1, TFT_MOSI, TFT_CS);


  tft.initR(INITR_MINI160x80);

  tft.setRotation(3);


  tft.fillScreen(BLACK);


  // =================================================

  // BME280

  // =================================================

  Wire.begin(BME_SDA, BME_SCL);


  bool bmeOK = bme.begin(0x76);


  if (!bmeOK) {

    bmeOK = bme.begin(0x77);

  }


  if (!bmeOK) {

    Serial.println("BME280 NOT FOUND!");

  }

  else {

    Serial.println("BME280 OK");

  }


  // First BME reading

  readBME280();


  // =================================================

  // CREATE ESP32 HOTSPOT

  // =================================================

  WiFi.mode(WIFI_AP);


  WiFi.softAP(AP_SSID, AP_PASSWORD);


  IPAddress IP = WiFi.softAPIP();


  Serial.println();

  Serial.println("==============================");

  Serial.println("ESP32 HOTSPOT STARTED");

  Serial.print("SSID: ");

  Serial.println(AP_SSID);

  Serial.print("PASSWORD: ");

  Serial.println(AP_PASSWORD);

  Serial.print("OPEN: http://");

  Serial.println(IP);

  Serial.println("==============================");


  // =================================================

  // WEB SERVER

  // =================================================

  server.on("/", handleRoot);


  server.on("/settime", handleSetTime);


  server.begin();


  Serial.println("Web server started");


  // =================================================

  // DRAW UI

  // =================================================

  drawUI();


  lastSecond = millis();

  lastSensorUpdate = millis();

}


// =====================================================

// LOOP

// =====================================================

void loop() {


  // =================================================

  // WEB SERVER

  // =================================================

  server.handleClient();


  // =================================================

  // CLOCK

  // =================================================

  if (millis() - lastSecond >= 1000) {


    lastSecond += 1000;


    seconds++;


    if (seconds >= 60) {


      seconds = 0;

      minutes++;

    }


    if (minutes >= 60) {


      minutes = 0;

      hours++;

    }


    if (hours >= 24) {


      hours = 0;


      // Next day

      dayOfWeek++;


      if (dayOfWeek >= 7) {

        dayOfWeek = 0;

      }


      day++;


      // New month

      if (day > daysInMonth(month, year)) {


        day = 1;

        month++;


        // New year

        if (month > 12) {


          month = 1;

          year++;

        }

      }


      drawDate();

    }


    drawTime();

  }


  // =================================================

  // BME280 UPDATE

  // =================================================

  if (millis() - lastSensorUpdate >= 500) {


    lastSensorUpdate = millis();


    readBME280();


    drawSensorValues();

  }

}


// =====================================================

// DAYS IN MONTH

// =====================================================

int daysInMonth(int m, int y) {


  switch (m) {


    case 1: return 31;


    case 2:


      if ((y % 400 == 0) ||

          ((y % 4 == 0) && (y % 100 != 0))) {


        return 29;

      }


      return 28;


    case 3: return 31;

    case 4: return 30;

    case 5: return 31;

    case 6: return 30;

    case 7: return 31;

    case 8: return 31;

    case 9: return 30;

    case 10: return 31;

    case 11: return 30;

    case 12: return 31;

  }


  return 30;

}


// =====================================================

// DAY OF WEEK CALCULATION

// =====================================================

int calculateDayOfWeek(int d, int m, int y) {


  // Zeller-like calculation

  int yy = y;

  int mm = m;


  if (mm < 3) {

    mm += 12;

    yy--;

  }


  int k = yy % 100;

  int j = yy / 100;


  int h = (d +

           (13 * (mm + 1)) / 5 +

           k +

           k / 4 +

           j / 4 +

           5 * j) % 7;


  // Zeller:

  // 0 = Saturday

  // 1 = Sunday

  // ...

  int result = (h + 6) % 7;


  return result;

}


// =====================================================

// READ BME280

// =====================================================

void readBME280() {


  temperature = bme.readTemperature();


  humidity = bme.readHumidity();


  pressure = bme.readPressure() / 100.0F;


  Serial.print("Temp: ");

  Serial.print(temperature, 1);


  Serial.print(" C | Hum: ");

  Serial.print(humidity, 0);


  Serial.print("% | Press: ");

  Serial.print(pressure, 0);


  Serial.println(" hPa");

}


// =====================================================

// WEB PAGE

// =====================================================

void handleRoot() {


  String html = "";


  html += "<!DOCTYPE html>";

  html += "<html>";

  html += "<head>";


  html += "<meta name='viewport' content='width=device-width, initial-scale=1'>";


  html += "<title>ESP32 Weather Clock</title>";


  html += "<style>";


  html += "body{";

  html += "background:#111;";

  html += "color:white;";

  html += "font-family:Arial;";

  html += "text-align:center;";

  html += "padding-top:40px;";

  html += "}";


  html += "button{";

  html += "background:#00c8ff;";

  html += "border:0;";

  html += "padding:15px 30px;";

  html += "font-size:18px;";

  html += "border-radius:10px;";

  html += "}";


  html += "</style>";


  html += "</head>";


  html += "<body>";


  html += "<h1>ESP32 Weather Clock</h1>";


  html += "<p>Mobile Date & Time</p>";


  html += "<button onclick='syncTime()'>SYNC TIME NOW</button>";


  html += "<p id='status'>Press button to sync</p>";


  html += "<script>";


  html += "function syncTime(){";


  html += "let d=new Date();";


  html += "let data=";


  html += "d.getFullYear()+','+";


  html += "(d.getMonth()+1)+','+";


  html += "d.getDate()+','+";


  html += "d.getHours()+','+";


  html += "d.getMinutes()+','+";


  html += "d.getSeconds();";


  html += "fetch('/settime?t='+data)";


  html += ".then(r=>r.text())";


  html += ".then(x=>{";


  html += "document.getElementById('status').innerHTML=x;";


  html += "});";


  html += "}";


  // Automatically sync when page opens

  html += "window.onload=function(){syncTime();};";


  html += "</script>";


  html += "</body>";


  html += "</html>";


  server.send(200, "text/html", html);

}


// =====================================================

// RECEIVE MOBILE TIME

// =====================================================

void handleSetTime() {


  if (!server.hasArg("t")) {


    server.send(400, "text/plain", "Time data missing");


    return;

  }


  String data = server.arg("t");


  Serial.println();

  Serial.print("Mobile time received: ");

  Serial.println(data);


  int values[6];


  int index = 0;

  int start = 0;


  for (int i = 0; i <= data.length(); i++) {


    if (i == data.length() || data[i] == ',') {


      if (index < 6) {


        values[index] = data.substring(start, i).toInt();


        index++;

      }


      start = i + 1;

    }

  }


  if (index == 6) {


    year    = values[0];

    month   = values[1];

    day     = values[2];


    hours   = values[3];

    minutes = values[4];

    seconds = values[5];


    // Calculate correct weekday

    dayOfWeek = calculateDayOfWeek(day, month, year);


    timeSynced = true;


    // Reset clock timer

    lastSecond = millis();


    // Update TFT

    drawDate();

    drawTime();


    Serial.println("TIME UPDATED FROM MOBILE!");


    Serial.print("Date: ");

    Serial.print(day);

    Serial.print("/");

    Serial.print(month);

    Serial.print("/");

    Serial.println(year);


    Serial.print("Time: ");

    Serial.print(hours);

    Serial.print(":");

    Serial.print(minutes);

    Serial.print(":");

    Serial.println(seconds);


    server.send(

      200,

      "text/plain",

      "Time synced successfully!"

    );

  }

  else {


    server.send(

      400,

      "text/plain",

      "Invalid time data"

    );

  }

}


// =====================================================

// MAIN UI

// =====================================================

void drawUI() {


  tft.fillScreen(BLACK);


  // =================================================

  // CITY

  // =================================================

  tft.setTextSize(2);


  tft.setTextColor(LIGHT_PURPLE);


  tft.setCursor(5, 5);


  tft.print("London");


  // =================================================

  // DATE

  // =================================================

  drawDate();


  // =================================================

  // WEATHER

  // =================================================

  tft.setTextSize(1);


  tft.setTextColor(ORANGE);


  tft.setCursor(5, 25);


  tft.print("Clouds");


  // =================================================

  // TIME

  // =================================================

  drawTime();


  // =================================================

  // LABELS

  // =================================================

  tft.setTextSize(1);


  tft.setTextColor(PINK);


  tft.setCursor(60, 53);

  tft.print("Press");


  tft.setCursor(101, 53);

  tft.print("Temp");


  tft.setCursor(136, 53);

  tft.print("Humi");


  // =================================================

  // VALUES

  // =================================================

  drawSensorValues();


  // =================================================

  // WEATHER ICON

  // =================================================

  drawWeatherIcon();

}


// =====================================================

// DATE

// =====================================================

void drawDate() {


  // Clear day

  tft.fillRect(88, 0, 72, 16, BLACK);


  tft.setTextSize(1);


  tft.setTextColor(ORANGE);


  if (dayOfWeek == 3) {


    tft.setCursor(87, 5);

  }

  else if (dayOfWeek == 4) {


    tft.setCursor(91, 5);

  }

  else {


    tft.setCursor(98, 5);

  }


  tft.print(dayNames[dayOfWeek]);


  // =================================================

  // DATE

  // =================================================

  tft.fillRect(88, 17, 72, 10, BLACK);


  tft.setTextColor(GREEN);


  tft.setCursor(91, 19);


  if (day < 10)

    tft.print("0");


  tft.print(day);


  tft.print("/");


  if (month < 10)

    tft.print("0");


  tft.print(month);


  tft.print("/");


  tft.print(year);

}


// =====================================================

// TIME

// =====================================================

void drawTime() {


  tft.fillRect(60, 31, 100, 20, BLACK);


  tft.setTextSize(2);


  tft.setTextColor(CYAN);


  tft.setCursor(62, 33);


  if (hours < 10)

    tft.print("0");


  tft.print(hours);


  tft.print(":");


  if (minutes < 10)

    tft.print("0");


  tft.print(minutes);


  tft.print(":");


  if (seconds < 10)

    tft.print("0");


  tft.print(seconds);

}


// =====================================================

// SENSOR VALUES

// =====================================================

void drawSensorValues() {


  tft.setTextSize(1);


  // =================================================

  // PRESSURE

  // =================================================

  tft.fillRect(58, 64, 45, 10, BLACK);


  tft.setTextColor(YELLOW);


  tft.setCursor(58, 65);


  int p = (int)round(pressure);


  if (p > 999)

    p = 999;


  if (p < 0)

    p = 0;


  tft.print(p);


  tft.print("hPa");


  // =================================================

  // TEMPERATURE

  // =================================================

  tft.fillRect(104, 64, 35, 10, BLACK);


  tft.setTextColor(BLUE);


  tft.setCursor(101, 65);


  tft.print(temperature, 1);


  tft.print("C");


  // =================================================

  // HUMIDITY

  // =================================================

  tft.fillRect(140, 64, 20, 10, BLACK);


  tft.setTextColor(RED);


  tft.setCursor(136, 65);


  int h = (int)round(humidity);


  if (h > 99)

    h = 99;


  if (h < 0)

    h = 0;


  tft.print(h);


  tft.print("%");

}


// =====================================================

// WEATHER ICON

// =====================================================

void drawWeatherIcon() {


  int sunX = 23;

  int sunY = 55;


  // SUN

  tft.fillCircle(

    sunX,

    sunY,

    8,

    CYAN

  );


  // SUN RAYS

  for (int i = 0; i < 360; i += 45) {


    float angle = i * 0.0174533;


    int x1 =

      sunX + cos(angle) * 11;


    int y1 =

      sunY + sin(angle) * 11;


    int x2 =

      sunX + cos(angle) * 14;


    int y2 =

      sunY + sin(angle) * 14;


    tft.drawLine(

      x1,

      y1,

      x2,

      y2,

      CYAN

    );

  }


  // CLOUD

  tft.fillCircle(

    25,

    65,

    7,

    CLOUD

  );


  tft.fillCircle(

    34,

    64,

    9,

    CLOUD

  );


  tft.fillCircle(

    44,

    66,

    6,

    CLOUD

  );


  tft.fillRect(

    22,

    65,

    27,

    7,

    CLOUD

  );

}


Post a Comment

Previous Post Next Post

Contact Form