#include <WiFi.h>
#include <PubSubClient.h>
#include <HTTPClient.h>
#include <Ultrasonic.h>
// Pin Definitions
const int relayPin = 14;
const int triggerPin = 21;
const int echoPin = 22;
const int wifiConnectedLedPin = 5;
const int wifiDisconnectedLedPin = 4;
// Relay State (define active state)
#define RELAY_ON LOW
#define RELAY_OFF HIGH
bool relayState = false;
// Thresholds for Relay Control
int maxheight = 200;
int minpercent = 20;
int maxpercent = 80;
// Wi-Fi Credentials
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// MQTT Broker Info
const char* mqtt_server = "broker.emqx.io";
const int mqtt_port = 1883;
const char* distance_topic = "vir_distance"; // Distance topic
const char* percent_topic = "vir_percent"; // Tank percentage topic
const char* selectionSwitch_topic = "vir_selectionSwitch"; // Selection switch topic
const char* manualSwitch_topic = "vir_manualSwitch"; // Manual switch topic
const char* relayControl_topic = "vir_relayControl"; // Relay control topic
const char* led_topic = "vir_led"; // LED topic
WiFiClient espClient;
PubSubClient client(espClient);
HTTPClient http;
// Manual mode flag
bool manualMode = false;
unsigned long lastPostTime = 0;
const char* serverURL = "https://emslte.arkaautomaations.com/teltonika_test.php"; // Replace with your server's URL
void reconnectMQTT() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection... ");
// Generate a unique client ID, e.g., using the ESP32's MAC address
String clientId = "ESP32Client-" + String(WiFi.macAddress());
Serial.print(clientId);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println(" connected");
// Resubscribe to topics after reconnecting
client.subscribe(selectionSwitch_topic);
client.subscribe(relayControl_topic);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
// Callback function to handle incoming MQTT messages
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message received on topic: ");
Serial.print(topic);
Serial.print(": ");
// Print the received payload
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
if (strcmp(topic, selectionSwitch_topic) == 0) {
if (payload[0] == '1') {
manualMode = true; // Enable manual mode
client.publish(manualSwitch_topic, "Manual Mode");
Serial.println("Manual Mode Activated");
} else {
manualMode = false; // Switch to automatic mode
client.publish(manualSwitch_topic, "Automatic Mode");
Serial.println("Automatic Mode Activated");
}
}
if (strcmp(topic, relayControl_topic) == 0 && manualMode) {
if (payload[0] == '1') {
relayState = true;
digitalWrite(relayPin, RELAY_ON); // Turn relay ON
Serial.println("Relay ON in manual mode");
} else {
relayState = false;
digitalWrite(relayPin, RELAY_OFF); // Turn relay OFF
Serial.println("Relay OFF in manual mode");
}
client.publish(led_topic, relayState ? "1" : "0");
}
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to WiFi!");
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
// Subscribe to the topics
client.subscribe(selectionSwitch_topic);
client.subscribe(relayControl_topic);
// Configure pins
pinMode(relayPin, OUTPUT);
pinMode(triggerPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(wifiConnectedLedPin, OUTPUT);
pinMode(wifiDisconnectedLedPin, OUTPUT);
digitalWrite(wifiConnectedLedPin, LOW);
digitalWrite(wifiDisconnectedLedPin, HIGH);
digitalWrite(relayPin, RELAY_OFF);
digitalWrite(wifiConnectedLedPin, HIGH);
digitalWrite(wifiDisconnectedLedPin, LOW);
}
void postJSONData(float distance, int percentage) {
if (WiFi.status() == WL_CONNECTED) {
http.begin(serverURL);
http.addHeader("Content-Type", "application/json");
String jsonData = "{";
jsonData += "\"distance\":" + String(distance) + ",";
jsonData += "\"percentage\":" + String(percentage);
jsonData += "}";
int httpResponseCode = http.POST(jsonData);
if (httpResponseCode > 0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
} else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
http.end();
} else {
Serial.println("WiFi Disconnected");
}
}
float calculateDistance() {
digitalWrite(triggerPin, LOW);
delayMicroseconds(5);
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
long duration = pulseIn(echoPin, HIGH, 30000); // 30ms timeout
if (duration == 0) {
Serial.println("No echo received!");
return maxheight; // Default to max height
}
return duration * 0.0343 / 2;
}
int calculatePercent(float distance) {
return 100 - ((distance / maxheight) * 100);
}
void controlRelayBasedOnDistance(int tankLevelPercentage) {
if (manualMode) {
Serial.println("Manual Mode - Skipping Automatic Control");
return; // Don't change relay state if in manual mode
}
if (tankLevelPercentage < minpercent) {
if (!relayState) {
relayState = true;
digitalWrite(relayPin, RELAY_ON);
Serial.println("Relay Status: ON (NC State)");
}
} else if (tankLevelPercentage >= maxpercent) {
if (relayState) {
relayState = false;
digitalWrite(relayPin, RELAY_OFF);
Serial.println("Relay Status: OFF (NO State)");
}
}
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Wi-Fi Disconnected: Turning Relay OFF");
relayState = false;
digitalWrite(relayPin, RELAY_OFF);
digitalWrite(wifiDisconnectedLedPin, HIGH);
digitalWrite(wifiConnectedLedPin, LOW);
delay(500);
return;
} else {
digitalWrite(wifiDisconnectedLedPin, LOW);
digitalWrite(wifiConnectedLedPin, HIGH);
}
if (!client.connected()) {
reconnectMQTT();
}
client.loop();
// If in manual mode, skip distance calculation and control relay based on manual commands
if (manualMode) {
//Serial.println("Manual Mode Active");
return; // Skip distance checks and relay control if in manual mode
}
unsigned long currentMillis = millis();
if (currentMillis - lastPostTime >= 30000) { // 30 seconds interval
lastPostTime = currentMillis;
float distance = calculateDistance();
int tankLevelPercentage = calculatePercent(distance);
postJSONData(distance, tankLevelPercentage);
}
float distance = calculateDistance();
int tankLevelPercentage = calculatePercent(distance);
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
Serial.print("Tank Level Percentage: ");
Serial.println(tankLevelPercentage);
controlRelayBasedOnDistance(tankLevelPercentage);
char msg[50];
sprintf(msg, "%d", (int)distance); // Send as integer (distance)
client.publish(distance_topic, msg);
sprintf(msg, "%d", tankLevelPercentage); // Send as integer (percentage)
client.publish(percent_topic, msg);
client.publish(led_topic, relayState ? "1" : "0");
delay(500); // 500 ms delay for loop pacing
}