Upload kode laporan akhir IOT

This commit is contained in:
Ferdi 2026-08-10 15:24:57 +07:00
commit 26380e2d0f
1 changed files with 431 additions and 0 deletions

431
kode_laporan_akhir_IOT.ino Normal file
View File

@ -0,0 +1,431 @@
#include <Wire.h>
#include <Adafruit_AHTX0.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include <FirebaseESP32.h>
#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 && avgRH<RH_ON) return "Suhu Tinggi dan RH Rendah";
if (avgSuhu>SUHU_ON) return "Suhu Tinggi";
if (avgRH<RH_ON) return "RH Rendah";
return "Normal";
}
String formatStatus() {
String msg = "";
msg += "\xF0\x9F\x93\xA1 Update Otomatis\n\n";
msg += "\xF0\x9F\x8C\xA1 Sensor 1\n";
msg += "Suhu : " + String(suhu1,1) + " C\n";
msg += "RH : " + String(rh1,1) + " %\n\n";
msg += "\xF0\x9F\x8C\xA1 Sensor 2\n";
msg += "Suhu : " + String(suhu2,1) + " C\n";
msg += "RH : " + String(rh2,1) + " %\n\n";
msg += "\xF0\x9F\x93\x8A Rata-rata\n";
msg += "Suhu : " + String(avgSuhu,1) + " C\n";
msg += "RH : " + String(avgRH,1) + " %\n\n";
msg += "\xE2\x9A\x99 Status Relay\n";
msg += "\xF0\x9F\x8C\x80 Kipas : " + String(kipasState?"ON \xE2\x9C\x85":"OFF \xE2\x9D\x8C") + "\n";
msg += "\xF0\x9F\x92\xA7 Pompa : " + String(pompaState?"ON \xE2\x9C\x85":"OFF \xE2\x9D\x8C") + "\n";
return msg;
}
String formatHelp() {
String msg = "Daftar Perintah Bot\n";
msg += "-------------------\n";
msg += "/status Data sensor dan relay\n";
msg += "/kipason Kipas DC ON\n";
msg += "/kipasoff Kipas DC OFF\n";
msg += "/pompaon Pompa Air ON\n";
msg += "/pompaoff Pompa Air OFF\n";
msg += "/auto Mode otomatis\n";
msg += "/help Daftar perintah\n\n";
msg += "Batas kendali otomatis\n";
msg += "Kipas ON Suhu lebih dari " + String(SUHU_ON,1) + " C\n";
msg += "Kipas OFF Suhu kurang " + String(SUHU_OFF,1) + " C\n";
msg += "Pompa ON RH kurang dari " + String(RH_ON,1) + " persen\n";
msg += "Pompa OFF RH lebih dari " + String(RH_OFF,1) + " persen";
return msg;
}
bool kirimTelegram(String pesan) {
if (WiFi.status() != WL_CONNECTED) return false;
pesan.replace("\\", "\\\\");
pesan.replace("\"", "\\\"");
pesan.replace("\r", "");
pesan.replace("\n", "\\n");
String body = "{\"chat_id\":\"" + String(CHAT_ID) + "\",\"text\":\"" + pesan + "\"}";
String url = "/bot" + String(BOT_TOKEN) + "/sendMessage";
WiFiClientSecure client;
client.setInsecure();
client.setTimeout(12000);
if (!client.connect("api.telegram.org", 443)) {
Serial.println("[TELEGRAM] Gagal konek");
return false;
}
client.printf("POST %s HTTP/1.1\r\n", url.c_str());
client.println("Host: api.telegram.org");
client.println("Content-Type: application/json");
client.printf("Content-Length: %d\r\n", body.length());
client.println("Connection: close");
client.println();
client.print(body);
unsigned long t = millis();
while (!client.available() && millis()-t < 8000) { delay(50); }
String statusLine = client.readStringUntil('\n');
bool ok = statusLine.indexOf("200") > 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<JsonArray>();
for (JsonObject upd : results) {
lastMsgId = upd["update_id"].as<long>();
String chat_id = upd["message"]["chat"]["id"].as<String>();
String teks = upd["message"]["text"].as<String>();
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();
}