#include <WiFi.h>
#include "ThingsBoard.h"
#include <ESP32Servo.h>
#include "RTClib.h"
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
#define ECHO_PIN 4
#define TRIG_PIN 2
#define WIFI_AP_NAME "Wokwi-GUEST"
#define WIFI_PASSWORD ""
#define THINGSBOARD_MQTT_SERVER "thingsboard.cloud"
#define THINGSBOARD_MQTT_ACESSTOKEN "gvKNtxAyEt4oIgWVCDth"
#define SERIAL_DEBUG_BAUD 115200
WiFiClient espClient;
ThingsBoard tb(espClient);
RTC_DS1307 rtc;
Servo servoPakan;
Servo servoIsiUlang;
// Array with LEDs that should be controlled from ThingsBoard, one by one
uint8_t leds_control[] = { 26, 33, 25 };
// setting jam dan berapa menit servo terbuka
String jam_pakan[] = {"1:20", "1:21", "1:2"};
int status_servo_pakan = 0;
int menit_servo_terbuka = 5000;
String tempJam = "";
String labelServoIsiUlang = "Ditutup";
float TinggiSensor = 400; //Tinggi pemasangan sensor
float TingkatPakan = 0; //Tingkat Pakan
unsigned long TSekarang;
unsigned long TAkhir;
int status = WL_IDLE_STATUS;
// Main application loop delay
int quant = 20;
// Initial period of LED cycling.
int get_servo_isiulang = 0;
int status_servo_isiulang = 0;
// Period of sending a temperature/humidity data.
int send_delay = 2000;
// Time passed after LED was turned ON, milliseconds.
int led_passed = 0;
// Time passed after temperature/humidity data was sent, milliseconds.
int send_passed = 0;
// Set to true if application is subscribed for the RPC messages.
bool subscribed = false;
// LED number that is currenlty ON.
int current_led = 0;
float temperature = 0;
float humidity = 0;
RPC_Response processDelayChange(const RPC_Data &data)
{
Serial.println("Received the set delay RPC method");
// Process data
get_servo_isiulang = data;
Serial.print("Set new delay: ");
Serial.println(get_servo_isiulang);
return String(get_servo_isiulang);
}
RPC_Response processGetDelay(const RPC_Data &data)
{
Serial.println("Received the get value method");
return String(get_servo_isiulang);
}
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 },
};
float readDistanceCM() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
int duration = pulseIn(ECHO_PIN, HIGH);
return duration * 0.034 / 2;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(SERIAL_DEBUG_BAUD);
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
InitWiFi();
//sensor jarak
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
// Servo
servoPakan.attach(15);
servoIsiUlang.attach(5);
servoPakan.write(0);
servoIsiUlang.write(0);
// LED
for (size_t i = 0; i < COUNT_OF(leds_control); ++i) {
pinMode(leds_control[i], OUTPUT);
}
// Check RTC
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
}
void loop() {
delay(quant);
led_passed += quant;
send_passed += quant;
// Reconnect to WiFi, if needed
if (WiFi.status() != WL_CONNECTED) {
reconnect();
return;
}
// 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;
}
// buka servo berdasarkan settingan jam
DateTime now = rtc.now();
if(tempJam != String(now.hour())+":"+String(now.minute())){
status_servo_pakan =0;
tempJam = String(now.hour())+":"+String(now.minute());
}
for (int i = 0; i < COUNT_OF(jam_pakan); i++){
if(String(now.hour())+":"+String(now.minute()) == jam_pakan[i]){
if(status_servo_pakan ==0){
servoPakan.write(180);
status_servo_pakan = 1;
delay(menit_servo_terbuka);
servoPakan.write(0);
}
}
}
// cek ketersediaan jumlah pakan dalam persen
float distance = readDistanceCM();
TSekarang = millis();
if(TSekarang - TAkhir > 1000){ //Baca sensor setiap 1 detik
TingkatPakan = TinggiSensor - distance; //Rumus mencari tinggi pakan
if(TingkatPakan < 0){
TingkatPakan = 0;
}
else if(TingkatPakan > 400){
TingkatPakan = 400;
}
TingkatPakan = map(TingkatPakan, 0, 400, 0, 100); //Ubah ke persen(%)
TAkhir = TSekarang;
}
if(TingkatPakan <=30){
digitalWrite(26, HIGH);
digitalWrite(25, LOW);
digitalWrite(33, LOW);
}else if(TingkatPakan <=50){
digitalWrite(26, LOW);
digitalWrite(25, HIGH);
digitalWrite(33, LOW);
}else{
digitalWrite(26, LOW);
digitalWrite(25, LOW);
digitalWrite(33, HIGH);
}
if(get_servo_isiulang==1){
if(status_servo_isiulang==0){
labelServoIsiUlang = "Dibuka";
servoIsiUlang.write(180);
status_servo_isiulang = 1;
}
}
if(get_servo_isiulang==0){
if(status_servo_isiulang==1){
labelServoIsiUlang = "Ditutup";
servoIsiUlang.write(0);
status_servo_isiulang = 0;
}
}
// Check if it is a time to send DHT22 temperature and humidity
if (send_passed > send_delay) {
Serial.println();
Serial.print("Sending data... ");
Serial.print("Tingkat Ketersediaan: ");
Serial.print(TingkatPakan);
tb.sendTelemetryFloat("TingkatPakan", TingkatPakan);
send_passed = 0;
}
tb.loop();
}
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");
}
}