WEB_PROJECT_TA/api/laporan_odp.php

314 lines
8.1 KiB
PHP

<?php
require_once __DIR__ . '/../config/database.php';
header('Content-Type: application/json');
$db = new Database();
$conn = $db->getConnection();
if (isset($_GET['kirim']) && isset($_GET['id'])) {
function kirimWA($pesan) {
$token = "XjC9oSr4jECWG93JQRWf";
$data = [
"target" => "120363407747513164@g.us",
"message" => $pesan,
];
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fonnte.com/send",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_HTTPHEADER => [
"Authorization: $token"
],
]);
curl_exec($curl);
curl_close($curl);
}
$id = $_GET['id'];
// 🔥 ambil ODP
$stmt = $conn->prepare("
SELECT i.id, i.name, i.latitude, i.longitude
FROM ftth_items i
WHERE i.id = ?
");
$stmt->execute([$id]);
$odp = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$odp) {
echo json_encode(['success' => false]);
exit;
}
// 🔥 ambil client
$stmtClient = $conn->prepare("
SELECT fi.id, fi.name, fi.serial_number
FROM cable_routes cr
JOIN ftth_items fi
ON (cr.to_item_id = fi.id OR cr.from_item_id = fi.id)
WHERE (cr.from_item_id = :id OR cr.to_item_id = :id)
AND fi.id != :id
");
$stmtClient->bindParam(':id', $id);
$stmtClient->execute();
$clients = $stmtClient->fetchAll(PDO::FETCH_ASSOC);
$rxValues = [];
$clientBad = [];
foreach ($clients as $c) {
if (empty($c['serial_number'])) continue;
$query = json_encode(["_id" => $c['serial_number']]);
$url = "http://rmtstb.megadataisp.net:7557/devices/?query=" . urlencode($query);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$res = curl_exec($ch);
curl_close($ch);
if (!$res) continue;
$json = json_decode($res, true);
if (
isset($json[0]['VirtualParameters']['RXPower']['_value']) &&
is_numeric($json[0]['VirtualParameters']['RXPower']['_value'])
) {
$rx = floatval($json[0]['VirtualParameters']['RXPower']['_value']);
$rxValues[] = $rx;
if ($rx < -23) {
$clientBad[] = $c['name'] . " (" . $rx . " dBm)";
}
}
}
// 🔥 HITUNG
$total = count($rxValues);
$bad = count($clientBad);
$good = $total - $bad;
$avg = $total > 0 ? round(array_sum($rxValues) / $total, 2) : '-';
$min = $total > 0 ? min($rxValues) : '-';
// 🔥 STATUS
$status = "BAIK";
if ($total == 0) {
$status = "NO DATA";
} elseif ($min < -27) {
$status = "KRITIS";
} elseif ($avg < -25 || $bad > ($total * 0.5)) {
$status = "BURUK";
} elseif ($avg < -23 || $bad > ($total * 0.3)) {
$status = "WARNING";
}
// 🔥 FORMAT WA
$maps = "https://www.google.com/maps?q={$odp['latitude']},{$odp['longitude']}";
$pesan = "🚨 *LAPORAN ODP*\n\n";
$pesan .= "📍 *ODP:* {$odp['name']}\n";
$pesan .= "📊 *Status:* {$status}\n\n";
$pesan .= "👥 *Total Client:* {$total}\n";
$pesan .= "🟢 Client Baik: {$good}\n";
$pesan .= "🔴 Client Buruk: {$bad}\n\n";
$pesan .= "📶 *AVG RX:* {$avg} dBm\n";
$pesan .= "📉 *MIN RX:* {$min} dBm\n\n";
if (!empty($clientBad)) {
$pesan .= "⚠ *Client Bermasalah:*\n";
$pesan .= implode("\n", array_slice($clientBad, 0, 10));
$pesan .= "\n\n";
}
$pesan .= "📌 Lokasi:\n$maps\n\n";
$pesan .= "🔎 Silakan cek detail di dashboard.";
kirimWA($pesan);
echo json_encode(['success' => true]);
exit;
}
// ✅ Ambil semua ODP
$stmt = $conn->query("
SELECT i.id, i.name, i.latitude, i.longitude
FROM ftth_items i
LEFT JOIN item_types it ON i.item_type_id = it.id
WHERE LOWER(it.name) = 'odp'
AND i.user_id = 22
");
$odps = $stmt->fetchAll(PDO::FETCH_ASSOC);
$result = [];
foreach ($odps as $odp) {
// ✅ ambil client
$stmtClient = $conn->prepare("
SELECT fi.id, fi.name, fi.serial_number
FROM cable_routes cr
JOIN ftth_items fi
ON (cr.to_item_id = fi.id OR cr.from_item_id = fi.id)
WHERE (cr.from_item_id = :id OR cr.to_item_id = :id)
AND fi.id != :id
");
$stmtClient->bindParam(':id', $odp['id']);
$stmtClient->execute();
$clients = $stmtClient->fetchAll(PDO::FETCH_ASSOC);
$rxValues = [];
$rxList = [];
$rxBadList = [];
$clientBad = [];
foreach ($clients as $c) {
if (empty($c['serial_number'])) continue;
$query = json_encode(["_id" => $c['serial_number']]);
$url = "http://rmtstb.megadataisp.net:7557/devices/?query=" . urlencode($query);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$res = curl_exec($ch);
curl_close($ch);
if (!$res) continue;
$json = json_decode($res, true);
if (
isset($json[0]['VirtualParameters']['RXPower']['_value']) &&
is_numeric($json[0]['VirtualParameters']['RXPower']['_value'])
) {
$rx = floatval($json[0]['VirtualParameters']['RXPower']['_value']);
$rxValues[] = $rx;
$rxList[] = $rx;
if ($rx < -23) {
$rxBadList[] = $rx;
$clientBad[] = $c['name'] . " (" . $rx . " dBm)";
}
}
}
// 🔴 Tidak ada data
if (count($rxValues) == 0) {
$result[] = [
'id' => $odp['id'],
'nama' => $odp['name'],
'lat' => $odp['latitude'],
'lng' => $odp['longitude'],
'total' => 0,
'avg_rx' => null,
'bad_count' => 0,
'min_rx' => null,
'status' => 'NO DATA',
'status_color' => 'secondary',
'analisa' => 'Tidak ada data pelanggan / ONU offline semua'
];
continue;
}
$total = count($rxValues);
$avg = array_sum($rxValues) / $total;
$min = min($rxValues);
$bad = count($rxBadList);
// 🔥 DETEKSI SELISIH
$selisih = abs($avg - $min);
// 🔥 STATUS
$status = "BAIK";
$color = "success";
if ($selisih > 1.5) {
$status = "WARNING";
$color = "warning";
}
if ($avg < -23 || $bad > ($total * 0.3)) {
$status = "WARNING";
$color = "warning";
}
if ($avg < -25 || $bad > ($total * 0.5)) {
$status = "BURUK";
$color = "danger";
}
if ($min < -27) {
$status = "KRITIS";
$color = "dark";
}
// 🔥 ANALISA + TAMBAHAN INFORMASI CLIENT
if ($min < ($avg - 1.5)) {
$analisa = "Ada client lebih jelek dari yang lain → kemungkinan IKR/dropcore bermasalah";
}
elseif ($status === "KRITIS") {
$analisa = "Banyak RX < -27 dBm → kemungkinan feeder/ODP bermasalah";
}
elseif ($status === "BURUK") {
$analisa = "Lebih dari 50% client jelek → indikasi splitter ODP / konektor kotor";
}
elseif ($status === "WARNING") {
$analisa = "Sebagian client jelek → kemungkinan jalur ke rumah";
}
else {
$analisa = "Semua pelanggan normal";
}
// 🔥 TAMBAHKAN DETAIL RX & CLIENT BURUK KE ANALISA
$analisa .= " | RX: " . implode(", ", $rxList);
if (!empty($clientBad)) {
$analisa .= " | Client bermasalah: " . implode(", ", $clientBad);
}
$result[] = [
'id' => $odp['id'],
'nama' => $odp['name'],
'lat' => $odp['latitude'],
'lng' => $odp['longitude'],
'total' => $total,
'avg_rx' => round($avg, 2),
'bad_count' => $bad,
'min_rx' => $min,
'status' => $status,
'status_color' => $color,
'analisa' => $analisa
];
}
echo json_encode([
'success' => true,
'data' => $result
]);