1. Grundidee
Der Shelly Plus 1 kann über seine lokale Web-API angesprochen werden. Für einfache Projekte ist die Kommunikation über HTTP/RPC am übersichtlichsten.
Ein einfacher HTTP-Aufruf zum Einschalten des Relais sieht so aus:
http://192.168.178.55/rpc/Switch.Set?id=0&on=true
switch:0. Die wichtigsten RPC-Befehle sind Switch.Set, Switch.Toggle, Switch.GetStatus und Shelly.GetStatus.
2. Browser-Test vor dem Programmieren
Bevor der ESP32 ins Spiel kommt, sollten die Befehle im Browser getestet werden. Das vermeidet viele kleine Fehler mit großer Wirkung.
http://SHELLY-IP/rpc/Shelly.GetStatus
http://SHELLY-IP/rpc/Switch.Set?id=0&on=true
http://SHELLY-IP/rpc/Switch.Set?id=0&on=false
http://SHELLY-IP/rpc/Switch.Toggle?id=0
http://SHELLY-IP/rpc/Switch.GetStatus?id=0
3. ESP32 schaltet Shelly ein
import network
import urequests
import time
WIFI_SSID = "DEIN_WLAN"
WIFI_PASS = "DEIN_PASSWORT"
SHELLY_IP = "192.168.178.55"
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(WIFI_SSID, WIFI_PASS)
while not wlan.isconnected():
print("Verbinde mit WLAN...")
time.sleep(0.5)
print("Verbunden:", wlan.ifconfig())
url = "http://{}/rpc/Switch.Set?id=0&on=true".format(SHELLY_IP)
response = urequests.get(url)
print(response.text)
response.close()
4. ESP32 schaltet Shelly aus
import urequests
SHELLY_IP = "192.168.178.55"
url = "http://{}/rpc/Switch.Set?id=0&on=false".format(SHELLY_IP)
response = urequests.get(url)
print(response.text)
response.close()
5. Shelly umschalten - Toggle
Dieser Befehl ist besonders praktisch für Taster: Jeder Aufruf wechselt den Schaltzustand.
import urequests
SHELLY_IP = "192.168.178.55"
url = "http://{}/rpc/Switch.Toggle?id=0".format(SHELLY_IP)
response = urequests.get(url)
print(response.text)
response.close()
6. Zustand des Shelly abfragen
Mit Shelly.GetStatus kann man den Gesamtstatus des Shelly abrufen.
import urequests
import json
SHELLY_IP = "192.168.178.55"
url = "http://{}/rpc/Shelly.GetStatus".format(SHELLY_IP)
response = urequests.get(url)
data = response.json()
response.close()
print(data)
# Relaiszustand auslesen
relais_an = data["switch:0"]["output"]
print("Relais ist an:", relais_an)
Typischer Ausschnitt aus der Antwort:
{
"switch:0": {
"id": 0,
"output": true
},
"input:0": {
"id": 0,
"state": false
}
}
7. Nur Relaisstatus abfragen
import urequests
SHELLY_IP = "192.168.178.55"
url = "http://{}/rpc/Switch.GetStatus?id=0".format(SHELLY_IP)
response = urequests.get(url)
data = response.json()
response.close()
print("Antwort:", data)
print("Relais an:", data["output"])
8. ESP32-Taster schaltet Shelly
Schülerfreundliches Beispiel: Ein Taster am ESP32 löst einen HTTP-Request aus, der das Shelly-Relais umschaltet.
import network
import urequests
import time
from machine import Pin
WIFI_SSID = "DEIN_WLAN"
WIFI_PASS = "DEIN_PASSWORT"
SHELLY_IP = "192.168.178.55"
button = Pin(14, Pin.IN, Pin.PULL_UP)
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(WIFI_SSID, WIFI_PASS)
while not wlan.isconnected():
print("Verbinde mit WLAN...")
time.sleep(0.5)
print("ESP32 verbunden:", wlan.ifconfig())
alter_zustand = 1
while True:
zustand = button.value()
# Taster gedrückt: Wechsel von 1 nach 0
if alter_zustand == 1 and zustand == 0:
print("Taster gedrückt - Shelly wird umgeschaltet")
try:
url = "http://{}/rpc/Switch.Toggle?id=0".format(SHELLY_IP)
response = urequests.get(url)
print(response.text)
response.close()
except Exception as e:
print("Fehler:", e)
time.sleep(0.3) # Entprellen
alter_zustand = zustand
time.sleep(0.05)
9. Shelly schaltet ESP32 per HTTP
Die Kommunikation kann auch umgekehrt laufen: Der Shelly ruft eine Adresse auf dem ESP32 auf.
ESP32 als einfacher Webserver
import network
import socket
from machine import Pin
import time
WIFI_SSID = "DEIN_WLAN"
WIFI_PASS = "DEIN_PASSWORT"
led = Pin(2, Pin.OUT)
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(WIFI_SSID, WIFI_PASS)
while not wlan.isconnected():
print("Verbinde mit WLAN...")
time.sleep(0.5)
print("ESP32 IP:", wlan.ifconfig()[0])
addr = socket.getaddrinfo("0.0.0.0", 80)[0][-1]
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(1)
print("Webserver läuft...")
while True:
cl, addr = s.accept()
request = cl.recv(1024).decode()
print(request)
if "/led/on" in request:
led.on()
antwort = "LED eingeschaltet"
elif "/led/off" in request:
led.off()
antwort = "LED ausgeschaltet"
else:
antwort = "ESP32 bereit"
cl.send("HTTP/1.1 200 OK\r\n")
cl.send("Content-Type: text/plain\r\n")
cl.send("Connection: close\r\n\r\n")
cl.send(antwort)
cl.close()
Test im Browser, wenn der ESP32 zum Beispiel die IP 192.168.178.60 hat:
http://192.168.178.60/led/on
http://192.168.178.60/led/off
Im Shelly kann dann eine Action beziehungsweise ein Webhook eingerichtet werden, der diese URL aufruft.
10. ESP32 fragt Shelly regelmäßig ab
Damit kann der ESP32 zum Beispiel mit einer LED anzeigen, ob das Shelly-Relais gerade eingeschaltet ist.
import network
import urequests
import time
WIFI_SSID = "DEIN_WLAN"
WIFI_PASS = "DEIN_PASSWORT"
SHELLY_IP = "192.168.178.55"
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(WIFI_SSID, WIFI_PASS)
while not wlan.isconnected():
print("Verbinde...")
time.sleep(0.5)
while True:
try:
url = "http://{}/rpc/Switch.GetStatus?id=0".format(SHELLY_IP)
response = urequests.get(url)
data = response.json()
response.close()
print("Shelly Relais:", data["output"])
except Exception as e:
print("Fehler bei Abfrage:", e)
time.sleep(5)
11. Sicheres Einschalten mit Auto-Aus
Für Pumpen, Magnetventile oder Experimente ist ein automatisches Ausschalten sinnvoll.
import urequests
SHELLY_IP = "192.168.178.55"
url = "http://{}/rpc/Switch.Set?id=0&on=true&toggle_after=10".format(SHELLY_IP)
response = urequests.get(url)
print(response.text)
response.close()
12. Didaktische Reihenfolge für die AG
- Browser-Test: Shelly-IP herausfinden und RPC-Befehle im Browser testen.
- ESP32 sendet HTTP-Requests: ESP32 steuert den Shelly.
- Tasterprojekt: Taster am ESP32 schaltet Shelly-Relais.
- Statusabfrage: ESP32 liest den Relaiszustand aus.
- Rückrichtung: Shelly ruft ESP32-Webserver per HTTP auf.
- Sicherheitslogik: Automatisches Ausschalten mit
toggle_after.