From 26380e2d0fa350acfd0373263a733bf497cb7fe3 Mon Sep 17 00:00:00 2001 From: Ferdi Date: Mon, 10 Aug 2026 15:24:57 +0700 Subject: [PATCH] Upload kode laporan akhir IOT --- kode_laporan_akhir_IOT.ino | 431 +++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 kode_laporan_akhir_IOT.ino diff --git a/kode_laporan_akhir_IOT.ino b/kode_laporan_akhir_IOT.ino new file mode 100644 index 0000000..95753d0 --- /dev/null +++ b/kode_laporan_akhir_IOT.ino @@ -0,0 +1,431 @@ +#include +#include +#include +#include +#include +#include +#include + +#define SDA1 21 +#define SCL1 22 +#define SDA2 16 +#define SCL2 17 + +#define RELAY_KIPAS 27 +#define RELAY_POMPA 26 + +const char* ssid = "Oppo12"; +const char* password = "12345678"; + +#define BOT_TOKEN "8628991486:AAEWwreXf8lXAFrb0fokQcrS_pqY6-C19_o" +#define CHAT_ID "6963743941" + +#define FIREBASE_HOST "database-ta-cbb47-default-rtdb.asia-southeast1.firebasedatabase.app" +#define FIREBASE_AUTH "hCpBMPxOKsHLVv5Unyfd5YikGtFy11Z01Olx7477" + +#define SUHU_ON 28.0 +#define SUHU_OFF 27.5 +#define RH_ON 80.0 +#define RH_OFF 90.0 + +#define MS_BACA 2000 +#define MS_PERINTAH 1000 +#define MS_UPDATE 30000 +#define MS_FIREBASE 25000 +#define MS_KIRIM 3000 + +#define QUEUE_SIZE 5 +String msgQueue[QUEUE_SIZE]; +int qHead=0, qTail=0, qCount=0; + +void queuePush(String msg) { + if (qCount >= QUEUE_SIZE) { qHead=(qHead+1)%QUEUE_SIZE; qCount--; } + msgQueue[qTail] = msg; + qTail = (qTail+1) % QUEUE_SIZE; + qCount++; + Serial.printf("[QUEUE] Antrian: %d\n", qCount); +} +bool queuePop(String &msg) { + if (qCount==0) return false; + msg = msgQueue[qHead]; + qHead = (qHead+1) % QUEUE_SIZE; + qCount--; + return true; +} + +FirebaseData fbData; +FirebaseConfig fbConfig; +FirebaseAuth fbAuth; + +Adafruit_AHTX0 sensor1; +Adafruit_AHTX0 sensor2; + +bool kipasState=false, pompaState=false; +bool prevKipas=false, prevPompa=false; +bool modeManual=false; +bool sensor1_ok=false, sensor2_ok=false; +float suhu1=0,rh1=0,suhu2=0,rh2=0,avgSuhu=0,avgRH=0; +unsigned long lastBaca=0,lastPerintah=0,lastUpdate=0; +unsigned long lastFirebase=0,lastKirim=0,dataCount=0; +long lastMsgId = 0; + + +void setKipas(bool nyala) { + kipasState = nyala; + digitalWrite(RELAY_KIPAS, nyala ? LOW : HIGH); + Serial.printf("[RELAY] Kipas %s (GPIO%d)\n", nyala?"ON":"OFF", RELAY_KIPAS); +} +void setPompa(bool nyala) { + pompaState = nyala; + digitalWrite(RELAY_POMPA, nyala ? LOW : HIGH); + Serial.printf("[RELAY] Pompa %s (GPIO%d)\n", nyala?"ON":"OFF", RELAY_POMPA); +} + + +String getKondisi() { + if (avgSuhu>SUHU_ON && avgRHSUHU_ON) return "Suhu Tinggi"; + if (avgRH 0; + Serial.printf("[TELEGRAM] %s (%s)\n", ok?"OK":"GAGAL", statusLine.substring(9,12).c_str()); + + client.stop(); + return ok; +} + + +void prosesPerintah() { + if (WiFi.status() != WL_CONNECTED) return; + + String url = "/bot" + String(BOT_TOKEN) + + "/getUpdates?offset=" + String(lastMsgId+1) + + "&limit=5&timeout=1"; + + WiFiClientSecure client; + client.setInsecure(); + client.setTimeout(10000); + + if (!client.connect("api.telegram.org", 443)) { + Serial.println("[BOT] Gagal konek getUpdates"); + return; + } + + client.printf("GET %s HTTP/1.1\r\n", url.c_str()); + client.println("Host: api.telegram.org"); + client.println("Connection: close"); + client.println(); + + unsigned long t = millis(); + while (client.connected() && millis()-t < 8000) { + String line = client.readStringUntil('\n'); + if (line == "\r") break; + } + + String json = ""; + t = millis(); + while (client.available() && millis()-t < 5000) { + json += client.readString(); + } + client.stop(); + + if (json.length() < 10) return; + + DynamicJsonDocument doc(2048); + if (deserializeJson(doc, json)) { Serial.println("[BOT] JSON error"); return; } + + JsonArray results = doc["result"].as(); + for (JsonObject upd : results) { + lastMsgId = upd["update_id"].as(); + String chat_id = upd["message"]["chat"]["id"].as(); + String teks = upd["message"]["text"].as(); + if (chat_id != CHAT_ID) continue; + + Serial.printf("[BOT] Perintah: %s\n", teks.c_str()); + + if (teks=="/start"||teks=="/status") queuePush(formatStatus()); + else if (teks=="/help") queuePush(formatHelp()); + else if (teks=="/kipason") { modeManual=true; setKipas(true); queuePush("Mode Manual\nKipas DC ON"); } + else if (teks=="/kipasoff") { modeManual=true; setKipas(false); queuePush("Mode Manual\nKipas DC OFF"); } + else if (teks=="/pompaon") { modeManual=true; setPompa(true); queuePush("Mode Manual\nPompa Air ON"); } + else if (teks=="/pompaoff") { modeManual=true; setPompa(false); queuePush("Mode Manual\nPompa Air OFF"); } + else if (teks=="/auto") { modeManual=false; queuePush("Mode Otomatis Aktif"); } + else queuePush("Perintah tidak dikenal."); + } +} + + +void bacaSensor() { + sensors_event_t hum, tmp; + if (sensor1_ok) { + sensor1.getEvent(&hum, &tmp); + if (tmp.temperature>-22 &&tmp.temperature<28&& + hum.relative_humidity>=80&&hum.relative_humidity<90) { + suhu1=tmp.temperature; rh1=hum.relative_humidity; + } else { + Serial.println("[SENSOR1] Nilai tidak valid, reinit..."); + sensor1_ok = sensor1.begin(&Wire); + } + } + if (sensor2_ok) { + sensor2.getEvent(&hum, &tmp); + if (tmp.temperature>-22&&tmp.temperature<28&& + hum.relative_humidity>=80&&hum.relative_humidity<90) { + suhu2=tmp.temperature; rh2=hum.relative_humidity; + } else { + Serial.println("[SENSOR2] Nilai tidak valid, reinit..."); + Wire1.begin(SDA2, SCL2, 400000); + sensor2_ok = sensor2.begin(&Wire1); + } + } + if (sensor1_ok&&sensor2_ok) { avgSuhu=(suhu1+suhu2)/2.0; avgRH=(rh1+rh2)/2.0; } + else if (sensor1_ok) { avgSuhu=suhu1; avgRH=rh1; } + else if (sensor2_ok) { avgSuhu=suhu2; avgRH=rh2; } +} + + +void kendaliRelay() { + if (modeManual) return; + prevKipas=kipasState; prevPompa=pompaState; + + + if (avgSuhu > SUHU_ON) setKipas(true); + else if (avgSuhu < SUHU_OFF) setKipas(false); + if (avgRH < RH_ON) setPompa(true); + else if (avgRH > RH_OFF) setPompa(false); + + + if (kipasState != prevKipas) { + String notif = ""; + if (kipasState) { + notif += "\xF0\x9F\x92\xA7 Suhu berubah : " + String(avgSuhu,1) + " C\n\n"; + } + notif += formatStatus(); + queuePush(notif); + } + + + if (pompaState != prevPompa) { + String notif = ""; + notif += "\xF0\x9F\x92\xA7 RH berubah : " + String(avgRH,1) + " %\n\n"; + notif += formatStatus(); + queuePush(notif); + } +} + + +void kirimFirebase() { + if (!Firebase.ready()) { Serial.println("[FIREBASE] Tidak siap"); return; } + + Firebase.setFloat(fbData, "/kumbung/realtime/sensor1/suhu", suhu1); + Firebase.setFloat(fbData, "/kumbung/realtime/sensor1/rh", rh1); + Firebase.setFloat(fbData, "/kumbung/realtime/sensor2/suhu", suhu2); + Firebase.setFloat(fbData, "/kumbung/realtime/sensor2/rh", rh2); + Firebase.setFloat(fbData, "/kumbung/realtime/avg/suhu", avgSuhu); + Firebase.setFloat(fbData, "/kumbung/realtime/avg/rh", avgRH); + Firebase.setBool(fbData, "/kumbung/realtime/relay/kipas", kipasState); + Firebase.setBool(fbData, "/kumbung/realtime/relay/pompa", pompaState); + Firebase.setString(fbData,"/kumbung/realtime/kondisi", getKondisi()); + + dataCount++; + char path[50]; sprintf(path,"/kumbung/history/data_%04lu",dataCount); + FirebaseJson json; + json.set("s1t",suhu1); json.set("s1rh",rh1); + json.set("s2t",suhu2); json.set("s2rh",rh2); + json.set("avgt",avgSuhu); json.set("avgrh",avgRH); + json.set("kipas",kipasState?"ON":"OFF"); + json.set("pompa",pompaState?"ON":"OFF"); + json.set("kondisi",getKondisi()); + + Firebase.setJSON(fbData, path, json) + ? Serial.printf("[FIREBASE] OK -> %s\n", path) + : Serial.printf("[FIREBASE] Gagal: %s\n", fbData.errorReason().c_str()); +} + + +void setup() { + Serial.begin(115200); + delay(1000); + Serial.println("\n=== MONITORING JAMUR TIRAM v7.3 FIX (ESP32) ===\n"); + Serial.println("[INFO] RELAY_KIPAS = GPIO" + String(RELAY_KIPAS)); + Serial.println("[INFO] RELAY_POMPA = GPIO" + String(RELAY_POMPA)); + + pinMode(RELAY_KIPAS, OUTPUT); digitalWrite(RELAY_KIPAS, HIGH); + pinMode(RELAY_POMPA, OUTPUT); digitalWrite(RELAY_POMPA, HIGH); + Serial.println("[OK] Relay OFF"); + + + Wire.begin(SDA1, SCL1); + delay(200); + sensor1_ok = sensor1.begin(&Wire); + Serial.println(sensor1_ok?"[OK] Sensor 1 (Wire GPIO21/22)":"[GAGAL] Sensor 1"); + + + Wire1.begin(SDA2, SCL2, 400000); + delay(200); + sensor2_ok = sensor2.begin(&Wire1); + if (sensor2_ok) { + Wire1.begin(SDA2, SCL2, 400000); + Serial.println("[OK] Sensor 2 (Wire1 GPIO16/17)"); + } else { + Serial.println("[GAGAL] Sensor 2"); + } + + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + Serial.printf("[INFO] WiFi: %s\n", ssid); + int r=0; + while (WiFi.status()!=WL_CONNECTED && r<40) { + delay(500); Serial.print("."); r++; + } + Serial.println(WiFi.status()==WL_CONNECTED + ? "\n[OK] WiFi: " + WiFi.localIP().toString() + : "\n[GAGAL] WiFi!"); + + fbConfig.host = FIREBASE_HOST; + fbConfig.signer.tokens.legacy_token = FIREBASE_AUTH; + Firebase.begin(&fbConfig, &fbAuth); + Firebase.reconnectWiFi(true); + fbData.setResponseSize(2048); + Serial.println(Firebase.ready()?"[OK] Firebase":"[GAGAL] Firebase"); + + delay(500); + bacaSensor(); + kendaliRelay(); + + String boot = "\xE2\x9C\x85 ESP32 Monitoring Jamur Online\n\n"; + boot += "WiFi : " + String(ssid) + "\n"; + boot += "Sensor 1 : " + String(sensor1_ok?"OK":"Gagal") + "\n"; + boot += "Sensor 2 : " + String(sensor2_ok?"OK":"Gagal") + "\n"; + boot += "Firebase : " + String(Firebase.ready()?"OK":"Gagal") + "\n\n"; + boot += formatStatus(); + queuePush(boot); + + lastBaca=lastPerintah=lastUpdate=lastFirebase=lastKirim=millis(); + Serial.println("\n[INFO] Sistem siap!\n"); +} + + +void loop() { + unsigned long now = millis(); + + if (now - lastKirim >= MS_KIRIM && qCount > 0) { + lastKirim = now; + String msg; + if (queuePop(msg)) { + bool ok = kirimTelegram(msg); + if (!ok) { + queuePush(msg); + lastKirim = now + 10000; + Serial.println("[TELEGRAM] Coba lagi 10 detik lagi"); + } + } + } + + if (now - lastBaca >= MS_BACA) { + lastBaca = now; + bacaSensor(); + kendaliRelay(); + Serial.printf("[S] S1:%.1fC %.1f%% S2:%.1fC %.1f%% AVG:%.1fC %.1f%% K:%s P:%s\n", + suhu1,rh1,suhu2,rh2,avgSuhu,avgRH, + kipasState?"ON":"OFF",pompaState?"ON":"OFF"); + } + + if (now - lastPerintah >= MS_PERINTAH && qCount == 0) { + lastPerintah = now; + prosesPerintah(); + } + + if (now - lastUpdate >= MS_UPDATE) { + lastUpdate = now; + Serial.println("[INFO] Update otomatis -> queue"); + queuePush(formatStatus()); + } + + if (now - lastFirebase >= MS_FIREBASE && qCount == 0) { + lastFirebase = now; + kirimFirebase(); + } + + if (WiFi.status() != WL_CONNECTED) { + Serial.println("[WARNING] WiFi putus!"); + WiFi.disconnect(); delay(1000); + WiFi.begin(ssid, password); + int r=0; + while (WiFi.status()!=WL_CONNECTED && r<20) { delay(500); r++; } + Serial.println(WiFi.status()==WL_CONNECTED?"[OK] Reconnect!":"[GAGAL] Reconnect!"); + } + + yield(); +}