Absensi Online menggunakan NodeMCU dan modul RFID RC522

absensi online arduino nodemcu dengan rc522 rfid mudah sederhana
Absensi Online menggunakan NodeMCU dan modul RFID RC522

Prototype ini hampir sejenis dengan mesin absensi sederhana yang pernah dibahas pada post sebelumnya. Karena adanya teknologi wireless serta konsep IoT yang mudah dan praktis diimplementasikan maka aplikasi menggunakan board nodeMCU bisa menjadi opsi. Nah untuk memudahkan dalam ujicoba, akan saya sediakan sample sistem informasi (berbasis web) yang dapat dimanfaatkan untuk coba-coba. Saya tidak akan menjelaskan secara rinci terkait pembuatan sistem infomasinya jadi harap maklum. Pastikan kalian sudah memahami/belajar tentang pembuatan aplikasi berbasis web sebagai dasarnya.

Absensi Online menggunakan NodeMCU dan modul RFID RC522

Konsep dari sistem absensi online dengan RFID kurang lebih akan seperti gambar diatas walaupun secara spesifik tidaklah sesimpel itu. Ini agak berbeda dari tutorial sebelumnya karena untuk memfasilitasi semua jenis kartu mifare classic (emoney, RFID tag, Sticker Tag) maka data yang akan diolah adalah uid saja (tidak ada proses write data). Reader RC522 akan membaca uid kemudian datanya diproses oleh NodeMCU untuk dikirim ke server (database). Nah dari proses pengiriman data ini, maka akan diperoleh response terkait dengan informasi dari uid hasil pembacaan (misal nama, status absensi, dll). Pengaturan informasi yang berkaitan dengan pengguna kartu dapat di atur dalam sistem informasi. Bagian yang paling penting adalah pembuatan Web API untuk menyediakan layanan penyimpanan data dan juga response. Biar lebih mudah dipahami, silahkan dipelajari tutorial pada post ini. Untuk mempermudah development maka percobaan dilakukan secara local. Pada dasarnya semua aplikasi yang dijalankan di localhost dapat di onlinekan dengan mengupload aplikasi tersebut ke hosting (lebih jelasnya dapat dipelajari sendiri). Ok langsung saja kita mulai proses pembuatan sistem Absensi menggunakan NodeMCU dan modul RFID RC522.


Alat dan Bahan

Hardware:
  • NodeMCU
  • RC522 - RFID module
  • I2C OLED 128x64
  • Buzzer
  • Kabel-kabel Jumper
Software:
  • Arduino IDE
  • Notepad ++ (text editor)
  • XAMPP (Saya pakai versi 7.4)
  • Postman (web API testing)

Membuat Web API

Pertama-tama mari kita siapkan terlebih dahulu Web APInya. Kita mulai dengan pembuatan database MySQL. Disini saya menyimpan data absen pada database absensi dengan 3 buah tabel didalamnya yaitu data_karyawan, data_absen, dan data_invalid. Tabel data_karyawan digunakan untuk menyimpan data umum dari karyawan (nama, alamat, divisi, dll), tabel data_absen digunakan untuk menyimpan data absensi seperti uid, tanggal, jam, status absensi. Sementara itu, untuk tabel data_invalid digunakan untuk meyimpan uid yang belum tersimpan pada data_karyawan atau bisa juga disebut sebagai log untuk hasil pembacaan kartu yang tidak valid (karena belum didaftarkan).
Buka Xampp dan jalankan service apache dan MySQL
mesin absensi nodeMCU
Buka phpMyAdmin dan jalankan SQL berikut untuk membuat database yang diperlukan
CREATE DATABASE IF NOT EXISTS absensi;
USE absensi;

/*Table structure for table `data_absen` */
CREATE TABLE data_absen (
  id int(100) NOT NULL AUTO_INCREMENT,
  tanggal date NOT NULL DEFAULT current_timestamp(),
  waktu time NOT NULL DEFAULT current_timestamp(),
  uid varchar(20) NOT NULL,
  status varchar(20) NOT NULL,
  PRIMARY KEY (id)
);

/*Table structure for table `data_invalid` */
CREATE TABLE data_invalid (
  id int(100) NOT NULL AUTO_INCREMENT,
  tanggal date NOT NULL DEFAULT current_timestamp(),
  waktu time NOT NULL DEFAULT current_timestamp(),
  uid varchar(10) NOT NULL,
  status varchar(10) NOT NULL,
  PRIMARY KEY (id)
);

/*Table structure for table `data_karyawan` */
CREATE TABLE data_karyawan (
  id int(50) NOT NULL AUTO_INCREMENT,
  created date NOT NULL DEFAULT current_timestamp(),
  uid varchar(20) NOT NULL,
  nama varchar(50) NOT NULL,
  division varchar(50) NOT NULL,
  mail varchar(50) NOT NULL,
  alamat text NOT NULL,
  picture varchar(100) NOT NULL,
  PRIMARY KEY (id)
);
mesin absensi nodeMCU database MySQL
Setelah database siap lanjut ke directory httdocs (C:\xampp\htdocs). Buat folder absensi dan selanjutnya didalam folder absensi buat folder webapi. Terakhir dalam folder webapi buat folder  api, class dan config
mesin absensi nodeMCU database MySQL
Selanjutnya masuk ke folder config (C:\xampp\htdocs\absensi\webapi\config), buat file database.php. Buka file dengan notepad ++ dan isi dengan code berikut. File database.php digunakan untuk melakukan koneksi ke database yang digunakan (absensi). Untuk username dan password silahkan disesuaikan.
database.php
<?php 
    class Database {
        private $host = "localhost";
        private $database_name = "absensi";
        private $username = "root";
        private $password = "";

        public $conn;

        public function getConnection(){
            $this->conn = null;
            try{
                $this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->database_name, $this->username, $this->password);
                $this->conn->exec("set names utf8");
            }catch(PDOException $exception){
                echo "Database could not be connected: " . $exception->getMessage();
            }
            return $this->conn;
        }
    }  
?>
lanjut ke tahap selanjutnya masuk ke folder class (C:\xampp\htdocs\absensi\webapi\class). Buat file  absensi.php. File ini merupakan program untuk mengatur proses penyimpanan data yang dikirim melalui request GET. Alurnya adalah sebagai berikut
absensi online Node MCU RC522 RFID
Untuk program pada absensi.php , dapat dilihat pada kode dibawah
absensi.php
<?php
date_default_timezone_set('Asia/Jakarta');
class Absensi{
	// Connection
	private $conn;

	// Table
	private $db_table = "data_absen";
	private $db_table1 = "data_karyawan";
	private $db_table2 = "data_invalid";

	// Columns
	public $id;
	public $tanggal;
	public $waktu;
	public $uid;
	public $status;
	public $last_status;
	public $nama;

	// Db connection
	public function __construct($db){
		$this->conn = $db;
	}

	// CREATE
	public function createData(){
	//1. Cek user
		$sqlQuery = "SELECT * FROM ". $this->db_table1 ." WHERE uid = :uid LIMIT 0,1";
		$stmt = $this->conn->prepare($sqlQuery);
		$stmt->bindParam(":uid", $this->uid);
		$stmt->execute();
		if($stmt->errorCode() == 0) {
			while(($dataRow = $stmt->fetch(PDO::FETCH_ASSOC)) != false) {
				$this->nama = $dataRow['nama'];
			}
		} else {
			$errors = $stmt->errorInfo();
			echo($errors[2]);
		}
		$itemCount = $stmt->rowCount();
		
		if($itemCount > 0){
			//UID terdaftar -> cek status terakhir
			$sqlQuery = "SELECT data_absen.id, data_absen.uid, data_absen.status, data_karyawan.nama 
						FROM ". $this->db_table .", ". $this->db_table1 ."
						WHERE data_absen.id = (SELECT MAX(data_absen.id) 
						FROM ". $this->db_table ." WHERE data_absen.uid = :uid) 
						AND data_karyawan.uid= :uid";
			$stmt = $this->conn->prepare($sqlQuery);
			$stmt->bindParam(":uid", $this->uid);
			$stmt->execute();
			$itemCount = $stmt->rowCount();
			if($itemCount > 0){
				//error handling
				if($stmt->errorCode() == 0) {
					while(($dataRow = $stmt->fetch(PDO::FETCH_ASSOC)) != false) {
						$this->last_status = $dataRow['status'];
						$this->nama = $dataRow['nama'];
						//echo($this->last_status);
					}
				} else {
					$errors = $stmt->errorInfo();
					echo($errors[2]);
				}
			}else{
				$this->last_status ="OUT";
			}
			
			//set status
			if ($this->last_status == "IN"){
				$this->status = "OUT";
			}else{
				$this->status= "IN";
			}
			//Insert Data to data_absen	
			$sqlQuery = "INSERT INTO ". $this->db_table ."
					SET	waktu = :waktu, uid = :uid, status = :now_status";
						
			$this->waktu = date("H:i:s");
			
			$stmt = $this->conn->prepare($sqlQuery);
		
			// sanitize
			$this->uid=htmlspecialchars(strip_tags($this->uid));
		
			// bind data
			$stmt->bindParam(":uid", $this->uid);
			$stmt->bindParam(":now_status", $this->status);
			$stmt->bindParam(":waktu", $this->waktu);
		
			if($stmt->execute()){
			   return true;
			}
			return false;
		}
		else{
			//UID tidak terdaftar
			$this->status= "INVALID";
			$this->nama ="Invalid";
			
			//Insert Data to data_invalid	
			$sqlQuery = "INSERT INTO
						". $this->db_table2 ."
					SET
						waktu = :waktu,
						uid = :uid, 
						status = :now_status";
			$this->waktu = date("H:i:s");
			
			$stmt = $this->conn->prepare($sqlQuery);
		
			// sanitize
			$this->uid=htmlspecialchars(strip_tags($this->uid));
		
			// bind data
			$stmt->bindParam(":uid", $this->uid);
			$stmt->bindParam(":now_status", $this->status);
			$stmt->bindParam(":waktu", $this->waktu);
		
			if($stmt->execute()){
			   return true;
			}
			return false;
			
		}
		
	}
}
?>
Selanjutnya masuk ke folder api (C:\xampp\htdocs\absensi\webapi\api). File terakhir yang akan dibuat adalah create.php fungsinya digunakan sebagai penghubung dan pengoleksi data (dari proses GET) yang selanjutnya diproses ke fungsi createData() pada absensi.php. Setelah fungsi create data selesai maka akan memberikan response berupa json data dengan struktur sebagai berikut
{
    "waktu": "15:55:02",
    "nama": "Nama User",
    "uid": "B6B3C614",
    "status": "IN"
}
Untuk kode dari create.php dapat dicopas dibawah ini
create.php
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");

include_once '../config/database.php';
include_once '../class/absensi.php';

$database = new Database();
$db = $database->getConnection();

$item = new Absensi($db);
$item->uid = isset($_GET['uid']) ? $_GET['uid'] : die('wrong structure!');
	
if($item->createData()){
	// create array
	$data_arr = array(
		"waktu" => $item->waktu,
		"nama" => $item->nama,
		"uid" => $item->uid,
		"status" =>  $item->status
	);
	http_response_code(200);
	echo json_encode($data_arr);
} else{
	http_response_code(404);
	echo json_encode("Failed!");
}
?>
Ok program PHP Rest API udah selesai dibuat. untuk memastikan susunan dan lokasi foldernya adalah sebagai berikut:
Setelah semuanya ok, mari kita test apakah web API dapat berfungsi dengan baik. Pengetesan dapat dilakukan via browser atau postman dengan mengakses url berikut:
http://localhost/absensi/webapi/api/create.php?uid=YOUR_UID_TAG
Apabila uid belum didaftarkan di tabel data_karyawan, maka akan diperoleh status invalid. Sementara bila uid sudah terdaftar maka akan diperoleh data nama dan status
data karyawan (uid terdaftar)

mesin Absensi Node MCU RC522 RFID
uid tidak terdaftar sehingga masuk ke kategori invalid  (data disimpan di tabel data_invalid)

mesin Absensi Node MCU RC522 RFID
uid terdaftar sehingga diperoleh data nama dan status (data disimpan di tabel data_absen)

Apabila tidak ada kendala, maka bagian Web API sudah selesai. Mari kita lanjut ke bagian hardwarenya!

Mesin Absensi NodeMCU + RC522

Wiring Diagram

Sesuai dengan alat dan bahan yang telah disebutkan sebelumnya (NodeMCU, Buzzer, display OLED 0.96", dan RFID reader RC-522) , maka rangkaian mesin absensi online nodeMCU dapat dilihat pada gambar berikut (rev.1 =>062023)

Absensi Online menggunakan NodeMCU dan modul RFID RC522

Program NodeMCU 

Terdapat beberapa library yang harus di install yaitu: MFRC522, Adafruit_GFX, Adafruit_SSD1306, dan ArduinoJson. Untuk versi library silahkan disesuaikan apabila terdapat error saat compile program.
NodeMCU time attendance based on RF522 RFID module
NodeMCU time attendance based on RF522 RFID module
NodeMCU time attendance based on RF522 RFID module

Setelah library siap, langsung saja copas program dibawah ini. Sesuaikan wifi SSID, wifi Password, dan alamat server (atau IP komputer yang digunakan sebagai server). 
*update juli 2022 (error HTTPClient::begin -> esp8266 board v.3.0.0) solved
Nah, karena ada tambahan icon buat visualisasi pada display OLED nya maka buat file header icon.h (new tab - ketik icon.h - Ok). copy kode berikut ke icon.h
Program telah siap. Cus langsung upload ke nodeMCU dan mari lanjut ke tahap pengetesan.

Let's test

Berikut gambaran dari hasil pembacaan kartu, proses pengiriman data - pembacaan respon, dan penyimpanan data kedatabase. Oh iya, kalau lihat di youtube-youtube, reader RC522 dapat digunakan untuk membaca uid eKTP. Namun untuk reader RC522 yang saya gunakan kebetulan tidak dapat membaca uid eKTP.
NodeMCU time attendance based on RF522 RFID module
Arduino Absensi dengan emoney
absensi online nodemcu arduino rc522
*just info: setelah dicek eKTP saya jenisnya MIFARE DESFire. menurut info dari si empunya library MFRC522, kartu MIFARE DESFire memang tidak dapat dibaca menggunakan reader ini.

Nah.. apabila data-data tersebut di tampilkan melalui sistem informasi (berbasis web)  kurang lebih seperti gambar berikut:
sistem absensi murah arduino nodemcu

Add some Custumization

Untuk memudahkan proses pendaftaran uid dan melihat rekapitulasi absensi maka kita dapat menggunakan sebuah dashboard. Dasar dari sistem aplikasi web yang digunakan pada dashboard adalah CRUD. Disini saya menggunakan pemrograman PHP untuk pembuatan CRUD ini. Biar mudah prosesnya pembuatannya saya menggunakan Crudiy ( https://github.com/jan-vandenberg/cruddiy).

Download file dashboard diatas kemudian ekstrak di folder absensi (C:\xampp\htdocs\absensi)
Selanjutnya silahkan akses http://localhost/absensi maka akan tampil halaman dashboard dari sistem yang telah dibuat. Dashboard ini bersifat demo, jadi silahkan di modif-modif sendiri sesuai kebutuhan. 

Apabila ingin versi fullnya (seperti di web demo dibawah), dapat menghubungi saya via email : thecroser@gmail.com. Just buy me a coffe for that 

Make it Online!

Untuk membuat agar service Web API dapat diakses secara online, kita memerlukan web hosting dan perangkat pendukungnya (web hosting, domain). Silahkan teman teman cari sendiri (googling) terkait hal ini dengan kata kunci "Upload website ke hosting". Selanjutnya upload program API dan file aplikasi web nya yang telah dibuat serta konfigurasi database yang ada di web hosting. Sebagai contoh teman-teman dapat mencoba melalui aplikasi yang telah saya publish di https://siab.arducoding-projects.online/. Untuk masuk ke halaman dahboard silahkan login terlebih dahulu dengan 
username:admin  dan passwordnya: Arducoding2024

Untuk akses webAPI nya teman-teman dapat mengaksesnya di link berikut. Silahkan test aplikasi hardware yang telah teman-teman buat untuk menyimpan data pada aplikasi demo diatas.
http://siab.arducoding-projects.online/webapi/api/create.php?uid=CARD_UID    //[GET]Proses Absensi
http://siab.arducoding-projects.online/webapi/api/get_last.php?uid=CARD_UID  //[GET] Cek Tap kartu terakhir
*pada program nodmcu, silahkan ubah bagian String server_addr= "192.168.0.5"
menjadi String server_addr= "sistem-presensi.arducoding-projects.my.id";

Kesimpulan

Project ini masih bersifat dasar dan memiliki fitur yang sederhana. Masih terdapat beberapa Error handling yang perlu dibuat / diperbaharui baik dari segi program nodemcu ataupun program web API nya, dari segi keamanan penggunaan kartu, dan dari segi yang lainnya. Sementara dari sisi user interface, diperlukan metode yang cocok sehingga dapat menampilkan data yang diperlukan dengan baik. Silahkan untuk diskusi terkait projek ini agar lebih bermanfaat bagi siapapun yang membutuhkan.
Dalam kesempatan selanjutnya, akan saya coba bahas untuk pembuatan Sistem Informasi berbasis web yang fokus pada pengolahan data (CRUD) menggunakan pemrograman php native (ane gak jago pemrograman web, hanya sebatas tahu)


Troubleshooting Error
=> deserializeJson() failed
Apabila sistem mendapat pesan (pada serial monitor): deserializeJson() failed , ada beberapa kemungkinan yaitu: server tidak merepon, ukuran data json respon tidak sesuai (pada program arduino, ukuran hanya dibatasi dengan 4 objek data saja (waktu, nama, uid, status) => const size_t capacity = JSON_OBJECT_SIZE(4) + 70;). teman-teman bisa cek kondisi berikut apabila menemui error ini:
1. Pastikan service Apache dan MySql sudah aktif (Xampp Control panel)
2. Pastikan alamat direktori file API sudah sesuai
3. Matikan firewall. Bisa jadi komunikasi terhambat karena dihalangi oleh firewall
 


Keyword: