#include #include #include #include #include #include #define DOUT_PIN 25 #define CLK_PIN 27 #define RELAY_PIN_2 18 #define RELAY_PIN_1 19 #define TRIGGER_PIN 12 #define ECHO_PIN 14 #define DHTPIN 23 #define DHTTYPE DHT11 #define USERNAME "btwnty" #define DEVICE_ID "esp32" #define DEVICE_CREDENTIAL "AfUm_FeJ@Zr@pIN?" #define SSID "arya" #define SSID_PASSWORD "12345678" const char* ntpServer = "0.pool.ntp.org"; const long gmtOffset_sec = 6L * 60L * 60L; const int daylightOffset_sec = 3600; const long interval = 5000; DHT dht(DHTPIN, DHTTYPE); ThingerESP32 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL); Servo myServo; HX711 scale; Ultrasonic ultrasonic(TRIGGER_PIN, ECHO_PIN); unsigned long notifikasiterakhir = 0; unsigned long conditionStartTime = 0; bool relayActive1 = true; bool relayActive2 = false; unsigned long relay1StartTime = 0; unsigned long relay2StartTime = 0; const float bebanmax = 30.0; const unsigned long durasiRelayAktif = 2500; const float suhumin = 30; const float suhumax = 35; const int tinggiWadah = 20; unsigned long bacaSensorTerakhir = 0; const unsigned long bacaSensorInterval = 1000; enum WiFiState { DISCONNECTED, CONNECTING, CONNECTED }; WiFiState wifiState = DISCONNECTED; unsigned long wifiConnectStartTime = 0; const unsigned long wifiReconectInterval = 5000; void setup() { Serial.begin(9600); thing.add_wifi(SSID, SSID_PASSWORD); myServo.attach(5); myServo.write(0); dht.begin(); pinMode(RELAY_PIN_2, OUTPUT); pinMode(RELAY_PIN_1, OUTPUT); digitalWrite(RELAY_PIN_2, HIGH); digitalWrite(RELAY_PIN_1, HIGH); scale.begin(DOUT_PIN, CLK_PIN); scale.set_scale(-1057.89); scale.tare(0); configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); thing["servoControl"] << [](pson& in) { if (in.is_empty()) { return; } myServo.write(75); delay(1000); myServo.write(0); }; thing["sensorData"] >> [](pson& out) { float temperature = dht.readTemperature(); float weight = getWeight(); float distance = ultrasonic.read(); int ketinggianPakan = tinggiWadah - distance; struct tm timeinfo; if (getLocalTime(&timeinfo)) { char timeStr[30]; strftime(timeStr, sizeof(timeStr), "%d %B %Y %H:%M:%S", &timeinfo); String timeString = String(timeStr); out["Waktu"] = timeString; } else { out["Waktu"] = "Failed to obtain time"; } out["Suhu"] = temperature; out["Beban Kotoran"] = weight; out["Ketinggian Pakan"] = ketinggianPakan; }; wifiState = DISCONNECTED; } void loop() { unsigned long currentTime = millis(); koneksiwifi(); thing.handle(); if (currentTime - bacaSensorTerakhir >= bacaSensorInterval) { bacaSensorTerakhir = currentTime; float temperature = dht.readTemperature(); float weight = getWeight(); unsigned int distance = ultrasonic.read(); int ketinggianPakan = tinggiWadah - distance; handleNotifications(ketinggianPakan, currentTime); handleRelayControls(temperature, weight, currentTime); handleServoSchedule(); struct tm timeinfo; if (getLocalTime(&timeinfo)) { Serial.print(&timeinfo, "%d %B %Y %H:%M:%S\t"); } else { Serial.print("Failed to obtain time"); } Serial.print("Weight: "); Serial.print(weight); Serial.print(" g\t"); Serial.print("Ketinggian Pakan: "); Serial.print(ketinggianPakan); Serial.print(" cm\t"); Serial.print("Suhu: "); Serial.print(temperature); Serial.println(" °C"); } } void koneksiwifi() { unsigned long currentTime = millis(); switch (wifiState) { case DISCONNECTED: WiFi.begin(SSID, SSID_PASSWORD); wifiState = CONNECTING; wifiConnectStartTime = currentTime; Serial.println("Connecting to WiFi..."); break; case CONNECTING: if (WiFi.status() == WL_CONNECTED) { Serial.println("WiFi connected."); wifiState = CONNECTED; } else if (currentTime - wifiConnectStartTime >= wifiReconectInterval) { wifiState = DISCONNECTED; Serial.println("Retrying WiFi connection..."); } break; case CONNECTED: if (WiFi.status() != WL_CONNECTED) { Serial.println("WiFi disconnected."); wifiState = DISCONNECTED; } break; } } float getWeight() { float weight = scale.get_units(10); if (weight >= -2.0 && weight <= 2.0) { return 0.0; } return weight; } void moveServo() { myServo.write(75); delay(1000); myServo.write(0); pson data; data["action"] = "servo_moved"; thing.write_bucket("Servo", data); } void handleNotifications(int ketinggianPakan, unsigned long currentTime) { if (ketinggianPakan <= 2) { // Notifikasi "habis" if (conditionStartTime == 0) { conditionStartTime = currentTime; } else if (currentTime - conditionStartTime >= 5 * 1000) { if (currentTime - notifikasiterakhir >= 60 * 1000 && wifiState == CONNECTED) { Serial.println("Mengirim Notifikasi Habis..."); bool result = thing.call_endpoint("notifikasi_habis"); if (result) { Serial.println("Notifikasi Habis Sukses Terkirim."); } else { Serial.println("Gagal Mengirim Notifikasi Habis."); } notifikasiterakhir = currentTime; } } } else if (ketinggianPakan < 5) { // Notifikasi "hampir habis" if (conditionStartTime == 0) { conditionStartTime = currentTime; } else if (currentTime - conditionStartTime >= 5 * 1000) { if (currentTime - notifikasiterakhir >= 60 * 1000 && wifiState == CONNECTED) { Serial.println("Mengirim Notifikasi Hampir Habis"); bool result = thing.call_endpoint("notifikasi_hampir_habis"); if (result) { Serial.println("Berhasil Mengirim Notifikasi Hampir Habis."); } else { Serial.println("Gagal Mengirim Notifikasi Hampir Habis."); } notifikasiterakhir = currentTime; } } } else { conditionStartTime = 0; } } void handleRelayControls(float temperature, float weight, unsigned long currentTime) { if (!isnan(temperature)) { if (temperature > suhumax && !relayActive1) { digitalWrite(RELAY_PIN_2, HIGH); relayActive1 = true; } else if (temperature <= suhumin && relayActive1) { digitalWrite(RELAY_PIN_2, LOW); relayActive1 = false; } } if (weight > bebanmax && !relayActive2) { digitalWrite(RELAY_PIN_1, LOW); relayActive2 = true; relay2StartTime = currentTime; } if (relayActive2 && (currentTime - relay2StartTime >= durasiRelayAktif)) { digitalWrite(RELAY_PIN_1, HIGH); relayActive2 = false; scale.tare(); } } void handleServoSchedule() { struct tm timeinfo; if (!getLocalTime(&timeinfo)) { return; } int currentHour = timeinfo.tm_hour; int currentMinute = timeinfo.tm_min; int currentSecond = timeinfo.tm_sec; if (currentHour == 6 && currentMinute == 0 && currentSecond == 1) { moveServo(); } if (currentHour == 11 && currentMinute == 0 && currentSecond == 1) { moveServo(); } if (currentHour == 16 && currentMinute == 0 && currentSecond == 1) { moveServo(); } if (currentHour == 21 && currentMinute == 0 && currentSecond == 1) { moveServo(); } }