Control ESP32 and ESP8266 GPIOs from Anywhere in the World

In this project, you’ll learn how to control your ESP32 or ESP8266 GPIOs from anywhere in the world. This can be very useful to control a relay, a thermostat, or any other device remotely.

Control ESP32 and ESP8266 GPIOs from Anywhere in the World

Updated on 27 March 2023

This project is also very versatile. Through your cloud dashboard, you can easily control more outputs (without uploading new code to your board) and you can even connect multiple boards to your server.

Previously, we’ve stored sensor readings into a database and we’ve used different methods to display sensor readings on a:

Now, I’ve created this new project where you can create buttons in a dashboard and assign them to a Board and GPIO number. Then, you can use the toggle switches to control the ESP32 or ESP8266 outputs from anywhere.

There are many ways of controlling outputs from anywhere, and even though this is a working solution there are other methods that provide a two-way communication with your devices. I also recommend that you take this project further and add more features to fit your own needs.

To build this project, you’ll use these technologies:

  • ESP32 or ESP8266 programmed with Arduino IDE
  • Hosting server and domain name
  • PHP scripts to store and retrieve the output states stored in a MySQL database

Table of Contents

This project is divided into the following main sections:

  1. Hosting Your PHP Application and MySQL Database
  2. Preparing Your MySQL Database
  3. Creating Your Dashboard Files
  4. PHP Script – Update and Retrieve Output States
  5. PHP Script for Database Functions
  6. PHP Script – Control Buttons
  7. Setting Up the ESP32 or ESP8266

Watch the Video Demonstration

To see how the project works, you can watch the following video demonstration:

0. Download Source Code

For this project, you’ll need these files:

1. Hosting Your PHP Application and MySQL Database

The goal of this project is to have your own domain name and hosting account that allows you to control your ESP32 or ESP8266 GPIOs from anywhere in the world.

Here’s a high-level overview of how the project works:

Control outputs from anywhere project overview
  1. You have a web page running a PHP script with some toggle buttons that allow you to control the outputs on and off;
  2. When you press the buttons, it updates the output state and saves it in your database;
  3. You can add more buttons or delete them from your dashboard;
  4. Then, you can have an ESP32 or ESP8266 or even multiple boards that make HTTP GET requests every X number of seconds to your server;
  5. Finally, according to the result of that HTTP GET request, the ESP board updates its GPIOs accordingly.

Hosting Services

I recommend using one of the following hosting services that can handle all the project requirements:

  • Bluehost (user-friendly with cPanel): free domain name when you sign up for the 3-year plan. I recommend choosing the unlimited websites option;
  • Digital Ocean: Linux server that you manage through a command line. I only recommended this option for advanced users.

Those two services are the ones that I use and personally recommend, but you can use any other hosting service. Any hosting service that offers PHP and MySQL will work with this tutorial. If you don’t have a hosting account, I recommend signing up for Bluehost.

Get Hosting and Domain Name with Bluehost »

When buying a hosting account, you’ll also have to purchase a domain name. This is what makes this project interesting: you’ll be able to go your domain name (http://example.com) and control your boards.

If you like our projects, you might consider signing up for one of the recommended hosting services, because you’ll be supporting our work.

Note: you can also run a LAMP (Linux, Apache, MySQL, PHP) server on a Raspberry Pi to control your boards in your local network. However, the purpose of this tutorial is to control the ESP outputs with your own domain name that you can access from anywhere in the world.

2. Preparing Your MySQL Database

After signing up for a hosting account and setting up a domain name, you can login to your cPanel or similar dashboard. After that, follow the next steps to create your database, username, password and SQL table.

Creating a database and user

Open the “Advanced” tab:

Bluehost Advanced tab

1. Type “database” in the search bar and select “MySQL Database Wizard”.

CPanel select MySQL database wizard to create db

2. Enter your desired Database name. In my case, the database name is esp_data. Then, press the “Next Step” button:

ESP32 ESP8266 CPanel Create MySQL Database

Note: later you’ll have to use the database name with the prefix that your host gives you (my database prefix in the screenshot above is blurred). I’ll refer to it as example_esp_data from now on.

3. Type your Database username and set a password. You must save all those details, because you’ll need them later to establish a database connection with your PHP code.

ESP32 ESP8266 CPanel Create MySQL Database User and Password

That’s it! Your new database and user were created successfully. Now, save all your details because you’ll need them later:

  • Database name: example_esp_data
  • Username: example_esp_board
  • Password: your password

Creating a SQL table

After creating your database and user, go back to cPanel dashboard and search for “phpMyAdmin”.

ESP32 ESP8266 CPanel Open PHPMyAdmin

In the left sidebar, select your database name example_esp_data and open the “SQL” tab.

ESP32 ESP8266 PHPMyAdmin Open Database

Important: make sure you’ve opened the example_esp_data database. Then, click the SQL tab. If you don’t follow these exact steps and run the SQL query, you might create a table in the wrong database.

Copy the SQL query in the following snippet:

CREATE TABLE Outputs (
    id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(64),
    board INT(6),
    gpio INT(6),
    state INT(6)
);
INSERT INTO `Outputs`(`name`, `board`, `gpio`, `state`) VALUES ("Built-in LED", 1, 2, 0);

CREATE TABLE Boards (
    id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    board INT(6),
    last_request TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
INSERT INTO `Boards`(`board`) VALUES (1);

View raw code

Paste it in the SQL query field (highlighted with a red rectangle) and press the “Go” button to create your table:

Create MySQL Tables for control ESP32 ESP8266 GPIOs Dashboard

After that, you should see your newly created tables called Boards and Outputs in the example_esp_data database as shown in the figure below:

MySQL Tables created for control ESP32 ESP8266 GPIOs Dashboard

3. Creating Your Dashboard Files

In this section, we’re going to create the files that are responsible for creating your Dashboard. Here are the files:

If you’re using a hosting provider with cPanel, you can search for “File Manager”:

ESP32 ESP8266 CPanel Open Edit PHP Files with File Manager

Then, select the public_html option and press the “+ File” button to create a new file.

ESP32 ESP8266 CPanel Create New PHP File

Note: if you’re following this tutorial and you’re not familiar with PHP, I recommend creating these exact files.

Create four new files in /public_html with these exact names and extensions:

  • esp-database.php
  • esp-outputs-action.php
  • esp-outputs.php
  • esp-style.css
Create PHP files for control ESP32 ESP8266 GPIOs Dashboard

4. PHP Script – Update and Retrieve Output States

In this section, we’re going to create a PHP script that is responsible for receiving incoming requests and interacting with your MySQL database.

Edit the newly created file (esp-outputs-action.php) and copy the following snippet:

<?php
    include_once('esp-database.php');

    $action = $id = $name = $gpio = $state = "";

    if ($_SERVER["REQUEST_METHOD"] == "POST") {
        $action = test_input($_POST["action"]);
        if ($action == "output_create") {
            $name = test_input($_POST["name"]);
            $board = test_input($_POST["board"]);
            $gpio = test_input($_POST["gpio"]);
            $state = test_input($_POST["state"]);
            $result = createOutput($name, $board, $gpio, $state);

            $result2 = getBoard($board);
            if(!$result2->fetch_assoc()) {
                createBoard($board);
            }
            echo $result;
        }
        else {
            echo "No data posted with HTTP POST.";
        }
    }

    if ($_SERVER["REQUEST_METHOD"] == "GET") {
        $action = test_input($_GET["action"]);
        if ($action == "outputs_state") {
            $board = test_input($_GET["board"]);
            $result = getAllOutputStates($board);
            if ($result) {
                while ($row = $result->fetch_assoc()) {
                    $rows[$row["gpio"]] = $row["state"];
                }
            }
            echo json_encode($rows);
            $result = getBoard($board);
            if($result->fetch_assoc()) {
                updateLastBoardTime($board);
            }
        }
        else if ($action == "output_update") {
            $id = test_input($_GET["id"]);
            $state = test_input($_GET["state"]);
            $result = updateOutput($id, $state);
            echo $result;
        }
        else if ($action == "output_delete") {
            $id = test_input($_GET["id"]);
            $board = getOutputBoardById($id);
            if ($row = $board->fetch_assoc()) {
                $board_id = $row["board"];
            }
            $result = deleteOutput($id);
            $result2 = getAllOutputStates($board_id);
            if(!$result2->fetch_assoc()) {
                deleteBoard($board_id);
            }
            echo $result;
        }
        else {
            echo "Invalid HTTP request.";
        }
    }

    function test_input($data) {
        $data = trim($data);
        $data = stripslashes($data);
        $data = htmlspecialchars($data);
        return $data;
    }
?>

View raw code

5. PHP Script for Database Functions

Edit your file esp-database.php that inserts, deletes, and retrieves data. Copy the next PHP script:

<?php
    $servername = "localhost";
    // Your Database name
    $dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
    // Your Database user
    $username = "REPLACE_WITH_YOUR_USERNAME";
    // Your Database user password
    $password = "REPLACE_WITH_YOUR_PASSWORD";

    function createOutput($name, $board, $gpio, $state) {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "INSERT INTO Outputs (name, board, gpio, state)
        VALUES ('" . $name . "', '" . $board . "', '" . $gpio . "', '" . $state . "')";

       if ($conn->query($sql) === TRUE) {
            return "New output created successfully";
        }
        else {
            return "Error: " . $sql . "<br>" . $conn->error;
        }
        $conn->close();
    }

    function deleteOutput($id) {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "DELETE FROM Outputs WHERE id='". $id .  "'";

       if ($conn->query($sql) === TRUE) {
            return "Output deleted successfully";
        }
        else {
            return "Error: " . $sql . "<br>" . $conn->error;
        }
        $conn->close();
    }

    function updateOutput($id, $state) {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "UPDATE Outputs SET state='" . $state . "' WHERE id='". $id .  "'";

       if ($conn->query($sql) === TRUE) {
            return "Output state updated successfully";
        }
        else {
            return "Error: " . $sql . "<br>" . $conn->error;
        }
        $conn->close();
    }

    function getAllOutputs() {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "SELECT id, name, board, gpio, state FROM Outputs ORDER BY board";
        if ($result = $conn->query($sql)) {
            return $result;
        }
        else {
            return false;
        }
        $conn->close();
    }

    function getAllOutputStates($board) {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "SELECT gpio, state FROM Outputs WHERE board='" . $board . "'";
        if ($result = $conn->query($sql)) {
            return $result;
        }
        else {
            return false;
        }
        $conn->close();
    }

    function getOutputBoardById($id) {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "SELECT board FROM Outputs WHERE id='" . $id . "'";
        if ($result = $conn->query($sql)) {
            return $result;
        }
        else {
            return false;
        }
        $conn->close();
    }

    function updateLastBoardTime($board) {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "UPDATE Boards SET last_request=now() WHERE board='". $board .  "'";

       if ($conn->query($sql) === TRUE) {
            return "Output state updated successfully";
        }
        else {
            return "Error: " . $sql . "<br>" . $conn->error;
        }
        $conn->close();
    }

    function getAllBoards() {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "SELECT board, last_request FROM Boards ORDER BY board";
        if ($result = $conn->query($sql)) {
            return $result;
        }
        else {
            return false;
        }
        $conn->close();
    }

    function getBoard($board) {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "SELECT board, last_request FROM Boards WHERE board='" . $board . "'";
        if ($result = $conn->query($sql)) {
            return $result;
        }
        else {
            return false;
        }
        $conn->close();
    }

    function createBoard($board) {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "INSERT INTO Boards (board) VALUES ('" . $board . "')";

       if ($conn->query($sql) === TRUE) {
            return "New board created successfully";
        }
        else {
            return "Error: " . $sql . "<br>" . $conn->error;
        }
        $conn->close();
    }

    function deleteBoard($board) {
        global $servername, $username, $password, $dbname;

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "DELETE FROM Boards WHERE board='". $board .  "'";

       if ($conn->query($sql) === TRUE) {
            return "Board deleted successfully";
        }
        else {
            return "Error: " . $sql . "<br>" . $conn->error;
        }
        $conn->close();
    }

?>

View raw code

Before saving the file, you need to modify the $dbname, $username and $password variables with your unique details:

// Your Database name
$dbname = "example_esp_data";
// Your Database user
$username = "example_esp_board";
// Your Database user password
$password = "YOUR_USER_PASSWORD";

After adding the database name, username and password, save the file and continue with this tutorial.

6. PHP Script – Control Buttons

You’ll also need to add a CSS file to style your dashboard (esp-style.css). Copy that CSS to your file and save it:

/**
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/control-esp32-esp8266-gpios-from-anywhere/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
**/

html {
    font-family: Arial;
    display: inline-block;
    text-align: center;
}

h2 {
    font-size: 3.0rem;
}

body {
    max-width: 600px;
    margin:0px auto;
    padding-bottom: 25px;
}

.switch {
    position: relative;
    display: inline-block;
    width: 120px;
    height: 68px;
}

.switch input {
    display: none
}

.slider {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #949494;
    border-radius: 34px;
}

.slider:before {
    position: absolute;
    content: "";
    height: 52px;
    width: 52px;
    left: 8px; bottom: 8px;
    background-color: #fff;
    -webkit-transition: .4s;
    transition: .4s;
    border-radius: 68px;
}

input:checked+.slider {
    background-color: #008B74;
}

input:checked+.slider:before {
    -webkit-transform: translateX(52px);
    -ms-transform: translateX(52px);
    transform: translateX(52px);
}

input[type=text], input[type=number], select {
    width: 100%;
    padding: 12px 20px;
    margin: 8px 0;
    display: inline-block;
    border: 1px solid #ccc;
    border-radius: 4px;
    box-sizing: border-box;
}

input[type=submit] {
    width: 100%;
    background-color: #008B74;
    color: white;
    padding: 14px 20px;
    margin: 8px 0;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

input[type=submit]:hover {
    background-color: #005a4c;
}

div {
    text-align: left;
    border-radius: 4px;
    background-color: #efefef;
    padding: 20px;
}

View raw code

Finally, copy the next PHP script to your esp-outputs.php files that will display your control buttons and allow you to create/delete buttons:

<!--
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/control-esp32-esp8266-gpios-from-anywhere/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
-->
<?php
    include_once('esp-database.php');

    $result = getAllOutputs();
    $html_buttons = null;
    if ($result) {
        while ($row = $result->fetch_assoc()) {
            if ($row["state"] == "1"){
                $button_checked = "checked";
            }
            else {
                $button_checked = "";
            }
            $html_buttons .= '<h3>' . $row["name"] . ' - Board '. $row["board"] . ' - GPIO ' . $row["gpio"] . ' (<i><a onclick="deleteOutput(this)" href="javascript:void(0);" id="' . $row["id"] . '">Delete</a></i>)</h3><label class="switch"><input type="checkbox" onchange="updateOutput(this)" id="' . $row["id"] . '" ' . $button_checked . '><span class="slider"></span></label>';
        }
    }

    $result2 = getAllBoards();
    $html_boards = null;
    if ($result2) {
        $html_boards .= '<h3>Boards</h3>';
        while ($row = $result2->fetch_assoc()) {
            $row_reading_time = $row["last_request"];
            // Uncomment to set timezone to - 1 hour (you can change 1 to any number)
            //$row_reading_time = date("Y-m-d H:i:s", strtotime("$row_reading_time - 1 hours"));

            // Uncomment to set timezone to + 4 hours (you can change 4 to any number)
            //$row_reading_time = date("Y-m-d H:i:s", strtotime("$row_reading_time + 7 hours"));
            $html_boards .= '<p><strong>Board ' . $row["board"] . '</strong> - Last Request Time: '. $row_reading_time . '</p>';
        }
    }
?>

<!DOCTYPE HTML>
<html>
    <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">

        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" type="text/css" href="esp-style.css">
        <title>ESP Output Control</title>
    </head>
<body>
    <h2>ESP Output Control</h2>
    <?php echo $html_buttons; ?>
    <br><br>
    <?php echo $html_boards; ?>
    <br><br>
    <div><form onsubmit="return createOutput();">
        <h3>Create New Output</h3>
        <label for="outputName">Name</label>
        <input type="text" name="name" id="outputName"><br>
        <label for="outputBoard">Board ID</label>
        <input type="number" name="board" min="0" id="outputBoard">
        <label for="outputGpio">GPIO Number</label>
        <input type="number" name="gpio" min="0" id="outputGpio">
        <label for="outputState">Initial GPIO State</label>
        <select id="outputState" name="state">
          <option value="0">0 = OFF</option>
          <option value="1">1 = ON</option>
        </select>
        <input type="submit" value="Create Output">
        <p><strong>Note:</strong> in some devices, you might need to refresh the page to see your newly created buttons or to remove deleted buttons.</p>
    </form></div>

    <script>
        function updateOutput(element) {
            var xhr = new XMLHttpRequest();
            if(element.checked){
                xhr.open("GET", "esp-outputs-action.php?action=output_update&id="+element.id+"&state=1", true);
            }
            else {
                xhr.open("GET", "esp-outputs-action.php?action=output_update&id="+element.id+"&state=0", true);
            }
            xhr.send();
        }

        function deleteOutput(element) {
            var result = confirm("Want to delete this output?");
            if (result) {
                var xhr = new XMLHttpRequest();
                xhr.open("GET", "esp-outputs-action.php?action=output_delete&id="+element.id, true);
                xhr.send();
                alert("Output deleted");
                setTimeout(function(){ window.location.reload(); });
            }
        }

        function createOutput(element) {
            var xhr = new XMLHttpRequest();
            xhr.open("POST", "esp-outputs-action.php", true);

            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

            xhr.onreadystatechange = function() {
                if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
                    alert("Output created");
                    setTimeout(function(){ window.location.reload(); });
                }
            }
            var outputName = document.getElementById("outputName").value;
            var outputBoard = document.getElementById("outputBoard").value;
            var outputGpio = document.getElementById("outputGpio").value;
            var outputState = document.getElementById("outputState").value;
            var httpRequestData = "action=output_create&name="+outputName+"&board="+outputBoard+"&gpio="+outputGpio+"&state="+outputState;
            xhr.send(httpRequestData);
        }
    </script>
</body>
</html>

View raw code

If you try to access your domain name in the following URL path, you’ll see the following:

https://example.com/esp-outputs.php
ESP32 ESP8266 Output Control Default Button and Board

That’s it! You should see that web page with your default button. The default button is called Built-in LED, it’s assigned to Board 1 and controls GPIO 2.

7. Setting Up the ESP32 or ESP8266

This project is compatible with both the ESP32 and ESP8266 boards. You just need to assemble a simple circuit and upload the sketches provided.

ESP32 vs ESP8266 Development Boards

Parts Required

To test this project, we’ll connect some LEDs to the ESP32 and ESP8266 GPIOs. Here’s a list of parts you need to build the circuit for this project:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Schematics

For this example, we’ll use an ESP32 board with 3 LEDs and an ESP8266 with 2 LEDs. Instead of LEDs, you can connect a relay module or any other device to the ESP GPIOs.

LEDs wiring to ESP32 – Board #1

ESP32 Control LEDs GPIOs from anywhere circuit schematic diagram

Recommended reading: which ESP32 GPIOs should you use.

LEDs wiring to ESP8266 – Board #2

ESP8266 Control LEDs GPIOs from anywhere circuit schematic diagram

Recommended reading: which ESP8266 GPIOs should you use.

ESP32 Code – Board #1

We’ll program the ESP32/ESP8266 using Arduino IDE, so you must have the ESP add-on installed in your Arduino IDE.

Follow one of the next tutorials depending on the board you’re using:

You also need to install the Arduino_JSON library. You can install this library in the Arduino IDE Library Manager. Just go to Sketch > Include Library > Manage Libraries … and search for the library name as follows:

Install Arduino JSON library Arduino IDE

After installing the necessary board add-ons and libraries, copy the following code to your Arduino IDE, but don’t upload it yet. You need to make some changes to make it work for you.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/control-esp32-esp8266-gpios-from-anywhere/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

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

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

//Your IP address or domain name with URL path
const char* serverName = "https://example.com/esp-outputs-action.php?action=outputs_state&board=1";

// Update interval time set to 5 seconds
const long interval = 5000;
unsigned long previousMillis = 0;

String outputsState;

void setup() {
  Serial.begin(115200);
  
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) { 
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  unsigned long currentMillis = millis();
  
  if(currentMillis - previousMillis >= interval) {
     // Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED ){ 
      outputsState = httpGETRequest(serverName);
      Serial.println(outputsState);
      JSONVar myObject = JSON.parse(outputsState);
  
      // JSON.typeof(jsonVar) can be used to get the type of the var
      if (JSON.typeof(myObject) == "undefined") {
        Serial.println("Parsing input failed!");
        return;
      }
    
      Serial.print("JSON object = ");
      Serial.println(myObject);
    
      // myObject.keys() can be used to get an array of all the keys in the object
      JSONVar keys = myObject.keys();
    
      for (int i = 0; i < keys.length(); i++) {
        JSONVar value = myObject[keys[i]];
        Serial.print("GPIO: ");
        Serial.print(keys[i]);
        Serial.print(" - SET to: ");
        Serial.println(value);
        pinMode(atoi(keys[i]), OUTPUT);
        digitalWrite(atoi(keys[i]), atoi(value));
      }
      // save the last HTTP GET Request
      previousMillis = currentMillis;
    }
    else {
      Serial.println("WiFi Disconnected");
    }
  }
}

String httpGETRequest(const char* serverName) {
  WiFiClientSecure *client = new WiFiClientSecure;
  
  // set secure client without certificate
  client->setInsecure();
  HTTPClient https;
    
  // Your IP address with path or Domain name with URL path 
  https.begin(*client, serverName);
  
  // Send HTTP POST request
  int httpResponseCode = https.GET();
  
  String payload = "{}"; 
  
  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = https.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  https.end();

  return payload;
}

View raw code

Note: Most servers require you to make HTTPS requests. The code above makes HTTPS requests to be compliant with the requirements of most cloud servers nowadays.

Your server doesn’t support HTTPS? Use this code instead.

Setting your network credentials

You need to modify the following lines with your network credentials: SSID and password. The code is well commented on where you should make the changes.

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Setting your serverName

You also need to type your domain name, so the ESP makes the HTTP GET request to your own server.

const char* serverName = "https://example.com/esp-outputs-action.php?action=outputs_state&board=1";

Notice that on the URL serverName we have a parameter board=1. This indicates the board ID. If you want to add more boards, you should change that ID. That identifies the board you want to control.

Now, you can upload the code to your board. It should work straight away.

This project is already quite long, so we won’t cover how the code works. In summary, your ESP32 makes an HTTP GET request to your server every X number of seconds to update the GPIOs states (by default it’s set to 5 seconds).

const long interval = 5000;

Then, the board will update its outputs accordingly to the request response.

Open your Serial Monitor and you should see something similar:

ESP32 Arduino IDE Serial Monitor Example

The request retrieves a JSON object that contains the GPIO number and its state. In this case, it tells us that GPIO 2 should be LOW {“2″:”0”}.

ESP8266 Code – Board #2

For this example, we’re controlling the outputs from two boards simultaneously. You can use next code for your ESP8266 board:

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/control-esp32-esp8266-gpios-from-anywhere/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
#include <Arduino_JSON.h>

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

//Your IP address or domain name with URL path
//const char* serverName = "https://example.com/esp-outputs-action.php?action=outputs_state&board=1";

// Update interval time set to 5 seconds
const long interval = 5000;
unsigned long previousMillis = 0;

String outputsState;

void setup() {
  Serial.begin(115200);
  
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) { 
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  unsigned long currentMillis = millis();
  
  if(currentMillis - previousMillis >= interval) {
     // Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED ){ 
      outputsState = httpGETRequest(serverName);
      Serial.println(outputsState);
      JSONVar myObject = JSON.parse(outputsState);
  
      // JSON.typeof(jsonVar) can be used to get the type of the var
      if (JSON.typeof(myObject) == "undefined") {
        Serial.println("Parsing input failed!");
        return;
      }
    
      Serial.print("JSON object = ");
      Serial.println(myObject);
    
      // myObject.keys() can be used to get an array of all the keys in the object
      JSONVar keys = myObject.keys();
    
      for (int i = 0; i < keys.length(); i++) {
        JSONVar value = myObject[keys[i]];
        Serial.print("GPIO: ");
        Serial.print(keys[i]);
        Serial.print(" - SET to: ");
        Serial.println(value);
        pinMode(atoi(keys[i]), OUTPUT);
        digitalWrite(atoi(keys[i]), atoi(value));
      }
      // save the last HTTP GET Request
      previousMillis = currentMillis;
    }
    else {
      Serial.println("WiFi Disconnected");
    }
  }
}

String httpGETRequest(const char* serverName) {
  std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);

  // Ignore SSL certificate validation
  client->setInsecure();

  HTTPClient https;
    
  // Your IP address with path or Domain name with URL path 
  https.begin(*client, serverName);
  
  // Send HTTP POST request
  int httpResponseCode = https.GET();
  
  String payload = "{}"; 
  
  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = https.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  https.end();

  return payload;
}

View raw code

To prepare the code for your ESP8266, just enter the SSID, password, domain name, and board ID (in this case, it’s board ID number 2).

Note: Most servers require you to make HTTPS requests. The code above makes HTTPS requests to be compliant with the requirements of most cloud servers nowadays.

Your server doesn’t support HTTPS? Use this code instead.

Demonstration

After completing all the steps, power both your ESP boards.

ESP32 ESP8266 Control GPIOs from Anywhere circuit schematic diagram

If you open your domain name in this URL path:

https://example.com/esp-outputs.php

You should see the default button in your Dashboard:

ESP32 ESP8266 Output Control Default Button and Board

If you press that button on and off, you should be able to control GPIO 2 from your ESP32 – Board #1.

You can add more buttons to your project, type a name (LED 2), set board the id to number 1, then type the desired GPIO that you want to control (33).

Create Dashoard switches buttons to control ESP32 ESP8266 GPIOs

Create another button for Board 1 to control GPIO 32. Then, add two buttons for Board 2 (GPIO 2 and GPIO 4).

ESP32 ESP8266 Output Control Default Button and Board

At any point in time, you can use the delete link to remove buttons from your Dashboard or use the form at the bottom to create more.

Note: in some devices, you might need to refresh the page to see your newly created buttons or to remove deleted buttons.

Finally, there’s a section that shows the last time a board made a request and updated its outputs.

Since this is not a two-way communication, when you press the buttons to control your outputs, your board doesn’t update the outputs instantly. It will take a few seconds for your ESP board to make a new HTTP GET request and update its output states. With the Last Request Time section, you can see when that happened. Just refresh the page to see the updated values.

The web page is also mobile responsive, so you can use any device to access your server.

Control ESP32 ESP8266 GPIOs from Anywhere in the World dashboard demonstration

Wrapping Up

In this tutorial you’ve learned how to control your ESP32 and ESP8266 outputs from anywhere in the world. This requires that you have your own server and domain name (alternatively, you can use a Raspberry Pi LAMP Server for local access).

There are many other features that you can add to your server, you can merge it with our previous projects to display sensor readings. Feel free to add more ESP boards to run simultaneously and define other outputs to control.

I encourage you to change the web page appearance, add more features like email notifications, publish data from different sensors, use multiple ESP boards, and much more.

You might also like reading:

Learn more about the ESP32 and ESP8266 with our resources:

Thank you for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

231 thoughts on “Control ESP32 and ESP8266 GPIOs from Anywhere in the World”

  1. Fascinating and all that, but how is the security?
    That was the first thing that I thought of when I saw it using a domain name and cloud services.
    I also thought about what would happen if the server goes down.
    Sure, you can do some smart programming with backup servers, but personally I don’t trust running stuff remotely (unless it’s secure and redundant).
    Especially if you’re running something vital, like burglar alarm (Controlling on/off for sections, sensors, alarms etc).

    Sure, it’s one in a million that someone would both find your tech, hack it and then burglarize you, but it can happen.

    But, it’s something less vital which doesn’t affect anything, sure. As long as it’s something that doesn’t attract too much attention.
    Otherwise, it has to be secured.

    Also seem to be dependent on many factors, PHP-scripts, db-server, webserver and the connection between these servers and softwares.
    I’m sure a home-server can be set up too, in case you feel that’s any better.
    But, still, it can malfunction with all these components.
    It would be awesome if there were some db-engine which could be incorporated in the ESP module directly, without having it need to read/write into the flash (Don’t even know if it has a writable area, just spit-balling here) or so, and thereby eliminating any third-party provider.
    The fewer services required, the better IMHO.

    Reply
    • I didn’t want to make this project much longer, yes it’s currently available for anyone to guess your URL and access the Dashboard.
      However if you search online for PHP login script, you can add it to your page protect the control Dashboard with a login system and that’s going to be very secure (that’s going to be one of my next projects).
      I’ve been personally running a similar server since 2014 (it’s been 6 years now) and I’ve only encountered a issue once while updating the server (it has daily backups, so you can always go back).

      Reply
          • Hello, do you have any good tutorial on WebSockets?
            I’m trying to establish a WebSocket with a Nano board in order to make a similar control like the one you show as here but instead of using the GET method after a delay I want it to be more responsive.
            Also I need your advice in this subject…
            I’m using Nano + SIM800L(GPRS)+GPS(UBLOX 7) and will add LoRa (if the first part works), I use SoftwareSerial(can go up to 4) to connect the devices. I’ve been told thats a bad idea because,besides being small data packets, the system can crash,and I should use Hardware interrupts, for example I can move to a ATMEGA which has 4 (hardware serial ports).What do you think> Thank you, Alejandro.

      • Hello, project is great, i have made it and working about 3 years but please, please tell me how to secure it to not access it without password anyone who guess the link.

        Reply
      • Do you think you can use WebSockets in order to make it more responsive, I mean with less delay?
        Is it possible to use a Nano board instead of a ESP32?
        Can you explain the PHP and MySQL part, the way you configure it?
        Thank you for your tutorials, they are of great help.

        Reply
      • Good afternoon!
        This project would be perfect if it had a physical button on the arduino and updated on the website as the button was pressed. Could anyone help me with this issue?

        Reply
        • Yes, this would be great to do, I could really use it, like a response that a relay is on it turns a “LED” on the web page next to switch green if on etc..

          Reply
    • While authentication is important and maybe a good topic for a separate tutorial, it would be good to illustrate some defensive programming practices. For example, assume the json packet retrieved could be malicious. It doesn’t take much to check for invalid input, not just for hacking defense, but software bugs. Rather than blindly setting pinMode and digitalWrite, first verify the pin numbers as being ones suitable for writing, and maybe check the value for “0” or “1”. The atoi returns 0 on an invalid number, but supposedly sets the errno global which could be checked.

      Only a few extra lines of code are required to set a mask of allowable output pins and then check the json values are OK.

      Rui, Thanks for a nice tutorial. Maybe for this application there are simpler ways but it’s a good illustration of using these software packages. There are tradeoffs using a remote server for control vs ESP-embedded server with portal in a router. The latter could make a different tutorial.

      I can see how some security gets complex, and makes a pretty detailed tutorial longer. Setting up https can be complex, but Bluehost supposedly includes an SSL certificate. Httpd login, cookies, OATH, etc. can be complex, so maybe good to isolate these in a separate IoT security tutorial.

      Reply
      • Carl,

        You mean something like this?

        if ((atoi(keys[i]) >= 0 && atoi(keys[i]) <= 99) &&
        (atoi(value) == 0 || atoi(value) == 1)) {
        Serial.print("GPIO: ");
        Serial.print(keys[i]);
        Serial.print(" – SET to: ");
        Serial.println(value);
        pinMode(atoi(keys[i]), OUTPUT);
        digitalWrite(atoi(keys[i]), atoi(value));
        }
        else Serial.println("GPIO or status in not an integer");

        Reply
  2. Thanks Rui, excellent how-to as usual! I’ve been waiting for this one to see how you’d save the IO state on the server and if you’d use web sockets or get requests. I’ve been thinking of how to implement this sort of thing without using an mqtt server as I already have a hosting plan, (no mqtt and I don’t think they allow one to be installed). A quick question, do you think if multiple devices, say 50-75, are making get requests to the server I may need to alter the time delay? Or would another type of connection/protocol be better for that situation?

    Reply
    • Hello Mark, I haven’t tested this project with so many devices, but for such application I would run an MQTT server. The idea behind this project is for those who already have a hosting account can take advantage and control the outputs from anywhere. For more than 10 devices I would definitely go with MQTT.

      Reply
  3. This looks great; thanks for sharing.

    Just a quick question. How secure is this i.e. how easy would it be for some to hack this and gain access to your system?

    Reply
    • I didn’t want to make this project much longer, yes it’s currently available for anyone to guess your URL. However if you search online for PHP login script, you can add it to your page protect the control Dashboard with a login system (that’s going to be one of my next projects).

      Reply
  4. WOW
    Excelente tutorial, se entiende facil y rápido. Muy bien, dejarnos la tarea de agregar la lectura de sensores y cosas así.
    Pronto espero poder mostrarte mi proyecto mas avanzado.

    Muchas gracias por compartir tu conocimiento.

    “Excellent tutorial, it is easy and fast. All right, leave us the task of adding sensor reading and things like that.
    Soon I hope to show you my most advanced project.

    Thank you very much for sharing your knowledge.”

    Reply
  5. I’m guessing nobody will probably accidentally go to my ESP webpage but what if someone does? Can they control the off and on buttons from their browser?

    Reply
    • I didn’t want to make this project much longer, yes it’s currently available for anyone to guess your URL. However if you search online for PHP login script, you can add it to your page protect the control Dashboard with a login system (that’s going to be one of my next projects).

      Reply
    • A login script or page can be drafted and you will be able to secure it by your login credentials.
      Other wise it is not secure.

      Reply
  6. Can one 1 guide me when any GPIO already high or ON, while getting http response and change its state again to High or On, will GPIO or relay will off for a second?

    Reply
  7. Hi Sir,
    For the project posted yesterday “Control ESP32 and ESP8266 GPIOs from Anywhere in the World”.

    The URl to be set to ESP8266 is: “http://example.com/esp-outputs-action.php?action=outputs_state&board=2”.

    As you are using the domain bluehost, I wonder if the URL is in detail?

    Reply
  8. The concat of Gpio and board value should be unique, so that a specific board with specific GPIO can be registered once, overall you did great, very nicely I have completed my all project, which has 2 pzem004 for two supplies and which send voltage, current, power to mysql, then after a specified consumption or manually switch to another supply.
    Thankyou so much for your projects.

    Reply
  9. Hello and thanks for this amazing work
    i done the job but i get this message in serial monitor:

    Error code: -11
    {}
    JSON object = {}

    what is the reason and how can fix it?

    Reply
  10. Dear Rui,
    this is a project which I was waiting for for a long time.
    Thank you.
    I’m owning a domain already and php is running.
    I followed the steps of the project and it seemed to work.
    But there are 2 things which don’t:
    1. In the “ESP Output Control” dashboard no additional outputs can be created. But outputs can be deleted.
    2. The ESP32 sketch shows in the serial monitor:
    ….
    {“2″:”0”}
    Parsing input failed!
    HTTP Response code: 200
    ….
    But it acts when I toggle the button in the dashboard and shows
    …..
    {“2″:”1”}
    Parsing input failed!
    HTTP Response code: 200
    ….
    Any idea?

    Reply
      • Hi Rui,

        I updated the existing code with the code provided in the .zip file.
        Still i am facing the same issue “Parsing input failed”.

        Can you please suggest me how to debug and solve the issue. I really need your help and guidance.

        If possible please reply me as early as possible.

        Thanks.

        Reply
    • Dear Klaus,

      I was also waiting for this feature from long time.

      I am facing an error. ESP32 sketch showing the below error in the serial monitor.
      Parsing input failed
      HTTP response code : 302.

      I am trying to make it work since one week. If you can guide, that would be a great help for me.
      I am trying to get response from Rui as well but somehow not getting any response from him.

      As he suggested to download the code provided in the zip file and update with the existing code, i did the same but still the issue is not resolved.

      I will be waiting for your reply…!!!

      Thanks in advance.

      Reply
  11. Good job as usual, thank you for sharing!

    Just a question: All the functions work except the createOutput(element).

    For it to work, I had to add a line before the last one.
    Would you know why? It’s driving me nuts. Thank you

    alert(xhr.send(httpRequestData)); <——
    xhr.send(httpRequestData);

    Reply
  12. hi again
    i modify server name and now i get this message in serial monitor:
    HTTP Response code: 200
    outputsState:⸮
    Parsing input failed!

    Reply
  13. I’m getting an error when trying to upload sketch to esp32

    HTTPClient.h: No such file or directory

    Not sure whats going on there, I’ve been following the tutorial closely. Thanks.

    Reply
  14. Excellent and very practical tutorial to learn PHP techniques and use and communications with ESP devices!

    I have connected the two types of modules and receive constantly, in ESP32 (
    the same happens to me in ESP8266).

    HTTP Response code: 200

    {“26”: “1”, “27”: “0”, “25”: “1”}
    Parsing input failed!

    And I can’t activate any output. In neither of the two programs.
    Where can I have the error?
    Where does all the comment type text appear after the code:
    HTTP Response 200?
    Because the Parsing input failed !?

    Any problem with the Arduino_Json?
    Could you adapt to the ArduinoJson de Benoit Blanchon from the Arduino library?

    I hope this helps other followers if the same thing has happened to them.
    Go ahead Rui and congratulations.

    Reply
    • Hi Rui.
      I still marvel at your tutorials but in this one I still can’t make it work for me.
      Although I reloaded all the PHP files and the Wi-Fi module files, I still can’t “advance” in the JSON part:

      JSONVar myObject = JSON.parse (outputsState);

      if (JSON.typeof (myObject) == “undefined”) {Serial.println (“Parsing input failed!”);
      return;
      }
      Serial.print (“JSON object =”); Serial.println (myObject);

      Always run “return” because the response to JSON.typeof (myObject) is null or empty.
      And I can’t keep going.
      To the other members of the forum this has not happened?

      It’s amazing that it happens to me alone!
      Will I have library problems?
      There is only one version of Arduino_JSON.

      If someone can give me a hand with this it would be spectacular!

      One more issue but it is from PWM.

      Where should I write about a question I have on the subject?

      On Facebook ?
      I am already part of the forum or in the PWM tutorial that is already on your page for led control?

      But it refers to generating a very low PWM frequency and it only works up to 1 Hz and I need 0.44 Hz.

      Thanks for your attention.
      And I will continue learning from all your new tutorials.

      Alejandro
      Buenos Aires

      Reply
  15. I must add this since it was not sent in my previous post and it is the “comment” that appears after the reply:

    HTTP Response code: 200
    >
    Rui Santos
    Complete project details at https://RandomNerdTutorials.com/control-esp32-esp8266-gpios-from-anywhere/

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files.

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.
    ->

    is always
    prior to {“26”: “1”, “27”: “0”, “25”: “1”}
    Parsing input failed!
    Thank you.

    Reply
  16. Hi, thank you for the tuto,
    I followed all what you wrote but got this message “Connection failed: No such file or directory” in the web page.
    What to do? thank you…

    Reply
  17. Great project!! I thought this was possible but didn’t know how to approach it.
    I had one problem. The string that that was retrieved by httpGETRequest started with the comments in the esp-outputs.php file, then the JSON info. I stripped out the comment portion and was able to get it working. I don’t know php (something new to learn) so I couldn’t figure out why the comment got included.

    Reply
  18. Since i don’t have ESP’s, i want to use Ethernet shield to turn on/off the arduino pins.
    Does this work with Ethernet ? If not ,
    Could you adapt to the ArduinoJson de Benoit Blanchon from the Arduino library?
    Thanks in advance !

    Reply
  19. Hello !! It’s working fine, but the message displays in the browse: Notice: Undefined variable: html_buttons in /storage/ssd5/988/11371988/public_html/esp-outputs.php on line 24
    and Undefined variable: html_board … on line 31.
    Can you help me ? Thanks

    Reply
  20. cool project. i had to mess around with schematics a bit but eventually got it figured out. I cant figure out why but im assuming the 5 minute delay is server side? Im hosting with bluehost is there somewhere in cpanel i can adjust database update schedule?

    Reply
      • well kind of, the board updates every 5 minutes. so i can press the button at anytime during the 5 minute interval, depending when the button is pushed within the interval is how long it takes to activate. i dont believe it has anything to do with the code because everything is working fine, except the 5 minute intervals.

        Reply
  21. Notice: Undefined variable: html_buttons in /home/luijay60/public_html/esp-outputs.php on line 24

    Notice: Undefined variable: html_boards in /home/luijay60/public_html/esp-
    outputs.php on line 31
    is what i get tried both scripts and i dont remember much of php last i saw it was over 2o years ago it mostly working i think Santos is a genious!

    Reply
  22. Two buttons (GPIO2, GPIO13) are now displayed.
    I have the button with:
    INSERT INTO `Outputs` (` name`, `board`,` gpio`, `state`) VALUES (” LED_RED “, 1, 13, 0);
    added to the database.
    The board page now shows:
    JSON object = “1 1”
    HTTP response code: 200
    “1 1”
    Nothing else is displayed (GPIO?)
    The corresponding GPIO is also not controlled.

    Reply
  23. Hi Rui, congratulations for an excellent website and work. I purchased your training but found this free tutorial which i’m interested in learning. I employ exaclty the same components you do (ESP32 DOIT Dev Kit and ESP8266). I verified that the output from the Http request is {“2″:”0”} but the Arduino IDE serial com window shows the following:
    {“2″:”0”}
    Parsing input failed!
    Evidently this is turning TRUE:
    if (JSON.typeof(myObject) == “undefined”)
    but I don’t know why since the typeof should be an object, or am I wrong. I am fairly new to PHP, JAVA, so please explain as if you where talking to a moron.
    Thanks

    Reply
  24. HTTP Response code: 200

    This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support.

    Parsing input failed!

    Reply
      • Hi Rui,

        I found another reason for “Parsing input failed!”. If you are using plesk panel or similar and if you set SSL, this problem happening. Also if you just installed plesk, SSL option comes as active. So you need to go to the domain settings and remove the checkbox “SSL/TLS support”.

        Hey Rui, is there a way for SSL support?

        Best Regards.

        Reply
  25. Hi Rui, nevermind my last comment. I copied the new files onto the Bluehost files and that solved the parse error message. The problem I have is that the slides buttons state do not have any effect on the LEDs (I only tried one LED on the ESP32 (COM3) and one in the ESP8266 (COM8)). If I change the state manually for LED GPIO2 for ESP32 in the database using pHpMyAdmin to “1” and then enter this in the URL: esp-outputs-action.php?action=outputs_state&board=1, I will have this result in the web page result: {“2″:”1”}, but it doesn’t turn on the LED in GPIO2 of board 1 and COM3 keeps displaying the object as {“2″:”0”}. While writing this I noticed that sometimes the LEDs on both boards come on and off randomly. That’s weird. Before I start from scratch again (even dumping the MySQL Database) do you recommend anything?. Thanks.

    Reply
    • Hello Emiliano,
      Note: it takes up to 5 seconds for your boards to update the outputs states (so, if you press the buttons very quickly, you won’t see them change in real time).
      Does your ESP8266 board is set to board=2 in the server variable?

      For example for board #2:
      http://www.your-domain-name.com/esp-outputs-action.php?action=outputs_state&board=2

      Then, in your Dashboard you should create buttons and assign them to Board 2.

      Reply
      • hi rui thanks for the tutorial, I want to ask, on my serial monitor I have an error JSON Object = {}
        Error Code = -11
        help me please

        Reply
        • I get this error too and found this forum
          https://forum.arduino.cc/index.php?topic=539146.0

          I identified it’s actually HTTP Error code 411.
          Then, I found out it’s actually because of the bad implementation of the content-length and close connection… something like that… (I’m not a pro).

          So I got through this
          tools.ietf.org/html/rfc7230#section-3.3.2

          and then, I found this
          kodlogs.com/blog/183/http-error-411-the-request-must-chunked-have-content-length

          and Finally, I found this
          stackoverflow.com/questions/2623963/webkit-refused-to-set-unsafe-header-content-length

          I fixed this error by adding the following code

          xhr.setRequestHeader(“Content-Length”, data.length);
          xhr.setRequestHeader(“Connection”, “close”);

          inside the “ESP_OUTPUTS.PHP” after Line 102

          Reply
  26. Hello Rui Santos,
    Thank you for sharing this cool project. Congratulations!..
    I need your help. I configured my database and php files like above but I didnt reached mywebpage.com/esp-outputs.php file on my web page. I get this error “Connection failed: Access denied for user ‘myweb_esp’@’localhost’ to database ‘myweb_esp_data’ ”
    And also, I checked error.log in my web page. I get this error “PHP Warning: mysqli::mysqli(): (HY000/1044): Access denied for user ‘myweb_esp’@’localhost’ to database ‘myweb_esp_data’ in /home/myweb/public_html/esp-database.php on line 78
    Do you have an idea for this error.

    Reply
    • It looks like your database user doesn’t have full permissions to access the database or you didn’t include the right credentials in your esp-database.php file. Double-check that you’ve replaced those lines with your exact credentials:
      // Your Database name
      $dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
      // Your Database user
      $username = "REPLACE_WITH_YOUR_USERNAME";
      // Your Database user password
      $password = "REPLACE_WITH_YOUR_PASSWORD";

      Reply
    • Hey, I had a similar project and I fixed this by resetting the password of my cPanel account. Maybe this isn’t the same, but maybe it is!
      Good Luck

      Reply
    • FIXED!

      Same exact issue on my website being hosted on SiteGround. The new username / password was not being recognized, and I needed to clear the website’s cache.

      If you are hosting on SiteGround, search google how to manually clear cache (https://www.siteground.com/kb/clear-site-cache/)

      If for any reason your website’s cache is still not cleared, see if you have a pre-existing user that you can use:

      siteground –> website –> site tools –> site –> mySQL –> users
      Username (will be listed under name)
      Password (press 3 dots, and you have option to change password)

      Use these for your username / password.

      Hope this helps.

      Reply
  27. Hi Rui,

    Again thank you so much for this project.

    I want to use DHT11 or DHT22 with this project. So i need set a degree, then the DHT sensor will check current degree and stop or start a GPIO port. How can i implement it to this project?

    Best Regards.

    Reply
  28. Good day,

    I would like to use the program code for other projects (e.g. smart home system).
    I have the following question:
    Which program code is used to transmit the data (e.g. {“2”: “0”, “13”: “0”}) for controlling the selected GPIOs?
    Could you please tell me.
    Many thanks in advance.

    Kind Regards

    Juergen B.

    Reply
  29. Hello Rui Santos and Sara Santos,

    good evening,
    thank you very much for your sketch on this project.

    really helpful, i modify the script to work with raspberry.

    thank you,
    Panji P

    Reply
  30. Hell Rui
    The Connection failed issue was resolved after discussion with technical team of Blue Host.in. The problem was due to corruption of data base.

    Thanks

    Reply
  31. Hello,
    I have made your project and it works perfect. Can you help me to modify it and the buttons to be monostabile? I need it when i push the button to give me output 1 second and then off until next push. So no slide button.
    Thank you

    Reply
  32. Thanks for the great tutorial! I’ve much to learn from you.
    But there is something I’m still curious about.

    Can you provide a tutorial about controlling the PWM/analog signal to adjust the brightness of LED or speed/rotation of motor dc?

    I hope you grant my request, once more Thanks a lot!

    Reply
  33. Thanks for the amazing tutorial! I followed everything exactly, and also updated the codes from the latest github release. The webpage works perfect, except in serial monitor of my esp I get the following error:

    “15:31:38.880 -> Parsing input failed!
    15:31:38.917 -> HTTP Response code: 301
    15:31:38.917 ->
    15:31:38.917 ->
    15:31:38.917 -> 301 Moved Permanently
    15:31:38.917 ->
    15:31:38.917 ->

    Moved Permanently

    15:31:38.917 ->

    The document has moved here.

    15:31:38.917 -> ”

    Do you know what this means? Let me know and thank you!

    Reply
    • Ok so update, I realise that the link its sending me to, is changing from (2:0) to (2:1) when I toggle the led switch on the other page. So somehow instead of talking to my ESP, its sending the data to a different page..
      Do you know how I can continue?

      Reply
  34. Hello everyone,
    I have a problem with Arduino_json.h in my node_mcu project.
    when i compile it, i face with a problem as follow,
    C:\Users\Majid\AppData\Local\Temp\arduino_build_48742\libraries\Arduino_JSON\cjson\cJSON.c.o: In function print_string_ptr’: C:\Users\Majid\Documents\Arduino\libraries\Arduino_JSON\src\cjson/cJSON.c:81: undefined reference to ctype_ptr’
    C:\Users\Majid\AppData\Local\Temp\arduino_build_48742\libraries\Arduino_JSON\cjson\cJSON.c.o:(.text.print_value+0x24): undefined reference to sscanf’ C:\Users\Majid\AppData\Local\Temp\arduino_build_48742\libraries\Arduino_JSON\cjson\cJSON.c.o: In function print_value’:
    C:\Users\Majid\Documents\Arduino\libraries\Arduino_JSON\src\cjson/cJSON.c:81: undefined reference to `sscanf’
    collect2.exe: error: ld returned 1 exit status
    Using library ESP8266WiFi at version 1.0 in folder: C:\Users\Majid\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi
    Using library ESP8266HTTPClient at version 1.1 in folder: C:\Users\Majid\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266HTTPClient
    Using library Arduino_JSON at version 0.1.0 in folder: C:\Users\Majid\Documents\Arduino\libraries\Arduino_JSON
    exit status 1
    Error compiling for board NodeMCU 1.0 (ESP-12E Module).

    I delete Arduino_json.h from C:\Users\Majid\Documents\Arduino\libraries\Arduino_JSON\ and then I install it again.
    But, unfortunately, I have this error in the project.
    Please guide me what happen by such error.
    Thanks

    Reply
  35. Hi everyone,
    At first, thanks for amazing and practical tutorials.
    I am going to implement this project with access point mode simultaneously. I mean that I sometimes want to control objects without any internet or modem. how can i change esp32 program for this aim?

    Reply
  36. Good Afternoon,
    I get the following message when I call up the “esp-outputs-action.php” website:
    Notice: Undefined index: action in /storage/ssd2/816/14960816/public_html/esp-outputs-action.php on line 27
    Invalid HTTP request.

    Browser: Firefox 81.0 (64 Bit)

    With the ESP32 I get the following output:
    HTTP response code: 200
    {“2”: “0”, “12”: “0”, “13”: “0”, “14”: “0”}
    JSON object = {“2”: “0”, “12”: “0”, “13”: “0”, “14”: “0”}
    GPIO: “2” – SET to: “0”
    GPIO: “12” – SET to: “0”
    GPIO: “13” – SET to: “0”
    GPIO: “14” – SET to: “0”

    Unfortunately I don’t know where the problem is.

    Kind Regards

    Juergen B.

    Reply
    • Hello,
      Issued by:
      http: //my-webaddress/esp-outputs-action.php? action = outputs_state & board = 1
      {
      “2”: “0”, “12”: “0”, “13”: “0”, “14”: “0”
      }

      It all looks good.
      But why do I get: “Invalid HTTP request”?

      Kind Regards
      Juergen B.

      Reply
      • Hello,
        Wrong mistake
        With: “http: //my-webaddress/esp-outputs.php” I get the right website to control the GPIO’s.
        Create New Output doesn’t work with Firefox but only with Google Chrome.
        Is there a solution for Firefox?

        Kind Regards
        Juergen B.

        Reply
        • I found the fix to this, although I’m not sure why it works… I had the same problem regarding the Create Outputs button not working in the firefox browser (chrome worked).

          Solution: In the file esp-outputs.php, inside its createOutput() function, add alert(“your message here”); to the very last line of the function. E.g. after the line xhr.send(httpRequestData); and it should work.

          Reply
  37. Hi Rui,
    thank you so much for this toturial.
    I have a problem with parsing in nodemcu. It executes terms of “Parsing input failed!”
    when i visit address …/esp-outputs-action.php?action=outputs_state&board=1″ it returns correct terms {“4″:”0″,”5″:”1”} but myObject in [JSONVar myObject = JSON.parse(input);] dosn’t return correct result. how can I improve that?
    Thanks alot.

    Reply
  38. Hi again,
    excuse me, I understand that my problem is not related to parsing process but it is related to payload in payload = http.getString(); that returns nonsense terms.
    what is my problem in your opinion?

    Reply
  39. Hellow, awsome tutorial, but i have a problem, when i run my esp32 it gives me this message
    Parsing input failed!
    sendRequest code=200
    HTTP Response code: 200
    i dont undestand why, i replaced evrything as needed

    Reply
  40. Hello and thank you for the wonderful tutorial.
    Is it possible tp append files under this tutorial to your weather station tutorial to establish a two way communication with the esp board.

    Reply
  41. This is a great project, thanks for posting it! Mine seems to be working correctly except it only turns the LED’s on/off every two hours. Is anyone else having that issue?

    Reply
  42. Hi!
    When I try to access http:// mydomain.net/esp-outputs.php all I get is : Connection failed: No such file or directory. I copied the php to all the files exactly.

    Reply
  43. Hi Rui Santos and others contributing. This is super tutorial learning esp8266 and controlling it over internet. Thank you so much. I already managed almost complete my current project.

    One thing I’m having a hard time to figure out. What would be the best way to toggle relays or leds over internet for only certain time? My plan is to toggle relay for 2 seconds. I’m trying different options and don’t know if I should do it in Arduino side or should I do the timer on website. I can do it in simpler code in Arduino easily, but with this complicate code I don’t have the skills to tweak it right. I’m just learning to code, so all tutorials about this are super welcome.

    Reply
  44. I attempted this project and everything seems to work except that when I click the buttons on the page I created the LED’s don’t update right away. They update every two hours (exactly two hours), regardless of when I push the buttons. So, for example, if I push a button right after the LED’s have updated it will take two hours to turn on or off. I can’t see where in the Arduino ESP32/ESP8266 code or the web server code has this two hour time. Is there something I am missing or is it maybe the settings in my hosting account. I have already asked this question and no one responded so I am posting again with more details in the hopes someone can help me with the added detail. Thanks!

    Reply
    • Hey Colin did you manage to resolve the issue? I have the same problem but that 2 hours time to me is 5 min (fortunately, even though is still too much)

      Cheers 🙂

      Reply
      • Hi Marco, I never did. I think I am just going to delete everything and start from scratch. I am not sure when I will have time to do it but I will let you know if/when I figure it out.

        Reply
      • Hi Marco, I finally figured it out. I was on the most basic hosting plan with my hosting service. I upgraded to the next plan after the basic option and it works great now. I assume it has something to do with how often the basic plan lets you update your web page information, which is probably based on the amount of data you can transfer. Anyway I don’t know if this will help fix your issue but it worked for me.

        Reply
  45. great

    I joined blue host and implemented the example successfully

    Glad I did. Now I have a site for the first time

    Thanks Sara and Rui for the added value

    Reply
  46. Hi Sara and Rui, thank you for the tutorial! I think everything is working fine but the fact that regardless the value I set for “update interval time” the output takes 5 min plus that time to update. I am using Bluehost and the Esp32.

    Any clue?

    Thank you.

    Reply
  47. Hello Rui,
    thank you for this nice example.
    after several hours i think now ist everything running.
    ESP8266 sketch and the php-files on my own domain.
    Now i have still a problem:
    When i toggle the gpio’s in my chrome browser i can switch each gpio once to “on ” and once to “off”. After switching all Gpio’s once on/off they dont react anymore. If i change the chrome browser into the desktop-mode i can make the the same procedure again with the same result. Switching back to mobile-mode in the browser i can switch immediatly again.
    What is the reason ?? The php-files and the esp-sketch and the databank-connectivity are always the same.
    Please ,can you help me !!

    Thanks Karl

    Reply
  48. Project work only for 2 times then everytime i have to restart my browser to get Gpio switch working again…

    i have mentioned the website whete i used your project code
    🙂

    Any tipe how do i fix it

    Reply
  49. Hello Rui, Hello Sara.

    I am writing this comment again since my first one disappeared.
    I am using impulse bistabile relay instead of LEDs. And using this script it causes my relay to latch every few seconds. I believe the cause is that ESP32 is checking the database every few seconds and switching the GPIOS correspondigly.
    I would like to know is it possible to have the database (or the server) to send the data to ESP every time the data inside da DB changes? This way I would have my relay respond only to changes, and not continuously. I am still a newbie at this IoT and PHP.

    Maybe you could put this in one of your books so it would be available for purchase?

    BR,
    Ivan

    Reply
  50. Hallo Rui and Sara,

    Your tutorials are some of the most comprehensive i have seen on the internet.
    I can see you has put a lot of effort in this, Thank you so much.

    Kind regards,
    Kobus from South Africa.

    Reply
  51. First of all i would like to thank you for giving such a beautiful concept.

    I am facing the error mentioned below with this code. Can you please help me to resolve the issue.

    Parsing input failed!
    HTTP Response code: 302

    302 Found

    Found

    The document has moved <a href=”https://smartlyf.net/esp-outputs-action.php?action=outputs_stat…

    Reply
  52. First of all i would like to thank you for this amazing concept and tutorial.

    Actually i don’t know about PHP. So i followed all the steps and instructions mentioned in the site to make it work.
    But still i am facing an error(mentioned below).
    I need your help to resolve this help. Kindly guide me.

    Error :
    Parsing input failed.
    Http response post code 302.

    Reply
  53. Hi,
    First of all i would like to thank for this amazing concept.

    I followed all the steps and instructions mentioned in the site. Still i am getting an error in serial monitor saying ” Parsing input failed”.

    Can you please help me to resolve the issue.

    Thanks.

    Reply
  54. Hello Rui and Sara,

    I would like to extend my great appreciation and gratefulness for your work on this project here. I also gladly like to share with everyone how I recently managed to make this project a password-protected one. At least no one can access it as easily as before.
    I successfully incorporate today the entire project’s contents including the modification I made to it into my own humble personal website “https://sc-tronix.tech”. If interested to see it’s working, one can find it under the right column topic “esp8266 basic home IoT”.

    Thankfully yours,
    Demy

    Reply
  55. Hi! I did everything right. My code compile successfully and i can access the webpage successfully too. Also, in the serial monitor i’m having a response code of 200. The problem i’m facing is that The GPIO pins i set on the webpage never work (turn ON or OFF) when i toggle the button. I don’t know what is happening or what i did wrong ? Help please

    Reply
  56. Hi ! Super work as always ! I’m wondering why you use php in this one, and you work with java when the server is set directly in the esp32 ? Is there a good reason ? I would host the sever already existing in my esp32 (using java) to Bluehost, but I’m scared I’ll have to rewrite most of it :/

    Huge thank you !
    Xavier

    Reply
  57. I have tried matching with storing sensor readings into a database and using line chart to display sensor readings. But my esp can send once time to database and can’t control GPIOs

    Reply
  58. Dear Rui, Sarah,

    Thank you for the customary sound tutorial – a base to build from.

    Is there a mechanism for the Server to poll the Client “on demand” for a change of state of the switch rather than the continuous 5 second (or other) interval checking by the client? The overhead of this is significant and very inefficient for a switch that may be turned on/off once a day or at irregular intervals.
    Just theory/principal into pragmatism.

    Kind Regards

    Reply
  59. Great project, I am very interested in it, congratulations for the realization.
    I have implemented the circuit and the sketch and everything works fine, I just wanted help on how to get feedback if the esp32 is connected to the network.
    Let me explain better: if the esp32 is not connected to the internet when I access the web page (http://example.com/esp-outputs.php) for the GPIO control I would like that it is impossible to activate the GPIO switching. Is it possible to implement a control in the sketch and in the php script?

    Thanks in advance for your help and sorry for my incorrect English.
    Massimo

    Reply
  60. Hi guys,
    I really am interested in this project. I have a question about posting this project to my domain. Can I still have my main Index.html page displayed with its various links after creating this project? Can I access the project through a direct link as you describe. Such as myexample.com shows my published web stuff and your myexample.com/esp-outputs doesn’t interfere with my main site. I’t’s been a while since I’ve messed with domains, so I hope this isn’t a dumb question.Hope that makes sense and thanks for your help.
    Terry

    Reply
  61. I set GPIO5 on esp8266 nodemcu, but when I on any device it got off after a while itself, what the problem may be?

    Reply
  62. What could be incorrect? After the setups the websites shows the initial screen as in your video. The initial board can be deleted but no other boards can be netered. The attempt to create another input fails; no entry into database tables occurs.
    Any help would be appreciated!

    Reply
  63. thanks for this wonderful project.i have made this and it works fine with esp32 but i only get ……… connecting status with esp8266 can anyone help with this problem. the esp8266 bard runs perfect with other code from the examples and only gives this problem in this esp2866 code. while uploading theres no problem uploads smoothly and restarts also then in serial mmonotor “……………..” it goes like this forever

    Reply
    • instead of while i used if and it worked perfectly
      “if ((WiFiMulti.run() == WL_CONNECTED))”
      while ((WiFiMulti.run() == WL_CONNECTED))
      thanks

      Reply
  64. Hi I have a couple of questions.
    1)Can I run this project with an esp8266 only (one board)?
    2)Can you please provide links to the necessary libraries. I have tried many times but am unable to find ESP8266HTTPClient.h
    When I run the ESP8266 , (ESP8266_HTTP_GET_Request_JSON.ino) I never seem to get past the setup – just constant …….. yet my credentials are fine
    Any help greatly appreciated

    WiFi.mode(WIFI_STA);
    WiFiMulti.addAP(ssid, password);
    while((WiFiMulti.run() == WL_CONNECTED)) {
    delay(500);
    Serial.print(“.”);
    }
    Serial.println(“”);
    Serial.println(“Connected to WiFi”);
    }

    Reply
  65. Just a follow up on my previous email – I replaced the wifi connect code with the one used in the Arduino Authorisation sketch and can now connect – no problem. Unfortunately, I’m now getting the error 302 problem. I am able to ping the esp-outputs-action.php file and get the expected response using a browser or POSTMAN client – so I think that end is working. ould it be in the JSON library?
    This is a great project – I’d love to get it working

    Reply
  66. Thank you Rui Santos,
    You are the everlasting hero of ESP32. You are the best. This tutorial is so good and useful.

    I just want to say that in my case I was connecting to my website with https.
    So my server url was:
    const char* serverName = “https://example.com/esp-outputs-action.php?action=outputs_state&board=2”;

    If I uploaded your code without any change I got an error from the page:

    Parsing Input failed!
    HTTP Response code: 400
    400 the plain HTTP request was sent to HTTPS port

    I corrected this making the modification below in the code:
    http.begin(client, serverName); //WRONG
    http.begin(serverName); //IT WORKS

    Reply
    • Hello Pietro,

      I tried your program change “http.begin(serverName); //IT WORKS” but it didnt works. I get this message:

      Documents\Arduino\ESP8266_Relais\ESP8266_Relais.ino: In function ‘String httpGETRequest(const char*)’:
      ESP8266_Relais:92:14: error: call to ‘HTTPClient::begin’ declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
      92 | http.begin(serverName);
      | ~~~~~~~~~~^~~~~~~~~~~~
      exit status 1
      call to ‘HTTPClient::begin’ declared with attribute error: obsolete API, use ::begin(WiFiClient, url)

      Can you help me please?
      Greetings, Jens

      Reply
        • Hi Sara,

          thank you very much for your answer. I change all programs.

          I use the versions from 02.07.2021. But the result ist the same:

          09:05:49.994 -> Parsing input failed!
          09:05:50.040 -> HTTP Response code: 400
          09:05:50.040 ->
          09:05:50.040 -> 400 The plain HTTP request was sent to HTTPS port
          09:05:50.040 ->
          09:05:50.040 ->

          400 Bad Request

          09:05:50.040 -> The plain HTTP request was sent to HTTPS port
          09:05:50.040 ->

          nginx
          09:05:50.040 ->
          09:05:50.040 ->

          Greetings Jens

          Reply
    • Hi Pietro, this fixed my issue thank you! Only issue is now there is no error, but the GPIO state does not update. Did you have the same issue after? Thank you!

      Reply
  67. Thank you Rui Santos,

    This is amazing work. How would you send a int value in the json message as well.

    for example; if I wanted to turn on the cooling mode and set a target temperture remotely.

    what is the easiest way to send the int valve to the mySQL and use the ESP32 HTTP get request to set it on the ESP32. thanks in advance

    Reply
  68. Dear Rui and Sara,

    Thank you both for the excellent project, I posted a question some weeks ago about creating this project for each customer separately as I’m a sensor products maker, but you didn’t approve it yet. Anyways, I have made this project successfully on my own hosting, please allow me to introduce the dashboard to try out with others interested on it. And it would be useful to add some code to get live feedback from switches operated.
    try on iotserver.fixmation.com

    Reply
  69. Hi Rui,

    Your article is so useful and I really appreciate that so much :).

    One thing I would like to ask you if you could help me is do you know which way I can send email notification whenever user create, delete, switch on and off.

    Regard

    Reply
  70. Hi Sara and Rui, i guess if i can read the input status instead the outputs (Analog and digital) and then, show them just like this example? could you explain that? thanks for your support.

    Reply
  71. Hello!
    Has anyone figure out how to solve this problem in serial monitor?
    I’m trying to host my website using XAMPP on local machine.

    error code: -1
    {}
    json object = {}

    Thank you, Jake

    Reply
  72. for use GPIO 0 then must change file esp-outputs-action.php
    echo json_encode($rows);
    to
    echo json_encode($rows, JSON_FORCE_OBJECT);

    Reply
  73. Hi,

    Can you explain me how to make this example work with pttps?
    (sp32)
    const char* serverName = “https://example.com/ …

    Thank you,

    Manuel

    Reply
  74. Please post tutorial on esp32 as server sent events receiver or client which receives events from custom own web server like bluehost etc

    Reply
  75. Rui, parabéns pelo projeto, também parabéns ao autor…
    Encontrei um problema que ainda não consegui resolver… o script exclui e muda o valor do GPIO, porem, ao preencher o formulário, o registro não é inserido. Não sei pq, mas tentarei localizar. Caso tenha alguma ideia e puder me ajudar….agradeço !

    Abs, Bruno.

    Reply
  76. Rui, congratulations on the project, congratulations also to the author…
    I found a problem that I still couldn’t solve… the script deletes and changes the GPIO value, however, when entering the data in the form, the record is not added to the database. I don’t know why, but I’ll try to find it. If you have any ideas and can help me….thank you!

    Regards, Bruno.

    Reply
  77. Hi,
    I add to new column at Outpust table. I want to this column’s value read at Arduino.
    How can I do it. What changes need to be made in the codes? Thanks.

    Reply
  78. love it works perfectly. However is there any way to remove the quotation marks “” from the mysql query. Instead of “8” just 8
    it appeasers to be coming through on the esp32

    Reply
  79. You are calling server(PHP) in loop.
    Don’t you think it’s bad practice ?
    Also, Can you create Rest resource on ESP32 /ESP8266, so that PHP can consume that api whenever there is any change from Web.
    i.e
    server.on(‘/on’,turnOnLed);
    server.on(‘/off’,turnOffLed);

    Reply
  80. Hello – thanks for your website!

    I have carefully made this project and all works fine but only IF i clear the cache in Bluehost after every button press. I have turned off the caching option in Bluehost under WordPress “MySites” and “Performance”. This has not helped.

    Any suggestion for turning off the caching option in Bluehost 100% or clearing the cache at the appropriate place in one of the PHP files?

    Many thanks again, – james

    Reply
  81. I am having parsing error

    /aes.jsfunction toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e=””,f=0;fd[f]?”0″:””)+d[f].toString(16);return e.toLowerCase()}var a=toNumbers(“f655ba9d09a112d4968c63579db590b4”),b=toNumbers(“98344c2eee86c3994890592585b49f80”),c=toNumbers(“d5369e153c9e71d670ef3f2613ef28b1″);document.cookie=”__test=”+toHex(slowAES.decrypt(c,2,a,b))+”; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/”; location.href=”http://figs.com.pk/esp-outputs-action.php?action=outputs_state&board=1&i=1″;This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support
    Parsing input failed!
    HTTP Response code: 200

    Reply
  82. Good afternoon Rui, this project is amazing.
    exactly what i.

    Just a question, (sorry for my ignorance)
    tell me how to place the buttons side by side?

    Hugs and success.

    Reply
  83. Hi Santos, can you give some useful tips if I want to use this tutorial by using local host? i got error at ESP32:
    Connected to WiFi network with IP Address: 192.168.*.
    Error code: -1
    Output State: {}
    JSON object = {}
    And for the HTTP, my error is:
    Notice: Undefined index: action in C:\wamp64\www\dashboard\esp-outputs-action.php on line 27
    Call Stack
    # Time Memory Function | Location
    1 0.0008 361784 {main}( ) | …\esp-outputs-action.php:0
    Invalid HTTP request.

    Your help will be meaningful for me.
    Thank you.

    Reply
    • Hi.
      Try replacing the following line:
      http.begin(client, serverName);
      with
      http.begin(serverName);
      Let me know if this solves the issue.
      Regards,
      Sara

      Reply
      • hi Sara, I already try your suggestion and unfortunately the error code is still the same:
        10:19:07.438 -> JSON object = {}
        10:19:12.442 -> Error code: -1
        I am very grateful if you can suggest other solution. I am a student and quite new to JSON and HTTP.

        Sincerely,
        Aesya

        Reply
        • Hi Rui and Sara Santos, I’m so grateful for this detailed tuitorial. Mine worked and i can now be able to control the GPIO pins of esp8266 from my website. I use 000webhost.com and its working perfectly well. I was unable to see my web server before but after renaming the esp-outputs.php folder to index.php, its now working well.
          I was also getting error code-1 but that was because of my internet connection to my router.
          I was also getting parsing failed but after adding another GPIO number I was able to fix it. It working now. One question, how can i fix the response time, it takes about 5 sec and I’m working on a project that requires time precision. Thanks.

          Reply
  84. This tutorial being detailed it bypasses completely a far more elegant solution,in one line:
    1. create a google sheet with the buttons you want
    2. Deploy that
    3. Use in your code
    4. No webserver needed no complicated connections, indefinite logging, no problem after surge
    5. Infinite menus, submenus, layouts, all you need to know is there, and google goes the rest.
    6. And last but not least, no conflicting ports, no speed loss, no limit to users

    Reply
  85. Rui and Sara —

    Let me join the chorus of thanks and appreciation for this tutorial. I have it operating, but for one glitch — the switch for the Built-In LED works in reverse. Turning the switch On, turns the LED Off, and turning the switch Off, turns the LED On. The New Controls that I create work as expected.

    I tried deleting the Built-In LED control and creating a new one. The problem remained with the created control.

    How can I solve this problem?

    Thank you.

    Reply
    • Hi.
      I’m sorry, but I didn’t understand your question.
      If you’re using an ESP8266 board, the built-in LED works with inverted logic.
      You need to send a HIGH signal to turn it off and a LOW signal to turn it on.
      Regards,
      Sara

      Reply
      • Hi Sara,
        Good afternoon!
        This project would be perfect if it had a physical button on the arduino and updated on the website as the button was pressed. Could you help me with this issue?

        Reply
  86. Hello,

    I’ve followed the same steps but when I try to go to http://example.com/esp-outputs.php I get this error.

    [03-Feb-2023 06:02:01 America/Boise] PHP Fatal error: Uncaught mysqli_sql_exception: Access denied for user ‘‘@’‘ (using password: YES) in /home3//public_html/esp-database.php:78
    Stack trace:
    #0 /home3/
    /public_html/esp-database.php(78): mysqli->__construct(‘***’, ‘***’, ‘***’, ‘***’)
    #1 /home3/***/public_html/esp-outputs.php(14): getAllOutputs()
    #2 {main}
    thrown in /home3/***/public_html/esp-database.php on line 78

    I am also using a shared server so I wonder if that’s the issue. I did change the server name from localhost to my own server name but that doesn’t seem to work.

    Would purchasing a VPS plan solve the issue?

    Reply
  87. Your credentials are wrong…crosscheck your databasename,username and password…you need to change it in the original code
    also amke sure that you created the correct databse and table

    Reply
  88. How I can create an mobile application for controlling the ESP32 instead of having the web pages, i wanted to have my mobile app that talks to ESP32 or its server.

    Reply
  89. Great tutorial. I have a question :
    If any situation changes in the hardware e.g. the hed change the state due a timer, the esp informs the mysql. How is the page updated? Is ok to use a javascript setinterval function ?

    Reply
  90. Hi guys this is a great project I have no knowledge of php , jason etc but followed this tutorial and have it working in no time at all. What would be nice is if you could put press buttons as well in this project for manual control when the wifi is down plus a button that pulses for the garage doors

    Reply
  91. I did everything as it was in the tutorial and even updated all the files but still im getting the error as follows:
    parsing input failed
    error code 200
    i think there might be some problem with my domain name but im not sure about it

    Reply
  92. Good afternoon!
    This project would be perfect if it had a physical button on the arduino and updated on the website as the button was pressed. Could anyone help me with this issue?

    Raphael Stephen
    [email protected]

    Reply
  93. Good afternoon!
    This project would be perfect if it had a physical button on the arduino and updated on the website as the button was pressed. Could anyone help me with this issue?

    Reply
  94. I followed your instructions, but I am not getting the same results as explained in this tutorial.
    My first attempt did exactly as shown with the exception that once I deleted the example
    “Built-in LED”, I could not create a new Output Control.
    I have followed the instructions once again by deleting the files on the server, then uploaded new copies of the files, and created a new SQL database.
    Now the “Built-in LED” control does not display, and I still can’t create a new control.

    What am I missing?
    Joel

    Reply
  95. Hi I did it perfectly,
    but i cant read the serial monitor. It shows a random caracter, i cant see is this unit has been connected to the internet.

    i’m using DOIT ESP32 DEVKIT V1.

    Reply
  96. Hi everyone
    I have an error when i run esp-outputs.php file in google browser.when i run it, i see failed to open stream:No such file or directory in home/Myhostname/public_html/esp-outputs.php
    What is that error?
    I performed this project exactly from this website

    Reply
    • you have to create index.html file and link the esp-outputs.php file in index.html file using hyperlinks , i also faced this error i fixed it this way. Try this way.

      Reply
  97. please help me i’m beginer
    {“2″:”0″,”4″:”0”} this outputs-action but in the serial only like this..
    JSON OBJECT = {}
    ERROR CODE =-1

    Reply
  98. Hello,
    I have a question:
    Does ESP8266 include a Watchdog? How can be implemented?
    I can add an additional external circuit for a Watchdog function, but first I’d like to activate the internal, simple watchdog if possible.
    I created a project, a small Mini ESP8266 board with 2 relays, connected to the heating system in my house, which can adjust the temperature in the house “from Anywhere in the World”. It works very well, but after several days of continuous operation it stopped communication. The operation resumed after a reset. I think the best fix is a Watchdog.

    Reply
  99. Hello,
    I have a question:
    Does ESP8266 include a Watchdog? How can be implemented?
    I can add an additional external circuit for a Watchdog function, but first I’d like to activate the internal, simple watchdog if possible.
    I created a project, a small Mini ESP8266 board with 2 relays, connected to the heating system in my house, which can adjust the temperature in the house “from Anywhere in the World”. It works very well, but after several days of continuous operation it stopped communication. The operation resumed after a reset. I think the best fix is a Watchdog.

    Reply
  100. Your project is very good. I only made some graphical changes to the php files but it basically stayed the same and works great. I have one question to submit. I use your design with an ESP32 board to drive three relays to turn on and off two light fixturesand a water heater.
    All three consumers are also activated by a wall switch.
    Of this switch, which is obviously not connected to the ESP32 board, I would like to know the status so that I can connect it to the software switches. In your opinion, is it possible to do this?

    Translated with DeepL.com (free version)

    Reply
    • Hello Luigi,
      the automated translation is not very clear. Maybe I can understand the Italian version. (Are you Italian?)
      I think you want to transmit over Internet the status of the three switches. The switches must be connected to inputs in ESP32 board. Is this your question?
      Yes, it is possible, but it is not easy. An interface (adaptation) must be done from switch (AC 230V) to ESP32 (DC 3.3V). Safety and insulation against high voltage must be considered for humans and for ESP32 board. Optocouplers are the safest way for this interface.
      I can help with a detailed schematic if you confirm this is what you need.

      Reply
      • Thank you Cristian, yes I am Italian and I apologize for the delay in my reply but I had some problems.
        Not really. I made Rui’s project, making only a few graphic changes and using a relay instead of the led. The project works fine and without problems if I control the GPIO dedicated to the relay remotely. What I cannot do are the following two things :
        1) turn on the relay with a real button mounted on a GPIO used as an INPUT PULLUP.
        2) update the on/off status on the remote button.
        The problem is purely SW not electrical!
        Basically what I am trying to do is to modify the SW so that it can handle not only output GPIOs but also input GPIOs.

        Ciao and thanks

        Reply
  101. Hello Luigi,
    1) Reading a digital input (pin) is the easiest thing with Arduino IDE. But you should check what pin of ESP32 you use as input:
    https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
    2) For reverse communication ESP32 –> web server, you can use another good tutorial
    https://randomnerdtutorials.com/esp32-esp8266-mysql-database-php/ .
    In my last project I added some code from both tutorials. The ESP8266 board sends data to the web server and receives back another data. One php page on web server receives data from ESP, writes in the database and sends back orders to ESP.
    I am not very good in software and I can not create a code for your application. It was quite difficult to write the code for my own application.

    Reply
  102. Hi Rui and Sara,

    Would long polling be suitable for this project?
    Just wondered if you had any examples using this technique.
    BTW I have followed a number of your projects. Thanks for making them clear and concise!

    Best Regards

    -Robert

    Reply
  103. Hello. Thank you for this great and wonderful project. I was always looking for such a project. My problem is when the project is compiled, it gives me this message.
    src\main.cpp: In function ‘void loop()’:
    src\main.cpp:41:22: error: ‘httpGETRequest’ was not declared in this scope
    41 | outputsState = httpGETRequest(serverName);
    | ^~~~~~~~~~~~~~
    *** [.pio\build\nodemcuv2\src\main.cpp.o] Error 1

    Please help me with the project, I really need it

    Reply
  104. Hello. I solved the problem myself. The problem was that this function was not defined in advance, which we must introduce before the setup() function, as below:
    String httpGETRequest(const char* serverName);

    Reply
  105. Hello Rui and everyone,

    Very nice project, I am using it to automate my irrigation system.

    I have looked thru many of the comments but I can’t figure out how to invert the output of the control, ie, when the button is “ON” the output is LOW. My wifi relay board (ESP-01S) turns on the relay with a LOW, not a HIGH.

    I could probably figure it out but my brain is fried.

    Thanks to anyone who could help me.

    Cheers

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.