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.

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 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
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:
- SQL query to create your table: Outputs_and_Boards_Table.sql
- Insert and access database: esp-database.php
- Handle HTTP requests: esp-outputs-action.php
- CSS file to style your web page: esp-style.css
- Display your control buttons: esp-outputs.php
- Arduino Sketch for ESP32: ESP32_HTTP_GET_Request_JSON.ino
- Arduino Sketch for ESP8266: ESP8266_HTTP_GET_Request_JSON.ino
- Download all projects 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 control your ESP32 or ESP8266 GPIOs from anywhere in the world.
Here’s a high level overview on how the projects works:
- You have a web page running a PHP script with some toggle buttons that allow you to control the outputs on and off;
- When you press the buttons, it updates the output state and saves it in your database;
- You can add more buttons or delete them from your dashboard;
- 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;
- 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 to 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:

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

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

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.

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”.

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

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);
Paste it in the SQL query field (highlighted with a red rectangle) and press the “Go” button to create your table:

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:

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:
- Insert and access database: esp-database.php
- Handle HTTP requests: esp-outputs-action.php
- CSS file to style your web page: esp-style.css
- Display your control buttons: esp-outputs.php
If you’re using a hosting provider with cPanel, you can search for “File Manager”:

Then, select the public_html option and press the “+ File” button to create a new 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

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;
}
?>
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();
}
?>
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;
}
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>
If you try to access your domain name in the following URL path, you’ll see the following:
http://example.com/esp-outputs.php

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. Preparing Your ESP32 and 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.

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:
- ESP32 board (read Best ESP32 dev boards)
- ESP8266 board (read Best ESP8266 dev boards)
- 5x LEDs
- 5x 220 Ohm resistors
- Jumper wires
- Breadboard
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

Recommended reading: which ESP32 GPIOs should you use.
LEDs wiring to ESP8266 – Board #2

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:

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 <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 = "http://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) {
WiFiClient client;
HTTPClient http;
// Your IP address with path or Domain name with URL path
http.begin(client, serverName);
// Send HTTP POST request
int httpResponseCode = http.GET();
String payload = "{}";
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
payload = http.getString();
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
return payload;
}
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 = "http://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:

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 <WiFiClient.h>
#include <Arduino_JSON.h>
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti WiFiMulti;
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 = "http://example.com/esp-outputs-action.php?action=outputs_state&board=2";
// Update interval time set to 5 seconds
const long interval = 5000;
unsigned long previousMillis = 0;
String outputsState;
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to WiFi");
}
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval) {
// Check WiFi connection status
if ((WiFiMulti.run() == 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) {
WiFiClient client;
HTTPClient http;
// Your IP address with path or Domain name with URL path
http.begin(client, serverName);
// Send HTTP POST request
int httpResponseCode = http.GET();
String payload = "{}";
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
payload = http.getString();
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
return payload;
}
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).
Demonstration
After completing all the steps, power both your ESP boards.

If you open your domain name in this URL path:
http://example.com/esp-outputs.php
You should see the the default button in your Dashboard:

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 another button for Board 1 to control GPIO 32. Then, add two buttons for Board 2 (GPIO 2 and GPIO 4).

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.

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:
- [Course] Learn ESP32 with Arduino IDE
- DIY Cloud Weather Station with ESP32/ESP8266 (MySQL Database and PHP)
- ESP32/ESP8266 Send Email Notification using PHP Script
- Visualize Your Sensor Readings from Anywhere in the World (ESP32/ESP8266 + MySQL + PHP) using Charts
I hope you liked this project. If you have any questions, post a comment below and we’ll try to get back to you.
If you like ESP32, you might consider enrolling in our course “Learn ESP32 with Arduino IDE“. You can also access our free ESP32 resources here.
Thank you for reading.
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.
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).
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.
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");
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?
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.
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?
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).
Dear Rui,
Thank you so much for “Control ESP32 and ESP8266 GPIOs from Anywhere in the World”. This is exactly what i want. Thank you so so much.
Best Regards.
Thanks for reading!
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.”
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?
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).
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.
excellent tutorial… Has anyone successfully got this working using 000webhost
Yes I was using 000wehost and its working.
Hello Ray! Yes, it should work with that host.
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?
It will always remain on (it won’t blink/change the state).
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?
That’s just a sample domain name, you must replace “example” with your own actual domain name that you register with your domain provider (or hosting account).
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.
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?
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?
Please update your files or download them again here: https://github.com/RuiSantosdotme/control-esp32-esp8266-gpios-from-anywhere/archive/master.zip
I had to delete one copyright notice and it should be working now.
Thanks for letting me know!
Regards,
Rui
Thanks. Now everything is working fine !!!
Regards
Klaus-Juergen
Dear Rui,
please take into account that all this works with the extra cheap ESP8266-01module if you only want to use one or two outputs.
Extremely nice !
Is there any chance to realize a sort of back chanel? I.e. a feedback if the garage door is really closed or open?
Regards
Klaus-Juerge Eich
Take a look at this project:
https://randomnerdtutorials.com/cloud-weather-station-esp32-esp8266/
I’m glad it worked!
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 the same error(mentioned below).
Can your help me to resolve this issue. Kindly guide me. I am trying to make it work since last week.
Error :
Parsing input failed.
Http response post code 302.
I’m on the same boat here as Joy Kumar Sen.
I went back into my website made sure that all the code was updated and re uploaded the code to my esp8266M0D.
However I am getting this error when I look at the serial connection
Parsing input failed!
HTTP Response code: 200
Please advise
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.
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.
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);
Thanks. Works for me too. Why I do not know…
hi again
i modify server name and now i get this message in serial monitor:
HTTP Response code: 200
outputsState:⸮
Parsing input failed!
I had to remove one copyright notice. Please update your files or download them again here: https://github.com/RuiSantosdotme/control-esp32-esp8266-gpios-from-anywhere/archive/master.zip
Thanks for letting me know and it should be fixed now!
Regards,
Rui
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.
Hello Jon,
Are you using the latest version of the ESP32 board installed in your Arduino IDE?
Regards,
Rui
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.
Is it solved now? Please update your files or download them again here: https://github.com/RuiSantosdotme/control-esp32-esp8266-gpios-from-anywhere/archive/master.zip
Thanks for letting me know and it should be fixed now!
Regards,
Rui
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
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.
Is it solved now? Please update your files or download them again here: https://github.com/RuiSantosdotme/control-esp32-esp8266-gpios-from-anywhere/archive/master.zip
Thanks for letting me know and it should be fixed now!
Regards,
Rui
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…
It looks like you’ve moved the files to the wrong folder in your server…
Did you also add your database details?
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.
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 !
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
Can you please modify those lines to the following?
$html_buttons = null;
$html_boards = null;
Does adding = null; remove that error?
Thanks!
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?
Hello Tim, it should only have a 5 second delay between each outputs state request update.. Are you experiencing 5 minutes delay?
Thanks,
Rui
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.
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!
Can you please modify those lines to the following?
$html_buttons = null;
$html_boards = null;
Does adding = null; remove that error?
Thanks!
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.
Hello Juergen,
Which browser are you using? Can you try using Google Chrome (in order to create/delete buttons)?
What do you see when your open your URL:
http://www.your-domain-name.com/esp-outputs-action.php?action=outputs_state&board=1
Does the server name variable in your Arduino sketch is the same as the preceding working URL?
My browser: Firefox 72.0.2 (64-bit).
With Google Chrome I can create / delete buttons.
Edition of:
http://www.your-domain-name.com/esp-outputs-action.php?action=outputs_state&board=1 -> “0 0 1” (with three buttons).
The server name in my Arduino Sketch is OK.
But no GPIO is controlled.
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
Did you modify the URL in the code that you uploaded your board?
Is your URL set as follows:
http://www.your-domain-name.com/esp-outputs-action.php?action=outputs_state&board=1
?
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!
Hello Karloz, what do you see when you access your URL?
http://www.your-domain-name.com/esp-outputs-action.php?action=outputs_state&board=1
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.
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.
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.
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
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
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.
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";
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
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.
Hi.
I think you want to set a threshold and then, make something happen when the temperature goes above or below a certain threshold.
You can add a input field to your web server and then compare the current readings with that input field to make something happen.
Here’s a project that shows how to add an input field to your project: https://randomnerdtutorials.com/esp32-esp8266-input-data-html-form/
Project that uses DHT: https://randomnerdtutorials.com/esp32-dht11-dht22-temperature-humidity-web-server-arduino-ide/
Project that publishes sensor readings to a database: https://randomnerdtutorials.com/esp32-esp8266-mysql-database-php/
Regards,
Sara
Hi Sara,
Thank you so much. Okay, i will check them and inform you.
Best Regards.
Thank you Rui for the project! It work like a charm. 🙂
Great!
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.
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
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
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
Hi.
You can follow this tutorial: https://randomnerdtutorials.com/esp32-esp8266-web-server-timer-pulse/
Regards,
Sara
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!
controlled by local web and integrated with MySQL
Yes, we have that project in our to-do list! Thanks for letting me know your interest. We already have many projects lined up, so we don’t know when we will post it.
Thanks again!
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!
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?
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
Change version of json, install 5.
Thanks Mudassar for the reply.
But as i mentioned, I used Arduino_JSON at version 0.1.0 according of above files.
Do you mean i should change Arduino_JSON at version 0.1.0 to ArduinoJson version 5 or not?
You have not installed arduinoJson, install any version.
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?
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.
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.
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.
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.
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?
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
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.
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?
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.
update.
Had to change servername from “localhost” to the servername that my host gave me.
works now.
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.
Hi Mike.
Take a look at this tutorial that might help: https://randomnerdtutorials.com/esp32-esp8266-web-server-timer-pulse/
Regards,
Sara
Hey Sara!
Thank you so much. Exactly what I was looking for. These tutorials are so good!
Cheers,
Mikko
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!
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 🙂
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.
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.
13:29:50.789 -> HTTP Response code: 200
13:29:50.789 -> {“1”
Incomple response in serial monitor.Any Help?
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
That’s great!
Thanks for sharing your feedback.
Regards,
Sara
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.
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
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
http://all4more.com/esp-outputs.php?name=G&board=1&gpio=2&state=1
here i used this project code but its working for 2 times.. when everytime i restart browser
please help…
If we able to fix it.. I will let everyone use my website and server for IOT project based on this project
Hi.
What is the hosting service that you are using?
Free hosting services don’t work properly with this tutorial.
Regards,
Sara
dear mam
im using hosatinger
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
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.
Hello Rui,
first of all I would like to congratulate you on your great books.
I have seen the great article of you unfortunately too late and built my own project that sends the data via HTTP POST to my Strato server !
But I will test your project with my ESP8266 I/O board.
https://www.linkedin.com/pulse/hmi-web-control-esp8266-io-board-josef-bernhardt/
Greetings
Josef Bernhardt Bad Abbach Germany
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…
Can anyone please help me to resolve this issue.
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.
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.
Thanks Rui and Sara.
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
Thanks for sharing.
Regards,
Sara
You’re welcome, Sara. Just keep up the good work!
Regards,
Demy
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
It is possible that your hardware (esp module) might have a problem. Or consider checking every connection on it.
Regards,
Demy
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
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
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
How to with only esp 32. Can You help me, please?
Connecting
…..
Connected to WiFi network with IP Address: 192.168.1.5
Error code: -1
{}
JSON object = {}
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
Hi , can anyone help me solve my problem ? , I think it would be a useful thing.
Greetings to all
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
I set GPIO5 on esp8266 nodemcu, but when I on any device it got off after a while itself, what the problem may be?
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!
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
instead of while i used if and it worked perfectly
“if ((WiFiMulti.run() == WL_CONNECTED))”
while ((WiFiMulti.run() == WL_CONNECTED))
thanks
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”);
}
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
Can we also implement a Esp32 Cam for video surveillance in this project?
Hello, I was wondering if it might be possible to use a momentary switch instead of a toggle switch?
Hi.
Check this tutorial that might help: https://randomnerdtutorials.com/esp32-esp8266-web-server-outputs-momentary-switch/
Regards,
Sara
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
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
Hi.
Use our code with the latest installation of the ESP8266 board.
Regards,
Sara
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
Hi.
Please check that your servername is HTTP and not HTTPS.
Regards,
Sara
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
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
Izam, according to your site iotserver.fixmation.com. it looks like your account has been suspended.
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
Hi.
Maybe this project might help: https://randomnerdtutorials.com/esp32-esp8266-send-email-notification/
Regards,
Sara
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.
Hi.
Here is an example for sensor readings: https://randomnerdtutorials.com/visualize-esp32-esp8266-sensor-readings-from-anywhere/
Regards,
Sara
Thank you Sara
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
Hi!
What can i do, if the get request returns the entire HTML code in serial monitor?
Sincerely, Diego
for use GPIO 0 then must change file esp-outputs-action.php
echo json_encode($rows);
to
echo json_encode($rows, JSON_FORCE_OBJECT);
Hi,
Can you explain me how to make this example work with pttps?
(sp32)
const char* serverName = “https://example.com/ …
Thank you,
Manuel
Please post tutorial on esp32 as server sent events receiver or client which receives events from custom own web server like bluehost etc
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.
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.
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.