Upload files to "/"
This commit is contained in:
parent
366a49907f
commit
7ace429544
|
|
@ -0,0 +1,318 @@
|
||||||
|
#include <Wire.h>
|
||||||
|
#include "Adafruit_SHT31.h"
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <Firebase_ESP_Client.h>
|
||||||
|
#include <RTClib.h>
|
||||||
|
|
||||||
|
// ================= WIFI =================
|
||||||
|
#define WIFI_SSID "Toge"
|
||||||
|
#define WIFI_PASSWORD "123123123"
|
||||||
|
|
||||||
|
// ================= FIREBASE =================
|
||||||
|
#define DATABASE_URL "https://smarttoge-default-rtdb.firebaseio.com/"
|
||||||
|
#define DATABASE_SECRET "0CWsHxiRJar3qXSx4uGX385rf0VAnpKKOhQ1wbok"
|
||||||
|
|
||||||
|
// ================= PIN =================
|
||||||
|
#define RELAY_PIN 5
|
||||||
|
|
||||||
|
// ================= OBJECT =================
|
||||||
|
Adafruit_SHT31 sht31 = Adafruit_SHT31();
|
||||||
|
RTC_DS3231 rtc;
|
||||||
|
|
||||||
|
FirebaseData fbdo;
|
||||||
|
FirebaseAuth auth;
|
||||||
|
FirebaseConfig config;
|
||||||
|
|
||||||
|
FirebaseJson json;
|
||||||
|
FirebaseJsonData result;
|
||||||
|
|
||||||
|
// ================= VAR GLOBAL =================
|
||||||
|
bool relayOn = false;
|
||||||
|
bool pumpRunning = false;
|
||||||
|
bool pumpManual = false;
|
||||||
|
bool humidityNotifSent = false;
|
||||||
|
bool wateringDoneNotifSent = false;
|
||||||
|
String activeScheduleKey = "";
|
||||||
|
|
||||||
|
|
||||||
|
// TIMER
|
||||||
|
unsigned long lastSensor = 0;
|
||||||
|
unsigned long lastFirebase = 0;
|
||||||
|
unsigned long lastSchedule = 0;
|
||||||
|
unsigned long lastManual = 0;
|
||||||
|
|
||||||
|
// DATA GLOBAL
|
||||||
|
float suhu = 0;
|
||||||
|
float kelembaban = 0;
|
||||||
|
|
||||||
|
String rtcDate = "";
|
||||||
|
String rtcTime = "";
|
||||||
|
|
||||||
|
// ================= SET RTC DARI SERIAL =================
|
||||||
|
void setRTCFromSerial() {
|
||||||
|
|
||||||
|
if (Serial.available()) {
|
||||||
|
|
||||||
|
String input = Serial.readStringUntil('\n');
|
||||||
|
input.trim();
|
||||||
|
|
||||||
|
int year, month, day, hour, minute, second;
|
||||||
|
|
||||||
|
if (sscanf(input.c_str(), "%d-%d-%d %d:%d:%d",
|
||||||
|
&year, &month, &day,
|
||||||
|
&hour, &minute, &second) == 6) {
|
||||||
|
|
||||||
|
rtc.adjust(DateTime(year, month, day, hour, minute, second));
|
||||||
|
|
||||||
|
Serial.println("RTC berhasil di-set!");
|
||||||
|
} else {
|
||||||
|
Serial.println("Format salah! Gunakan: YYYY-MM-DD HH:MM:SS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= SETUP =================
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
pinMode(RELAY_PIN, OUTPUT);
|
||||||
|
digitalWrite(RELAY_PIN, HIGH);
|
||||||
|
|
||||||
|
Wire.begin(21, 22);
|
||||||
|
|
||||||
|
if (!sht31.begin(0x44)) {
|
||||||
|
Serial.println("Sensor tidak ditemukan!");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rtc.begin()) {
|
||||||
|
Serial.println("RTC tidak ditemukan!");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set otomatis kalau RTC kehilangan daya
|
||||||
|
if (rtc.lostPower()) {
|
||||||
|
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("Masukkan waktu RTC format:");
|
||||||
|
Serial.println("YYYY-MM-DD HH:MM:SS");
|
||||||
|
|
||||||
|
// ================= WIFI =================
|
||||||
|
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||||
|
Serial.print("Connecting WiFi");
|
||||||
|
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
Serial.print(".");
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("\nWiFi Connected");
|
||||||
|
|
||||||
|
config.database_url = DATABASE_URL;
|
||||||
|
config.signer.tokens.legacy_token = DATABASE_SECRET;
|
||||||
|
|
||||||
|
Firebase.begin(&config, &auth);
|
||||||
|
Firebase.reconnectWiFi(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= LOOP =================
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
setRTCFromSerial(); // 🔥 input waktu dari serial
|
||||||
|
|
||||||
|
unsigned long nowMillis = millis();
|
||||||
|
|
||||||
|
// ================= SENSOR =================
|
||||||
|
if (nowMillis - lastSensor > 2000) {
|
||||||
|
lastSensor = nowMillis;
|
||||||
|
|
||||||
|
suhu = sht31.readTemperature();
|
||||||
|
kelembaban = sht31.readHumidity();
|
||||||
|
|
||||||
|
DateTime now = rtc.now();
|
||||||
|
|
||||||
|
char tgl[11];
|
||||||
|
sprintf(tgl, "%02d-%02d-%04d", now.day(), now.month(), now.year());
|
||||||
|
rtcDate = String(tgl);
|
||||||
|
|
||||||
|
char jam[9];
|
||||||
|
sprintf(jam, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
|
||||||
|
rtcTime = String(jam);
|
||||||
|
|
||||||
|
Serial.println("Sensor Update");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= MANUAL =================
|
||||||
|
if (nowMillis - lastManual > 2000) {
|
||||||
|
lastManual = nowMillis;
|
||||||
|
|
||||||
|
if (Firebase.RTDB.getBool(&fbdo, "/pump/status")) {
|
||||||
|
pumpManual = fbdo.boolData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= SCHEDULE =================
|
||||||
|
if (nowMillis - lastSchedule > 15000) {
|
||||||
|
lastSchedule = nowMillis;
|
||||||
|
|
||||||
|
relayOn = false;
|
||||||
|
|
||||||
|
if (Firebase.RTDB.getJSON(&fbdo, "/schedules")) {
|
||||||
|
|
||||||
|
json = fbdo.jsonObject();
|
||||||
|
size_t len = json.iteratorBegin();
|
||||||
|
|
||||||
|
String key, value;
|
||||||
|
int type;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
|
||||||
|
json.iteratorGet(i, type, key, value);
|
||||||
|
|
||||||
|
String scheduleTime, scheduleDate, scheduleStatus;
|
||||||
|
|
||||||
|
if (json.get(result, key + "/time"))
|
||||||
|
scheduleTime = result.to<String>();
|
||||||
|
|
||||||
|
if (json.get(result, key + "/date"))
|
||||||
|
scheduleDate = result.to<String>();
|
||||||
|
|
||||||
|
if (json.get(result, key + "/status"))
|
||||||
|
scheduleStatus = result.to<String>();
|
||||||
|
|
||||||
|
int schHour = 0, schMinute = 0;
|
||||||
|
sscanf(scheduleTime.c_str(), "%d:%d", &schHour, &schMinute);
|
||||||
|
|
||||||
|
DateTime now = rtc.now();
|
||||||
|
int hour = now.hour();
|
||||||
|
int minute = now.minute();
|
||||||
|
|
||||||
|
if (rtcDate == scheduleDate &&
|
||||||
|
(hour > schHour || (hour == schHour && minute >= schMinute)) &&
|
||||||
|
scheduleStatus == "idle" &&
|
||||||
|
kelembaban < 85) {
|
||||||
|
|
||||||
|
relayOn = true;
|
||||||
|
|
||||||
|
activeScheduleKey = key;
|
||||||
|
|
||||||
|
Firebase.RTDB.setString(
|
||||||
|
&fbdo,
|
||||||
|
"/schedules/" + key + "/status",
|
||||||
|
"watering");
|
||||||
|
|
||||||
|
Serial.println("TRIGGER SCHEDULE");
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (scheduleStatus == "watering" && !pumpRunning) {
|
||||||
|
Firebase.RTDB.setString(&fbdo,
|
||||||
|
"/schedules/" + key + "/status",
|
||||||
|
"done");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json.iteratorEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= RELAY =================
|
||||||
|
if (pumpManual) {
|
||||||
|
digitalWrite(RELAY_PIN, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (relayOn && !pumpRunning) {
|
||||||
|
|
||||||
|
digitalWrite(RELAY_PIN, LOW);
|
||||||
|
pumpRunning = true;
|
||||||
|
|
||||||
|
Serial.println("POMPA ON");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= AUTO OFF SAAT KELEMBAPAN >= 85 =================
|
||||||
|
if (pumpRunning && kelembaban >= 85) {
|
||||||
|
|
||||||
|
digitalWrite(RELAY_PIN, HIGH);
|
||||||
|
|
||||||
|
pumpRunning = false;
|
||||||
|
relayOn = false;
|
||||||
|
|
||||||
|
Serial.println("POMPA OFF - KELEMBAPAN SUDAH 85%");
|
||||||
|
|
||||||
|
// UPDATE STATUS JADWAL MENJADI DONE
|
||||||
|
if (activeScheduleKey != "") {
|
||||||
|
|
||||||
|
Firebase.RTDB.setString(
|
||||||
|
&fbdo,
|
||||||
|
"/schedules/" + activeScheduleKey + "/status",
|
||||||
|
"done");
|
||||||
|
|
||||||
|
activeScheduleKey = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTIFIKASI
|
||||||
|
Firebase.RTDB.setString(
|
||||||
|
&fbdo,
|
||||||
|
"/notification/type",
|
||||||
|
"watering_done");
|
||||||
|
|
||||||
|
Firebase.RTDB.setString(
|
||||||
|
&fbdo,
|
||||||
|
"/notification/message",
|
||||||
|
"Penyiraman selesai. Kelembapan telah mencapai 85%");
|
||||||
|
|
||||||
|
Firebase.RTDB.setInt(
|
||||||
|
&fbdo,
|
||||||
|
"/notification/timestamp",
|
||||||
|
millis());
|
||||||
|
|
||||||
|
wateringDoneNotifSent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= DEFAULT OFF =================
|
||||||
|
if (!relayOn && !pumpRunning && !pumpManual) {
|
||||||
|
digitalWrite(RELAY_PIN, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= FIREBASE UPDATE =================
|
||||||
|
if (nowMillis - lastFirebase > 5000) {
|
||||||
|
lastFirebase = nowMillis;
|
||||||
|
|
||||||
|
Firebase.RTDB.setFloat(&fbdo, "/sht/temperature", suhu);
|
||||||
|
Firebase.RTDB.setFloat(&fbdo, "/sht/humidity", kelembaban);
|
||||||
|
Firebase.RTDB.setString(&fbdo, "/sht/time", rtcTime);
|
||||||
|
Firebase.RTDB.setString(&fbdo, "/sht/date", rtcDate);
|
||||||
|
|
||||||
|
// ================= NOTIFIKASI KELEMBAPAN =================
|
||||||
|
if (kelembaban < 70) {
|
||||||
|
|
||||||
|
if (!humidityNotifSent) {
|
||||||
|
|
||||||
|
Firebase.RTDB.setString(
|
||||||
|
&fbdo,
|
||||||
|
"/notification/type",
|
||||||
|
"humidity_low");
|
||||||
|
|
||||||
|
Firebase.RTDB.setString(
|
||||||
|
&fbdo,
|
||||||
|
"/notification/message",
|
||||||
|
"Kelembapan rendah, segera lakukan penyiraman");
|
||||||
|
|
||||||
|
Firebase.RTDB.setInt(
|
||||||
|
&fbdo,
|
||||||
|
"/notification/timestamp",
|
||||||
|
millis());
|
||||||
|
|
||||||
|
humidityNotifSent = true;
|
||||||
|
wateringDoneNotifSent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
humidityNotifSent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("Firebase Update");
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue