Instalasi dan konfigurasi Bell Sekolah Otomatis di Debian 13

Panduan Instalasi dan Konfigurasi Bel Sekolah Otomatis (bel.sh) — Beberapa waktu lalu saya sempat kerepotan mengurus bel sekolah yang masih manual, harus pencet tombol sendiri tiap pergantian jam pelajaran, belum lagi kalau lupa atau telat mencet. Akhirnya saya coba pakai skrip otomatisasi berbasis Debian ini, dan ternyata cukup membantu.

Nah, di tulisan ini saya mau bagikan cara pasang dan mengatur skrip Installer-bel.sh tersebut, saya tulis dengan bahasa yang sesantai mungkin supaya yang belum terbiasa dengan Linux pun tetap bisa mengikuti.


Sekilas Tentang Skrip Ini

Jadi, Installer-bel.sh itu semacam skrip "sekali jalan" yang akan mengubah komputer atau mini PC biasa menjadi mesin pengatur bel sekolah yang bekerja sendiri, 24 jam nonstop. Setelah dipasang, saya sudah tidak perlu lagi mikirin:

  • 🔔 Bel ujian — bunyi sesuai jam yang sudah diatur
  • 🎵 Lagu pagi, Indonesia Raya, sampai bel Dzuhur — otomatis muter tiap hari
  • 🕌 Tarhim menjelang Subuh dan Maghrib — jadwalnya diambil otomatis dari internet sesuai lokasi sekolah
  • 🔊 Koneksi ke speaker Bluetooth — otomatis nyambung lagi kalau putus di tengah jalan

Semua kegiatan itu juga dicatat rapi ke dalam log, dan setiap malam ada backup otomatis. Lumayan, jadi saya tidak was-was kalau ada apa-apa.

Perlu saya sampaikan dulu, skrip ini dibuat untuk sistem operasi Debian (atau turunannya seperti Ubuntu Server), dan sebaiknya dipasang di komputer/mini PC yang memang dikhususkan untuk urusan bel saja, bukan komputer yang dipakai kerja sehari-hari.

Sebelum Mulai, Siapkan Ini Dulu

Supaya prosesnya lancar dan tidak bolak-balik berhenti di tengah jalan, ada beberapa hal yang perlu saya siapkan lebih dulu:

No. Yang Perlu Disiapkan Keterangan
1 Komputer/Mini PC ber-Debian Nyambung internet, kalau bisa nyala 24 jam
2 Akun user biasa (non-root) Misalnya lenovo, bukan akun root
3 Speaker atau mixer Bluetooth Sudah menyala dan diketahui MAC Address-nya
4 Koordinat lokasi sekolah Latitude & longitude, dipakai buat hitung jadwal adzan
5 File audio bel (.mp3) Bel masuk, bel istirahat, lagu wajib, dan lain-lain

Untuk cari MAC Address speaker Bluetooth, saya biasanya pasangkan (pairing) dulu speakernya, lalu ketik perintah ini di terminal:

bluetoothctl devices

Nanti akan muncul baris semacam Device 7D:5B:22:C8:4D:AB Nama Speaker. Kombinasi huruf-angka itu yang nanti dipakai sebagai MAC Address.

Kalau koordinat lokasi sekolah, gampang saja — tinggal buka Google Maps, klik kanan di titik sekolah, nanti muncul angka Latitude dan Longitude, tinggal disalin.


Isi Lengkap Script Installer-bel.sh

Sebelum masuk ke langkah konfigurasi, saya taruh dulu isi lengkap script-nya di sini, biar bisa dicek atau dipelajari duluan sebelum dijalankan. Supaya halamannya tidak kepanjangan, saya buat bisa di-klik untuk dibuka-tutup (show/hide).

📄 Klik di sini untuk Lihat/Sembunyikan Script Installer-bel.sh
#!/bin/bash
# ====================================================================
# MASTER INSTALLER AUTOMATION AUDIO SEKOLAH (VERSION 3)
# SYSTEM: MULTI-AUDIO BEL UJIAN, BEL HARIAN & DAEMON TAHRIM
# UPDATED: RE-BRANDING 'BEL TES' TO 'UJIAN' & INTEGRATED SCENARIOS
# ====================================================================

# --------------------------------------------------------------------
# 1. KONFIGURASI SEKOLAH (SESUAIKAN DI SINI SEBELUM MENJALANKAN)
# --------------------------------------------------------------------
USER_SISTEM="lenovo"                   # Nama user non-root di Debian
NAMA_SEKOLAH="SMK Negeri Purworejo"     # Nama Sekolah Anda
GARIS_LINTANG="-7.7134"                # Koordinat Lintang Sekolah
GARIS_BUJUR="109.9961"                 # Koordinat Bujur Sekolah
MAC_SPEAKER="7d:5b:22:c8:4d:ab"        # MAC Address Mixer/Speaker Bluetooth

# Jalur Direktori (Otomatis menyesuaikan dengan USER_SISTEM)
DIR_BASE="/home/${USER_SISTEM}"
DIR_AUDIO="${DIR_BASE}/audio"
DIR_FLAG="${DIR_BASE}/jadwal_nonaktif"
LOG_FILE="/var/log/otomasi_audio.log"

# Memastikan skrip dijalankan sebagai ROOT / SUDO
if [ "$EUID" -ne 0 ]; then
  echo "[ERROR] Harap jalankan skrip ini sebagai root atau gunakan 'sudo ./install_bel.sh'"
  exit 1
fi

echo "===================================================="
echo " Memulai Instalasi Otomatisasi Audio V3 untuk:"
echo " ${NAMA_SEKOLAH}"
echo "===================================================="

# --------------------------------------------------------------------
# 2. INSTALASI PAKET DEPENDENSI SISTEM
# --------------------------------------------------------------------
echo "[1/8] Menginstal paket pendukung Debian..."
apt update && apt upgrade -y
apt install bluez bluez-tools bluez-alsa-utils alsa-utils mpv curl jq rfkill nano fail2ban systemd-timesyncd -y

# Atur zona waktu dan aktifkan NTP
timedatectl set-timezone Asia/Jakarta
systemctl enable --now systemd-timesyncd
systemctl enable --now fail2ban

# Matikan PipeWire jika ada (agar tidak berebut bluetooth adapter)
systemctl disable --now pipewire pipewire-pulse wireplumber 2>/dev/null

# Mencegah PC masuk ke mode tidur/suspend
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

# Masukkan user ke grup audio dan bluetooth
usermod -aG audio,bluetooth ${USER_SISTEM}

# Konfigurasi BlueALSA ke mode A2DP sink saja
echo "[2/8] Mengonfigurasi BlueALSA..."
mkdir -p /etc/systemd/system/bluealsa.service.d
cat <<EOF > /etc/systemd/system/bluealsa.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/bluealsa -p a2dp-sink
EOF
systemctl daemon-reload
systemctl restart bluetooth bluealsa
rfkill unblock bluetooth
bluetoothctl power on

# Izinkan perintah reset adapter tanpa password untuk pemulihan otomatis
if ! grep -q "rfkill" /etc/sudoers; then
    echo "${USER_SISTEM} ALL=(ALL) NOPASSWD: /usr/sbin/rfkill" >> /etc/sudoers
fi

# --------------------------------------------------------------------
# 3. MEMBUAT STRUKTUR DIREKTORI & FILE KONFIGURASI SENTRAL
# --------------------------------------------------------------------
echo "[3/8] Membuat struktur folder dan file konfigurasi..."
mkdir -p "${DIR_AUDIO}"
mkdir -p "${DIR_FLAG}"

cat <<EOF > ${DIR_BASE}/sekolah.conf
# FILE KONFIGURASI GENERATED AUTOMATICALLY
NAMA_SEKOLAH="${NAMA_SEKOLAH}"
GARIS_LINTANG="${GARIS_LINTANG}"
GARIS_BUJUR="${GARIS_BUJUR}"
MAC_SPEAKER="${MAC_SPEAKER}"
DIR_BASE="${DIR_BASE}"
DIR_AUDIO="${DIR_AUDIO}"
DIR_FLAG="${DIR_FLAG}"
LOG_FILE="${LOG_FILE}"
DB_LOKAL="${DIR_BASE}/jadwal_sholat.json"
CONF_UJIAN="${DIR_BASE}/jadwal_ujian.conf"
EOF

# MEMBUAT DEFAULT JADWAL BEL UJIAN (Berdasarkan Istirahat Baru V2)
if [ ! -f "${DIR_BASE}/jadwal_ujian.conf" ]; then
cat <<EOF > ${DIR_BASE}/jadwal_ujian.conf
# ====================================================================
# JADWAL BEL UJIAN & ISTIRAHAT (FORMAT: JAM[SPASI]NAMA_FILE.mp3)
# Sesuai Lampiran Jadwal Harian Sekolah / Masa Ujian Semester/Kelas 3
# ====================================================================

# --- SHIFT PAGI ---
06:50 bel-masuk-ruangan.mp3
07:00 bel-mulai-ujian.mp3

# --- ISTIRAHAT PERTAMA (09.00 - 09.15) ---
09:00 istirahat.mp3
09:12 bel-sisa-5menit.mp3
09:15 istirahat-selesai.mp3

# --- PERSIAPAN SHIFT SIANG ---
10:10 bel-masuk-ruangan.mp3
10:30 bel-mulai-ujian.mp3

# --- ISTIRAHAT KEDUA (12.15 - 12.45) ---
12:15 istirahat.mp3
12:42 bel-sisa-5menit.mp3
12:45 istirahat-selesai.mp3

# --- AKHIR SELURUH UJIAN HARI INI ---
13:45 bel-ujian-selesai.mp3
EOF
fi

# --------------------------------------------------------------------
# 4. MEMBUAT SEMUA SKRIP INTI SISTEM (UPDATED LOGIC TO 'UJIAN')
# --------------------------------------------------------------------
echo "[4/8] Membuat berkas skrip operasional audio..."

# Skrip sambung_bt.sh
cat <<'EOF' > ${DIR_BASE}/sambung_bt.sh
#!/bin/bash
source /home/lenovo/sekolah.conf
GAGAL_FILE="${DIR_BASE}/.gagal_beruntun"
pkill -x "play" 2>/dev/null

if bluetoothctl info "$MAC_SPEAKER" | grep -q "Connected: yes"; then
    echo 0 > "$GAGAL_FILE"
    exit 0
fi

bluetoothctl power on
sleep 1
echo "$(date '+%Y-%m-%d %H:%M:%S') - [INFO] - Memulai jaring pengaman koneksi Bluetooth di ${NAMA_SEKOLAH}..." >> "$LOG_FILE"

for i in {1..3}; do
    bluetoothctl connect "$MAC_SPEAKER"
    sleep 3
    if bluetoothctl info "$MAC_SPEAKER" | grep -q "Connected: yes"; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - [SUCCESS] - Bluetooth tersambung pada percobaan ke-$i." >> "$LOG_FILE"
        echo 0 > "$GAGAL_FILE"
        exit 0
    fi
done

GAGAL_KE=$(( $(cat "$GAGAL_FILE" 2>/dev/null || echo 0) + 1 ))
echo "$GAGAL_KE" > "$GAGAL_FILE"
echo "$(date '+%Y-%m-%d %H:%M:%S') - [WARNING] - Gagal koneksi (beruntun ke-$GAGAL_KE)." >> "$LOG_FILE"

if [ "$GAGAL_KE" -ge 3 ]; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') - [RECOVERY] - Reset adapter Bluetooth karena gagal beruntun." >> "$LOG_FILE"
    sudo rfkill block bluetooth
    sleep 2
    sudo rfkill unblock bluetooth
    sleep 3
    bluetoothctl power on
    bluetoothctl connect "$MAC_SPEAKER"
    echo 0 > "$GAGAL_FILE"
fi
EOF

# Skrip anti_putus.sh
cat <<'EOF' > ${DIR_BASE}/anti_putus.sh
#!/bin/bash
source /home/lenovo/sekolah.conf
HENING_PID=""
while true; do
    if pgrep -x "mpv" > /dev/null; then
        if [ -n "$HENING_PID" ] && kill -0 "$HENING_PID" 2>/dev/null; then
            kill "$HENING_PID" 2>/dev/null
            HENING_PID=""
        fi
    else
        if [ -z "$HENING_PID" ] || ! kill -0 "$HENING_PID" 2>/dev/null; then
            aplay -q -D bluealsa -f cd -t raw /dev/zero > /dev/null 2>&1 &
            HENING_PID=$!
        fi
    fi
    sleep 2
done
EOF

# Skrip putar_audio.sh
cat <<'EOF' > ${DIR_BASE}/putar_audio.sh
#!/bin/bash
exec 201>/tmp/putar_audio.lock
flock -n 201 || exit 0

source /home/lenovo/sekolah.conf
mkdir -p "$DIR_FLAG"

KUNCI="$1"; NAMA="$2"; shift 2
FILES=("$@")

if [ -f "${DIR_FLAG}/semua.off" ] || [ -f "${DIR_FLAG}/${KUNCI}.off" ]; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') - [SKIP] - $NAMA dilewati (mode nonaktif sedang aktif)." >> "$LOG_FILE"
    exit 0
fi

for f in "${FILES[@]}"; do
    [ -f "$f" ] || echo "$(date '+%Y-%m-%d %H:%M:%S') - [CRITICAL] - File hilang: $f" >> "$LOG_FILE"
done

${DIR_BASE}/sambung_bt.sh
amixer -q sset Master 100% 2>/dev/null

DAFTAR=$(printf '%s, ' "${FILES[@]##*/}")
echo "$(date '+%Y-%m-%d %H:%M:%S') - [PLAY] - Memutar $NAMA: ${DAFTAR%, } (Volume 80%)" >> "$LOG_FILE"
mpv --no-video --audio-device=alsa/bluealsa --volume=80 --audio-fallback-to-ids=no --audio-delay=1.5 "${FILES[@]}" >> "$LOG_FILE" 2>&1
EOF

# Skrip cek_ujian.sh (REBRANDED FROM cek_bel_tes.sh)
cat <<'EOF' > ${DIR_BASE}/cek_ujian.sh
#!/bin/bash
source /home/lenovo/sekolah.conf
JAM_SEKARANG=$(date +%H:%M)

[ -f "$CONF_UJIAN" ] || exit 0

BARIS_JADWAL=$(grep -v '^#' "$CONF_UJIAN" | grep "^${JAM_SEKARANG}")

if [ -n "$BARIS_JADWAL" ]; then
    NAMA_AUDIO=$(echo "$BARIS_JADWAL" | awk '{print $2}')
    JALUR_AUDIO="${DIR_AUDIO}/${NAMA_AUDIO}"
    
    if [ -f "$JALUR_AUDIO" ]; then
        ${DIR_BASE}/putar_audio.sh ujian "Bel Ujian (${JAM_SEKARANG})" "$JALUR_AUDIO"
    else
        echo "$(date '+%Y-%m-%d %H:%M:%S') - [CRITICAL] - Gagal Bunyi! File $NAMA_AUDIO tidak ada di folder audio." >> "$LOG_FILE"
    fi
fi
EOF

# Skrip tahrim_daemon.sh
cat <<'EOF' > ${DIR_BASE}/tahrim_daemon.sh
#!/bin/bash
source /home/lenovo/sekolah.conf

ambil_jadwal() {
    local tanggal="$1"
    local api="https://api.aladhan.com/v1/timings/${tanggal}?latitude=${GARIS_LINTANG}&longitude=${GARIS_BUJUR}&method=2"
    local data
    data=$(curl -4 -s --connect-timeout 10 --max-time 20 --retry 3 --retry-delay 5 "$api")
    if echo "$data" | jq -e '.code==200' > /dev/null 2>&1; then
        echo "$data" > "$DB_LOKAL"
        echo "$(date '+%Y-%m-%d %H:%M:%S') - [INFO] - Jadwal online sukses diambil untuk lokasi ${NAMA_SEKOLAH}." >> "$LOG_FILE"
        echo "$data"
    elif [ -f "$DB_LOKAL" ]; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - [RECOVERY] - Offline, menggunakan database lokal terakhir." >> "$LOG_FILE"
        cat "$DB_LOKAL"
    else
        echo "$(date '+%Y-%m-%d %H:%M:%S') - [CRITICAL] - Tidak ada data jadwal sholat sama sekali." >> "$LOG_FILE"
        echo ""
    fi
}

while true; do
    if ! timedatectl show -p NTPSynchronized --value | grep -q "yes"; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - [WARNING] - Jam sistem belum tersinkron NTP." >> "$LOG_FILE"
    fi

    TANGGAL_HARI_INI=$(date +%d-%m-%Y)
    JADWAL=$(ambil_jadwal "$TANGGAL_HARI_INI")

    if [ -n "$JADWAL" ]; then
        JAM_SUBUH=$(echo "$JADWAL" | jq -r '.data.timings.Fajr // empty')
        JAM_MAGHRIB=$(echo "$JADWAL" | jq -r '.data.timings.Maghrib // empty')

        if [ -n "$JAM_SUBUH" ] && [ -n "$JAM_MAGHRIB" ] && [[ "$JAM_SUBUH" =~ ^[0-2][0-9]:[0-5][0-9]$ ]]; then
            TAHRIM_SUBUH=$(date -d "${JAM_SUBUH} 20 minutes ago" +%s 2>/dev/null)
            TAHRIM_MAGHRIB=$(date -d "${JAM_MAGHRIB} 20 minutes ago" +%s 2>/dev/null)
            ANGKA_HARI=$(date +%u)
            NOMOR_LAGU=$(( (ANGKA_HARI - 1) % 3 + 1 ))
            FILE_MAGHRIB="${DIR_AUDIO}/tarhim-maghrib-${NOMOR_LAGU}.mp3"

            for pasangan in "${TAHRIM_SUBUH}|tarhim_subuh|${DIR_AUDIO}/tarhim-subuh.mp3|Tarhim Subuh" \
                            "${TAHRIM_MAGHRIB}|tarhim_maghrib|${FILE_MAGHRIB}|Tarhim Maghrib"; do
                target_epoch="${pasangan%%|*}"
                if [ -z "$target_epoch" ] || ! [[ "$target_epoch" =~ ^[0-9]+$ ]]; then
                    continue
                fi
                sisa="${pasangan#*|}"
                kunci="${sisa%%|*}"
                sisa2="${sisa#*|}"
                file_audio="${sisa2%%|*}"
                nama="${sisa2##*|}"

                sekarang=$(date +%s)
                tunggu=$(( target_epoch - sekarang ))
                if [ "$tunggu" -gt 0 ]; then
                    echo "$(date '+%Y-%m-%d %H:%M:%S') - [STANDBY] - $nama menunggu ${tunggu} detik." >> "$LOG_FILE"
                    sleep "$tunggu"
                    ${DIR_BASE}/putar_audio.sh "$kunci" "$nama" "$file_audio"
                else
                    echo "$(date '+%Y-%m-%d %H:%M:%S') - [SKIP] - $nama sudah lewat, dilewati." >> "$LOG_FILE"
                fi
            done
        else
            echo "$(date '+%Y-%m-%d %H:%M:%S') - [CRITICAL] - Format jam sholat tidak valid." >> "$LOG_FILE"
        fi
    fi
    detik_ke_tengah_malam=$(( $(date -d "tomorrow 00:02" +%s) - $(date +%s) ))
    sleep "$detik_ke_tengah_malam"
done
EOF

# Skrip kelola_ujian.sh (REBRANDED FROM kelola_bel_tes.sh)
cat <<'EOF' > ${DIR_BASE}/kelola_ujian.sh
#!/bin/bash
source /home/lenovo/sekolah.conf
touch "$CONF_UJIAN"
AKSI="$1"; JAM="$2"; FILE_MP3="$3"
case "$AKSI" in
    tambah)
        if [[ ! "$JAM" =~ ^[0-2][0-9]:[0-5][0-9]$ ]]; then echo "Format jam salah (HH:MM)."; exit 1; fi
        if [ -z "$FILE_MP3" ]; then echo "Harap masukkan nama file mp3 target. Contoh: ./kelola_ujian.sh tambah 07:00 bel-mulai-ujian.mp3"; exit 1; fi
        if grep -q "^${JAM} " "$CONF_UJIAN"; then 
            sed -i "/^${JAM} /d" "$CONF_UJIAN"
        fi
        echo "$JAM $FILE_MP3" >> "$CONF_UJIAN"
        sort -o "$CONF_UJIAN" "$CONF_UJIAN"
        echo "Jadwal Ujian $JAM dengan suara $FILE_MP3 berhasil disimpan." ;;
    hapus) 
        if grep -q "^${JAM} " "$CONF_UJIAN"; then 
            sed -i "/^${JAM} /d" "$CONF_UJIAN"
            echo "Jadwal ujian jam $JAM berhasil dihapus."
        else 
            echo "Jadwal ujian jam $JAM tidak ditemukan."
        fi ;;
    kosongkan) > "$CONF_UJIAN"; echo "Semua antrean jadwal bel ujian telah dikosongkan." ;;
    daftar) echo "=== DAFTAR JADWAL BEL UJIAN AKTIF ==="; [ -s "$CONF_UJIAN" ] && cat "$CONF_UJIAN" || echo "(kosong)" ;;
    *) echo "Pakai: ./kelola_ujian.sh [tambah|hapus|daftar|kosongkan] [HH:MM] [nama_file.mp3]" ;;
esac
EOF

# Skrip mode_sekolah.sh (PENGGANTI INTEGRASI MANUAL JAUH LEBIH MUDAH)
cat <<'EOF' > ${DIR_BASE}/mode_sekolah.sh
#!/bin/bash
source /home/lenovo/sekolah.conf
mkdir -p "$DIR_FLAG"
AKSI="$1"

status_sistem() {
    echo "===================================================="
    echo " STATUS MODE AUDIO OPERASIONAL SEKOLAH"
    echo "===================================================="
    for fitur in lagu_pagi indonesia_raya bel_dzuhur ujian tarhim_subuh tarhim_maghrib; do
        if [ -f "${DIR_FLAG}/${fitur}.off" ]; then
            printf "  %-15s : [ OFF ] NONAKTIF\n" "$fitur"
        else
            printf "  %-15s : [ ON  ] AKTIF NORMAL\n" "$fitur"
        fi
    done
    echo "===================================================="
}

case "$AKSI" in
Lebih lamaTerbaru

Posting Komentar