Embedded System Project 09: ESP32 with Database
Halo, semuanya!
Pada kesempatan kali ini, kita akan melanjutkan project ESP32 sebelumnya dengan mencoba menggunakan database untuk menerima hasil pembacaan sensor dari BMP280. Kita akan banyak belajar tentang mekanisme penggunaan paradigma komunikasi request-response beserta penyimpanan data hasil komunikasi tersebut melalui project ini. Tanpa berlama-lama, mari kita mulai!
— Objective
Tujuan dari project 09 ini adalah untuk membuat ESP32 client yang akan melakukan HTTP POST request ke suatu PHP script untuk memasukkan data pembacaan sensor tersebut ke MySQL database. Kemudian, data yang diperoleh akan ditampilkan pada suatu web page.
— Requirements
Beberapa tools yang perlu disiapkan untuk memulai project ini adalah
- Microcontroller ESP32 Devkit V1
- Kabel data (USB Type A to Micro USB)
- Arduino IDE yang terinstall pada Laptop/PC
- Kabel jumper Male to Male
- Sensor BMP280
- Breadboard
- Hosting server dan nama domain
- PHP script untuk insert data ke MySQL dan penampilannya
- MySQL database untuk menyimpan data hasil pembacaan sensor
— Steps
Create MySQL Table
Untuk membuat MySQL table, banyak sekali pilihan di luar sana yang dapat kita gunakan. Dalam project ini, aku akan menggunakan 000webhost karena penggunaannya yang gratis. Berikut langkah pembuatan MySQL table-nya.
- Masuk ke www.000webhost.com dan buat akun baru jika belum memiliki akun
- Setelah membuat akun, klik ‘Create New Site’ untuk membuat web hosting yang baru
- Masukkan nama website dan password yang diinginkan
- Jika sudah terbuat, masuk ke menu Tools > Database Manager pada sidebar.
- Buat database baru dengan klik ‘+ New Database’ dan masukkan nama, username, dan password untuk database baru tersebut.
- Setelah database terbuat, klik menu Manage > PhpMyAdmin pada database tersebut.
- Klik pada database yang baru dibuat dan pilih tab SQL.
- Kemudian, buat sebuah query pembuatan tabel data pembacaan sensor atau bisa salin query berikut.
CREATE TABLE SensorData (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
sensor VARCHAR(30) NOT NULL,
location VARCHAR(30) NOT NULL,
value1 VARCHAR(10),
value2 VARCHAR(10),
value3 VARCHAR(10),
reading_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
- Terakhir, klik tombol ‘Go’ dan query akan dijalankan untuk membuat tabel data pembacaan sensor kita.
Berikut adalah pesan berhasil dari hasil eksekusi query pembuatan tabel.
Create PHP Script HTTP POST
Berikutnya akan dibuat PHP script yang digunakan untuk menerima request dari ESP32 dan melakukan response berupa inserting data hasil pembacaan sensor ke MySQL database.
- Masuk kembali ke menu website kita sebelumnya dan pilih menu File Manager > Upload Files.
- Kemudian, buka folder ‘public_html’.
- Buat file php baru di folder ‘public_html’ tersebut dengan nama dan format berikut: ‘post-esp-data.php’
- Setelah itu, salin PHP script berikut ke dalam file yang baru dibuat serta ubah nama, username, dan password dari database sesuai yang sudah dibuat.
<?php
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-mysql-database-php/
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.
*/
$servername = "localhost";
// REPLACE with your Database name
$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
// REPLACE with Database user
$username = "REPLACE_WITH_YOUR_USERNAME";
// REPLACE with Database user password
$password = "REPLACE_WITH_YOUR_PASSWORD";
// Keep this API Key value to be compatible with the ESP32 code provided in the project page.
// If you change this value, the ESP32 sketch needs to match
$api_key_value = "tPmAT5Ab3j7F9";
$api_key= $sensor = $location = $value1 = $value2 = $value3 = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$api_key = test_input($_POST["api_key"]);
if($api_key == $api_key_value) {
$sensor = test_input($_POST["sensor"]);
$location = test_input($_POST["location"]);
$value1 = test_input($_POST["value1"]);
$value2 = test_input($_POST["value2"]);
$value3 = test_input($_POST["value3"]);
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "INSERT INTO SensorData (sensor, location, value1, value2, value3)
VALUES ('" . $sensor . "', '" . $location . "', '" . $value1 . "', '" . $value2 . "', '" . $value3 . "')";
if ($conn->query($sql) === TRUE) {
echo "New record created successfully";
}
else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close();
}
else {
echo "Wrong API Key provided.";
}
}
else {
echo "No data posted with HTTP POST.";
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
- Apabila telah disimpan, kita dapat melihat alamat website domain kita dengan path nama file php tersebut (‘post-esp-data.php’) yang menampilkan tampilan berikut.
Create PHP Script to Display Database Content
Selain file yang sudah dibuat sebelumnya, kita juga perlu membuat 1 file php lagi yang akan menampilkan konten dari website berupa hasil pembacaan sensor BMP280 pada ESP32 nanti. Buat file php baru dan salin PHP script berikut ke dalamnya.
<!DOCTYPE html>
<html><body>
<?php
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-mysql-database-php/
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.
*/
$servername = "localhost";
// REPLACE with your Database name
$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
// REPLACE with Database user
$username = "REPLACE_WITH_YOUR_USERNAME";
// REPLACE with Database user password
$password = "REPLACE_WITH_YOUR_PASSWORD";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT id, sensor, location, value1, value2, value3, reading_time FROM SensorData ORDER BY id DESC";
echo '<table cellspacing="15" cellpadding="5">
<tr>
<th>ID</th>
<th>Sensor</th>
<th>Location</th>
<th>Temperature (°C)</th>
<th>Pressure (Pa)</th>
<th>Approx Altitude (m)</th>
<th>Timestamp</th>
</tr>';
if ($result = $conn->query($sql)) {
while ($row = $result->fetch_assoc()) {
$row_id = $row["id"];
$row_sensor = $row["sensor"];
$row_location = $row["location"];
$row_value1 = $row["value1"];
$row_value2 = $row["value2"];
$row_value3 = $row["value3"];
$row_reading_time = $row["reading_time"];
// 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 + 4 hours"));
echo '<tr>
<td>' . $row_id . '</td>
<td>' . $row_sensor . '</td>
<td>' . $row_location . '</td>
<td>' . $row_value1 . '</td>
<td>' . $row_value2 . '</td>
<td>' . $row_value3 . '</td>
<td>' . $row_reading_time . '</td>
</tr>';
}
$result->free();
}
$conn->close();
?>
</table>
</body>
</html>
- Sama seperti sebelumnya, ubah nama, username, dan password dari database sesuai yang sudah dibuat.
// REPLACE with your Database name
$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
// REPLACE with Database user
$username = "REPLACE_WITH_YOUR_USERNAME";
// REPLACE with Database user password
$password = "REPLACE_WITH_YOUR_PASSWORD";
- Jika sudah, kita juga dapat melihat alamat website domain kita dengan path nama file php tersebut (‘esp-data.php’) yang menampilkan tampilan berikut.
Apabila tampilan sudah sesuai seperti di atas, artinya kita semua pengaturan sudah siap. Tabel tersebut masih kosong karena belum ada data yang disimpan. Untuk mengisi data tersebut, kita akan melakukan inserting data hasil pembacaan sensor BMP280 dari ESP32 ke dalam database. Mari kita lanjut ke ESP32!
Get into ESP32
Kita akan membuat rangkaian sederhana terlebih dahulu sesuai skema berikut yang dapat mengirimkan data temperatur, tekanan, dan estimasi ketinggian ke dalam database setiap 30 detik.
Selanjutnya, salin code berikut ke dalam Arduino IDE dan upload ke dalam ESP32 sesuai rangkaian yang sudah dibuat.
/*
This code references to: Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-mysql-database-php/
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 <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
// Replace with your network credentials
const char* ssid = "Realme GT Master Edition";
const char* password = "rizasatria123";
// REPLACE with your Domain name and URL path or IP address with path
const char* serverName = "https://fiknaufalh-emsys.000webhostapp.com/post-esp-data.php";
// Keep this API Key value to be compatible with the PHP code provided in the project page.
// If you change the apiKeyValue value, the PHP file /post-esp-data.php also needs to have the same key
String apiKeyValue = "tPmAT5Ab3j7F9";
String sensorName = "BMP280";
String sensorLocation = "Office";
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BMP280 bmp; // I2C
//Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
//Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);
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());
// (you can also pass in a Wire library object like &Wire2)
bool status = bmp.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BMP280 sensor, check wiring or change I2C address!");
while (1);
}
}
void loop() {
//Check WiFi connection status
if(WiFi.status()== WL_CONNECTED){
HTTPClient http;
// Your Domain name with URL path or IP address with path
http.begin(serverName);
// Specify content-type header
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
// Prepare your HTTP POST request data
String httpRequestData = "api_key=" + apiKeyValue + "&sensor=" + sensorName
+ "&location=" + sensorLocation + "&value1=" + String(bmp.readTemperature())
+ "&value2=" + String(bmp.readPressure()) + "&value3=" + String((bmp.readAltitude(SEALEVELPRESSURE_HPA))) + "";
Serial.print("httpRequestData: ");
Serial.println(httpRequestData);
// You can comment the httpRequestData variable above
// then, use the httpRequestData variable below (for testing purposes without the BMP280 sensor)
//String httpRequestData = "api_key=tPmAT5Ab3j7F9&sensor=BMP280&location=Office&value1=24.75&value2=49.54&value3=1005.14";
// Send HTTP POST request
int httpResponseCode = http.POST(httpRequestData);
// If you need an HTTP request with a content type: text/plain
//http.addHeader("Content-Type", "text/plain");
//int httpResponseCode = http.POST("Hello, World!");
// If you need an HTTP request with a content type: application/json, use the following:
//http.addHeader("Content-Type", "application/json");
//int httpResponseCode = http.POST("{\"value1\":\"19\",\"value2\":\"67\",\"value3\":\"78\"}");
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
}
else {
Serial.println("WiFi Disconnected");
}
//Send an HTTP POST request every 30 seconds (30.000 mili seconds)
delay(30000);
}
- Jangan lupa untuk mengganti SSID, password, dan domain name yang sudah disiapkan sebelum upload.
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";// REPLACE with your Domain name and URL path or IP address with path
const char* serverName = "DOMAIN_NAME";
— Result
Tada! Terlihat pada Serial Monitor bahwa HTTP response code yang diperoleh adalah 200, artinya OK atau success :D
Apabila alamat website domain kita dengan path nama file php yang menampilkan data (‘esp-data.php’) kita dibuka, maka akan terlihat data yang dibaca oleh sensor akan ditampilkan.
Kita juga dapat melihat pada database kita bahwa data hasil pembacaan sensor berhasil dimasukkan ke dalam database.
— Problem(s) Encountered
Satu masalah minor yang sempat aku hadapi adalah adanya pesan akses database tertolak seperti pada gambar berikut.
Padahal awalnya kukira semua konfigurasi sudah sesuai dengan yang kusiapkan. Namun, setelah dicek kembali, ternyata nama database dan database user yang perlu dimasukkan adalah nama yang sudah diberikan random number atau hash di depan nama yang kita masukkan sebelumnya.
Setelah kusesuaikan dengan hasil nama yang sebenarnya, project sudah bisa berjalan sebagaimana mestinya. So, jangan sampai salah yaa!
Itu dia untuk project 09 kali ini, stay tune untuk project berikutnya :D
— Resource(s)
- https://randomnerdtutorials.com/esp32-esp8266-mysql-database-php/
- https://www.000webhost.com/forum/t/how-to-create-a-mysql-database-on-000webhost/39142?__cf_chl_jschl_tk__=f3274e03d43d7d0e1b0ba91c56294b287cd5f3a2-1617854081-0-Ae81-_tVAC0M41s2Dac9ioJ6PsE1zshi5NuZirBIlVw56H7BWQp6xK2U5yKLjo6wQXQCflHUcwIZeK9IFOmgrKG8d8qZkgWn10B1c1RvXMDbousIx5YzYIJQeU01N0Z5HfLOeAwgJ3qOnMq8oaRLGEUVO5BxxkkXGOb02Kot6It15JaDe7GzWRwdJjlCu0x-lisGChFlceEdSo_rBh8nwQpCjkKqwH4QpqwIDYcwGShuwSMzlv6tJqok_rigRfyTPxarHe8Heqyq_q1XrnZNunuWiHUExbJOvszgvB9i0WcSpUX1e9SG5GfwsWUatBcK3M1pvm0f7Knki-BJ6SP-MtdO6ebqdZqMPuUAxV5KydRVghG6GiDOlPm4SeK3BKqfA0vNnmDlqVFHuRsAgPXv_RvFNSuK9QNk7IDK0avF5QNZqtkvq4Ye9e9zCR5ud323pNReFUmImbXINK4odguXimk