#include <Arduino.h>
#include <DHT.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#define DHT_PIN 15
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
const char* ssid = "FIRELINK";
const char* password = "06101111";
const String apiKey = "VGIH0VJY05I73ISC";
const int channelID = 3174042;
const char* backendHost = "host.wokwi.internal";
const int backendPort = 3000;
const char* backendEndpoint = "/api/data";
const char* discordWebhook = "https://discord.com/api/webhooks/1447591817595060278/cM-XEDpPEsoQiSOjqDGMfcBnIuFhaFOYBLtqLxeEyBTS4JovpbTbox5dhcy56Ke2uIJs";
const float HIGH_TEMP_THRESHOLD = 30.0;
const float LOW_TEMP_THRESHOLD = 10.0;
const float HIGH_HUMIDITY_THRESHOLD = 80.0;
const float LOW_HUMIDITY_THRESHOLD = 20.0;
unsigned long previousRead = 0;
unsigned long previousUpload = 0;
unsigned long previousDiscordAlert = 0;
const unsigned long READ_INTERVAL = 3000;
const unsigned long UPLOAD_INTERVAL = 5000;
const unsigned long DISCORD_ALERT_INTERVAL = 5000;
float temperature = 0;
float humidity = 0;
bool alertSent = false;
void connectWiFi();
void readSensor();
void uploadToThingSpeak(float temp, float humi);
void uploadToBackend(float temp, float humi);
void sendDiscordAlert(const char* message);
void checkThresholdsAndAlert();
String getTimeString();
void printSystemInfo();
void connectWiFi() {
Serial1.print("Connecting to WiFi");
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial1.println("\n WiFi connected!");
Serial1.print("IP Address: ");
Serial1.println(WiFi.localIP());
} else {
Serial1.println("\n WiFi connection failed!");
}
}
void readSensor() {
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(t) || isnan(h)) {
Serial1.println(" Sensor read error!");
return;
}
temperature = t;
humidity = h;
Serial1.print("[");
Serial1.print(getTimeString());
Serial1.print("] Temp: ");
Serial1.print(temperature);
Serial1.print("°C | Humidity: ");
Serial1.print(humidity);
Serial1.println("%");
}
void uploadToThingSpeak(float temp, float humi) {
if (WiFi.status() != WL_CONNECTED) {
Serial1.println(" WiFi disconnected. Reconnecting...");
connectWiFi();
return;
}
HTTPClient http;
String url = "http://api.thingspeak.com/update?api_key=" + apiKey +
"&field1=" + String(temp, 2) +
"&field2=" + String(humi, 2);
Serial1.println(" Sending to ThingSpeak...");
http.begin(url);
int httpResponse = http.GET();
if (httpResponse > 0) {
Serial1.print("ThingSpeak Response: ");
Serial1.println(httpResponse);
} else {
Serial1.print("HTTP Error: ");
Serial1.println(httpResponse);
}
http.end();
}
void uploadToBackend(float temp, float humi) {
if (WiFi.status() != WL_CONNECTED) {
Serial1.println(" WiFi not connected for backend upload");
return;
}
HTTPClient http;
String url = "http://" + String(backendHost) + ":" + String(backendPort) + backendEndpoint;
Serial1.print("Sending to backend: ");
Serial1.println(url);
StaticJsonDocument<200> jsonDoc;
jsonDoc["temperature"] = temp;
jsonDoc["humidity"] = humi;
jsonDoc["device_id"] = "pico_w_jami";
jsonDoc["timestamp"] = getTimeString();
String payload;
serializeJson(jsonDoc, payload);
http.begin(url);
http.addHeader("Content-Type", "application/json");
http.addHeader("User-Agent", "PicoW-DHT22/1.0");
Serial.println("Payload: " + payload);
int httpResponse = http.POST(payload);
if (httpResponse > 0) {
String response = http.getString();
Serial1.print("Backend Response (");
Serial1.print(httpResponse);
Serial1.print("): ");
Serial1.println(response);
} else {
Serial1.print("Backend Error: ");
Serial1.println(httpResponse);
Serial1.println("Error: " + http.errorToString(httpResponse));
}
http.end();
}
void sendDiscordAlert(const char* message) {
if (WiFi.status() != WL_CONNECTED) {
return;
}
unsigned long currentTime = millis();
if (currentTime - previousDiscordAlert < DISCORD_ALERT_INTERVAL) {
return;
}
HTTPClient http;
http.begin(discordWebhook);
http.addHeader("Content-Type", "application/json");
String payload = "{";
payload += "\"embeds\": [{";
payload += "\"title\": \"Pico W Sensor Alert\",";
payload += "\"description\": \"" + String(message) + "\",";
payload += "\"color\": 16711680,";
payload += "\"fields\": [";
payload += "{\"name\": \" Temperature\", \"value\": \"" + String(temperature, 1) + "°C\", \"inline\": true},";
payload += "{\"name\": \" Humidity\", \"value\": \"" + String(humidity, 1) + "%\", \"inline\": true},";
payload += "{\"name\": \" Time\", \"value\": \"" + getTimeString() + "\", \"inline\": false}";
payload += "],";
payload += "\"footer\": {\"text\": \"Pico W DHT22 Monitor\"}";
payload += "}]";
payload += "}";
Serial1.println(" Sending Discord alert...");
int httpResponse = http.POST(payload);
if (httpResponse > 0) {
Serial1.print("Discord alert sent (");
Serial1.print(httpResponse);
Serial1.println(")");
previousDiscordAlert = currentTime;
alertSent = true;
} else {
Serial1.print("Discord error: ");
Serial1.println(httpResponse);
}
http.end();
}
void checkThresholdsAndAlert() {
char alertMessage[200];
bool shouldAlert = false;
if (temperature >= HIGH_TEMP_THRESHOLD) {
snprintf(alertMessage, sizeof(alertMessage),
"**HIGH TEMPERATURE ALERT**\nTemperature is %.1f°C (Threshold: %.1f°C)",
temperature, HIGH_TEMP_THRESHOLD);
shouldAlert = true;
} else if (temperature <= LOW_TEMP_THRESHOLD) {
snprintf(alertMessage, sizeof(alertMessage),
" **LOW TEMPERATURE ALERT**\nTemperature is %.1f°C (Threshold: %.1f°C)",
temperature, LOW_TEMP_THRESHOLD);
shouldAlert = true;
}
if (humidity >= HIGH_HUMIDITY_THRESHOLD) {
snprintf(alertMessage, sizeof(alertMessage),
" **HIGH HUMIDITY ALERT**\nHumidity is %.1f%% (Threshold: %.1f%%)",
humidity, HIGH_HUMIDITY_THRESHOLD);
shouldAlert = true;
} else if (humidity <= LOW_HUMIDITY_THRESHOLD) {
snprintf(alertMessage, sizeof(alertMessage),
" **LOW HUMIDITY ALERT**\nHumidity is %.1f%% (Threshold: %.1f%%)",
humidity, LOW_HUMIDITY_THRESHOLD);
shouldAlert = true;
}
if (shouldAlert && !alertSent) {
sendDiscordAlert(alertMessage);
}
if (temperature < HIGH_TEMP_THRESHOLD && temperature > LOW_TEMP_THRESHOLD &&
humidity < HIGH_HUMIDITY_THRESHOLD && humidity > LOW_HUMIDITY_THRESHOLD) {
alertSent = false;
}
}
String getTimeString() {
unsigned long seconds = millis() / 1000;
unsigned long minutes = seconds / 60;
unsigned long hours = minutes / 60;
seconds %= 60;
minutes %= 60;
char timeStr[20];
snprintf(timeStr, sizeof(timeStr), "%02lu:%02lu:%02lu", hours, minutes, seconds);
return String(timeStr);
}
void printSystemInfo() {
Serial1.println("\nSYSTEM INFORMATION");
Serial1.println("========================");
Serial1.print("WiFi SSID: ");
Serial1.println(ssid);
Serial.print("WiFi Status: ");
Serial1.println(WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected");
Serial1.print("Backend Server: ");
Serial1.print(backendHost);
Serial1.print(":");
Serial1.println(backendPort);
Serial1.println("Alert Thresholds:");
Serial1.print(" Temperature: ");
Serial1.print(LOW_TEMP_THRESHOLD);
Serial1.print("°C - ");
Serial1.print(HIGH_TEMP_THRESHOLD);
Serial1.println("°C");
Serial1.print(" Humidity: ");
Serial1.print(LOW_HUMIDITY_THRESHOLD);
Serial1.print("% - ");
Serial1.print(HIGH_HUMIDITY_THRESHOLD);
Serial1.println("%");
Serial1.println("========================");
}
void setup() {
Serial1.begin(115200);
delay(2000); // Wait for serial monitor
Serial1.println("\nStarting Pico W DHT22 Monitor");
Serial1.println("=================================");
dht.begin();
delay(2000); // Let DHT sensor stabilize
connectWiFi();
printSystemInfo();
Serial1.println("\n System initialized and ready!");
Serial1.println("=================================\n");
}
void loop() {
unsigned long now = millis();
if (now - previousRead >= READ_INTERVAL) {
readSensor();
previousRead = now;
checkThresholdsAndAlert();
}
if (now - previousUpload >= UPLOAD_INTERVAL) {
if (temperature != 0 && humidity != 0) {
Serial1.println("\nUPLOAD CYCLE STARTED");
Serial1.println("---------------------");
uploadToThingSpeak(temperature, humidity);
uploadToBackend(temperature, humidity);
checkThresholdsAndAlert();
Serial1.println("---------------------");
Serial1.println("UPLOAD CYCLE COMPLETE\n");
}
previousUpload = now;
}
static unsigned long lastStatusPrint = 0;
if (now - lastStatusPrint >= 60000) {
printSystemInfo();
lastStatusPrint = now;
}
delay(100);
}