Setelah QR Code dan barcode berhasil dibuat, pekerjaan berikutnya adalah membaca kode tersebut dari aplikasi web.
Di bagian ini saya sempat mengira QR Code dan barcode bisa diperlakukan dengan cara yang sama. Ternyata setelah melihat dokumentasi library dan beberapa contoh implementasi scanner berbasis web, perangkat yang digunakan sangat menentukan cara kita menulis program.
QR Code dapat dibaca dari aliran video kamera menggunakan JavaScript. Sementara barcode scanner USB pada umumnya dapat bekerja sebagai keyboard wedge: hasil scan masuk ke elemen input seperti data yang diketik dari keyboard.
Karena itu, pada tutorial ini kita akan membuat satu halaman scanner dengan dua jalur input.
QR Code dibaca menggunakan kamera browser dan Nimiq QR Scanner. Barcode 1D dibaca menggunakan scanner USB melalui input HTML. Hasil keduanya kemudian dikirim ke PHP.
Library QR Scanner yang Digunakan
Untuk membaca QR Code dari kamera browser, kita tetap menggunakan Nimiq QR Scanner.
Repository resminya menjelaskan bahwa library ini dapat membaca QR Code dari aliran video webcam dan dari file gambar. Demo resmi Nimiq juga memperlihatkan proses start dan stop scanner, pemilihan kamera, serta hasil QR yang terdeteksi.
Sumber library:
Nimiq QR Scanner di GitHub
Nimiq QR Scanner Releases
Demo Resmi Nimiq QR Scanner
Pada project yang sedang kita gunakan, library ditempatkan di:
C:\xampp\htdocs\absensi\libs\qr-scanner-master
File yang digunakan:
C:\xampp\htdocs\absensi\libs\qr-scanner-master\qr-scanner.min.js
C:\xampp\htdocs\absensi\libs\qr-scanner-master\qr-scanner-worker.min.js
Artikel ini sengaja mengikuti struktur file tersebut agar tetap sama dengan project sebelumnya.
Nimiq QR Scanner pada tutorial ini digunakan untuk membaca QR Code. Untuk barcode 1D dari scanner USB, kita tidak memaksa kamera QR membaca barcode. Scanner USB ditangani sebagai input keyboard pada halaman HTML.
Kenapa Scanner QR dan Barcode Dipisahkan?
Kalau dilihat dari hasil akhirnya, keduanya memang sama-sama menghasilkan sebuah kode.
Misalnya:
RL000123
Namun cara kode tersebut masuk ke browser berbeda.
| Scanner | Cara Membaca | Input ke Web |
|---|---|---|
| QR kamera | Video kamera | Callback JavaScript |
| Barcode scanner USB | Laser/imager scanner | Seperti keyboard |
Panduan integrasi scanner USB dari IDAutomation menjelaskan penggunaan scanner dalam mode keyboard wedge untuk aplikasi. Microsoft juga mendokumentasikan konsep keyboard wedge sebagai cara memasukkan hasil scan pada posisi kursor seperti input keyboard.
Artinya, untuk barcode scanner USB kita cukup menyiapkan input yang selalu siap menerima hasil scan.
Struktur Folder Project
Contoh project kita masih berada di XAMPP:
C:\xampp\htdocs\absensi
Struktur sederhananya:
absensi
│
├── libs
│ └── qr-scanner-master
│ ├── qr-scanner.min.js
│ └── qr-scanner-worker.min.js
│
├── scanner.php
├── proses_scan.php
└── index.php
Kita akan membuat halaman utama scanner pada scanner.php.
File proses_scan.php digunakan untuk menerima kode dari browser.
Membuat Tampilan Scanner
Buat file:
scanner.php
Kita mulai dari HTML sederhana.
<div class="scanner-box">
<h2>Scan QR Code</h2>
<video id="qr-video"></video>
<div id="hasil-qr">
Belum ada QR terbaca
</div>
</div>
<div class="scanner-box">
<h2>Scan Barcode</h2>
<input
type="text"
id="barcode-input"
placeholder="Scan barcode di sini"
autocomplete="off"
>
<div id="hasil-barcode">
Belum ada barcode terbaca
</div>
</div>
Ada dua area.
Elemen video digunakan untuk preview kamera QR.
Elemen input digunakan untuk menerima data dari barcode scanner USB.
Membuat Scanner QR Code dari Kamera Browser
Repository Nimiq menampilkan pola penggunaan QrScanner dengan elemen video dan callback hasil scan.
Tambahkan script berikut pada halaman:
<script type="module">
import QrScanner from "./libs/qr-scanner-master/qr-scanner.min.js";
const video = document.getElementById("qr-video");
const hasilQr = document.getElementById("hasil-qr");
const scanner = new QrScanner(
video,
result => {
console.log("QR terbaca:", result.data);
hasilQr.textContent = result.data;
},
{
returnDetailedScanResult: true
}
);
scanner.start();
</script>
Ketika QR terdeteksi, library menjalankan callback.
Jika isi QR adalah:
RL000123
maka:
result.data
akan berisi nilai tersebut.
Pada tahap pertama, jangan langsung menghubungkan scanner ke database. Tampilkan hasilnya di halaman atau console terlebih dahulu.
Pastikan kamera terbuka. Pastikan QR terdeteksi. Pastikan nilai muncul di halaman. Setelah tiga bagian tersebut bekerja, baru kirim hasil scan ke PHP.
Memilih Kamera Belakang pada Smartphone
Untuk aplikasi scanner, kamera belakang biasanya lebih nyaman digunakan daripada kamera depan.
Nimiq QR Scanner menyediakan opsi preferredCamera. Repository resminya memberikan contoh penggunaan nilai environment untuk memilih kamera belakang.
const scanner = new QrScanner(
video,
result => {
console.log(result.data);
},
{
preferredCamera: "environment",
returnDetailedScanResult: true
}
);
Browser dan perangkat tetap memiliki kendali atas kamera yang tersedia. Karena itu, hasil akhir perlu diuji pada smartphone atau tablet yang benar-benar akan digunakan.
Kamera Tidak Terbuka dari Browser
Ini salah satu masalah yang sering muncul pada implementasi scanner kamera web.
Browser menggunakan getUserMedia() untuk meminta akses kamera. Dokumentasi MDN menjelaskan bahwa fitur tersebut hanya tersedia pada secure context.
localhost dapat digunakan untuk pengembangan lokal.
Namun ketika aplikasi dibuka dari perangkat lain melalui alamat IP HTTP biasa, perilakunya dapat berbeda.
Contoh pengujian lokal:
http://localhost/absensi/scanner.php
Jika halaman akan dibuka dari tablet atau smartphone pada jaringan, pertimbangkan penggunaan HTTPS dan periksa izin kamera browser.
Sebelum membongkar kode, cek empat hal berikut:
- Apakah browser memberikan izin kamera?
- Apakah halaman berjalan pada secure context?
- Apakah path
qr-scanner.min.jsbenar? - Apakah perangkat memiliki kamera yang dapat digunakan browser?
Demo resmi Nimiq QR Scanner juga dapat digunakan sebagai pembanding untuk memastikan kamera dan browser perangkat dapat menjalankan scanner.
Mencegah QR yang Sama Diproses Berkali-kali
Video kamera berjalan terus. QR yang berada di depan kamera dapat terdeteksi lebih dari satu kali.
Ini tidak terlalu terasa ketika kita hanya menampilkan hasil ke console. Masalah mulai muncul ketika callback langsung mencatat absensi atau transaksi.
Kita dapat menyimpan hasil scan terakhir.
let qrTerakhir = "";
let waktuScanTerakhir = 0;
const scanner = new QrScanner(
video,
result => {
const sekarang = Date.now();
const kode = result.data;
if (
kode === qrTerakhir &&
sekarang - waktuScanTerakhir < 3000
) {
return;
}
qrTerakhir = kode;
waktuScanTerakhir = sekarang;
prosesKode(kode, "QR");
},
{
preferredCamera: "environment",
returnDetailedScanResult: true
}
);
Pada contoh ini, QR yang sama diabaikan selama tiga detik.
Ini membantu di sisi antarmuka. Namun untuk aplikasi absensi atau transaksi, validasi duplikasi tetap harus dilakukan di server.
Membuat Scanner Barcode USB di HTML
Sekarang kita masuk ke barcode.
Untuk scanner USB yang bekerja seperti keyboard, kita tidak membutuhkan library kamera.
Kita membutuhkan Text Box yang menerima hasil scan.
<input
type="text"
id="barcode-input"
placeholder="Scan barcode di sini"
autocomplete="off"
>
Kemudian JavaScript mendengarkan tombol Enter.
const barcodeInput = document.getElementById("barcode-input");
const hasilBarcode = document.getElementById("hasil-barcode");
barcodeInput.addEventListener("keydown", function(event) {
if (event.key === "Enter") {
event.preventDefault();
const kode = barcodeInput.value.trim();
if (kode === "") {
return;
}
hasilBarcode.textContent = kode;
console.log("Barcode terbaca:", kode);
barcodeInput.value = "";
}
});
Banyak scanner dapat dikonfigurasi untuk mengirim suffix Enter setelah barcode berhasil dibaca.
Jika scanner Anda tidak mengirim Enter, event di atas tidak akan langsung berjalan. Periksa konfigurasi scanner atau gunakan strategi pembacaan input yang sesuai dengan perangkat.
Pastikan Input Barcode Selalu Fokus
Salah satu masalah yang sering terjadi pada halaman scanner barcode adalah fokus berpindah ke tombol atau area lain.
Akibatnya, scanner mengirim kode tetapi karakter masuk ke tempat yang salah.
Kita dapat mengembalikan fokus ke input barcode.
barcodeInput.focus();
document.addEventListener("click", function() {
barcodeInput.focus();
});
Setelah barcode selesai diproses:
barcodeInput.value = "";
barcodeInput.focus();
Untuk aplikasi kiosk atau meja scan khusus, pola seperti ini cukup membantu.
Namun jika halaman memiliki banyak form yang harus diisi manual, jangan memaksa fokus kembali pada setiap klik. Sesuaikan dengan alur kerja halaman.
Menyatukan Hasil QR dan Barcode
Sampai tahap ini kita memiliki dua hasil.
QR kamera menghasilkan:
result.data
Barcode scanner menghasilkan:
barcodeInput.value
Keduanya sebenarnya dapat dikirim ke satu fungsi.
function prosesKode(kode, jenis) {
console.log("Jenis:", jenis);
console.log("Kode:", kode);
}
Pada QR scanner:
prosesKode(result.data, "QR");
Pada barcode scanner:
prosesKode(kode, "BARCODE");
Dengan pola ini, bagian yang mengirim data ke PHP tidak perlu ditulis dua kali.
Mengirim Hasil Scanner ke PHP
Sekarang ubah fungsi prosesKode().
function prosesKode(kode, jenis) {
fetch("proses_scan.php", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body:
"kode=" + encodeURIComponent(kode) +
"&jenis=" + encodeURIComponent(jenis)
})
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.error("Terjadi kesalahan:", error);
});
}
QR dan barcode sekarang menggunakan endpoint yang sama:
proses_scan.php
Membuat proses_scan.php
Buat file:
proses_scan.php
Isi contoh awal:
<?php
header('Content-Type: application/json');
$kode = trim($_POST['kode'] ?? '');
$jenis = trim($_POST['jenis'] ?? '');
if ($kode === '') {
echo json_encode([
'status' => false,
'message' => 'Kode kosong'
]);
exit;
}
echo json_encode([
'status' => true,
'jenis' => $jenis,
'kode' => $kode
]);
?>
Untuk tahap pengujian, PHP hanya mengembalikan data yang diterima.
Jika QR dipindai:
{
"status": true,
"jenis": "QR",
"kode": "RL000123"
}
Jika barcode dipindai:
{
"status": true,
"jenis": "BARCODE",
"kode": "RL000123"
}
Setelah alur ini bekerja, kita dapat menghubungkannya dengan database.
Mencari Data Berdasarkan Kode
Anggap kita memiliki tabel:
barang
Dengan field:
id_barang
kode_barang
nama_barang
Kita dapat mencari data berdasarkan kode.
SELECT id_barang, kode_barang, nama_barang
FROM barang
WHERE kode_barang = ?
LIMIT 1
Jika QR Code dan barcode menggunakan identitas yang sama, keduanya dapat menemukan barang yang sama.
Misalnya QR berisi:
RL000123
Barcode Code 39 juga merepresentasikan:
RL000123
Maka database tidak perlu memiliki field kode QR dan kode barcode yang berbeda hanya karena media scannya berbeda.
Jika QR dan barcode memang digunakan untuk barang yang sama, pertahankan satu kode identitas. Kamera dan scanner hanyalah dua cara berbeda untuk memasukkan kode tersebut.
Contoh proses_scan.php dengan PDO
Setelah pengujian dasar berhasil, endpoint dapat dikembangkan menggunakan PDO dan prepared statement.
<?php
header('Content-Type: application/json');
$kode = trim($_POST['kode'] ?? '');
$jenis = trim($_POST['jenis'] ?? '');
if ($kode === '') {
echo json_encode([
'status' => false,
'message' => 'Kode kosong'
]);
exit;
}
$pdo = new PDO(
'mysql:host=localhost;dbname=absensi;charset=utf8mb4',
'root',
''
);
$pdo->setAttribute(
PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION
);
$stmt = $pdo->prepare(
'SELECT id_barang, kode_barang, nama_barang
FROM barang
WHERE kode_barang = ?
LIMIT 1'
);
$stmt->execute([$kode]);
$barang = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$barang) {
echo json_encode([
'status' => false,
'message' => 'Data tidak ditemukan'
]);
exit;
}
echo json_encode([
'status' => true,
'jenis' => $jenis,
'data' => $barang
]);
?>
Prepared statement digunakan agar nilai hasil scan tidak ditempel langsung ke string SQL.
Jangan menganggap isi QR atau barcode selalu aman hanya karena kode dibuat oleh aplikasi kita. Endpoint tetap harus memvalidasi input.
Menampilkan Hasil Scan di Halaman
Supaya petugas tidak harus membuka console browser, tampilkan hasil dari PHP.
function prosesKode(kode, jenis) {
fetch("proses_scan.php", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body:
"kode=" + encodeURIComponent(kode) +
"&jenis=" + encodeURIComponent(jenis)
})
.then(response => response.json())
.then(data => {
const hasil = document.getElementById("hasil-scan");
if (!data.status) {
hasil.innerHTML =
"<strong>Gagal:</strong> " +
data.message;
return;
}
hasil.innerHTML =
"<strong>" +
data.data.kode_barang +
"</strong><br>" +
data.data.nama_barang;
});
}
Tambahkan area hasil:
<div id="hasil-scan">
Silakan scan QR Code atau barcode
</div>
Sekarang satu halaman dapat menerima QR dari kamera atau barcode dari scanner USB.
Contoh scanner.php yang Lebih Lengkap
Berikut contoh yang menggabungkan bagian utama scanner.
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta
name="viewport"
content="width=device-width, initial-scale=1"
>
<title>Scanner QR dan Barcode</title>
</head>
<body>
<h1>Scanner QR dan Barcode</h1>
<h2>Kamera QR</h2>
<video
id="qr-video"
style="width:100%;max-width:500px"
></video>
<h2>Barcode Scanner</h2>
<input
type="text"
id="barcode-input"
placeholder="Scan barcode"
autocomplete="off"
>
<hr>
<div id="hasil-scan">
Silakan scan QR Code atau barcode
</div>
<script type="module">
import QrScanner
from "./libs/qr-scanner-master/qr-scanner.min.js";
const video =
document.getElementById("qr-video");
const barcodeInput =
document.getElementById("barcode-input");
const hasil =
document.getElementById("hasil-scan");
let qrTerakhir = "";
let waktuScanTerakhir = 0;
function prosesKode(kode, jenis) {
fetch("proses_scan.php", {
method: "POST",
headers: {
"Content-Type":
"application/x-www-form-urlencoded"
},
body:
"kode=" + encodeURIComponent(kode) +
"&jenis=" + encodeURIComponent(jenis)
})
.then(response => response.json())
.then(data => {
if (!data.status) {
hasil.textContent = data.message;
return;
}
hasil.innerHTML =
"<strong>" +
data.data.kode_barang +
"</strong><br>" +
data.data.nama_barang;
});
}
const scanner = new QrScanner(
video,
result => {
const kode = result.data;
const sekarang = Date.now();
if (
kode === qrTerakhir &&
sekarang - waktuScanTerakhir < 3000
) {
return;
}
qrTerakhir = kode;
waktuScanTerakhir = sekarang;
prosesKode(kode, "QR");
},
{
preferredCamera: "environment",
returnDetailedScanResult: true
}
);
scanner.start();
barcodeInput.addEventListener(
"keydown",
function(event) {
if (event.key !== "Enter") {
return;
}
event.preventDefault();
const kode =
barcodeInput.value.trim();
if (kode === "") {
return;
}
prosesKode(kode, "BARCODE");
barcodeInput.value = "";
barcodeInput.focus();
}
);
</script>
</body>
</html>
Contoh ini sengaja dibuat sederhana. Tujuannya agar alur QR, barcode, dan PHP terlihat jelas.
Kesalahan yang Sering Terjadi
Menganggap Nimiq QR Scanner membaca semua barcode
Library yang kita gunakan di sini adalah QR scanner. Artikel ini tidak menggunakan Nimiq untuk membaca Code 39 dari kamera.
Barcode 1D diterima dari scanner USB sebagai input keyboard.
Langsung memasukkan hasil scan ke database
Uji nilai scan terlebih dahulu.
Tampilkan di console atau halaman.
Pastikan nilai:
RL000123
benar-benar diterima sebagai:
RL000123
Setelah itu baru jalankan query database.
QR diproses berulang kali
Kamera dapat membaca QR yang sama berkali-kali selama kode masih berada di depan kamera.
Gunakan jeda di sisi JavaScript dan validasi duplikasi di server.
Barcode scanner tidak mengirim Enter
Contoh JavaScript kita memproses barcode ketika tombol Enter diterima.
Periksa suffix scanner. Setiap perangkat dapat memiliki konfigurasi yang berbeda.
Kamera bekerja di localhost tetapi tidak di tablet
Periksa secure context dan izin kamera. Dokumentasi MDN untuk getUserMedia() menjelaskan persyaratan secure context.
Urutan Pengujian yang Saya Sarankan
Setelah membaca dokumentasi library dan beberapa pembahasan integrasi scanner, saya lebih menyukai pengujian bertahap.
- Buka demo resmi Nimiq QR Scanner pada perangkat.
- Pastikan kamera dapat membaca QR.
- Jalankan
scanner.php. - Tampilkan hasil QR di console.
- Uji barcode scanner di Notepad.
- Uji barcode scanner pada input HTML.
- Satukan QR dan barcode ke fungsi
prosesKode(). - Kirim kode ke PHP.
- Pastikan JSON dari PHP benar.
- Baru hubungkan ke database.
Dengan urutan ini, kita tidak menebak-nebak ketika sistem gagal.
Jika barcode gagal di Notepad, masalah kemungkinan bukan PHP.
Jika demo QR resmi tidak dapat membuka kamera, periksa browser, izin kamera, dan konteks halaman sebelum mengubah kode project.
Kesimpulan
Membuat scanner QR Code dan barcode di aplikasi web lebih mudah jika kita memisahkan cara kerja perangkatnya.
QR Code dibaca dari kamera browser menggunakan Nimiq QR Scanner.
Library tetap ditempatkan di:
C:\xampp\htdocs\absensi\libs\qr-scanner-master
Dengan file:
qr-scanner.min.js
qr-scanner-worker.min.js
Barcode 1D dari scanner USB tidak perlu dipaksa masuk melalui library QR. Scanner yang bekerja sebagai keyboard wedge dapat mengisi input HTML, lalu JavaScript memproses kode ketika suffix seperti Enter diterima.
Hasil QR dan barcode kemudian dapat disatukan dalam satu fungsi JavaScript dan dikirim ke endpoint PHP yang sama.
Dengan pendekatan tersebut, aplikasi dapat menggunakan kamera smartphone atau tablet untuk QR Code dan scanner USB untuk barcode tanpa membuat dua sistem pencarian data yang terpisah.
Keduanya cukup mengirim satu kode identitas ke PHP. Server kemudian mencari kode tersebut di database dan menjalankan proses sesuai kebutuhan aplikasi.
Tidak ada komentar
Posting Komentar
Punya pertanyaan, saran, atau kritik seputar topik ini? Yuk, tulis di kolom komentar.