219 lines
5.9 KiB
C++
219 lines
5.9 KiB
C++
#include <WiFi.h>
|
|
#include <FirebaseESP32.h> // Gunakan library "Firebase ESP32 Client" by Mobizt
|
|
|
|
#define RXD2 16 // RX pin ESP32
|
|
#define TXD2 17 // TX pin ESP32
|
|
|
|
// WiFi credentials
|
|
#define WIFI_SSID "hydrop"
|
|
#define WIFI_PASSWORD "123123123"
|
|
|
|
// Firebase config
|
|
#define FIREBASE_HOST "https://hydrop-a1e64-default-rtdb.firebaseio.com"
|
|
#define FIREBASE_AUTH "4lJpDHPo9LGh6WCYpjs1aRB6ABJZwHLOXkaCoLAV"
|
|
|
|
// Firebase objects
|
|
FirebaseData fbdo;
|
|
FirebaseAuth auth;
|
|
FirebaseConfig config;
|
|
|
|
struct SensorData {
|
|
float temperature;
|
|
float humidity;
|
|
float ph;
|
|
float tds;
|
|
bool tempValid;
|
|
bool humValid;
|
|
bool phValid;
|
|
bool tdsValid;
|
|
unsigned long lastUpdate;
|
|
} sensorData;
|
|
|
|
struct CommStats {
|
|
unsigned long totalReceived;
|
|
unsigned long validData;
|
|
unsigned long errorData;
|
|
unsigned long lastReceived;
|
|
} commStats = {0, 0, 0, 0};
|
|
|
|
const unsigned long DATA_TIMEOUT = 10000;
|
|
const unsigned long STATS_INTERVAL = 30000;
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
|
|
|
|
// Koneksi WiFi
|
|
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
|
Serial.print("Connecting to WiFi");
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
Serial.print(".");
|
|
delay(500);
|
|
}
|
|
Serial.println("\nWiFi connected!");
|
|
|
|
// Konfigurasi Firebase
|
|
config.database_url = FIREBASE_HOST;
|
|
config.signer.tokens.legacy_token = FIREBASE_AUTH;
|
|
|
|
Firebase.begin(&config, &auth);
|
|
Firebase.reconnectWiFi(true);
|
|
|
|
Serial.println("Firebase initialized.");
|
|
|
|
sensorData = {0, 0, 0, 0, false, false, false, false, 0};
|
|
|
|
Serial.println("=== ESP32 Hydroponic Receiver ===");
|
|
Serial.println("Menunggu data dari Arduino...");
|
|
}
|
|
|
|
void loop() {
|
|
if (Serial2.available()) {
|
|
String rawData = Serial2.readStringUntil('\n');
|
|
rawData.trim();
|
|
|
|
commStats.totalReceived++;
|
|
commStats.lastReceived = millis();
|
|
|
|
if (parseAndValidateData(rawData)) {
|
|
commStats.validData++;
|
|
sensorData.lastUpdate = millis();
|
|
|
|
displaySensorData();
|
|
sendToFirebase();
|
|
} else {
|
|
commStats.errorData++;
|
|
Serial.print("ERROR: Invalid data format: ");
|
|
Serial.println(rawData);
|
|
}
|
|
}
|
|
|
|
checkDataTimeout();
|
|
displayStats();
|
|
|
|
delay(100);
|
|
}
|
|
|
|
bool parseAndValidateData(String data) {
|
|
if (data.length() < 5) return false;
|
|
|
|
int idx1 = data.indexOf(',');
|
|
int idx2 = data.indexOf(',', idx1 + 1);
|
|
int idx3 = data.indexOf(',', idx2 + 1);
|
|
if (idx1 <= 0 || idx2 <= 0 || idx3 <= 0) return false;
|
|
|
|
String tempStr = data.substring(0, idx1);
|
|
String humStr = data.substring(idx1 + 1, idx2);
|
|
String phStr = data.substring(idx2 + 1, idx3);
|
|
String tdsStr = data.substring(idx3 + 1);
|
|
|
|
float temp = tempStr.toFloat();
|
|
float hum = humStr.toFloat();
|
|
float ph = phStr.toFloat();
|
|
float tds = tdsStr.toFloat();
|
|
|
|
sensorData.temperature = temp;
|
|
sensorData.humidity = hum;
|
|
sensorData.ph = ph;
|
|
sensorData.tds = tds;
|
|
sensorData.tempValid = validateTemperature(temp);
|
|
sensorData.humValid = validateHumidity(hum);
|
|
sensorData.phValid = validatePH(ph);
|
|
sensorData.tdsValid = validateTDS(tds);
|
|
|
|
return (sensorData.tempValid || sensorData.humValid || sensorData.phValid || sensorData.tdsValid);
|
|
}
|
|
|
|
void sendToFirebase() {
|
|
if (WiFi.status() != WL_CONNECTED) {
|
|
Serial.println("WiFi disconnected, skipping Firebase upload.");
|
|
return;
|
|
}
|
|
|
|
FirebaseJson json;
|
|
json.set("temperature", sensorData.tempValid ? sensorData.temperature : -999);
|
|
json.set("humidity", sensorData.humValid ? sensorData.humidity : -999);
|
|
json.set("ph", sensorData.phValid ? sensorData.ph : -999);
|
|
json.set("tds", sensorData.tdsValid ? sensorData.tds : -999);
|
|
json.set("timestamp", millis());
|
|
|
|
if (Firebase.updateNode(fbdo, "/sensorData", json)) {
|
|
Serial.println("Data sent to Firebase.");
|
|
} else {
|
|
Serial.print("Firebase failed: ");
|
|
Serial.println(fbdo.errorReason());
|
|
}
|
|
}
|
|
|
|
bool validateTemperature(float temp) {
|
|
return temp != -999 && temp >= -10 && temp <= 60;
|
|
}
|
|
|
|
bool validateHumidity(float hum) {
|
|
return hum != -999 && hum >= 0 && hum <= 100;
|
|
}
|
|
|
|
bool validatePH(float ph) {
|
|
return ph != -999 && ph >= 0 && ph <= 14;
|
|
}
|
|
|
|
bool validateTDS(float tds) {
|
|
return tds != -999 && tds >= 0 && tds <= 3000;
|
|
}
|
|
|
|
void displaySensorData() {
|
|
Serial.println("=== SENSOR DATA RECEIVED ===");
|
|
Serial.print("Temperature: ");
|
|
Serial.println(sensorData.tempValid ? String(sensorData.temperature, 2) + " °C" : "INVALID");
|
|
|
|
Serial.print("Humidity: ");
|
|
Serial.println(sensorData.humValid ? String(sensorData.humidity, 2) + " %" : "INVALID");
|
|
|
|
Serial.print("pH: ");
|
|
Serial.println(sensorData.phValid ? String(sensorData.ph, 2) : "INVALID");
|
|
|
|
Serial.print("TDS: ");
|
|
Serial.println(sensorData.tdsValid ? String(sensorData.tds, 0) + " ppm" : "INVALID");
|
|
|
|
Serial.println("===========================");
|
|
}
|
|
|
|
void checkDataTimeout() {
|
|
static unsigned long lastTimeoutCheck = 0;
|
|
if (millis() - lastTimeoutCheck >= 5000) {
|
|
if (sensorData.lastUpdate > 0 && (millis() - sensorData.lastUpdate) > DATA_TIMEOUT) {
|
|
Serial.println("⚠️ WARNING: No valid data for 10 seconds!");
|
|
sensorData.tempValid = false;
|
|
sensorData.humValid = false;
|
|
sensorData.phValid = false;
|
|
sensorData.tdsValid = false;
|
|
}
|
|
lastTimeoutCheck = millis();
|
|
}
|
|
}
|
|
|
|
void displayStats() {
|
|
static unsigned long lastStatsDisplay = 0;
|
|
if (millis() - lastStatsDisplay >= STATS_INTERVAL) {
|
|
Serial.println("=== STATISTIK KOMUNIKASI ===");
|
|
Serial.print("Total diterima: ");
|
|
Serial.println(commStats.totalReceived);
|
|
Serial.print("Valid: ");
|
|
Serial.println(commStats.validData);
|
|
Serial.print("Error: ");
|
|
Serial.println(commStats.errorData);
|
|
|
|
if (commStats.totalReceived > 0) {
|
|
float success = (float)commStats.validData / commStats.totalReceived * 100;
|
|
Serial.print("Success rate: ");
|
|
Serial.print(success, 1);
|
|
Serial.println(" %");
|
|
}
|
|
|
|
Serial.print("Terakhir diterima: ");
|
|
Serial.println((millis() - commStats.lastReceived) / 1000);
|
|
|
|
Serial.println("=============================");
|
|
lastStatsDisplay = millis();
|
|
}
|
|
} |