Was ist ein Shelly?
Der Shelly 1 ist ein vielseitiges, kleines Relaismodul, das speziell für Smart-Home-Anwendungen entwickelt wurde. Mit ihm lassen sich elektrische Geräte wie Lampen, Heizungen oder Ventilatoren steuern, indem er diese per WLAN ein- und ausschaltet. Der Shelly 1 wird direkt in die Stromleitung eingebaut und kann sowohl über die Shelly-App als auch über andere Smart-Home-Systeme gesteuert werden.
Ein großer Vorteil des Shelly 1 ist seine offene API-Schnittstelle, die Entwicklern erlaubt, ihn flexibel in eigene Systeme oder Projekte zu integrieren – sei es über MQTT, HTTP oder CoAP. Dadurch eignet sich der Shelly 1 nicht nur für Endanwender, sondern auch für Bastler und Entwickler, die ihre eigenen Automatisierungsideen umsetzen möchten.
Technische Highlights :
- WLAN-Steuerung : Direkt über das WLAN steuerbar, ohne zusätzliche Zentrale.
- Kompakte Größe : Passt in Standard-Unterputzdosen hinter Lichtschalter.
- Flexibilität : Unterstützt verschiedene Steuerungsprotokolle und kann auch lokal betrieben werden.
- Kompatibilität : Funktioniert mit Smart-Home-Plattformen wie Alexa, Google Home, Home Assistant und vielen mehr.
Shelly 1 ist bekannt für seine Benutzerfreundlichkeit und das hervorragende Preis-Leistungs-Verhältnis, was ihn zu einer beliebten Wahl für die Automatisierung im Smart Home macht.
Hier könnt ihr euch direkt beim Hersteller weiter informieren.
Ich habe immer noch ein paar Shelly 1 in der Kiste liegen und wollte euch zeigen, wie man sich ganz einfach mit dem ESP am Shelly anmeldet und mit http-Post-Protokoll die Schaltvorgänge auslösen kann.
Benötigte Teile und Konfiguration des Shelly
Shelly 1
ESP32
Arduino IDE oder VS Studio Code
Erst einmal muss der Shelly eingerichtet werden. Wichtig ist ja, dass dieser als Wireless Access Point arbeitet.
Der ESP32 soll sich ja als Client bei ihm anmelden können. Dafür schließt ihr den Shelly ans Stromnetz an. (Bitte beachtet, dass dies ein Fachmann ausführen sollte!) Sobald der Shelly im Betrieb ist, könnt Ihr euer Smartphone zur Hand nehmen und die verfügbaren WLAN-Netze durchsuchen. Da gibt es eins, was Shelly-irgendwas heißt.
Stellt diesen Wireless Access Point an eurem Smartphone ein und gebt in euren Browser die IP 192.168.33.1 ein.
Ihr landet direkt in der Oberfläche des Shelly und könnt unter Internet & Security->WIFI Mode-ACCESS Point den Namen und das Passwort vergeben. Diese Daten benötigen wir gleich in unserem Code.
Wie schaltet der ESP einen Shelly?
Um einen Schaltvorgang auslösen zu können, senden wir vom ESP32 über WIFI folgendes an den Shelly und bekommen auch eine Rückmeldung vom Shelly.
http://192.168.33.1/relay/0?turn=on; Antwort: {"ison":true,"has_timer":true,"timer_started":0,"timer_duration":3600,"timer_remaining":3600,"source":"http"} http://192.168.33.1/relay/0?turn=off; Antwort: {"ison":false,"has_timer":false,"timer_started":0,"timer_duration":0,"timer_remaining":0,"source":"http"}
Was uns besonders interessiert, ist das true oder false nach dem ison:. Damit haben wir die Rückmeldung erhalten, dass ein- oder ausgeschaltet wurde.
Der Code zum Schalten
// Einbinden benötigter Libraries #include <Arduino.h> #include <WiFi.h> #include <HTTPClient.h> //einige Konstanten hier WIFI Name und Passwort beispielhaft const char ssid[] = "shelly1-12BA14"; const char password[] = "shellyAP"; const char schalter_on[] = "http://192.168.33.1/relay/0?turn=on"; const char schalter_off[] = "http://192.168.33.1/relay/0?turn=off"; // Funktionsdeklarationen hier einfügen: void begin_wlan_client(); // WIFI-Verbindung hwerstellen String http_Post_Request(const char* url); // String für Post Request an Shelly void heizung_ein(); // Schaltvorgang ein void heizung_aus(); // Schaltvorgang aus // Setup - hier nur am Shelly anmelden void setup() { begin_wlan_client(); // WLAN-Verbindung starten } // Loop void loop() { // Beispiel für das Einschalten und Ausschalten der Heizung heizung_ein(); delay(10000); // Warte 10 Sekunden heizung_aus(); delay(10000); // Warte 10 Sekunden } // Funktionsdefinitionen hier einfügen: void begin_wlan_client() { WiFi.begin(ssid, password); Serial.begin(115200); // Zum Debuggen in der Konsole Serial.println("Verbindung zum WLAN herstellen..."); // Wartet, bis der ESP32 mit dem Shelly-WLAN verbunden ist while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Verbunden mit IP: "); Serial.println(WiFi.localIP()); } String http_Post_Request(const char* url) { HTTPClient http; http.begin(url); // Starte die HTTP-Verbindung int httpResponseCode = http.GET(); // Sende HTTP GET-Anfrage String payload = ""; // Leeres Payload für die Antwort if (httpResponseCode > 0) { payload = http.getString(); // Erhalte Antwort als String Serial.print("Antwort: "); Serial.println(payload); } else { Serial.print("Fehler bei der Anfrage, Fehlercode: "); Serial.println(httpResponseCode); } http.end(); // Beende die HTTP-Verbindung return payload; } void heizung_ein() { // Funktion zum Einschalten der Heizung Serial.println("Schalte Heizung ein..."); String payload = http_Post_Request(schalter_on); // mit indexOf nur das True oder false extrahieren int pos = payload.indexOf(':'); // Erstes ':' suchen, z.B. {"ison":true, int pos2 = payload.indexOf(','); String result = payload.substring(pos + 1, pos2); Serial.print("Antwort vom Shelly: "); Serial.println(result); if (result == "true") { Serial.println("Heizung erfolgreich eingeschaltet!"); Serial.println(); } else { Serial.println("Fehler beim Einschalten der Heizung."); Serial.println(); } } void heizung_aus() { // Funktion zum Ausschalten der Heizung Serial.println("Schalte Heizung aus..."); String payload = http_Post_Request(schalter_off); int pos = payload.indexOf(':'); int pos2 = payload.indexOf(','); String result = payload.substring(pos + 1, pos2); Serial.print("Antwort vom Shelly: "); Serial.println(result); if (result == "false") { Serial.println("Heizung erfolgreich ausgeschaltet!"); Serial.println(); } else { Serial.println("Fehler beim Ausschalten der Heizung."); Serial.println(); } }
#include <Arduino.h> #include <WiFi.h> #include <HTTPClient.h> #include <WebServer.h> const char ssid[] = "xxxx"; const char password[] = "xxxxxxxxxxxxxxx"; const char shelly_ip[] = "192.xxx.x.xxx"; // Beispiel IP-Adresse des Shelly im Heimnetzwerk String schalter_on = "/relay/0?turn=on"; String schalter_off = "/relay/0?turn=off"; WebServer server(80); // put function declarations here: void begin_wlan_client(); String http_Post_Request(const String& url); void heizung_ein(); void heizung_aus(); void handle_root(); void handle_heizung_ein(); void handle_heizung_aus(); void setup() { begin_wlan_client(); // WLAN-Verbindung starten // Webserver-Endpunkte definieren server.on("/", handle_root); server.on("/ein", handle_heizung_ein); server.on("/aus", handle_heizung_aus); server.begin(); Serial.println("Webserver gestartet."); } void loop() { server.handleClient(); } // put function definitions here: void begin_wlan_client() { WiFi.begin(ssid, password); Serial.begin(115200); // Zum Debuggen in der Konsole Serial.println("Verbindung zum WLAN herstellen..."); // Wartet, bis der ESP32 mit dem Heim-WLAN verbunden ist while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Verbunden mit IP: "); Serial.println(WiFi.localIP()); } String http_Post_Request(const String& url) { HTTPClient http; String fullUrl = "http://" + String(shelly_ip) + url; http.begin(fullUrl); // Starte die HTTP-Verbindung int httpResponseCode = http.GET(); // Sende HTTP GET-Anfrage String payload = ""; // Leeres Payload für die Antwort if (httpResponseCode > 0) { payload = http.getString(); // Erhalte Antwort als String Serial.print("Antwort: "); Serial.println(payload); } else { Serial.print("Fehler bei der Anfrage, Fehlercode: "); Serial.println(httpResponseCode); } http.end(); // Beende die HTTP-Verbindung return payload; } void heizung_ein() { // Funktion zum Einschalten der Heizung Serial.println("Schalte Heizung ein..."); String payload = http_Post_Request(schalter_on); int pos = payload.indexOf(':'); // Erstes ':' suchen, z.B. {"ison":true, int pos2 = payload.indexOf(','); String result = payload.substring(pos + 1, pos2); Serial.print("Antwort vom Shelly: "); Serial.println(result); if (result == "true") { Serial.println("Heizung erfolgreich eingeschaltet!"); Serial.println(); } else { Serial.println("Fehler beim Einschalten der Heizung."); Serial.println(); } } void heizung_aus() { // Funktion zum Ausschalten der Heizung Serial.println("Schalte Heizung aus..."); String payload = http_Post_Request(schalter_off); int pos = payload.indexOf(':'); int pos2 = payload.indexOf(','); String result = payload.substring(pos + 1, pos2); Serial.print("Antwort vom Shelly: "); Serial.println(result); if (result == "false") { Serial.println("Heizung erfolgreich ausgeschaltet!"); Serial.println(); } else { Serial.println("Fehler beim Ausschalten der Heizung."); Serial.println(); } } void handle_root() { String html = "<html><body style='text-align: center; display: flex; flex-direction: column; justify-content: center; height: 100vh;'>"; html += "<div style='margin-top: 10%;'>"; html += "<h1 style='text-align: center;'>ESP schaltet Shelly</h1>"; html += "<button style='font-size: 24px; width: 200px; height: 100px; background-color: green; color: white; margin: 20px;' onclick=\"location.href='/ein'\">Ein</button>"; html += "<button style='font-size: 24px; width: 200px; height: 100px; background-color: red; color: white; margin: 20px;' onclick=\"location.href='/aus'\">Aus</button>"; html += "<p id='status' style='font-size: 24px; margin-top: 40px;'></p>"; html += "</div>"; html += "</body></html>"; server.send(200, "text/html", html); } void handle_heizung_ein() { heizung_ein(); server.send(200, "text/html", "<html><body style='text-align: center; display: flex; flex-direction: column; justify-content: center; height: 100vh;'><div style='margin-top: 10%;'><h1>ESP schaltet Shelly</h1><p style='font-size: 24px; margin-top: 40px;'>Shelly Relais eingeschaltet</p><a href='/'>Zurück</a></div></body></html>"); } void handle_heizung_aus() { heizung_aus(); server.send(200, "text/html", "<html><body style='text-align: center; display: flex; flex-direction: column; justify-content: center; height: 100vh;'><div style='margin-top: 10%;'><h1>ESP schaltet Shelly</h1><p style='font-size: 24px; margin-top: 40px;'>Shelly Relais ist ausgeschaltet</p><a href='/'>Zurück</a></div></body></html>"); }
Die Ausgabe der seriellen Schnittstelle
Verbindung zum WLAN herstellen…
E (550) wifi:Set status to INIT
……..
Verbunden mit IP: 192.168.33.3
Schalte Heizung ein…
Antwort: {„ison“:true,“has_timer“:true,“timer_started“:0,“timer_duration“:3600,“timer_remaining“:3600,“source“:“http“}
Antwort vom Shelly: true
Heizung erfolgreich eingeschaltet!
Schalte Heizung aus…
Antwort: {„ison“:false,“has_timer“:false,“timer_started“:0,“timer_duration“:0,“timer_remaining“:0,“source“:“http“}
Antwort vom Shelly: false
Heizung erfolgreich ausgeschaltet!
Schalte Heizung ein…
Antwort: {„ison“:true,“has_timer“:true,“timer_started“:0,“timer_duration“:3600,“timer_remaining“:3600,“source“:“http“}
Antwort vom Shelly: true
Heizung erfolgreich eingeschaltet!
Schalte Heizung aus…
Antwort: {„ison“:false,“has_timer“:false,“timer_started“:0,“timer_duration“:0,“timer_remaining“:0,“source“:“http“}
Antwort vom Shelly: false
Heizung erfolgreich ausgeschaltet!
Wichtig ist mir, dass ich eine saubere Rückmeldung vom Shelly bekomme, damit das Schalten in der Ferne möglich ist.
In diesem DIYTechAdventure habe ich dir gezeigt, wie du mit einem ESP32 Schaltvorgänge am Shelly auslösen kannst. Anwendungen hierzu gibt es viele. Schalten einer Heizung nach Messung der Temperatur mit einem Sensor am ESP. Schalten von Licht und so weiter.
Im nächsten DIYTechAdventure zeige ich, wie der Shelly per Handy geschaltet werden kann.
Schreibe mir in den Kommentaren, wie dir dieses Adventure gefällt. Gerne stelle auch deine Fragen.