Pada Part sebelumnya saya sudah mencoba membuat proses provisioning PPPoE dari Laravel ke MikroTik RouterOS.
Laravel tidak lagi hanya membaca data dari router, tetapi sudah dapat membuat PPP Secret berdasarkan data pelanggan yang tersimpan pada aplikasi billing.
Setelah proses provisioning tersebut berhasil, muncul pertanyaan berikutnya:
Apakah pelanggan yang sudah memiliki PPP Secret benar-benar sedang terkoneksi ke jaringan?
Di RouterOS kita dapat melihat informasi tersebut melalui:
/ppp active print
Tetapi untuk aplikasi billing, saya tidak ingin dashboard harus membuka koneksi ke router setiap kali halaman dimuat.
Saya ingin Laravel memiliki salinan status koneksi terakhir yang sudah disinkronkan dari MikroTik.
Kurang lebih alurnya menjadi:
MikroTik RouterOS
│
│ /ppp active
▼
Laravel
│
│ sinkronisasi
▼
Database
│
▼
Dashboard
● Online
○ Offline
Pada tulisan ini saya akan mencatat bagaimana saya menyusun proses monitoring PPPoE online dan offline dari RouterOS ke aplikasi Laravel.
Tulisan ini merupakan catatan dari proses saya membangun dan menguji aplikasi billing ISP menggunakan Laravel dan MikroTik CHR. Konfigurasi disederhanakan untuk kebutuhan lab, tetapi alur dan masalah yang dibahas berasal dari proses implementasi yang saya kerjakan.
Seri Laravel + MikroTik ISP Billing
Tulisan ini merupakan Part 5 dari seri Laravel + MikroTik yang sedang saya kerjakan.
- Cara Membuat PPPoE Server MikroTik CHR di VirtualBox
- Membangun Web App Billing MikroTik dengan Laravel
- Cara Menghubungkan Laravel ke MikroTik RouterOS API
- Provisioning PPPoE Otomatis dari Laravel ke MikroTik RouterOS
- Monitoring PPPoE Online / Offline dari Laravel
- Suspend dan Reactivate Pelanggan
- Monitoring Traffic PPPoE
- Invoice dan Pembayaran
- Notifikasi WhatsApp
- Persiapan Production
Pada Part 4 kita berhenti pada kondisi:
Laravel
│
│ Provisioning
▼
RouterOS API
│
▼
/ppp secret
│
▼
PPPoE Account tersedia
Sekarang kita akan melanjutkannya menjadi:
/ppp secret
│
│ client melakukan authentication
▼
/ppp active
│
│ monitoring
▼
Laravel Database
│
▼
Dashboard
Artinya kita mulai memisahkan antara akun yang tersedia di router dan pelanggan yang benar-benar sedang terkoneksi.
Target Part 5
Target implementasi pada bagian ini adalah:
- Laravel dapat membaca session PPPoE aktif dari RouterOS
- session dicocokkan berdasarkan username PPPoE
- pelanggan aktif diberi status
online - pelanggan yang tidak memiliki session aktif diberi status
offline - IP address pelanggan dapat disimpan
- uptime session dapat ditampilkan
- waktu terakhir pelanggan terlihat online dapat disimpan
- sinkronisasi tidak bergantung pada browser
- proses dapat dijalankan melalui Laravel Scheduler
- monitoring tidak langsung menganggap pelanggan offline ketika router gagal dihubungi
- struktur monitoring siap digunakan untuk lebih dari satu router
Saya belum membahas traffic RX/TX pada bagian ini.
Monitoring bandwidth akan saya pisahkan pada Part 7.
PPP Secret dan PPP Active Bukan Hal yang Sama
Pada Part 4 saya sudah menyinggung perbedaan ini.
PPP Secret merupakan credential yang digunakan pelanggan untuk authentication.
Contohnya:
/ppp secret print
Kita mungkin memiliki:
name="ahmad-fauzi"
service=pppoe
profile=PAKET-10M
Tetapi keberadaan secret tersebut tidak berarti pelanggan sedang online.
Session yang benar-benar sedang terkoneksi dapat dilihat melalui:
/ppp active print
Secara sederhana:
PPP Secret
│
│ username + password
▼
Authentication
│
▼
PPP Active
Karena itu pada database saya memisahkan:
provision_status
dan:
connection_status
Contohnya:
provision_status = active
connection_status = offline
Kondisi tersebut valid.
Artinya akun pelanggan tersedia di MikroTik tetapi pelanggan sedang tidak terkoneksi.
Melihat PPP Active dari RouterOS
Pada MikroTik kita dapat menjalankan:
/ppp active print
Contoh hasil sederhananya:
# NAME SERVICE ADDRESS UPTIME
0 ahmad-fauzi pppoe 10.10.10.10 00:15:23
1 budi-toko pppoe 10.10.10.11 01:42:08
Dari data tersebut kita sudah mendapatkan informasi penting:
username
service
ip address
uptime
RouterOS juga dapat memberikan informasi lain tergantung jenis session dan versi RouterOS yang digunakan.
Untuk kebutuhan monitoring dasar kali ini saya fokus pada:
name
address
uptime
Data yang Ingin Saya Simpan
Pada Part 4 tabel pppoe_accounts sudah memiliki:
provision_status
connection_status
Sekarang saya menambahkan informasi monitoring seperti:
ip_address
uptime
last_seen_at
last_synced_at
Secara sederhana:
pppoe_accounts
id
customer_id
router_id
username
provision_status
connection_status
ip_address
uptime
last_seen_at
last_synced_at
created_at
updated_at
Contoh:
Customer : Ahmad Fauzi
Username : ahmad-fauzi
Router : chr-lab-01
Provision Status : active
Connection Status : online
IP Address : 10.10.10.10
Uptime : 00:15:23
Last Seen : 2026-09-22 01:40:00
Last Synced : 2026-09-22 01:40:00
last_seen_at dan last_synced_at memiliki arti berbeda.
last_seen_at:
Kapan terakhir kali username tersebut terlihat pada PPP Active?
Sedangkan last_synced_at:
Kapan terakhir kali aplikasi berhasil melakukan sinkronisasi status account tersebut?
Perbedaan kecil seperti ini akan berguna ketika router sedang bermasalah.
Menambahkan Field Monitoring
Secara konsep migration-nya dapat dibuat seperti:
Schema::table('pppoe_accounts', function (Blueprint $table) {
$table->string('connection_status')
->default('offline');
$table->string('ip_address')
->nullable();
$table->string('uptime')
->nullable();
$table->timestamp('last_seen_at')
->nullable();
$table->timestamp('last_synced_at')
->nullable();
});
Saya sengaja menggunakan struktur sederhana terlebih dahulu.
Nantinya jika kebutuhan monitoring berkembang, data session dapat dipisahkan ke tabel tersendiri.
Misalnya:
pppoe_sessions
untuk menyimpan history koneksi pelanggan.
Tetapi pada tahap ini saya ingin menyelesaikan monitoring status terkini terlebih dahulu.
Router Juga Perlu Memiliki Status Monitoring
Monitoring pelanggan tidak hanya membutuhkan status pelanggan.
Kita juga harus mengetahui apakah router berhasil dihubungi.
Misalnya tabel routers memiliki informasi:
name
host
api_port
status
last_seen_at
last_sync_at
last_sync_error
Contohnya:
Router
Name : chr-lab-01
Host : 192.168.1.7
Status : online
Last Seen : 2026-09-22 01:40:00
Last Sync : 2026-09-22 01:40:00
Last Sync Error : null
Kenapa informasi ini penting?
Karena:
pelanggan offline
dan:
router tidak dapat dihubungi
adalah dua kondisi yang berbeda.
Jangan Query Router Setiap Kali Dashboard Dibuka
Pendekatan paling sederhana sebenarnya adalah:
Browser membuka dashboard
↓
Laravel connect ke MikroTik
↓
/ppp active print
↓
return ke browser
Tetapi saya tidak ingin menggunakan pendekatan tersebut sebagai mekanisme utama.
Karena jika ada banyak administrator membuka dashboard:
Admin A ──┐
Admin B ──┼──> RouterOS
Admin C ──┤
Admin D ──┘
setiap request dashboard dapat membuat koneksi baru ke router.
Selain itu jika router sedang lambat:
Router timeout
↓
Dashboard ikut lambat
Karena itu saya lebih memilih:
RouterOS
│
│ scheduler
▼
Laravel Worker
│
▼
Database
│
▼
Dashboard
Dashboard cukup membaca database.
RouterosClient yang Sudah Kita Punya
Pada Part sebelumnya kita sudah memiliki konsep RouterosClient.
Salah satu method yang sudah disiapkan adalah:
public function getActivePppoeSessions(): array
{
// /ppp/active/print
}
Implementasi detailnya akan bergantung pada library RouterOS API yang digunakan.
Yang saya inginkan dari method ini adalah hasil yang sudah cukup sederhana untuk digunakan service.
Contohnya:
[
[
'name' => 'ahmad-fauzi',
'address' => '10.10.10.10',
'uptime' => '00:15:23',
],
[
'name' => 'budi-toko',
'address' => '10.10.10.11',
'uptime' => '01:42:08',
],
]
Dengan demikian layer monitoring tidak perlu mengetahui bagaimana library RouterOS melakukan query.
Membuat PppoeMonitoringService
Saya kemudian membuat service khusus untuk monitoring.
Strukturnya:
app/
├── Services/
│ └── MikroTik/
│ ├── RouterosClient.php
│ ├── PppoeProvisioningService.php
│ └── PppoeMonitoringService.php
│
└── Jobs/
├── ProvisionPppoeAccount.php
└── SyncPppoeSessions.php
Secara sederhana:
namespace App\Services\MikroTik;
use App\Models\Router;
use Illuminate\Support\Collection;
use Throwable;
class PppoeMonitoringService
{
public function sync(Router $router): void
{
try {
$sessions = $this->getRouterClient($router)
->getActivePppoeSessions();
$this->syncSessions(
$router,
collect($sessions)
);
$router->update([
'status' => 'online',
'last_seen_at' => now(),
'last_sync_at' => now(),
'last_sync_error' => null,
]);
} catch (Throwable $e) {
$router->update([
'status' => 'unreachable',
'last_sync_error' => $e->getMessage(),
]);
report($e);
throw $e;
}
}
}
Contoh tersebut masih disederhanakan.
Hal yang paling penting justru berada pada bagian error.
Jika router gagal dihubungi, saya tidak langsung mengubah semua pelanggan menjadi offline.
Mencocokkan Username
Misalnya RouterOS mengembalikan:
$sessions = [
[
'name' => 'ahmad-fauzi',
'address' => '10.10.10.10',
'uptime' => '00:15:23',
],
[
'name' => 'budi-toko',
'address' => '10.10.10.11',
'uptime' => '01:42:08',
],
];
Kita dapat membuat index berdasarkan username:
$activeSessions = collect($sessions)
->keyBy('name');
Hasil konseptualnya:
ahmad-fauzi
address = 10.10.10.10
uptime = 00:15:23
budi-toko
address = 10.10.10.11
uptime = 01:42:08
Kemudian account yang berada pada router tersebut dapat dibandingkan.
Update Pelanggan Online
Misalnya:
$accounts = $router->pppoeAccounts()
->where('provision_status', 'active')
->get();
Kemudian:
foreach ($accounts as $account) {
$session = $activeSessions->get(
$account->username
);
if ($session) {
$account->update([
'connection_status' => 'online',
'ip_address' => $session['address'] ?? null,
'uptime' => $session['uptime'] ?? null,
'last_seen_at' => now(),
'last_synced_at' => now(),
]);
continue;
}
$account->update([
'connection_status' => 'offline',
'ip_address' => null,
'uptime' => null,
'last_synced_at' => now(),
]);
}
Secara sederhana:
username ada pada PPP Active?
│
┌───┴───┐
│ │
Ya Tidak
│ │
▼ ▼
Online Offline
Jangan Menghapus Last Seen Ketika Offline
Saat pelanggan berubah menjadi offline, saya tidak menghapus:
last_seen_at
Misalnya sebelumnya:
connection_status = online
last_seen_at = 2026-09-22 01:40:00
Kemudian pada sinkronisasi berikutnya pelanggan tidak lagi berada di /ppp active.
Status menjadi:
connection_status = offline
last_seen_at = 2026-09-22 01:40:00
Dengan demikian dashboard dapat mengatakan:
Deni Irawan
○ Offline
Terakhir terlihat:
22 September 2026 01:40
Kalau last_seen_at langsung dihapus ketika pelanggan offline, kita kehilangan informasi tersebut.
Bagaimana Menentukan Pelanggan Offline?
Untuk satu hasil /ppp active, logikanya terlihat sederhana.
Jika username ditemukan:
online
Jika tidak ditemukan:
offline
Tetapi ada syarat penting:
Kita hanya boleh mengambil kesimpulan tersebut jika pembacaan
/ppp activeberhasil.
Misalnya RouterOS memberikan response yang valid:
ahmad-fauzi
budi-toko
Kemudian account:
rina-rumah
tidak ditemukan.
Barulah kita dapat mengatakan:
rina-rumah = offline
Tetapi jika RouterOS timeout, kita tidak memiliki data yang cukup untuk mengambil kesimpulan.
Kesalahan yang Harus Dihindari: Router Timeout = Semua Offline
Ini salah satu bagian yang menurut saya paling penting dari monitoring ini.
Bayangkan router memiliki 500 pelanggan aktif.
Kemudian scheduler berjalan:
01:40:00
Tetapi RouterOS API timeout.
Jika code kita melakukan:
catch exception
↓
set semua pelanggan offline
maka dashboard tiba-tiba menampilkan:
Online : 0
Offline : 500
Padahal jaringan pelanggan mungkin tetap normal.
Yang gagal hanyalah:
Laravel → RouterOS API
Karena itu saya membedakan:
Connection Status Pelanggan
dengan:
Monitoring Status Router
Jika router tidak dapat dihubungi:
Router
status = unreachable
tetapi status pelanggan terakhir tetap dipertahankan.
Kondisi Monitoring Ketika Router Tidak Dapat Dihubungi
Flow yang saya gunakan secara konsep:
Scheduler
│
▼
Connect RouterOS
│
├── berhasil
│ │
│ ▼
│ /ppp active
│ │
│ ▼
│ sync account
│
└── gagal
│
▼
router = unreachable
│
▼
simpan error
│
▼
jangan ubah status pelanggan
Dengan begitu dashboard dapat menampilkan:
Router chr-lab-01
⚠ Monitoring unavailable
Last successful sync:
01:40:00
Ini jauh lebih informatif dibanding mengubah semua account menjadi offline.
Status Stale
Ada kondisi lain yang mulai menarik ketika monitoring dijalankan berkala.
Misalnya:
last successful sync
01:40
tetapi sekarang:
02:10
Berarti data connection status sudah berumur 30 menit.
Walaupun database mengatakan:
online
kita sebenarnya tidak tahu apakah status tersebut masih benar.
Karena itu pada UI nantinya kita dapat memiliki konsep:
Online
Offline
Unknown / Stale
Saya tidak harus langsung menambahkan status baru ke database.
UI dapat menghitungnya dari:
last_synced_at
Contohnya:
connection_status = online
tetapi
last_synced_at > 5 menit
Dashboard dapat menampilkan warning:
Status monitoring mungkin sudah tidak terbaru.
Dengan demikian kita tidak memberikan kesan bahwa data selalu realtime jika sinkronisasi sebenarnya sedang bermasalah.
Membuat Job SyncPppoeSessions
Seperti provisioning, saya juga memisahkan monitoring ke job.
Contohnya:
namespace App\Jobs;
use App\Models\Router;
use App\Services\MikroTik\PppoeMonitoringService;
class SyncPppoeSessions
{
public function __construct(
public int $routerId
) {
}
public function handle(
PppoeMonitoringService $service
): void {
$router = Router::findOrFail(
$this->routerId
);
$service->sync($router);
}
}
Kemudian job dapat dijalankan:
SyncPppoeSessions::dispatch(
$router->id
);
Keuntungannya sama seperti provisioning:
- proses tidak bergantung pada browser
- kegagalan dapat dicatat
- retry dapat dikontrol
- masing-masing router dapat memiliki job sendiri
- monitoring dapat dipindahkan ke worker
- proses lebih mudah diskalakan
Menjalankan Monitoring Menggunakan Laravel Scheduler
Setelah job tersedia, monitoring dapat dijalankan secara berkala.
Konsepnya:
Laravel Scheduler
│
│ setiap beberapa menit
▼
Dispatch Sync Job
│
▼
Queue Worker
│
▼
RouterOS
│
▼
Database
Contoh sederhananya:
use App\Jobs\SyncPppoeSessions;
use App\Models\Router;
use Illuminate\Support\Facades\Schedule;
Schedule::call(function () {
Router::query()
->where('is_active', true)
->each(function (Router $router) {
SyncPppoeSessions::dispatch(
$router->id
);
});
})->everyMinute();
Interval tersebut hanya contoh.
Frekuensi sebenarnya perlu disesuaikan dengan:
jumlah router
jumlah pelanggan
kapasitas server
latency jaringan
kebutuhan monitoring
beban RouterOS
Saya tidak ingin melakukan polling terlalu agresif hanya agar dashboard terlihat “realtime”.
Scheduler Bukan Berarti Browser Realtime
Ada perbedaan antara:
realtime
dan:
near realtime
Jika scheduler berjalan setiap satu menit, maka dashboard sebenarnya menampilkan status yang terakhir disinkronkan.
Misalnya:
01:40:00 → sync
01:40:25 → pelanggan disconnect
01:41:00 → sync berikutnya
Selama sekitar 35 detik database masih mungkin mengatakan pelanggan online.
Untuk kebutuhan dashboard billing, keterlambatan seperti ini biasanya masih dapat diterima tergantung kebutuhan operasional.
Karena itu saya lebih nyaman menyebut mekanisme ini:
periodic monitoring
atau:
near realtime monitoring
daripada mengklaim bahwa status selalu realtime.
Menampilkan Last Sync di Dashboard
Karena data berasal dari scheduler, saya ingin dashboard transparan mengenai kapan data terakhir diperbarui.
Contohnya:
PPPoE Monitoring
Router:
chr-lab-01
Status:
● Online
Last Sync:
beberapa detik lalu
Kemudian daftar pelanggan:
Customer Username IP Uptime Status
Ahmad Fauzi ahmad-fauzi 10.10.10.10 00:15:23 ● Online
Budi Santoso budi-toko 10.10.10.11 01:42:08 ● Online
Deni Irawan deni - - ○ Offline
Informasi Last Sync menurut saya penting.
Tanpa informasi tersebut admin dapat mengira data berasal langsung dari router pada detik yang sama.
Manual Sync dari Dashboard
Walaupun scheduler berjalan otomatis, saya juga dapat menyediakan tombol:
Sync Sekarang
Flow-nya bukan:
browser → langsung query router
melainkan:
Browser
│
▼
POST /routers/{router}/sync
│
▼
Laravel
│
▼
Dispatch SyncPppoeSessions
│
▼
Queue
API cukup memberikan response:
{
"success": true,
"message": "PPPoE synchronization has been queued."
}
Dashboard kemudian dapat melakukan refresh status beberapa saat kemudian.
Dengan demikian manual sync tetap menggunakan pipeline yang sama dengan scheduler.
Jangan Menjalankan Dua Sync pada Router yang Sama Bersamaan
Ketika scheduler dan tombol manual sync tersedia, muncul kemungkinan:
Scheduler
│
├── Sync chr-lab-01
│
Manual Sync
│
└── Sync chr-lab-01
berjalan pada waktu yang sama.
Untuk lab mungkin belum terasa.
Tetapi pada production saya ingin mencegah overlapping job untuk router yang sama.
Secara konsep:
router:chr-lab-01:pppoe-sync
dapat memiliki lock.
Sehingga:
Sync A sedang berjalan
│
▼
Sync B mencoba berjalan
│
▼
skip / retry kemudian
Tujuannya bukan hanya mengurangi beban router.
Kita juga menghindari dua proses menulis status monitoring pada waktu hampir bersamaan.
Bagaimana Jika Username Ada di Router tetapi Tidak Ada di Database?
Ada kemungkinan /ppp active mengembalikan:
legacy-user
tetapi database Laravel tidak mengenal username tersebut.
Artinya:
RouterOS
legacy-user
≠
Laravel
tidak ditemukan
Saya tidak ingin aplikasi otomatis membuat customer berdasarkan data tersebut.
Lebih aman mencatatnya sebagai:
Unmanaged PPP Session
atau:
Unknown Session
Kemudian administrator dapat memeriksanya.
Ini juga membantu menemukan akun lama yang dibuat secara manual melalui WinBox sebelum aplikasi billing digunakan.
Bagaimana Jika Satu Username Muncul Tidak Sesuai Router?
Karena setiap PPPoE account memiliki:
router_id
sinkronisasi harus dilakukan dalam scope router tersebut.
Jangan hanya mencari:
PppoeAccount::where(
'username',
$username
)->first();
tanpa memperhatikan router.
Lebih aman secara konsep:
PppoeAccount::where(
'router_id',
$router->id
)
->where(
'username',
$username
)
->first();
Karena ketika sistem berkembang menjadi multi-router, username yang sama mungkin saja muncul pada konteks router yang berbeda.
Multi-Router Monitoring
Pada awal lab saya hanya menggunakan:
chr-lab-01
Tetapi struktur monitoring sebaiknya tidak menganggap hanya akan ada satu router.
Contohnya nanti:
Laravel
│
├── chr-bandung-01
├── chr-bandung-02
├── router-jakarta-01
└── router-surabaya-01
Masing-masing router memiliki:
status
last_seen_at
last_sync_at
last_sync_error
Kemudian masing-masing memiliki job:
SyncPppoeSessions(router-1)
SyncPppoeSessions(router-2)
SyncPppoeSessions(router-3)
Dengan struktur ini kegagalan satu router tidak menghentikan monitoring router lainnya.
Jangan Polling Semua Router dalam Satu Request Panjang
Saya menghindari flow:
Sync command
│
├── router 1
├── router 2
├── router 3
├── router 4
├── router 5
└── router 6
secara sequential dalam satu proses panjang.
Jika router kedua timeout, proses menjadi lambat.
Saya lebih memilih:
Scheduler
│
├── Job Router 1
├── Job Router 2
├── Job Router 3
├── Job Router 4
├── Job Router 5
└── Job Router 6
Sehingga masing-masing router memiliki lifecycle job sendiri.
Logging Monitoring
Sama seperti provisioning, proses monitoring juga perlu log.
Contoh informasi:
timestamp
router_id
action
active_sessions
matched_accounts
unknown_sessions
duration
status
error
Contoh berhasil:
2026-09-22 01:40:00
router : chr-lab-01
action : sync_pppoe
active_sessions : 12
matched_accounts : 11
unknown_sessions : 1
status : success
duration : 310ms
Contoh gagal:
2026-09-22 01:41:00
router : chr-lab-01
action : sync_pppoe
status : failed
error : connection timeout
Informasi ini akan sangat membantu ketika admin mengatakan:
Kok pelanggan terlihat offline padahal internetnya jalan?
Kita dapat memeriksa apakah masalahnya berada pada pelanggan atau pada proses monitoring.
Jangan Simpan Credential pada Log Monitoring
Monitoring tidak membutuhkan password pelanggan.
Jadi log tidak perlu berisi:
PPPoE password
RouterOS password
API credential
Data yang dibutuhkan cukup:
username
router
status
address
uptime
timestamp
Credential tetap berada pada layer konfigurasi yang memang membutuhkannya.
Monitoring Dashboard
Setelah data tersimpan di database, dashboard tidak perlu berkomunikasi langsung dengan MikroTik.
Dashboard cukup membaca:
pppoe_accounts
routers
Contoh summary:
PPPoE Monitoring
Total Accounts
125
Online
97
Offline
28
Router Unreachable
0
Kemudian table:
Customer Username Router IP Address Status
Ahmad Fauzi ahmad-fauzi chr-lab-01 10.10.10.10 ● Online
Budi Santoso budi-toko chr-lab-01 10.10.10.11 ● Online
Deni Irawan deni chr-lab-01 - ○ Offline
Dari sisi aplikasi, ini jauh lebih sederhana daripada meminta browser melakukan query langsung ke setiap router.
Endpoint Monitoring
Jika frontend terpisah dari backend, endpoint monitoring dapat memberikan data seperti:
{
"success": true,
"data": {
"router": {
"name": "chr-lab-01",
"status": "online",
"last_sync_at": "2026-09-22T01:40:00+07:00"
},
"summary": {
"total": 3,
"online": 2,
"offline": 1
},
"accounts": [
{
"username": "ahmad-fauzi",
"connection_status": "online",
"ip_address": "10.10.10.10",
"uptime": "00:15:23",
"last_seen_at": "2026-09-22T01:40:00+07:00"
},
{
"username": "deni",
"connection_status": "offline",
"ip_address": null,
"uptime": null,
"last_seen_at": "2026-09-22T01:32:00+07:00"
}
]
}
}
Frontend tidak perlu mengetahui credential router ataupun cara RouterOS API bekerja.
Flow Monitoring Lengkap
Setelah seluruh bagian digabungkan, flow Part 5 menjadi:
Laravel Scheduler
│
▼
Dispatch SyncPppoeSessions
│
▼
Queue Worker
│
▼
PppoeMonitoringService
│
▼
RouterosClient
│
▼
MikroTik RouterOS
│
│
└── /ppp active print
│
▼
Active Sessions
│
▼
Match by Username
│
┌───────┴────────┐
│ │
ditemukan tidak ditemukan
│ │
▼ ▼
Online Offline
│ │
└───────┬────────┘
▼
Laravel Database
│
▼
Dashboard
Jika router gagal:
RouterOS Timeout
│
▼
Sync Failed
│
▼
Router = Unreachable
│
▼
Status pelanggan terakhir
TIDAK diubah
Bagian terakhir ini menurut saya merupakan salah satu aturan paling penting dalam monitoring.
Dari Online / Offline ke Last Seen
Dengan monitoring berkala, kita sekarang dapat mulai menjawab:
Apakah pelanggan online?
dan:
Kapan terakhir pelanggan terlihat online?
Misalnya:
Ahmad Fauzi
● Online
IP
10.10.10.10
Uptime
00:15:23
Last Seen
beberapa detik lalu
Sedangkan:
Deni Irawan
○ Offline
Last Seen
18 menit lalu
Informasi seperti ini nantinya juga berguna untuk troubleshooting customer support.
Apa yang Belum Dilakukan?
Sampai tahap ini monitoring baru menjawab:
siapa yang online?
siapa yang offline?
IP apa yang digunakan?
berapa uptime session?
kapan terakhir terlihat?
Kita belum menjawab:
berapa traffic RX?
berapa traffic TX?
berapa bandwidth saat ini?
berapa total pemakaian?
Saya sengaja belum memasukkan hal tersebut.
Karena monitoring status koneksi dan monitoring traffic memiliki karakteristik polling yang berbeda.
Traffic monitoring akan dibahas tersendiri pada Part 7.
Hasil Part 5
Sampai tahap ini flow aplikasi berkembang menjadi:
✓ Laravel terhubung RouterOS
✓ Laravel membaca system resource
✓ Laravel membaca PPP Active
✓ Laravel membuat PPP Secret
✓ provisioning memiliki status
✓ PPP Secret dan PPP Active dipisahkan
✓ session aktif disinkronkan ke database
✓ account dapat memiliki status online / offline
✓ IP address dapat disimpan
✓ uptime dapat ditampilkan
✓ last seen dapat disimpan
✓ monitoring berjalan melalui scheduler
✓ proses dapat dijalankan melalui queue
✓ router timeout tidak langsung membuat semua pelanggan offline
✓ status router dapat dimonitor
✓ struktur siap untuk multi-router
Jika Part 4 membuat Laravel mulai melakukan:
WRITE
ke MikroTik, maka Part 5 mulai membuat aplikasi memiliki:
OBSERVABILITY
terhadap koneksi pelanggan.
Selanjutnya: Suspend dan Reactivate Pelanggan
Setelah kita mengetahui:
pelanggan memiliki PPP Secret
dan:
pelanggan sedang online atau offline
pertanyaan berikutnya adalah:
Bagaimana jika pelanggan harus dihentikan sementara karena layanan disuspend?
Pada Part 6 saya akan melanjutkan ke proses suspend dan reactivate pelanggan.
Flow yang ingin dicapai:
Laravel Billing
│
│ suspend
▼
PPPoE Account
│
▼
MikroTik RouterOS
│
▼
Pelanggan tidak dapat menggunakan layanan
Kemudian setelah layanan diaktifkan kembali:
Payment / Admin
│
▼
Reactivate
│
▼
RouterOS
│
▼
Pelanggan dapat terkoneksi kembali
Bagian tersebut mulai menghubungkan lifecycle layanan pelanggan dengan konfigurasi jaringan.
Catatan dari Implementasi
Dari proses monitoring ini saya kembali menemukan bahwa integrasi aplikasi dengan perangkat jaringan tidak cukup hanya memikirkan:
online
dan:
offline
Kita juga harus mempertimbangkan:
router tidak dapat dihubungi
data monitoring sudah stale
scheduler tidak berjalan
queue worker berhenti
session ada tetapi account tidak dikenal
account ada tetapi session tidak ditemukan
dua sync berjalan bersamaan
satu router gagal tetapi router lain normal
Jika semua kondisi tersebut hanya diterjemahkan menjadi:
offline
dashboard justru dapat memberikan informasi yang menyesatkan.
Karena itu saya lebih memilih memisahkan:
status pelanggan
status router
status sinkronisasi
sebisa mungkin.
Dengan demikian ketika terjadi masalah, kita mempunyai informasi yang lebih jelas mengenai bagian mana yang sebenarnya gagal.
Penutup
Pada Part 4 saya mulai mengendalikan konfigurasi pelanggan dengan membuat PPP Secret dari Laravel.
Pada Part 5 ini arah komunikasinya kembali dari MikroTik menuju aplikasi.
Part 4
Laravel
│
│ WRITE
▼
MikroTik
Sekarang:
Part 5
MikroTik
│
│ SESSION STATE
▼
Laravel
Keduanya kemudian membentuk siklus:
Laravel
│
│ Provision
▼
MikroTik
│
│ Monitor
▼
Laravel
Menurut saya di titik ini aplikasi billing mulai terasa lebih hidup.
Kita tidak lagi hanya mengetahui bahwa pelanggan terdaftar, tetapi juga mulai mengetahui kondisi koneksi pelanggan dari router.
Pada Part berikutnya saya akan melanjutkan ke suspend dan reactivate pelanggan, sehingga aplikasi mulai dapat mengendalikan apakah layanan pelanggan boleh digunakan atau tidak.
Lanjut ke Part Berikutnya
Seri berikutnya:
Part 6 — Suspend dan Reactivate Pelanggan PPPoE dari Laravel
Pada bagian tersebut saya akan mencoba menyusun flow suspend dan reactivate dengan tetap memperhatikan sinkronisasi database, kondisi RouterOS, kegagalan request, dan kemungkinan pelanggan masih memiliki session aktif.
File pendukung dan resource lengkap untuk seri ini akan saya kumpulkan pada Part 10 setelah seluruh implementasi selesai.
Wallahu a’lam.

