-
Autor
Den Programmcode auf einem Webserver (mit PHP-Unterstützung) in eine php-Datei einfügen.
Das Skript erkennt automatisch um welchen Typ des Shelly PlugS es sich handelt.
Mit Schaltfunktion, Statusanzeige und Anzeige der Verfügbarkeit.
Die IP-Adressen und Namen im Code anpassen.
Die Shelly's und der Webserver müssen natürlich Kontakt zueinander haben.
PHP
<?php
// Steckdosen-Liste - hier namen und IP-Adressen anpassen
$devices = [
['name' => 'Shelly PlugS 01', 'ip' => '192.168.178.10'],
['name' => 'Shelly PlugS 02', 'ip' => '192.168.178.11'],
['name' => 'Shelly PlugS 03', 'ip' => '192.168.178.12'],
['name' => 'Shelly PlugS 04', 'ip' => '192.168.178.13'],
['name' => 'Shelly PlugS 05', 'ip' => '192.168.178.14'],
['name' => 'Shelly PlugS 06', 'ip' => '192.168.178.15'],
['name' => 'Shelly PlugS 07', 'ip' => '192.168.178.16'],
['name' => 'Shelly PlugS 08', 'ip' => '192.168.178.17'],
['name' => 'Shelly PlugS 09', 'ip' => '192.168.178.18'],
['name' => 'Shelly PlugS 10', 'ip' => '192.168.178.19'],
['name' => 'Shelly PlugS 11', 'ip' => '192.168.178.20'],
['name' => 'Shelly PlugS 12', 'ip' => '192.168.178.21'],
['name' => 'Shelly PlugS 13', 'ip' => '192.168.178.22'],
['name' => 'Shelly PlugS 14', 'ip' => '192.168.178.23'],
// Weitere Geräte hinzufügen...
];
// Funktion für parallele Statusabfragen
function getShellyStatuses($devices) {
$results = [];
foreach ($devices as $device) {
$ip = $device['ip'];
// Zuerst die Gen2-API versuchen
$urlGen2 = "http://$ip/rpc/Switch.GetStatus?id=0";
$responseGen2 = sendCurlRequest($urlGen2);
if ($responseGen2 !== false) {
$data = json_decode($responseGen2, true);
if (isset($data['output'])) {
$results[$ip] = [
'reachable' => true,
'output' => $data['output'],
'gen1' => false
];
continue;
}
}
// Falls die Gen2-API fehlschlägt, die Gen1-API versuchen
$urlGen1 = "http://$ip/relay/0";
$responseGen1 = sendCurlRequest($urlGen1);
if ($responseGen1 !== false) {
$data = json_decode($responseGen1, true);
if (isset($data['ison'])) {
$results[$ip] = [
'reachable' => true,
'output' => $data['ison'],
'gen1' => true
];
continue;
}
}
// Gerät ist nicht erreichbar
$results[$ip] = ['reachable' => false, 'output' => false];
}
return $results;
}
// Hilfsfunktion für CURL-Anfragen
function sendCurlRequest($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1); // Maximal 2 Sekunden für Verbindung
curl_setopt($ch, CURLOPT_TIMEOUT, 2); // Maximal 3 Sekunden für gesamte Abfrage
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
// Funktion zum Schalten der Steckdose
function setShellySwitch($ip, $turn_on, $gen1 = false) {
if ($gen1) {
$url = "http://$ip/relay/0";
$data = ['turn' => $turn_on ? 'on' : 'off'];
$postFields = http_build_query($data);
} else {
$url = "http://$ip/rpc/Switch.Set";
$data = json_encode(["id" => 0, "on" => $turn_on]);
$postFields = $data;
}
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
if (!$gen1) {
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
}
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
curl_exec($ch);
curl_close($ch);
}
// Schalten bei POST-Anfrage
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ip'], $_POST['action'])) {
$ip = $_POST['ip'];
$turn_on = $_POST['action'] === 'on';
$gen1 = isset($_POST['gen1']) && $_POST['gen1'] === '1';
setShellySwitch($ip, $turn_on, $gen1);
header("Location: " . $_SERVER['REQUEST_URI']); // Seite neu laden
exit();
}
// Geräte-Status abrufen
$statuses = getShellyStatuses($devices);
// Sicherstellen, dass $statuses ein Array ist
if (!is_array($statuses)) {
$statuses = []; // Standardwert bei Fehler
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="refresh" content="15"> <!-- Automatischer Reload alle 15 Sekunden -->
<title>Shelly Steuerung</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 10px;
padding: 10px;
}
.device {
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
text-align: center;
font-size: 14px;
background-color: #f9f9f9;
}
.status {
margin-bottom: 10px;
font-weight: bold;
}
.btn {
padding: 5px 10px;
font-size: 18px;
text-align: center;
border: none;
border-radius: 3px;
cursor: pointer;
margin: 2px;
}
.btn-on {
background-color: #4CAF50;
color: white;
}
.btn-off {
background-color: #f44336;
color: white;
}
.btn-disabled {
background-color: #ccc;
color: #666;
cursor: not-allowed;
}
</style>
</head>
<body>
<div class="container">
<?php foreach ($devices as $device):
$ip = $device['ip'];
$status = $statuses[$ip] ?? ['reachable' => false, 'output' => false];
$is_reachable = $status['reachable'];
$is_on = $status['output'];
$gen1 = $status['gen1'] ?? false;
$status_text = $is_reachable ? ($is_on ? 'EIN' : 'AUS') : '';
$status_color = $is_reachable ? ($is_on ? 'green' : 'red') : 'gray';
?>
<div class="device">
<div class="status" style="color: <?= $status_color ?>;">
<?= htmlspecialchars($device['name']) ?>: <?= $status_text ?>
</div>
<div>
<form method="post" style="display: inline;">
<input type="hidden" name="ip" value="<?= htmlspecialchars($ip) ?>">
<input type="hidden" name="gen1" value="<?= $gen1 ? '1' : '0' ?>">
<button type="submit" name="action" value="on"
class="btn btn-on <?= !$is_reachable ? 'btn-disabled' : '' ?>"
<?= !$is_reachable ? 'disabled' : '' ?>>EIN</button>
</form>
<form method="post" style="display: inline;">
<input type="hidden" name="ip" value="<?= htmlspecialchars($ip) ?>">
<input type="hidden" name="gen1" value="<?= $gen1 ? '1' : '0' ?>">
<button type="submit" name="action" value="off"
class="btn btn-off <?= !$is_reachable ? 'btn-disabled' : '' ?>"
<?= !$is_reachable ? 'disabled' : '' ?>>AUS</button>
</form>
</div>
</div>
<?php endforeach; ?>
</div>
</body>
</html>
Alles anzeigen
Viel Spaß beim Experimentieren.