//Thingsboard
#include <WiFi.h> // WiFi control for ESP32
//#include <ThingsBoard.h> // ThingsBoard SDK
#include "ThingsBoard.h"
#define WIFI_AP_NAME "Wokwi-GUEST"
#define WIFI_PASSWORD ""
#define THINGSBOARD_MQTT_SERVER "thingsboard.cloud"
#define THINGSBOARD_MQTT_ACESSTOKEN "FCfQFu3FOp5c9Sv8skea"
WiFiClient espClient;
ThingsBoard tb(espClient);
int status = WL_IDLE_STATUS;
// Set to true if application is subscribed for the RPC messages.
bool subscribed = false;
//KEDALAMAN AIR
int echoAir = 14;
int trigAir = 27;
//VOLUME PAKAN
int echoPakan = 25;
int trigPakan = 26;
//BUZZER
int buzzer = 5;
//OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 oled (128, 64, &Wire, -1);
//Servo Pompa Air
#include <Servo.h>
Servo servoAir;
Servo servoPakan;
//DHT 22 Suhu Air
#include "DHTesp.h"
DHTesp suhuAir;
int pinDHT = 15;
//PIR DEKSI MALING
int pirSensor = 32;
//RTC DS1307
#include "RTClib.h"
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
int led_delay = 1000;
uint8_t leds_control[] = { 12, 13};
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
RPC_Response processDelayChange(const RPC_Data &data)
{
Serial.println("Received the set delay RPC method");
// Process data
led_delay = data;
Serial.print("Set new delay: ");
Serial.println(led_delay);
return String(led_delay);
}
RPC_Response checkStatus(const RPC_Data &data){
bool ledState = digitalRead(33);
return String(ledState);
}
RPC_Response processGetDelay(const RPC_Data &data)
{
Serial.println("Received the get value method");
return String(led_delay);
}
RPC_Response processSetGpioState(const RPC_Data &data)
{
Serial.println("Received the set GPIO RPC method");
int pin = data["pin"];
bool enabled = data["enabled"];
Serial.print("Setting LED ");
Serial.print(pin);
Serial.print(" to state ");
Serial.println(enabled);
// Red: 26, Green: 33, Blue: 25
digitalWrite(pin, enabled);
return String("{\"" + String(pin) + "\": " + String(enabled?"true":"false") + "}");
}
RPC_Response processGetGpioState(const RPC_Data &data)
{
Serial.println("Received the get GPIO RPC method");
String respStr = "{";
for (size_t i = 0; i < COUNT_OF(leds_control); ++i) {
int pin = leds_control[i];
Serial.print("Getting LED ");
Serial.print(pin);
Serial.print(" state ");
bool ledState = digitalRead(pin);
Serial.println(ledState);
respStr += String("\"" + String(pin) + "\": " + String(ledState?"true":"false") + ", ");
} //"pin" :
respStr = respStr.substring(0, respStr.length() - 2);
respStr += "}";
return respStr;
}
// RPC handlers
RPC_Callback callbacks[] = {
{ "setValue", processDelayChange },
{ "getValue", processGetDelay },
{ "setGpioStatus", processSetGpioState },
{ "getGpioStatus", processGetGpioState },
};
void setup() {
Serial.begin(115200);
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
InitWiFi();
//KEDALAMAN AIR
pinMode(echoAir, INPUT);
pinMode(trigAir, OUTPUT);
//VOLUME PAKAN
pinMode(echoPakan, INPUT);
pinMode(trigPakan, OUTPUT);
//BUZZER
pinMode(buzzer, OUTPUT);
//OLED Display
oled.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
oled.setTextSize(1);
oled.setTextColor(SSD1306_WHITE);
//Servo Air
servoAir.attach(33);
//Servo Pakan
servoPakan.attach(33);
//DHT Air
suhuAir.setup(pinDHT, DHTesp::DHT22);
//RTC
#ifndef ESP8266
while (!Serial); // wait for serial port to connect. Needed for native USB
#endif
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running, let's set the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
DateTime now = rtc.now();
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
delay(1000);
//LAMPU TAMBAK
for (size_t i = 0; i < COUNT_OF(leds_control); ++i) {
pinMode(leds_control[i], OUTPUT);
}
//SENSOR PIR
pinMode(pirSensor, INPUT);
}
void loop() {
// Reconnect to ThingsBoard, if needed
if (!tb.connected()) {
subscribed = false;
// Connect to the ThingsBoard
Serial.print("Connecting MQTT to: ");
Serial.print(THINGSBOARD_MQTT_SERVER);
Serial.print(" with access token ");
Serial.println(THINGSBOARD_MQTT_ACESSTOKEN);
if (!tb.connect(THINGSBOARD_MQTT_SERVER, THINGSBOARD_MQTT_ACESSTOKEN)) {
Serial.println("Failed to connect");
return;
}
}
// Subscribe for RPC, if needed
if (!subscribed) {
Serial.println("Subscribing for RPC... ");
// Perform a subscription. All consequent data processing will happen in
// callbacks as denoted by callbacks[] array.
if (!tb.RPC_Subscribe(callbacks, COUNT_OF(callbacks))) {
Serial.println("Failed to subscribe for RPC");
return;
}
Serial.println("Subscribe done");
subscribed = true;
}
//KEDALAMAN AIR (2 - 400 cm), surut < 150cm, 150 < sedang < 300cm, pasang >= 300cm
//kedalamanAir();
//delay(1000);
//SUHU Air ()
//cekSuhuAir();
//delay(1000);
//VOLUME PAKAN (dalam persentase yang mewakili 0 - 4 liter)
//refillPakan();
//delay(1000);
//ESTIMASI PANEN
//estimasiPanen();
//delay(1000);
//SEBAR PAKAN OTOMATIS
//sebarPakan();
//delay(1000);
//DETEKSI MALING
deteksiMaling();
delay(1000);
tb.loop();
tb.loop();
}
void kedalamanAir(){
//jika air surut maka akan berbunyi buzzer, pada oled muncul peringatan
//jika air dalam maka buzzer berbunyi, pada oled muncul peringatan
//jika air sedang, buzzer tidak bunyi, pada oled peringatan kedalaman air: Normal
digitalWrite(trigAir, LOW);
delayMicroseconds(2);
digitalWrite(trigAir, HIGH);
delayMicroseconds(10);
digitalWrite(trigAir, LOW);
int duration = pulseIn(echoAir, HIGH);
duration = duration * 0.034 / 2;
Serial.println(duration);
tb.sendTelemetryInt("depth", duration);
if(duration<150){
//surut
//Servo Air
servoAir.write(90);
//OLED Display
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Air Surut");
oled.display();
//Buzzer
tone(buzzer, 700);
delay(100);
noTone(buzzer);
delay(100);
tone(buzzer, 700);
delay(100);
noTone(buzzer);
delay(500);
}else if(duration<300){
//sedang
noTone(buzzer);
}else if(duration>=300){
//pasang
//servoAir
servoAir.write(-180);
//OLED Display
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Air Pasang");
oled.display();
//Buzzer
tone(buzzer, 700);
delay(1000);
noTone(buzzer);
delay(500);
}
}
void cekSuhuAir(){
//jika suhu dingin maka muncul peringatan di oled
//jika suhu sedang maka tidak muncul peringatan
//jika suhu panas maka muncul peringatan di oled
TempAndHumidity data = suhuAir.getTempAndHumidity();
tb.sendTelemetryInt("temperature", data.temperature);
Serial.println("Temp: " + String(data.temperature, 2) + "°C");
if(data.temperature<20){
//suhu dingin
//OLED Display
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Suhu Air: Dingin");
oled.display();
//Buzzer
tone(buzzer, 700);
delay(100);
noTone(buzzer);
delay(100);
tone(buzzer, 700);
delay(100);
noTone(buzzer);
delay(500);
}else if(data.temperature<40){
//suhu sedang
noTone(buzzer);
}else if(data.temperature>40){
//suhu panas
//OLED Display
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Suhu Air: Panas");
oled.display();
//Buzzer
tone(buzzer, 700);
delay(1000);
noTone(buzzer);
delay(500);
}
}
void refillPakan(){
//menampilkan pada OLED mengenai sisa pakan berupa berat pakan (0 - 4 liter)
digitalWrite(trigPakan, LOW);
delayMicroseconds(2);
digitalWrite(trigPakan, HIGH);
delayMicroseconds(10);
digitalWrite(trigPakan, LOW);
int durationPakan = pulseIn(echoPakan, HIGH);
durationPakan = durationPakan * 0.034 / 2;
float persentase = durationPakan/10;
tb.sendTelemetryInt("feeding", persentase);
//OLED Display
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Sisa Pakan: ");
oled.print(persentase);
oled.print(" Kg");
oled.display();
}
void sebarPakan(){
//jam pakan dibagi 3: 8.00.00, 14.00.00, 20.00.00
DateTime now = rtc.now();
int jam = now.hour();
int menit = now.minute();
int detik = now.second();
if(jam==8 && menit==0 && detik==0){
//pakan pagi
//Servo pakan
Serial.println("Waktunya pakan pagi");
servoPakan.write(90);
delay(100);
servoPakan.write(0);
delay(100);
//OLED Display
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Pakan Pagi");
oled.display();
}else if(jam==14 && menit==00 && detik==0){
//pakan siang
//Servo pakan
Serial.println("Waktunya pakan siang");
servoPakan.write(90);
delay(100);
servoPakan.write(0);
delay(100);
//OLED Display
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Pakan Siang");
oled.display();
}else if(jam==20 && menit==00 && detik==0){
//pakan malam
//Servo pakan
Serial.println("Waktunya pakan malam");
servoPakan.write(90);
delay(100);
servoPakan.write(0);
delay(100);
//OLED Display
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Pakan Malam");
oled.display();
}
}
void estimasiPanen(){
//asumsi panen pada 80 hari
//pakan per hari = 5 Kg
//panen 0 hari = pakan habis 400 kg
//0kg = 80-0
//5kg = 80-1 (jarak/5)
//10kg= 80 -2
digitalWrite(trigPakan, LOW);
delayMicroseconds(2);
digitalWrite(trigPakan, HIGH);
delayMicroseconds(10);
digitalWrite(trigPakan, LOW);
int durationEstimasi = pulseIn(echoPakan, HIGH);
durationEstimasi = durationEstimasi * 0.034 / 2;
int estimasi = 80-(durationEstimasi/5);
tb.sendTelemetryInt("estimasi", estimasi);
Serial.println(estimasi);
//OLED Display
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Estimasi Panen: ");
oled.print(estimasi);
oled.print(" H");
oled.display();
}
void deteksiMaling(){
int nilaiSwitch = digitalRead((pirSensor));
if(nilaiSwitch == 1){
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
}
else{
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
}
}
//tampilan pada OLED: kedalaman air, suhu air, sisa pakan, estimasi waktu panen
void InitWiFi()
{
Serial.println("Connecting to AP ...");
// attempt to connect to WiFi network
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(WiFi.localIP());
Serial.println("Connected to AP");
}
void reconnect() {
// Loop until we're reconnected
status = WiFi.status();
if ( status != WL_CONNECTED) {
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(WiFi.localIP());
Serial.println("Connected to AP");
}
}