Before uploading the code, ensure the following libraries are installed in the Arduino IDE:
#include <Wire.h>
#include <LiquidCrystal_PCF8574.h> // Compatible with ESP8266
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <DHT.h>
#include <TimeLib.h> // For handling epoch time
#define DHTPIN D4
#define DHTTYPE DHT11
// WiFi credentials
const char* ssid = "Enter SSID";
const char* password = "Password";
// LCD configuration
LiquidCrystal_PCF8574 lcd(0x3F);
// DHT sensor
DHT dht(DHTPIN, DHTTYPE);
// NTP client for local and UTC time
WiFiUDP ntpUDP;
NTPClient localTimeClient(ntpUDP, "pool.ntp.org", 19800, 60000); // UTC+5:30 for Kalyan
NTPClient utcTimeClient(ntpUDP, "pool.ntp.org", 0, 60000);
// HamQSL API configuration
const char* hamqslUrl = "https://www.hamqsl.com/solarxml.php";
// Weather API configuration
const char* weatherApiHost = "api.openweathermap.org";
const String weatherApiPath = "/data/2.5/weather?q=Kalyan,IN&appid=806a74b5cdc039b3cbb7e9bbb8b8d82a&units=metric";
unsigned long lastUpdateTime = 0;
const unsigned long updateInterval = 15 * 60 * 1000; // 15 minutes
String solarFlux = "";
String kIndex = "";
String bandConditions[3] = {"", "", ""};
String weatherCondition = "Weather Unavailable";
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
// Initialize DHT sensor
dht.begin();
// Initialize LCD
lcd.begin(20, 4);
lcd.setBacklight(255);
lcd.setCursor(0, 0);
lcd.print("Connecting WiFi");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
lcd.print(".");
}
lcd.clear();
lcd.print("WiFi Connected");
delay(2000);
// Initialize NTP clients
localTimeClient.begin();
utcTimeClient.begin();
// Fetch initial data
fetchBandConditions();
fetchWeatherData();
}
void loop() {
// Update time
localTimeClient.update();
utcTimeClient.update();
// Read temperature and humidity
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
// Calculate date and time from epoch
time_t localTime = localTimeClient.getEpochTime();
time_t utcTime = utcTimeClient.getEpochTime();
int localYear = year(localTime);
int localMonth = month(localTime);
int localDay = day(localTime);
int localHour = hour(localTime);
int localMinute = minute(localTime);
int utcYear = year(utcTime);
int utcMonth = month(utcTime);
int utcDay = day(utcTime);
int utcHour = hour(utcTime);
int utcMinute = minute(utcTime);
// Update band conditions and weather data every 15 minutes
if (millis() - lastUpdateTime > updateInterval) {
fetchBandConditions();
fetchWeatherData();
lastUpdateTime = millis();
}
// Display data on LCD
lcd.setCursor(0, 0);
lcd.printf("LOC-%02d:%02d %02d/%02d", localHour, localMinute, localDay, localMonth);
lcd.setCursor(0, 1);
lcd.printf("UTC-%02d:%02d %02d/%02d", utcHour, utcMinute, utcDay, utcMonth);
lcd.setCursor(0, 2);
lcd.printf("TEMP:%.0fC HUM:%.0f%%", temperature, humidity);
lcd.setCursor(0, 3);
lcd.print("WEATHER-" + weatherCondition);
delay(1000); // Update display every second
}
void fetchBandConditions() {
WiFiClientSecure client;
client.setInsecure(); // Allow insecure connections for HTTPS
if (client.connect("www.hamqsl.com", 443)) {
client.println("GET /solarxml.php HTTP/1.1");
client.println("Host: www.hamqsl.com");
client.println("Connection: close");
client.println();
String response = "";
while (client.connected() || client.available()) {
if (client.available()) {
response += client.readString();
}
}
client.stop();
Serial.println("Full XML Response:");
Serial.println(response);
parseBandConditions(response);
} else {
Serial.println("Connection to hamqsl.com failed");
}
}
void parseBandConditions(String xml) {
int sIndex = xml.indexOf("<solarflux>");
if (sIndex != -1) {
solarFlux = xml.substring(sIndex + 11, xml.indexOf("</solarflux>", sIndex));
} else {
solarFlux = "N/A";
}
int kIndexPos = xml.indexOf("<kindex>");
if (kIndexPos != -1) {
kIndex = xml.substring(kIndexPos + 8, xml.indexOf("</kindex>", kIndexPos));
} else {
kIndex = "N/A";
}
String bands[] = {"20m", "40m", "80m"};
for (int i = 0; i < 3; i++) {
int bIndex = xml.indexOf("<band_" + bands[i] + ">");
if (bIndex != -1) {
bandConditions[i] = xml.substring(bIndex + 7 + bands[i].length(), xml.indexOf("</band_" + bands[i] + ">", bIndex)).substring(0, 1);
} else {
bandConditions[i] = "U"; // Unavailable
}
}
}
void fetchWeatherData() {
WiFiClientSecure client;
client.setInsecure(); // Allow insecure connections for HTTPS
if (client.connect(weatherApiHost, 443)) {
client.println("GET " + weatherApiPath + " HTTP/1.1");
client.println("Host: " + String(weatherApiHost));
client.println("Connection: close");
client.println();
String response = "";
while (client.connected() || client.available()) {
if (client.available()) {
response += client.readString();
}
}
client.stop();
Serial.println("Weather API Response:");
Serial.println(response);
parseWeatherData(response);
} else {
Serial.println("Connection to Weather API failed");
}
}
void parseWeatherData(String json) {
int descIndex = json.indexOf("\"description\":");
if (descIndex != -1) {
weatherCondition = json.substring(descIndex + 15, json.indexOf("\"", descIndex + 15));
} else {
weatherCondition = "Unavailable";
}
}