Ravensburg.cam Live & Pi Tech

Webcam Portal

Live Dashboard mit Status-Abfrage, Response-Time & FTP-Proxy

Besucher heute (IP): 7

Anleitung & Quellcode zum Kopieren

Binde dein eigenes Webcam-Dashboard inklusive PHP-Proxy mit diesem Code direkt ein.

Einrichtungsanleitung in 3 Schritten:

  1. Erstelle eine Datei namens index.php und füge den Code aus dem ersten Fenster ein.
  2. Erstelle eine zweite Datei namens cam_proxy.php im selben Ordner mit dem Code aus dem zweiten Fenster.
  3. Stelle sicher, dass PHP cURL auf deinem Server aktiviert ist, damit die Bilder sicher per Proxy abgerufen werden können.
1. Frontend: index.php
<?php
// IP-Zähler (1x pro Tag per ips.txt)
$ipFile = __DIR__ . '/ips.txt';
$today = date('Y-m-d');
if (file_exists($ipFile) && date('Y-m-d', filemtime($ipFile)) !== $today) {
    file_put_contents($ipFile, '');
}
$userIp = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
$savedIps = file_exists($ipFile) ? file($ipFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) : [];
if (!in_array($userIp, $savedIps)) {
    file_put_contents($ipFile, $userIp . PHP_EOL, FILE_APPEND | LOCK_EX);
    $savedIps[] = $userIp;
}
$dailyVisitors = count($savedIps);
?>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>Webcam Dashboard</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body { background: #0f0f0f; color: #eee; }
        .card { background: #1b1b1b; border: none; }
        .cam-img { width: 100%; height: 240px; object-fit: cover; background: #000; border-radius: 6px; }
        .badge-online { background: #28a745; }
        .badge-offline { background: #dc3545; }
    </style>
</head>
<body class="p-4">

<div class="container">
    <div class="d-flex justify-content-between align-items-center mb-4">
        <h1>Live Webcams</h1>
        <span class="badge bg-secondary">Besucher heute: <?php echo $dailyVisitors; ?></span>
    </div>
    <div class="row" id="camGrid"></div>
</div>

<script>
const cams = [
    { name: "Kamera 1", url: "https://beispiel.de/cam1.jpg" },
    { name: "Kamera 2", url: "https://beispiel.de/cam2.jpg" }
];

function loadCam(index) {
    const cam = cams[index];
    const status = document.getElementById(`status-${index}`);
    const img = document.getElementById(`img-${index}`);
    const info = document.getElementById(`info-${index}`);

    fetch(`cam_proxy.php?cam=${encodeURIComponent(cam.url)}`)
        .then(r => r.json())
        .then(data => {
            if (data.status === "online") {
                status.textContent = "ONLINE";
                status.className = "badge badge-online";
                img.src = data.image;
                info.textContent = `Antwortzeit: ${data.response_time} ms`;
            } else {
                status.textContent = "OFFLINE";
                status.className = "badge badge-offline";
                img.src = "";
                info.textContent = "Keine Verbindung";
            }
        });
}
</script>
</body>
</html>
2. Backend: cam_proxy.php
<?php
header('Content-Type: application/json');

$camUrl = $_GET['cam'] ?? '';

if (empty($camUrl) || !filter_var($camUrl, FILTER_VALIDATE_URL)) {
    echo json_encode(['status' => 'offline', 'response_time' => 0]);
    exit;
}

$startTime = microtime(true);

$ch = curl_init($camUrl);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 5,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_USERAGENT      => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
]);

$imageData = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);

$responseTime = round((microtime(true) - $startTime) * 1000);

if ($httpCode === 200 && $imageData && !$error) {
    $base64 = 'data:image/jpeg;base64,' . base64_encode($imageData);
    echo json_encode([
        'status'        => 'online',
        'image'         => $base64,
        'response_time' => $responseTime,
        'timestamp'     => time()
    ]);
} else {
    echo json_encode([
        'status'        => 'offline',
        'response_time' => $responseTime
    ]);
}
?>