#include <ESP8266WiFi.
h>
#include <ESP8266WebServer.h>
#include <TM1637Display.h>
#include <ESP8266mDNS.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
// Wi-Fi Credentials
const char* ssid = "Ask me";
const char* password = "31373139";
// Define TM1637 display pins
#define CLK 5 // GPIO5
#define DIO 4 // GPIO4
// Define button pins
#define BUTTON_INCREMENT 14 // GPIO14
#define BUTTON_DECREMENT 12 // GPIO12
#define BUTTON_RESET 13 // GPIO13
// Initialize TM1637 display (CLK, DIO pins)
TM1637Display display(CLK, DIO);
int counter = 0; // Counter variable
// Web server on port 80
ESP8266WebServer server(80);
// NTP setup
WiFiUDP udp;
NTPClient timeClient(udp, "pool.ntp.org", 18000, 3600000); // UTC+5 for Lahore (18000 seconds)
// Function to calculate the current date from epoch time
String getCurrentDate() {
time_t rawTime = timeClient.getEpochTime();
struct tm* timeInfo = gmtime(&rawTime); // Get time in UTC
int day = timeInfo->tm_mday;
int month = timeInfo->tm_mon + 1; // tm_mon is 0-11
int year = timeInfo->tm_year + 1900; // tm_year is years since 1900
return String(day) + "-" + String(month) + "-" + String(year);
// Convert 24-hour time to 12-hour format with AM/PM
String formatTimeWithAMPM(String formattedTime) {
int hour = formattedTime.substring(0, 2).toInt();
String minutes = formattedTime.substring(3, 5);
String seconds = formattedTime.substring(6, 8);
String ampm = (hour >= 12) ? "PM" : "AM";
if (hour == 0) hour = 12; // Midnight case
else if (hour > 12) hour -= 12; // Convert to 12-hour format
return String(hour) + ":" + minutes + ":" + seconds + " " + ampm;
// Get the current date and time from the NTP server
String getCurrentDateTime() {
timeClient.update();
String dateTime = getCurrentDate() + " " + formatTimeWithAMPM(timeClient.getFormattedTime()); //
Combine date and time
return dateTime;
// HTML content for the webpage
String getHTMLPage() {
String html = "<!DOCTYPE html><html><head><title>ESP8266 Counter</title>";
html += "<style>body { font-family: Arial; text-align: center; margin: 0; padding: 20px; background-color:
#f4f4f4; }";
html += "h1 { color: #333; }";
html += ".branding { color: red; font-weight: bold; }";
html += ".digitrixx { color: black; font-weight: bold; }";
html += ".container { position: relative; z-index: 1; padding-bottom: 60px; }"; // Padding to avoid
overlapping branding
html += "</style>";
html += "<script>function updateCounter() {";
html += " fetch('/getCounter').then(response => response.json()).then(data => {";
html += " document.getElementById('counterValue').innerText = data.counter; ";
html += " document.getElementById('currentDateTime').innerText = data.dateTime; ";
html += " });";
html += " setTimeout(updateCounter, 1000);"; // Update every second
html += "} function updateValue() {";
html += " var newValue = document.getElementById('counterInput').value;";
html += " fetch('/setCounter?value=' + newValue).then(response => response.json()).then(data => {";
html += " document.getElementById('counterValue').innerText = data.counter; ";
html += " });";
html += "} function copyInfo() {";
html += " var info = document.getElementById('info');";
html += " var range = document.createRange();";
html += " range.selectNode(info);";
html += " window.getSelection().removeAllRanges();";
html += " window.getSelection().addRange(range);";
html += " document.execCommand('copy');";
html += " alert('Info copied to clipboard!');";
html += "}</script></head><body onload='updateCounter()'>";
html += "<div class='container'>";
html += "<h1 id='currentDateTime'>" + getCurrentDateTime() + "</h1>";
html += "<h2>Welcome Dr. Faraz</h2>";
html += "<h3>FUE Count: <span id='counterValue'>" + String(counter) + "</span></h3>";
html += "<input type='number' id='counterInput' value='" + String(counter) + "'>";
html += "<button onclick='updateValue()'>Update Counter</button><br><br>";
html += "<button onclick='copyInfo()'>Copy Info</button><br><br>";
// Branding added above the Copy Info button
html += "<div class='branding'>Powered by <span
class='digitrixx'>TheDigitrixx</span>®</div><br><br>";
html += "<div id='info'>";
html += "<p>Date & Time: <span id='currentDateTimeCopy'>" + getCurrentDateTime() + "</span></p>";
html += "<p>FUE Count: <span id='counterValueCopy'>" + String(counter) + "</span></p>";
html += "<p>Powered by <span class='digitrixx'>TheDigitrixx</span>®</p>"; // Added to the copied
content
html += "</div>";
html += "</div>";
html += "</body></html>";
return html;
}
// Update the 7-segment display
void updateDisplay() {
display.showNumberDec(counter, false); // Display the counter
Serial.println("Counter: " + String(counter)); // Output to Serial Monitor
// Previous button states for detecting changes
bool lastIncrementState = HIGH;
bool lastDecrementState = HIGH;
bool lastResetState = HIGH;
void setup() {
Serial.begin(115200);
display.setBrightness(7);
display.clear();
display.showNumberDec(counter, false);
pinMode(BUTTON_INCREMENT, INPUT_PULLUP);
pinMode(BUTTON_DECREMENT, INPUT_PULLUP);
pinMode(BUTTON_RESET, INPUT_PULLUP);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(500);
// Print the IP address once connected
Serial.println("Connected to Wi-Fi");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP()); // This will print the IP address of the ESP8266
MDNS.begin("esp8266-counter");
timeClient.begin();
server.on("/", []() { server.send(200, "text/html", getHTMLPage()); });
server.on("/getCounter", []() {
String jsonResponse = "{\"counter\": " + String(counter) + ", \"dateTime\": \"" + getCurrentDateTime()
+ "\"}";
server.send(200, "application/json", jsonResponse);
});
server.on("/setCounter", HTTP_GET, []() {
if (server.hasArg("value")) {
counter = server.arg("value").toInt();
String jsonResponse = "{\"counter\": " + String(counter) + "}";
server.send(200, "application/json", jsonResponse);
updateDisplay();
});
server.begin();
void loop() {
server.handleClient();
bool incrementState = digitalRead(BUTTON_INCREMENT);
if (lastIncrementState == HIGH && incrementState == LOW) { // Detect only high-to-low transition
counter = min(counter + 1, 9999); // Prevent overflow
updateDisplay();
lastIncrementState = incrementState;
bool decrementState = digitalRead(BUTTON_DECREMENT);
if (lastDecrementState == HIGH && decrementState == LOW) { // Detect only high-to-low transition
counter = max(counter - 1, 0); // Prevent negative values
updateDisplay();
lastDecrementState = decrementState;
bool resetState = digitalRead(BUTTON_RESET);
if (lastResetState == HIGH && resetState == LOW) { // Detect only high-to-low transition
counter = 0;
updateDisplay();
lastResetState = resetState;