#define BLYNK_TEMPLATE_ID "TMPL2o2SqlCwx"
#define BLYNK_TEMPLATE_NAME "Quickstart Template"
#define BLYNK_AUTH_TOKEN "ctuVteBw_QTpAOSQcU5f3Z34IiO0CdjU"
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <BlynkSimpleEsp32.h>
#include <HTTPClient.h>
#include <EmonLib.h>
#include <time.h>
#include <ArduinoJson.h>
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
char auth[] = "ctuVteBw_QTpAOSQcU5f3Z34IiO0CdjU";
const char* appwriteHost = "cloud.appwrite.io";
const char* projectID = "66ad2625001249bd442c";
const char* collectionID = "66ad2db100146cb4e965";
const char* databaseID = "66ad2c74001a1bc74f45";
const char* apiKey = "c82a5f96d2690914c4524bed259b33fe68b83243289a42843f581ac53c3108e7f667c5154f5d36de6168045102d9a05b8a6cc03e5978a6584f063cfbea4d15c6d8c869a9bc3d3499f00318e086e498b6df9d40f9b8d1b7996cadfedb687645c5b359c40e027011b7df381b30d0648ac0bc31c970b9a16f53fa73314bf5c64d40";
const char* secondCollectionID = "66ad2cb5002b7c3a820b";
EnergyMonitor emon1;
unsigned long lastMillis = 0;
unsigned long lastDbCheckMillis = 0;
float energy = 0.0;
bool deviceStatus = false;
#define RELAY_PIN 4
#define DB_CHECK_INTERVAL 500 // 0.5 seconds
void setup() {
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
pinMode(RELAY_PIN, OUTPUT);
emon1.voltage(12, 320, 1.7);
emon1.current(12, 90);
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
while (!time(nullptr)) {
Serial.println("Waiting for time synchronization...");
delay(1000);
}
String deviceId = "Smart Socket";
String timestamp = getFormattedTime();
String userId = "your_user_id";
if (deviceExistsInDB(deviceId)) {
updateDeviceStatusFromDB(deviceId);
}
}
String getFormattedTime() {
time_t now = time(nullptr);
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
char buffer[25];
strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", &timeinfo);
return String(buffer);
}
String urlEncode(const String& str) {
String encoded = "";
for (size_t i = 0; i < str.length(); ++i) {
char c = str.charAt(i);
if (c == ' ') {
encoded += "+";
} else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~') {
encoded += c;
} else {
encoded += String("%") + String((int)c, HEX);
}
}
return encoded;
}
bool deviceExistsInDB(const String& deviceId) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = String("https://") + appwriteHost + "/v1/databases/" + String(databaseID) + "/collections/" + String(secondCollectionID) + "/documents";
url += "?filters[deviceName]=" + urlEncode(deviceId);
http.begin(url);
http.addHeader("X-Appwrite-Project", projectID);
http.addHeader("X-Appwrite-Key", apiKey);
int httpResponseCode = http.GET();
if (httpResponseCode == 200) {
String response = http.getString();
Serial.println("Response: " + response);
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, response);
if (error) {
Serial.print("JSON deserialization failed: ");
Serial.println(error.c_str());
http.end();
return false;
}
JsonArray documents = doc["documents"].as<JsonArray>();
if (documents.size() > 0) {
return true;
} else {
Serial.println("No documents found for device");
}
} else {
Serial.print("Error on GET request: ");
Serial.println(httpResponseCode);
handleHttpError(httpResponseCode);
}
http.end();
} else {
Serial.println("Error in WiFi connection");
}
return false;
}
void updateDeviceStatusFromDB(const String& deviceId) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = String("https://") + appwriteHost + "/v1/databases/" + String(databaseID) + "/collections/" + String(secondCollectionID) + "/documents";
url += "?filters[deviceName]=" + urlEncode(deviceId);
http.begin(url);
http.addHeader("X-Appwrite-Project", projectID);
http.addHeader("X-Appwrite-Key", apiKey);
int httpResponseCode = http.GET();
if (httpResponseCode == 200) {
String response = http.getString();
Serial.println("Response: " + response);
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, response);
if (error) {
Serial.print("JSON deserialization failed: ");
Serial.println(error.c_str());
http.end();
return;
}
JsonArray documents = doc["documents"].as<JsonArray>();
if (documents.size() > 0) {
bool status = documents[1]["status"];
deviceStatus = status;
digitalWrite(RELAY_PIN, deviceStatus ? HIGH : LOW);
Serial.print("Device status updated from DB: ");
Serial.println(deviceStatus ? "ON" : "OFF");
} else {
Serial.println("No documents found for device");
}
} else {
Serial.print("Error on GET request: ");
Serial.println(httpResponseCode);
handleHttpError(httpResponseCode);
}
http.end();
} else {
Serial.println("Error in WiFi connection");
}
}
void sendDataToAppwrite(const String& deviceId, const String& userId, bool status, const String& timestamp) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = String("https://") + appwriteHost + "/v1/databases/" + String(databaseID) + "/collections/" + String(secondCollectionID) + "/documents";
http.begin(url);
http.addHeader("Content-Type", "application/json");
http.addHeader("X-Appwrite-Project", projectID);
http.addHeader("X-Appwrite-Key", apiKey);
String jsonPayload = "{\"documentId\": \"unique()\", \"data\": {\"deviceName\": \"" + deviceId + "\", \"userId\": \"" + userId + "\", \"status\": " + (status ? "true" : "false") + "}}";
int httpResponseCode = http.POST(jsonPayload);
if (httpResponseCode > 0) {
String response = http.getString();
Serial.println(httpResponseCode);
Serial.println(response);
} else {
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
handleHttpError(httpResponseCode);
}
http.end();
} else {
Serial.println("Error in WiFi connection");
}
}
void handleHttpError(int code) {
String errorMessage;
switch (code) {
case 400:
errorMessage = "Bad Request";
break;
case 401:
errorMessage = "Unauthorized";
break;
case 403:
errorMessage = "Forbidden";
break;
case 404:
errorMessage = "Not Found";
break;
case 500:
errorMessage = "Internal Server Error";
break;
default:
errorMessage = "Unknown Error";
}
Serial.println("HTTP Response Error: " + errorMessage);
}
void loop() {
Blynk.run();
unsigned long currentMillis = millis();
emon1.calcVI(20, 2000);
float voltage = emon1.Vrms;
float current = emon1.Irms;
float power = emon1.realPower;
float deltaTime = (currentMillis - lastMillis) / 1000.0;
lastMillis = currentMillis;
energy += power * deltaTime;
Blynk.virtualWrite(V4, voltage);
Blynk.virtualWrite(V0, current);
Blynk.virtualWrite(V1, power);
Blynk.virtualWrite(V3, energy);
String deviceId = "Smart Socket"; // Declare deviceId here
String timestamp = getFormattedTime();
String userId = "your_user_id";
if (currentMillis - lastDbCheckMillis >= DB_CHECK_INTERVAL) {
lastDbCheckMillis = currentMillis;
if (deviceExistsInDB(deviceId)) {
updateDeviceStatusFromDB(deviceId);
}
}
float pricePerKWh = 1.753;
float totalPrice = energy * pricePerKWh;
// Send data to Appwrite (first collection)
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = String("https://") + appwriteHost + "/v1/databases/" + String(databaseID) + "/collections/" + String(collectionID) + "/documents";
http.begin(url);
http.addHeader("Content-Type", "application/json");
http.addHeader("X-Appwrite-Project", projectID);
http.addHeader("X-Appwrite-Key", apiKey);
String jsonPayload = "{\"documentId\": \"unique()\", \"data\": {\"deviceId\": \"" + deviceId + "\", \"timestamp\": \"" + timestamp + "\", \"voltage\": " + String(voltage) +
", \"current\": " + String(current) +
", \"power\": " + String(power) +
",\"price\": " + String(totalPrice) +
", \"energy\": " + String(energy) +
"}}";
int httpResponseCode = http.POST(jsonPayload);
if (httpResponseCode > 0) {
String response = http.getString();
Serial.println(httpResponseCode);
Serial.println(response);
} else {
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
}
http.end();
} else {
Serial.println("Error in WiFi connection");
}
Serial.print("Voltage: ");
Serial.print(voltage);
Serial.print(" V, Current: ");
Serial.print(current);
Serial.print(" A, Power: ");
Serial.print(power);
Serial.print(" W, Energy: ");
Serial.print(energy);
Serial.print(" Joules, Status: ");
Serial.println(deviceStatus ? "ON" : "OFF");
delay(500); // 500 milliseconds delay
}