ENERGY METER - PING - LCD

 #include <WiFi.h>

#include <WebServer.h>

#include <ESPmDNS.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#include <time.h>


#define SCREEN_WIDTH 128

#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);


// --- KONFIGURASI WIFI ---

const char* ssid       = "Dara@home";

const char* password   = "rejeki88";

const char* mdnsHostname = "glosindo-server";


// --- PING STATS ---

const char* pingHost = "google.com";

float lastPingTimeMs = 0.0;

bool isInternetConnected = false;

unsigned long lastPingAttemptTime = 0;

const long pingInterval = 5000;


// --- WEB SERVER ---

WebServer server(8888);


// --- SENSOR & ENERGI ---

float voltage = 0, current = 0, power = 0;

float energyWhPerSecond = 0, energyWhPerMinute = 0, energyWhPerHour = 0, energyWhPerDay = 0, totalEnergyWh = 0;

unsigned long lastSensorReadTime = 0;

const long sensorReadInterval = 2000;

unsigned long lastEnergyCalcTime = 0;

const long energyCalcInterval = 1000;

unsigned long lastDayChangeTime = 0;


// --- OLED ---

unsigned long lastOledUpdate = 0;

const long oledInterval = 3000;

int oledPage = 0;


void readSensors() {

  voltage = random(2200, 2400) / 10.0;

  current = random(50, 200) / 100.0;

  power = voltage * current;

  Serial.printf("Sensor: V=%.2f V, I=%.2f A, P=%.2f W\n", voltage, current, power);

}


void updateEnergyConsumption() {

  unsigned long now = millis();

  if (now - lastEnergyCalcTime >= energyCalcInterval) {

    float deltaHours = (now - lastEnergyCalcTime) / 3600000.0;

    float e = power * deltaHours;

    totalEnergyWh += e;

    energyWhPerSecond = power / 3600.0;

    energyWhPerMinute = power / 60.0;

    energyWhPerHour   = power;

    energyWhPerDay   += e;

    lastEnergyCalcTime = now;

    Serial.printf("Energi: total %.2f Wh, hour rate %.2f Wh/h, daily %.2f Wh/day\n",

                  totalEnergyWh, energyWhPerHour, energyWhPerDay);

  }

}


void performPing() {

  if (WiFi.status() != WL_CONNECTED) {

    isInternetConnected = false;

    Serial.println("WiFi belum terhubung");

    return;

  }

  IPAddress ip;

  if (!WiFi.hostByName(pingHost, ip)) {

    isInternetConnected = false;

    Serial.println("DNS resolve gagal");

    return;

  }

  WiFiClient client;

  unsigned long start = millis();

  if (client.connect(ip, 80)) {

    lastPingTimeMs = millis() - start;

    isInternetConnected = true;

    Serial.printf("Ping %s: %.2f ms\n", pingHost, lastPingTimeMs);

    client.stop();

  } else {

    lastPingTimeMs = 0;

    isInternetConnected = false;

    Serial.printf("Ping ke %s gagal\n", pingHost);

  }

}


void handleRoot() {

  String html = "<!DOCTYPE html><html><head><meta charset='UTF-8'><meta name='viewport' content='width=device-width,initial-scale=1'>";

  html += "<title>Glosindo Power Monitor</title><style>body{font-family:Arial;text-align:center;}</style></head><body>";

  html += "<h2>Monitor Energi & Internet</h2>";

  html += "<p><strong>Tegangan:</strong> " + String(voltage) + " V</p>";

  html += "<p><strong>Arus:</strong> " + String(current) + " A</p>";

  html += "<p><strong>Daya:</strong> " + String(power) + " W</p>";

  html += "<p><strong>Energi Jam:</strong> " + String(energyWhPerHour) + " Wh</p>";

  html += "<p><strong>Energi Harian:</strong> " + String(energyWhPerDay) + " Wh</p>";

  html += "<p><strong>Total Energi:</strong> " + String(totalEnergyWh) + " Wh</p>";

  html += "<p><strong>Status Internet:</strong> " + String(isInternetConnected ? "ONLINE" : "OFFLINE") + "</p>";

  html += "<p><strong>Ping:</strong> " + String(lastPingTimeMs) + " ms</p></body></html>";

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

}


void handleData() {

  String json = "{";

  json += "\"voltage\":" + String(voltage) + ",";

  json += "\"current\":" + String(current) + ",";

  json += "\"power\":" + String(power) + ",";

  json += "\"energyWhPerHour\":" + String(energyWhPerHour) + ",";

  json += "\"energyWhPerDay\":" + String(energyWhPerDay) + ",";

  json += "\"totalEnergy\":" + String(totalEnergyWh) + ",";

  json += "\"lastPingTimeMs\":" + String(lastPingTimeMs) + ",";

  json += "\"isInternetConnected\":" + String(isInternetConnected ? "true" : "false");

  json += "}";

  server.send(200, "application/json", json);

}


void updateOledDisplay() {

  if (millis() - lastOledUpdate >= oledInterval) {

    lastOledUpdate = millis();

    oledPage = (oledPage + 1) % 3;


    display.clearDisplay();

    display.setCursor(0, 0);


    if (oledPage == 0) {

      display.println("== Sensor Listrik ==");

      display.printf("Teg: %.1f V\n", voltage);

      display.printf("Arus: %.2f A\n", current);

      display.printf("Daya: %.1f W\n", power);

    } else if (oledPage == 1) {

      display.println("== Energi ==");

      display.printf("Jam: %.2f Wh\n", energyWhPerHour);

      display.printf("Hari: %.2f Wh\n", energyWhPerDay);

      display.printf("Total: %.2f Wh\n", totalEnergyWh);

    } else if (oledPage == 2) {

      time_t now = time(nullptr);

      struct tm *t = localtime(&now);

      display.println("== Waktu & Status ==");

      display.printf("%02d:%02d:%02d\n", t->tm_hour, t->tm_min, t->tm_sec);

      display.printf("WiFi: %s\n", WiFi.status() == WL_CONNECTED ? "Online" : "Offline");

      display.printf("Ping: %.0f ms\n", lastPingTimeMs);

    }


    display.display();

  }

}


void setup() {

  Serial.begin(115200);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {

    Serial.println(F("OLED gagal diinisialisasi"));

    while (true);

  }

  display.clearDisplay();

  display.setTextSize(1);

  display.setTextColor(SSD1306_WHITE);

  display.setCursor(0, 0);

  display.println("Glosindo Monitor");

  display.display();

  delay(1000);


  WiFi.begin(ssid, password);

  Serial.print("Menghubungkan ke WiFi");

  while (WiFi.status() != WL_CONNECTED) {

    delay(500); Serial.print(".");

  }

  Serial.printf("\nTerhubung! IP: %s\n", WiFi.localIP().toString().c_str());


  if (MDNS.begin(mdnsHostname)) {

    MDNS.addService("http", "tcp", 8888);

    Serial.printf("mDNS aktif: http://%s.local:8888\n", mdnsHostname);

  }


  configTime(7 * 3600, 0, "pool.ntp.org", "time.nist.gov");


  server.on("/", handleRoot);

  server.on("/data", handleData);

  server.begin();


  randomSeed(micros());

  readSensors();

  lastSensorReadTime = lastEnergyCalcTime = lastDayChangeTime = millis();

  performPing();

  lastPingAttemptTime = millis();

}


void loop() {

  server.handleClient();


  if (millis() - lastSensorReadTime >= sensorReadInterval) {

    readSensors();

    lastSensorReadTime = millis();

  }


  updateEnergyConsumption();


  if (millis() - lastPingAttemptTime >= pingInterval) {

    performPing();

    lastPingAttemptTime = millis();

  }


  if (millis() - lastDayChangeTime >= 86400000UL) {

    energyWhPerDay = 0;

    lastDayChangeTime = millis();

    Serial.println("Reset energi harian.");

  }


  updateOledDisplay();

}


Comments