314 lines
8.1 KiB
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
|
|
]); |