#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "time.h"
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
#include "Arduino.h"
#include "DFRobotDFPlayerMini.h"
RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27, 20, 4);
DFRobotDFPlayerMini myDFPlayer;
// ----------- Change this with your wifi Credentials -----------
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 5 * 3600; // Set time Zone (For +5 multiply with 5 and for -5 use accordingly)
const int daylightOffset_sec = 0;
const byte mp3ButtonPin = 5; // Button to play a specific MP3 sound
const int mp3SoundOnButton = 6; // Select the file that needs to be played on button press
String Fajr[12][31]; // Array to hold prayer time
String Dhuhr[12][31]; // Array to hold prayer time
String Asr[12][31]; // Array to hold prayer time
String Maghrib[12][31]; // Array to hold prayer time
String Isha[12][31]; // Array to hold prayer time
int currentYear = 2023; // Set current Year
int year; // Variable to hold year value
int month[12]; // Array to hold month values
int day[31]; // Variable to hold day value in integer
int nextPrayer = 1; // Variable to get next prayer number to be used with mp3
int currentMonth = 0;
int currentAlarmPrayer = 1; // Flag to check which prayer alarm will be set next
unsigned long previousLCDUpdateTime = 0;
void spinner() {
static int8_t counter = 0;
const char* glyphs = "\xa1\xa5\xdb";
lcd.setCursor(15, 1);
lcd.print(glyphs[counter++]);
if (counter == strlen(glyphs)) {
counter = 0;
}
}
void getTimeOnce() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
lcd.setCursor(0, 1);
lcd.println("Connection Err");
return;
}
char buf[3];
strftime(buf, 3, "%m", &timeinfo);
currentMonth = String(buf).toInt(); // get month value
strftime(buf, 3, "%Y", &timeinfo);
int currentYear = String(buf).toInt(); // get Year value
strftime(buf, 3, "%d", &timeinfo);
int currentDay = String(buf).toInt(); // get Day value
strftime(buf, 3, "%H", &timeinfo);
int currentHour = String(buf).toInt(); // get Hour value
strftime(buf, 3, "%M", &timeinfo);
int currentMinute = String(buf).toInt(); // get Minute value
strftime(buf, 3, "%S", &timeinfo);
int currentSecond = String(buf).toInt(); // get Second value
rtc.adjust(DateTime(currentYear, currentMonth, currentDay, currentHour, currentMinute, currentSecond)); // Adjust RTC Time
}
void printLocalTime() {
DateTime now = rtc.now();
char buf2[] = "hh:mm:ss";
Serial.println(now.toString(buf2));
char buf4[] = "MM-DD-YYYY";
Serial.println(now.toString(buf4));
lcd.setCursor(0, 0);
lcd.print(buf4); // Display MM-DD-YYYY on lcd
lcd.println(" "); // Remove any raw character
lcd.setCursor(0, 1); // Display Time on lcd
lcd.println(buf2);
lcd.println(" "); // Remove any raw character
}
void setup() {
Serial.begin(115200);
Serial2.begin(9600); // We will use Serial2 to connect MP3 Module
pinMode(mp3ButtonPin, INPUT_PULLUP); // Select button pin as input with pullup
// lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
if (!rtc.begin()) {
Serial.println("Couldn't find RTC!");
Serial.flush();
lcd.print("RTC Error");
while (1) delay(10);
}
if (!myDFPlayer.begin(Serial2)) { //Use serial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
lcd.print("MP3 Error");
while (true) {
delay(0); // Code to compatible with ESP8266 watch dog.
}
}
myDFPlayer.volume(10); //Set volume value. From 0 to 30
// set alarm 1 flag to false (so alarm 1, 2 didn't happen so far)
// if not done, this easily leads to problems, as both register aren't reset on reboot/recompile
// rtc.clearAlarm(1);
lcd.print("Connecting to ");
lcd.setCursor(0, 1);
lcd.print("WiFi ");
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.println("Connecting to WiFi...");
spinner();
delay(250);
}
Serial.println("Connected to WiFi");
lcd.clear();
lcd.setCursor(0, 0);
lcd.println("Online");
lcd.setCursor(0, 1);
lcd.println("Updating time...");
// Init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
getTimeOnce(); // Get month only once
printLocalTime();
// Call API and store JSON data
callAPI();
addAlarm(); // Add alarm
}
// ... (previous code remains the same)
void callAPI() {
HTTPClient http;
for (int monthLoop = currentMonth; monthLoop < 13; monthLoop++) {
Serial.print("MonthLoop Value");
Serial.print(monthLoop);
Serial.print("|");
Serial.println(currentMonth);
// Your API endpoint
String endpoint = "";
if (monthLoop < 10)
endpoint = "https://api.aladhan.com/v1/calendarByCity/" + String(currentYear) + "/0" + String(monthLoop) + "?city=Islamabad&country=Pakistan&method=2";
else
endpoint = "https://api.aladhan.com/v1/calendarByCity/" + String(currentYear) + "/" + String(monthLoop) + "?city=Islamabad&country=Pakistan&method=2";
tryAgain:
Serial.println("Connecting to API: ");
Serial.println(endpoint);
// Start connection
http.begin(endpoint);
// Send HTTP GET request
int httpCode = http.GET();
Serial.print("HTTP Code:");
Serial.println(httpCode);
if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK) {
// Handle JSON data
DynamicJsonDocument doc(99999); // Adjust size based on response
// Parse JSON
DeserializationError error = deserializeJson(doc, http.getStream());
if (!error) {
// JSON successfully parsed
Serial.println("JSON Parsing Successful:");
// serializeJsonPretty(doc, Serial); // Print JSON to Serial Monitor
// You can access JSON elements like doc["key"]
///////////////////////////////////////////////////
Serial.println("Get Month Data");
int totalCount = 0;
for (JsonObject data_item : doc["data"].as<JsonArray>()) {
JsonObject data_item_timings = data_item["timings"];
const char* data_item_timings_Fajr = data_item_timings["Fajr"]; // "05:41 (PKT)", "05:41 (PKT)", "05:42 ...
const char* data_item_timings_Dhuhr = data_item_timings["Dhuhr"]; // "11:57 (PKT)", "11:57 (PKT)", ...
const char* data_item_timings_Asr = data_item_timings["Asr"]; // "14:41 (PKT)", "14:41 (PKT)", "14:41 ...
const char* data_item_timings_Maghrib = data_item_timings["Maghrib"]; // "16:59 (PKT)", "16:59 (PKT)", ...
const char* data_item_timings_Isha = data_item_timings["Isha"]; // "18:12 (PKT)", "18:12 (PKT)", "18:13 ...
JsonObject data_item_date = data_item["date"];
JsonObject data_item_date_gregorian = data_item_date["gregorian"];
const char* data_item_date_gregorian_day = data_item_date_gregorian["day"]; // "01", "02", "03", "04", ...
int data_item_date_gregorian_month_number = data_item_date_gregorian["month"]["number"]; // 12, 12, 12, ...
const char* data_item_date_gregorian_year = data_item_date_gregorian["year"]; // "2023", "2023", "2023", ...
Fajr[monthLoop][totalCount] = String(data_item_timings_Fajr).substring(0, 5);
Dhuhr[monthLoop][totalCount] = String(data_item_timings_Dhuhr).substring(0, 5);
Asr[monthLoop][totalCount] = String(data_item_timings_Asr).substring(0, 5);
Maghrib[monthLoop][totalCount] = String(data_item_timings_Maghrib).substring(0, 5);
Isha[monthLoop][totalCount] = String(data_item_timings_Isha).substring(0, 5);
totalCount++;
}
Serial.println("Total Days in current Month:" + String(totalCount));
// Close HTTP connection
http.end();
// return;
} else {
Serial.print("Error parsing JSON: ");
Serial.println(error.c_str());
goto tryAgain;
}
} else {
Serial.print("HTTP request failed with error code: ");
Serial.println(httpCode);
goto tryAgain;
}
} else {
Serial.println("HTTP request failed");
goto tryAgain;
}
// Close HTTP connection
http.end();
}
}
// ... (rest of the code remains the same)
void loop() {
// if (rtc.alarmFired(1)) {
// rtc.clearAlarm(1);
// Serial.print(" - Alarm cleared");
// myDFPlayer.play(nextPrayer); //Play the mp3 of current prayer
// delay(65000); // wait for one minute
// addAlarm(); // Add alarm for next prayer
// }
if (digitalRead(mp3ButtonPin) == LOW) {
// Check if button is pressed play mp3 sound
myDFPlayer.play(mp3SoundOnButton); //Play the mp3 file assigned to button
while (!myDFPlayer.available()) { ; } // wait until mp3 ends
}
if ((millis() - previousLCDUpdateTime) > 800) { // Update lcd after every 800 milliseconds only for date and time
previousLCDUpdateTime = millis(); // Note current lcd update time
printLocalTime();
}
}
void addAlarm() {
DateTime now = rtc.now();
int nowHour = now.hour(); // Get current hour
int nowMinute = now.minute(); // Get current minute
int nowMonth = now.month(); // Get current month
int nowDay = now.day(); // Get current Day
int nowYear = now.year(); // Get current year
int nextPrayerTimeHour = 0; // Variable to hold next prayer time hour
int nextPrayerTimeMinute = 0; // Variable to hold next prayer time minute
lcd.setCursor(0, 3);
lcd.print(" "); // clear previous line
lcd.setCursor(0, 3);
if ((nowHour <= Fajr[nowMonth][nowDay].substring(0, 2).toInt()) && (nowMinute <= Fajr[nowMonth][nowDay].substring(3, 5).toInt())) {
Serial.println("Next Prayer time is for Fajr");
lcd.print("Fajr:");
nextPrayerTimeHour = Fajr[nowMonth][nowDay].substring(0, 2).toInt();
nextPrayerTimeMinute = Fajr[nowMonth][nowDay].substring(3, 5).toInt();
nextPrayer = 1; // Set next prayer number
} else if ((nowHour <= Dhuhr[nowMonth][nowDay].substring(0, 2).toInt()) && (nowMinute <= Dhuhr[nowMonth][nowDay].substring(3, 5).toInt())) {
Serial.println("Next Prayer time is for Dhuhr");
lcd.print("Dhuhr:");
nextPrayerTimeHour = Dhuhr[nowMonth][nowDay].substring(0, 2).toInt();
nextPrayerTimeMinute = Dhuhr[nowMonth][nowDay].substring(3, 5).toInt();
nextPrayer = 2; // Set next prayer number
} else if ((nowHour <= Asr[nowMonth][nowDay].substring(0, 2).toInt()) && (nowMinute <= Asr[nowMonth][nowDay].substring(3, 5).toInt())) {
Serial.println("Next Prayer time is for Asr");
lcd.print("Asr:");
nextPrayerTimeHour = Asr[nowMonth][nowDay].substring(0, 2).toInt();
nextPrayerTimeMinute = Asr[nowMonth][nowDay].substring(3, 5).toInt();
nextPrayer = 3; // Set next prayer number
} else if ((nowHour <= Maghrib[nowMonth][nowDay].substring(0, 2).toInt()) && (nowMinute <= Maghrib[nowMonth][nowDay].substring(3, 5).toInt())) {
Serial.println("Next Prayer time is for Maghrib");
lcd.print("Maghrib:");
nextPrayerTimeHour = Maghrib[nowMonth][nowDay].substring(0, 2).toInt();
nextPrayerTimeMinute = Maghrib[nowMonth][nowDay].substring(3, 5).toInt();
nextPrayer = 4; // Set next prayer number
} else if ((nowHour <= Isha[nowMonth][nowDay].substring(0, 2).toInt()) && (nowMinute <= Isha[nowMonth][nowDay].substring(3, 5).toInt())) {
lcd.print("Isha:");
Serial.println("Next Prayer time is for Isha");
nextPrayerTimeHour = Isha[nowMonth][nowDay].substring(0, 2).toInt();
nextPrayerTimeMinute = Isha[nowMonth][nowDay].substring(3, 5).toInt();
nextPrayer = 5; // Set next prayer number
} else if ((nowHour >= Isha[nowMonth][nowDay].substring(0, 2).toInt()) && (nowMinute >= Isha[nowMonth][nowDay].substring(3, 5).toInt())) {
DateTime nextDayPrayer = now + TimeSpan(1, 0, 0, 0); // One day later with TimeSpan addition.
lcd.print("Fajr:");
Serial.println("Next Prayer time is for Fajr Next day");
if (nextDayPrayer.year() != now.year()) {
// Check if next year is not same as current year update the arrays to get next year prayer timings
if (WiFi.status() != WL_CONNECTED) {
// Check if wifi is not connected display message on lcd
lcd.clear(); // Clear LCD
lcd.print("Connct with wifi");
}
while (WiFi.status() != WL_CONNECTED) {
Serial.println("Connecting to WiFi...");
spinner();
delay(250);
}
// Call API and store JSON data
callAPI(); // call api to get new year information
}
nowYear = nextDayPrayer.year(); // Check if next day year will change
nowMonth = nextDayPrayer.month(); // Check if next day month will change
nowDay = nextDayPrayer.day(); // Get date of next month
nextPrayerTimeHour = Fajr[nowMonth][nowDay].substring(0, 2).toInt();
nextPrayerTimeMinute = Fajr[nowMonth][nowDay].substring(3, 5).toInt();
nextPrayer = 1; // Set next prayer number
}
DateTime dtAlarm(nowYear, nowMonth, nowDay, nextPrayerTimeHour, nextPrayerTimeMinute, 0);
// rtc.setAlarm1( // Set alarm for next prayer
// dtAlarm, DS3231_A1_Second // this mode triggers the alarm when the seconds match. See Doxygen for other options
// );
lcd.setCursor(10, 3); // Set cursor
char buf2[] = "hh:mm:ss"; // Display time of next prayer on LCD
lcd.println(dtAlarm.toString(buf2));
// showDate("dt6", dt6);
}