#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include <WiFiClientSecure.h>
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Define the LED pin
const int ledPin = 13;
// NTP Client settings with Jakarta timezone offset (+7 hours)
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 7 * 3600, 60000); // 7 hours offset (Jakarta)
// LCD settings
LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD address to 0x27 for a 16 chars and 2 line display
// Telegram Bot settings
const char* botToken = "7035385520:AAF-xOeCI_ccpsxjIhJ5MWP-Yddm_Xr5zy0";
const char* chat_id = "987880117";
WiFiClientSecure client;
UniversalTelegramBot bot(botToken, client);
// Alarm time variables
int alarmHour = 6; // Default alarm hour
int alarmMinute = 0; // Default alarm minute
int alarmDuration = 1; // Default alarm duration in minutes
bool alarmActive = false; // Track if the alarm is currently active
bool messageSent = false; // Flag to track if the alarm message has been sent
unsigned long alarmStartTime = 0; // Time when the alarm was triggered
unsigned long lastTime = 0;
unsigned long botRequestDelay = 1000;
void setup() {
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.clear();
// Connect to Wi-Fi
lcd.setCursor(0, 0);
lcd.print("Connecting");
// Serial.print("Connecting to ");
// Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
// Serial.print(".");
lcd.print(".");
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi Connected");
// Serial.println("\nConnected to WiFi");
// Initialize NTP client
timeClient.begin();
while (!timeClient.update()) {
delay(500);
timeClient.forceUpdate();
}
// Set up Telegram client
client.setInsecure(); // For ESP32 only
lcd.clear();
}
void validateAlarmTime() {
if (alarmHour < 0 || alarmHour >= 24) {
alarmHour = 6; // Set default valid value
}
if (alarmMinute < 0 || alarmMinute >= 60) {
alarmMinute = 0; // Set default valid value
}
if (alarmDuration < 1) {
alarmDuration = 1; // Minimum duration is 1 minute
}
}
String formatTime(int value) {
return (value < 10 ? "0" : "") + String(value);
}
String formatDate(int day, int month, int year) {
return formatTime(day) + "/" + formatTime(month) + "/" + String(year % 100); // Format as dd/mm/yy
}
void handleTelegramMessages(int numNewMessages) {
for (int i = 0; i < numNewMessages; i++) {
String chat_id = bot.messages[i].chat_id;
String text = bot.messages[i].text;
if (text == "/start") {
String welcome = "Welcome to the Alarm Bot!\n";
welcome += "Here are your options:\n";
welcome += "/set_alarm - Set an alarm\n";
welcome += "/set_duration - Set the duration for the alarm\n";
welcome += "/resume_alarm - Resume the alarm\n";
welcome += "/stop_alarm - Stop the active alarm\n";
welcome += "/status - Check current time and alarm status\n";
bot.sendMessage(chat_id, welcome, "");
} else if (text == "/set_alarm") {
String message = "Please enter the time in HH:MM format (24-hour).\nExample: /set_alarm 06:30 to set the alarm for 6:30 AM.";
bot.sendMessage(chat_id, message, "");
} else if (text.startsWith("/set_alarm")) {
String timeString = text.substring(11); // Extract HH:MM part
int hour = timeString.substring(0, 2).toInt();
int minute = timeString.substring(3, 5).toInt();
alarmHour = hour;
alarmMinute = minute;
validateAlarmTime();
alarmActive = true; // Activate the alarm
messageSent = false; // Reset message flag
String formattedTime = formatTime(alarmHour) + ":" + formatTime(alarmMinute);
String message = "Alarm set for " + formattedTime;
bot.sendMessage(chat_id, message, "");
} else if (text == "/set_duration") {
String message = "Please enter the duration in minutes.\nExample: /set_duration 5 to set the alarm duration to 5 minutes.";
bot.sendMessage(chat_id, message, "");
} else if (text.startsWith("/set_duration")) {
int duration = text.substring(15).toInt();
alarmDuration = duration;
validateAlarmTime();
String message = "Alarm duration set to " + String(alarmDuration) + " minutes.";
bot.sendMessage(chat_id, message, "");
} else if (text == "/resume_alarm") {
if (!alarmActive) {
alarmActive = true; // Resume the alarm
messageSent = false; // Reset message flag
String formattedTime = formatTime(alarmHour) + ":" + formatTime(alarmMinute);
String message = "Alarm resumed for " + formattedTime;
bot.sendMessage(chat_id, message, "");
} else {
bot.sendMessage(chat_id, "Alarm is already active.", "");
}
} else if (text == "/stop_alarm") {
alarmActive = false;
digitalWrite(ledPin, LOW); // Ensure LED is off
messageSent = false; // Reset message flag
String message = "Alarm has been stopped.";
bot.sendMessage(chat_id, message, "");
} else if (text == "/status") {
String currentTime = timeClient.getFormattedTime();
int currentHour = timeClient.getHours();
int currentMinute = timeClient.getMinutes();
int currentSecond = timeClient.getSeconds();
unsigned long epochTime = timeClient.getEpochTime();
struct tm* ptm = gmtime((time_t*)&epochTime);
int currentDay = ptm->tm_wday; // 0: Minggu, 1: Senin, ..., 6: Sabtu
int currentDate = ptm->tm_mday;
int currentMonth = ptm->tm_mon + 1;
int currentYear = ptm->tm_year + 1900;
// Array for days of the week
const char* daysOfWeek[7] = { "Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu" };
String formattedAlarmTime = formatTime(alarmHour) + ":" + formatTime(alarmMinute);
String message = String(daysOfWeek[currentDay]) + ", " + formatDate(currentDate, currentMonth, currentYear) + " " + formatTime(currentHour) + ":" + formatTime(currentMinute) + ":" + formatTime(currentSecond) + "\n";
message += "Alarm set for " + formattedAlarmTime + "\n";
message += "Alarm is currently " + String(alarmActive ? "ON" : "OFF");
bot.sendMessage(chat_id, message, "");
} else {
bot.sendMessage(chat_id, "Invalid command. Use /start to see available commands.", "");
}
}
}
void loop() {
// Update NTP client
timeClient.update();
// Validate alarm time to ensure it is within a valid range
validateAlarmTime();
// Get current time details
int currentHour = timeClient.getHours();
int currentMinute = timeClient.getMinutes();
int currentSecond = timeClient.getSeconds();
unsigned long epochTime = timeClient.getEpochTime();
struct tm* ptm = gmtime((time_t*)&epochTime);
int currentDay = ptm->tm_wday; // 0: Minggu, 1: Senin, ..., 6: Sabtu
int currentDate = ptm->tm_mday;
int currentMonth = ptm->tm_mon + 1;
int currentYear = ptm->tm_year + 1900;
// Array for days of the week
const char* daysOfWeek[7] = { "Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu" };
// Display current time and alarm time on LCD
lcd.setCursor(0, 0);
lcd.printf("%s", daysOfWeek[currentDay]);
lcd.setCursor(8, 0);
lcd.printf("%02d/%02d/%02d", currentDate, currentMonth, currentYear % 100);
if (alarmActive) {
unsigned long remainingTime = alarmStartTime + alarmDuration * 60000 - millis();
unsigned long minutes = remainingTime / 60000;
unsigned long seconds = (remainingTime % 60000) / 1000;
lcd.setCursor(0, 1);
lcd.printf("Time left: %02lu:%02lu", minutes, seconds);
} else {
lcd.setCursor(0, 1);
lcd.print("Alarm OFF");
}
// Control LED based on alarm time
if (alarmActive && (currentHour >= alarmHour || (currentHour == alarmHour && currentMinute >= alarmMinute))) {
if (!messageSent) {
digitalWrite(ledPin, HIGH); // Turn on the LED
// Serial.println("LED ON");
bot.sendMessage(chat_id, "Alarm triggered, LED ON", "");
messageSent = true; // Set flag to true after sending message
alarmStartTime = millis(); // Record the time when the alarm was triggered
}
} else if (alarmActive && (millis() - alarmStartTime >= alarmDuration * 60000)) {
digitalWrite(ledPin, LOW); // Turn off the LED after duration
// Serial.println("LED OFF");
alarmActive = false; // Deactivate the alarm
messageSent = false; // Reset message flag
} else {
digitalWrite(ledPin, LOW); // Ensure LED is off when alarm is inactive
// Serial.println("LED OFF");
messageSent = false; // Reset flag when alarm is inactive
}
// Handle incoming Telegram messages
if (millis() > lastTime + botRequestDelay) {
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
while (numNewMessages) {
handleTelegramMessages(numNewMessages);
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
lastTime = millis();
}
// Add a small delay to avoid flooding the serial monitor
delay(100);
}