Site icon IT Blog

Script for polling ONU RX Power from BDCOM OLT

When connecting new subscribers, operators needed to check the optical level of the new ONU. ONUs didn’t appear immediately in the billing system. So, I first enabled a web interface on the OLT with limited access via ACL and a separate account with read permissions. However, the web interface page often opened with significant delays. So, I wrote a PHP script that displays the optical levels of all ONUs in a couple of seconds.

The script content has room for improvement and addition, but it already works (initial version 1.0):

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

$olts = [
    'olt_1' => ['name' => 'City 1',    'ip' => '192.168.5.1', 'community' => 'public'],
    'olt_2' => ['name' => 'City 2',    'ip' => '192.168.44.2', 'community' => 'public'],
    'olt_3' => ['name' => 'ixnfo.com',    'ip' => '192.168.12.3', 'community' => 'public'],
];

$oids = [
    'ifdescr' => "1.3.6.1.2.1.2.2.1.2",
    'ifindex' => "1.3.6.1.2.1.17.1.4.1.2",
    'mac'     => "1.3.6.1.4.1.3320.101.10.1.1.3",
    'rx'      => "1.3.6.1.4.1.3320.101.10.5.1.5",
    'model'   => "1.3.6.1.4.1.3320.101.10.1.1.2",
    'vendor'  => "1.3.6.1.4.1.3320.101.10.1.1.1"
];

$selected_olt_key = $_POST['olt_select'] ?? null;
$data = [];
$error = null;

// The poll occurs ONLY if OLT is selected from the list
if ($selected_olt_key && isset($olts[$selected_olt_key])) {
    $ip = $olts[$selected_olt_key]['ip'];
    $community = $olts[$selected_olt_key]['community'];

    // Execute requests
    $raw_data = [];
    foreach ($oids as $key => $oid) {
        $walk = @snmprealwalk($ip, $community, $oid);
        if ($walk === false && $key === 'mac') {
            $error = "Unable to retrieve data from OLT $ip. Please check your connection or Community.";
            break;
        }
        $raw_data[$key] = $walk ?: [];
    }

    if (!$error) {
        // Parsing the received data
        foreach ($raw_data['ifdescr'] as $oid => $val) {
            $idx = substr(strrchr($oid, "."), 1);
            $data[$idx]['ifdescr'] = trim($val, '" ');
        }
        foreach ($raw_data['ifindex'] as $oid => $val) {
            $idx = substr(strrchr($oid, "."), 1);
            $data[$idx]['ifindex'] = intval($val);
        }
        foreach ($raw_data['mac'] as $oid => $val) {
            $idx = substr(strrchr($oid, "."), 1);
            $data[$idx]['mac'] = strtoupper(str_replace(" ", ":", trim(str_replace(["Hex-STRING:", "\""], "", $val))));
        }
        foreach ($raw_data['rx'] as $oid => $val) {
            $idx = substr(strrchr($oid, "."), 1);
            $val_num = intval(str_replace("INTEGER:", "", $val));
            $data[$idx]['rx'] = ($val_num != 0) ? ($val_num / 10) . " dBm" : "N/A";
        }
        foreach ($raw_data['model'] as $oid => $val) {
            $idx = substr(strrchr($oid, "."), 1);
            $data[$idx]['model'] = trim($val, '" ');
        }
        foreach ($raw_data['vendor'] as $oid => $val) {
            $idx = substr(strrchr($oid, "."), 1);
            $data[$idx]['vendor'] = trim($val, '" ');
        }
        ksort($data);
    }
}
?>

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>ONU Signal Monitor</title>
    <style>
        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #f0f2f5; padding: 20px; }
        .container { max-width: 1100px; margin: 0 auto; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
        .header-form { text-align: center; border-bottom: 2px solid #eee; padding-bottom: 20px; margin-bottom: 20px; }
        select { padding: 10px; width: 300px; border-radius: 5px; border: 1px solid #ccc; font-size: 16px; }
        button { padding: 10px 20px; background: #28a745; color: #fff; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; }
        button:hover { background: #218838; }
        table { border-collapse: collapse; width: 100%; margin-top: 20px; }
        th, td { border: 1px solid #dee2e6; padding: 12px; text-align: center; }
        th { background: #343a40; color: #fff; }
        tr:nth-child(even) { background: #f8f9fa; }
        .low-signal { color: #dc3545; font-weight: bold; }
        .error-msg { color: #721c24; background: #f8d7da; padding: 15px; border-radius: 5px; text-align: center; }
        .info-msg { text-align: center; color: #666; font-style: italic; }
    </style>
</head>
<body>

<div class="container">
    <div class="header-form">
        <form method="POST">
            <label for="olt_select"><strong>Select a device to poll:</strong></label><br><br>
            <select name="olt_select" id="olt_select">
                <option value="">-- OLT --</option>
                <?php foreach ($olts as $key => $info): ?>
                    <option value="<?= $key ?>" <?= ($selected_olt_key == $key) ? 'selected' : '' ?>>
                        <?= htmlspecialchars($info['name']) ?> (<?= $info['ip'] ?>)
                    </option>
                <?php endforeach; ?>
            </select>
            <button type="submit">OK</button>
        </form>
    </div>

    <?php if ($error): ?>
        <div class="error-msg"><?= $error ?></div>
    <?php elseif ($selected_olt_key && !empty($data)): ?>
        <h3 style="text-align:center;">Results for <?= htmlspecialchars($olts[$selected_olt_key]['name']) ?></h3>
        <table>
            <tr>
                <th>Index</th>
                <th>ifDescr</th>
                <th>MAC Address</th>
                <th>RX Power</th>
                <th>Model / Vendor</th>
            </tr>
<?php foreach ($data as $idx => $row): 
    if (empty($row['mac'])) continue;

    // Fixing Warning: Checking for the presence of the 'rx' key
    $rx_raw = $row['rx'] ?? '0'; 
    $rx_val = floatval($rx_raw);
    
    // Bad signal highlighting
    $rx_class = ($rx_val < -25 && $rx_val != 0) ? 'class="low-signal"' : '';
?>
<tr>
    <td><?= $idx ?></td>
    <td><?= $row['ifdescr'] ?? '-' ?></td>
    <td><code><?= $row['mac'] ?? '-' ?></code></td>
    <td <?= $rx_class ?>><?= $row['rx'] ?? 'N/A' ?></td>
    <td><?= ($row['vendor'] ?? '') . " " . ($row['model'] ?? '') ?></td>
</tr>
<?php endforeach; ?>
        </table>
    <?php elseif ($selected_olt_key): ?>
        <div class="info-msg">Data not found or device did not respond.</div>
    <?php else: ?>
    <?php endif; ?>
</div>

</body>
</html>

See also my other scripts

Exit mobile version