top of page

Remote Controlling Endpoint devices using ESP32

Hello everyone, welcome to another series of video from Electronics Eternity. This time around we will be looking into "Remote Controlling Endpoint devices using ESP32".


Before we get into any details of this project, I would highly recommended that you check my previous videos on Bootstrap Radio Buttons and Port Forwarding. The content from these videos will help you understand this tutorial better as we will be using somewhat the same concepts.


Now, what is meant by "remotely controlling endpoint devices" is that we will try to turn ON and OFF a device by using radio buttons from a website. This website is locally hosted and connected to a local database. In this case, we are using PHP as our database however you can choose to any database flavors that you are familiar with. The inputs from this radio button is passed onto and stored in the PHB database. We would then have a status page which reflects the latest value of the radio button representing either ON or OFF state; which will be the state of endpoint device.


For the sake of simplicity, my endpoint device is a simple built-in LED from ESP32 but then again you can use any endpoint devices that you like. For an example, your endpoint devices can be a servo or DC motor, switch, LEDs or even relays to control higher voltage devices such as fans, wall lamp, shutter or just about any devices you desire.


For the ease of understanding, i have broken down this tutorial into 3 parts, where the first will be on the ESP Code. 2nd part on the Database Processing and finally on the Results.


Part 1 : ESP32 Code

Below is the entire ESP32 code used in this project.


#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "WIFI NAME HERE";
const char* password = "PASSWORD";
String buttonState;

void setup() {

  Serial.begin(115200);
  delay(4000);
  pinMode(LED_BUILTIN, OUTPUT);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  if ((WiFi.status() == WL_CONNECTED)) {  //Check the current connection status

HTTPClient http;
http.begin("http://12.345.56.78/Bootstrap%20from%20Desktop/Bootstrap%20Form/Status_Page.php");

    int httpCode = http.GET();
    if (httpCode > 0) {  //Check for the returning code

      String payload = http.getString();
      //Serial.println(httpCode);
      //Serial.println(payload);

      //Serial.println(payload);
      int firstcomma = payload.indexOf('State:');
      Serial.print("firstcomma :");
      Serial.println(firstcomma);
      int secondcomma = payload.indexOf('|', firstcomma + 1);
      Serial.print("secondcomma :");
      Serial.println(secondcomma);
      buttonState = payload.substring(firstcomma + 1, secondcomma);
      delay(1000);
      Serial.println(buttonState);


      if (buttonState == "ON") {
        //Serial.println("Button is ON");
        digitalWrite(LED_BUILTIN, HIGH); 
      } else {
        Serial.println("Button is OFF");
        digitalWrite(LED_BUILTIN, LOW); 
      }
    }
    else {
      Serial.println("Error on HTTP request");
    }
    http.end(); 
  }
  delay(5000);
}

Let's look into this code elaboration.


Below are the libraries used in this code :

#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "WIFI NAME HERE";
const char* password = "PASSWORD";
String buttonState;
  • WiFi.h: This library allows the microcontroller (like ESP32) to connect to a Wi-Fi network.

  • HTTPClient.h: Provides HTTP methods (GET, POST, etc.) to interact with a web server.

  • ssid: The name of the Wi-Fi network.

  • password: The password for the Wi-Fi network.

  • buttonState: A string that will hold the state of a button ("ON" or "OFF") retrieved from the server.

void setup() {
  Serial.begin(115200);       // Initialize serial communication at 115200 baud rate
  delay(4000);                // Delay to give the microcontroller time to initialize
  pinMode(LED_BUILTIN, OUTPUT); // Set the built-in LED as an output

  WiFi.begin(ssid, password);  // Start connecting to the Wi-Fi network

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  Serial.println("Connected to the WiFi network");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());  // Print the local IP address after successful connection
}
  • Serial.begin(115200): Starts serial communication for debugging, printing information to the console.

  • WiFi.begin(ssid, password): Connects to the Wi-Fi using the provided credentials.

  • while (WiFi.status() != WL_CONNECTED): Continuously checks if the device is connected to Wi-Fi. If not, it prints "Connecting to WiFi.." and retries every second.

  • Once connected, it prints the local IP address assigned to the device.

void loop() {
  if ((WiFi.status() == WL_CONNECTED)) {  
    HTTPClient http;
    http.begin("http://12.345.56.78//Bootstrap%20from%20Desktop/Bootstrap%20Form/Status_Page.php");

    int httpCode = http.GET();
    if (httpCode > 0) {
      String payload = http.getString();
  • The loop() continuously checks whether the device is connected to Wi-Fi.

  • http.begin(): Initializes an HTTP GET request to the specified URL.

  • http.GET(): Sends the GET request to the server. The response code (httpCode) is checked to determine if the request was successful (code > 0 means success).

      int firstcomma = payload.indexOf('State:');
      Serial.print("firstcomma :");
      Serial.println(firstcomma);
      int secondcomma = payload.indexOf('|', firstcomma + 1);
      Serial.print("secondcomma :");
      Serial.println(secondcomma);
      buttonState = payload.substring(firstcomma + 1, secondcomma);
      delay(1000);
      Serial.println(buttonState);
  • payload: The content of the URL (expected to contain the state of a button, e.g., "State", "|").

  • payload.indexOf('State:'): Finds the position of the string "State:" in the payload.

  • payload.indexOf('|', firstcomma + 1): Finds the position of the '|' character, marking the end of the button state value.

  • buttonState = payload.substring(): Extracts the substring between "State:" and '|', which will be either "ON" or "OFF".

      if (buttonState == "ON") {
        digitalWrite(LED_BUILTIN, HIGH);  // Turn on the built-in LED
      } else {
        digitalWrite(LED_BUILTIN, LOW);   // Turn off the built-in LED
      }
If buttonState is "O
  • If buttonState is "ON", the built-in LED will turn on whereas LED will be off when buttonState is "OFF"

    else {
      Serial.println("Error on HTTP request");
    }
    http.end();
  }
  delay(5000);
}
  • If the HTTP request fails (i.e., httpCode <= 0), it prints an error message.

  • http.end(): Closes the HTTP connection.

  • The loop() delays for 5 seconds before starting the process again.


Part 2 : Database Processing

Let's look at the next part of our project which is the Database Processing.


First of all, you need to create a table in your database. The table will have 3 columns named as id, created_at and state. ID will be the unique primary key whereas the Created_at and state will be the dynamic values that constantly changes depending on user's input


User's input is gathered from a web page. If you remember, i have mentioned this project will be about controlling endpoint device. In order to control an endpoint device, a user interface will be needed to key in our input which brings us to our next component of our project. The next component that we're talking about over here is Webpage for users to change buttonState to ON and OFF.


To establish a bridge between our user interface webpage to our PHP database, we need to have an action page. Action page contains all the necessary PHP commands that is needed to update our PHP database.

Accordingly, our radio button also needs to be linked with this action page by using form="action_page.php". Action_page is just a random name, you can have any other name that you like as long it is correctly configured.


Below is the entire code of our "action_page.php"


<html>
<body>
<?php
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "password_here";
$dbname = "database_name_here";

$connect = @mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
if(!$connect){
	echo "Error: " . mysqli_connect_error();
	exit();
}
echo "Connection Success!<br><br>";

$exampleRadios = $_GET['exampleRadios'];
if($exampleRadios == "option1"){
    $query = "INSERT INTO buttonstate (id, Created_at, State) VALUES (NULL, current_timestamp(), 'ON');";
}else{
    $query = "INSERT INTO buttonstate (id, Created_at, State) VALUES (NULL, current_timestamp(), 'OFF');";
}

$result = mysqli_query($connect,$query);
if($result){
    echo "Insertion Success!<br>";
}
?>
</body>
</html>

Now, let's look at the content of our action page. Our action page is a .php file.

<html>
<body>
<?php
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "password_here";
$dbname = "database_name_here";

We begin with html tags. Then, we have our php part. At the beginning, we're simply storing username, credentials and database names to our PHP database. I have hid my password for security reasons.

$connect = @mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
if(!$connect){
	echo "Error: " . mysqli_connect_error();
	exit();
}
echo "Connection Success!<br><br>";

Next, we will try to connect to the database using the earlier parameters and throw an error if the connection fails. Failure to connect to the page will be shown on the webpage when we cannot connect to the database.

$exampleRadios = $_GET['exampleRadios'];
if($exampleRadios == "option1"){
    $query = "INSERT INTO buttonstate (id, Created_at, State) VALUES (NULL, current_timestamp(), 'ON');";
}else{
    $query = "INSERT INTO buttonstate (id, Created_at, State) VALUES (NULL, current_timestamp(), 'OFF');";
}

Subsequently, we take the $exampleradios variable and transfer the values into our table. when $exampleradios=option1 the buttonState will be ON whereas buttonState will be OFF during option2. The values of option1 and option2 can be seen in the URL of user interface webpage which is our radio button page.

$result = mysqli_query($connect,$query);
if($result){
    echo "Insertion Success!<br>";
}
?>

We then transfer the query based on user's input to our database using mysqli_query command as shown. The page will display Insertion success if we successfully sent the values to the database. In the event of failure, mysqli error will be displayed in the page.


The final part of Database processing will be our Status_page. Again, our status will be a .php file again.


<html>
<head>
<meta http-equiv="refresh" content="2">
</head>
<body>

<?php
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "password_here";
$dbname = "database_name_here";

$connect = @mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
if(!$connect){
	echo "Error: " . mysqli_connect_error();
	exit();
}

$query = "SELECT State, Created_at FROM buttonstate ORDER BY id DESC LIMIT 1;";
$result = mysqli_query($connect,$query);
$all = $result->fetch_all();

echo "<h1>"."Button State:".$all[0][0]."|"."</h1>";
echo "<h1>"."When:".$all[0][1]."|"."</h1>";

?>
</body>
</html>

The earlier part of status_page code is quite similar to action page where we declare the username, password and database and the attempt to connect to database.

$query = "SELECT State, Created_at FROM buttonstate ORDER BY id DESC LIMIT 1;";
$result = mysqli_query($connect,$query);
$all = $result->fetch_all();

Let's look at the query that will give us the latest value from our button state table. We try to get 2 values from which are State and Created_at. We need to set the order as descending at limit to output row to only 1.

The output will be a matrix format as [Created_at, State] and hence, when echoing the output, we need to echo the specific matrix components as shown below.

echo "<h1>"."Button State:".$all[0][0]."|"."</h1>";
echo "<h1>"."When:".$all[0][1]."|"."</h1>";

With that, we have come to the end of all the codes and database components that is needed to actualize this project. You can view the live results and also gain more understanding on this project from my YouTube video below.



Hope you've enjoyed this tutorial. Please don't forget to Like and Subscribe to my channel.

Comments


bottom of page