Inserting ESP32’s Weather Data to SQL through PHP

ESP32 #10

Halo semua, apa kabar? Semoga baik-baik saja ya. Cuaca di Bali lagi kurang baik nih sekarang, mungkin karena musim peralihan ya, jadinya hujan-panas-hujan-panas. Tapi tidak apa-apa, yang penting kita harus menjaga kesehatan dan tidak ikut hujan-hujanan.

Minggu ini nih temen-temen, kita bakalan melanjutkan project kita dari minggu lalu, yaitu project 9 : web server x weather station. Nah kali ini kita gak hanya nampilin hasil pembacaan sensor cuaca ke web server, melainkan kita juga akan mencatat hasilnya pada SQL melalui web server.

Necessities

Hal yang kita perluin di eksperimen kali ini adalah sebuah domain server kita sendiri teman-teman. Domain server ini akan kita gunakan untuk menyimpan dan menampilkan data di SQL, sementara input data akan melalui PHP script.

Hosting dapat didapatkan melalui beberapa website pihak ketiga, salah satu yang paling disarankan adalah melalui Bluehost yang bisa memberi kita hosting domain tanpa embel-embel bluehost (bukan example.bluehost.com) . Namun sayang sekali bluehost bukanlah provider yang memberi layanan hosting yang gratis, serta pembayarannya memerlukan kartu kredit. Nah alternatif yang bisa digunakan bila kalian seorang mahasiswa adalah menggunakan Microsoft Azure. Namun untuk keperluan umum, aku menggunakan alternatif webhost dari 000webhost.com yang gratis. Beberapa downfallnya adalah domain yang kita dapatkan akan berisi embel-embel 000webhost dan fitur yang terbatas, namun tidak akan menjadi masalah bagi eksperimen ini. Langkah mendapatkan hosting kita sendiri:

  1. Sign up dengan email lalu verifikasi
  2. Saat ditanyakan What would you like to do? pilih saja opsi Other
  3. Setelah itu kita akan diarahkan memberi nama hosting, isi dengan nama domain yang diinginkan beserta password-nya, jangan sampai lupa password (kalau bisa simpan di browswe)
  4. Setelah berhasil, cek saja apakah domain kalian sudah terdaftar dengan cara ketik nama-domain.000webhostapp.com
domain berhasil dibuat

Setup Database

Setelah kita punya domain sendiri, langkah selanjutnya yang harus kita lakukan adalah membuat basis datanya. Disini aku akan menggunakan MySQL sebagai basis data, namun sebelumnya aku harus membuat tabel pada basis datanya. Tutorial basis data aku kutip dari sini. Berdasarkan web tersebut, yang harus kita lakukan setelah sign up dan login adalah melakukan Manage Website dilanjutkan dengan Tools lalu Database Manager.

Pada menu Database Manager, pilih opsi + New Database lalu isikan nama database, username database, dan password sesuai keinginan, penting untuk diperhatikan, password harus diingat jangan sampai lupa.

Setelah Database berhasil dibuat, pilih opsi PhpMyAdmin pada bagian Manage, buat tabel pada database dengan mengacu pada tutorial dari Randomnerdstutorial.

  1. Pilih opsi PhpMyAdmin
  2. Pilih tab SQL pada PhpMyAdmin
  3. Tuliskan kode 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
)

4. !!PENTING!! klik Go

PHP Script HTTP Post

Bagian ini akan berisikan cara membuat script PHP untuk menerima request dari ESP32 dan memasukkan data ke database MySQL. Langkah pertama adalah memilih File Manager dari Tools, lalu memencet tombol Upload Files

Kita akan diarahkan ke menu files dari domain, klik public_html dan pilih opsi New File untuk membuat sebuah file baru bernama post-esp-data.php

Kita akan melihat sebuah text editor kosong pada file yang baru dibuat. Pada text editor itu salinlah kode ini:

<?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;
}

setelah tersalin, jangan lupa untuk mengganti bagian $dbname, $username dan $password menjadi sesuai dengan spesifikasi kita.

Setelah selesai, jalankan test case dengan mengetikkan alamat ini pada browser. http://example-domain.com/post-esp-data.php

Jika kode berjalan sesuai, maka akan ditampilkan sesuatu seperti ini.

PHP Script — Display Database Content

Buatlah File PHP lain dalam /public_html yang bisa menampilkan semua isi database dalam sebuah web page. Beri nama datanya: esp-data.php

Setelah PHP baru terbuat, salin kode ini pada text editor untuk menampilkan hasil pembacaan database.

<!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="5" cellpadding="5">
<tr>
<td>ID</td>
<td>Sensor</td>
<td>Location</td>
<td>Value 1</td>
<td>Value 2</td>
<td>Value 3</td>
<td>Timestamp</td>
</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>

Selalu ingat untuk mengganti credentials pada kode sesuai dengan yang kita miliki, diantaranya $dbname, $username dan $password.

Setelah itu lakukan testcase pada kode dengan mengetikkan alamat ini pada browser: http://example-domain.com/esp-data.php

Jika berhasil, akan terlihat tampilan seperti ini

SETUP ESP32

Setelah necessities selesai, maka sekarang yang harus kita lakukan adalah memulai pengaturan pada ESP32 seperti biasa.

KOMPONEN

  • ESP32 dan Breadboard
  • Kabel Jumper
  • Arduino IDE
  • Sensor BMP280

RANGKAIAN

Sambungkan Ground ESP32 dengan Ground BMP280, V3V ESP32 dengan VDD BMP280, serta SDA BMP280 dengan SDA ESP32 (GPIO21), dan SCL BMP280 dengan SCL ESP32 (GPIO22).

SOURCE CODE

Kode yang aku gunakan merupakan modifikasi dari kode yang ada pada RandomNerdsTutorial

#ifdef ESP32
#include <WiFi.h>
#include <HTTPClient.h>
#else
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#endif

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

// 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 = "http://example.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 (1007.96)

Adafruit_BMP280 bmp;

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)
Serial.println(F("BMP280 test"));

if (!bmp.begin(0x76)) {
Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
while (1);
}

/* Default settings from datasheet. */
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
Adafruit_BMP280::FILTER_X16, /* Filtering. */
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
}

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.readAltitude(SEALEVELPRESSURE_HPA)) + "&value3=" + String(bmp.readPressure()/100.0F) + "";
Serial.print("httpRequestData: ");
Serial.println(httpRequestData);

// You can comment the httpRequestData variable above
// then, use the httpRequestData variable below (for testing purposes without the BME280 sensor)
//String httpRequestData = "api_key=tPmAT5Ab3j7F9&sensor=BME280&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
delay(30000);
}

Aku memodifikasi kodenya agar kompatibel dengan BMP280 karena kode yang ada dalam tutorial diperuntukkan untuk BME280. Ingatlah untuk mengubah beberapa entitas menjadi entitas credential yang menyesuaikan identitas server seperti

// Replace with your network credentials 
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
const char* serverName = "http://example-domain.com/post-esp-data.php";

dan jangan lupa sesuaikan tekanan pada permukaan laut

#define SEALEVELPRESSURE_HPA (1007.96)

DEMO

Jika semua berjalan lancar, maka pada serial monitor akan terlihat berita seperti ini

Dan pada domain web akan terlihat seperti ini

Jika kita mau melihat seluruh pembacaan pada MySQL, buka Database Manager > Manage > PhpMyAdmin > SensorData

ANALISIS

Pada percobaan ini ada banyak rintangan dan halangan sehingga kita harus sering-sering istigfar.

  • webhosting yang disarankan oleh web merupakan webhosting berbayar, sehingga kita harus memutar otak untuk mencari webhosting yang gratis dan mencari tutorial untuk menggunakan webhosting agar bisa mengakomodasi percobaan modul ini.
  • Tadinya value tidak mau terisi walau HTTP response code sudah benar, aku mencoba semuanya ulang namun ternyata aku hanya lupa membuat tabel terlebih dahulu pada PHP 💀
  • Pembacaan altitude pada sensor sedikit aneh, hasil yang ditunjukkan lebih kecil dari 0 (negatif) padahal aku sedang berada di daratan, kemungkinan karena data pressure above sea level yang kurang akurat

Baik itu saja untuk kali ini temans, see you next week!

(I Wayan Ananta W M Suandira / 18219038)

--

--