Shelly Plus Add-on Messwerte mit ESP32 abfragen

Überblick

Diese Seite zeigt praktische HTTP- und RPC-Abfragen für Messwerte des Shelly Plus Add-on. Die Beispiele decken Temperatur, Luftfeuchte, Analogwert, Spannung und Eingangszustand ab.

Das Shelly Plus Add-on ist kein eigenständiges WLAN-Gerät. Es erweitert den Shelly Plus 1 um Sensoranschlüsse. Der ESP32 fragt deshalb immer den Shelly Plus 1 ab, nicht direkt das Add-on.

Die Add-on-Messwerte erscheinen in der Shelly-API als zusätzliche Komponenten, meistens mit IDs ab 100, zum Beispiel temperature:100, humidity:100, input:100 oder voltmeter:100.

1. Vorbereitung am Shelly

  1. Shelly Plus Add-on auf den Shelly Plus 1 stecken.
  2. Sensor anschließen, zum Beispiel DS18B20, DHT22, Reedkontakt, LDR-Spannungsteiler oder analogen Sensor.
  3. Im Webinterface des Shelly das Add-on aktivieren.
  4. Passenden Sensor als Peripheral hinzufügen.
  5. Shelly neu starten, falls die Oberfläche oder API das verlangt.

Erst wenn die Messwerte im Shelly-Webinterface sichtbar sind, lohnt sich die Abfrage mit dem ESP32.

2. Wichtige RPC-Adressen im Browser testen

Die folgenden Adressen kann man zuerst direkt im Browser testen. Ersetze SHELLY_IP durch die IP-Adresse deines Shelly Plus 1.

http://SHELLY_IP/rpc/Shelly.GetStatus
http://SHELLY_IP/rpc/SensorAddon.GetPeripherals
http://SHELLY_IP/rpc/SensorAddon.OneWireScan
http://SHELLY_IP/rpc/Temperature.GetStatus?id=100
http://SHELLY_IP/rpc/Humidity.GetStatus?id=100
http://SHELLY_IP/rpc/Input.GetStatus?id=100
http://SHELLY_IP/rpc/Voltmeter.GetStatus?id=100

Beginne am besten immer mit Shelly.GetStatus. Diese Antwort zeigt sehr schnell, welche Komponenten wirklich vorhanden sind.

3. Add-on-Peripherie auflisten

Damit findest du heraus, welche Sensoren der Shelly dem Add-on zugeordnet hat.

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)

url = "http://{}/rpc/SensorAddon.GetPeripherals".format(SHELLY_IP)

response = urequests.get(url)
data = response.json()
response.close()

print(data)

Mögliche Antwort, stark vereinfacht:

{
  "ds18b20": [
    {
      "temperature:100": {
        "addr": "28ff641e2c2304a1"
      }
    }
  ],
  "dht22": [],
  "analog_in": [],
  "voltmeter": []
}

4. DS18B20-Temperatur abfragen

Ein DS18B20 wird als Temperatur-Komponente eingebunden. Beim Add-on ist die ID häufig 100.

import urequests

SHELLY_IP = "192.168.178.55"
TEMP_ID = 100

url = "http://{}/rpc/Temperature.GetStatus?id={}".format(SHELLY_IP, TEMP_ID)

response = urequests.get(url)
data = response.json()
response.close()

print("Antwort:", data)
print("Temperatur:", data["tC"], "°C")

Typische Antwort:

{
  "id": 100,
  "tC": 22.8,
  "tF": 73.0
}

5. Mehrere DS18B20-Sensoren abfragen

Bei mehreren Temperaturfühlern werden meist mehrere Temperatur-Komponenten angelegt, zum Beispiel temperature:100, temperature:101, temperature:102.

import urequests
import time

SHELLY_IP = "192.168.178.55"
TEMP_IDS = [100, 101, 102]

while True:
    for sensor_id in TEMP_IDS:
        try:
            url = "http://{}/rpc/Temperature.GetStatus?id={}".format(SHELLY_IP, sensor_id)
            response = urequests.get(url)
            data = response.json()
            response.close()

            temperatur = data.get("tC")
            print("Sensor", sensor_id, ":", temperatur, "°C")

        except Exception as e:
            print("Fehler bei Sensor", sensor_id, ":", e)

    print("---")
    time.sleep(5)

6. DHT22: Temperatur und Luftfeuchte abfragen

Ein DHT22 liefert zwei Komponenten: eine Temperatur-Komponente und eine Luftfeuchte-Komponente.

import urequests

SHELLY_IP = "192.168.178.55"
TEMP_ID = 100
HUM_ID = 100

def rpc(method, sensor_id):
    url = "http://{}/rpc/{}?id={}".format(SHELLY_IP, method, sensor_id)
    response = urequests.get(url)
    data = response.json()
    response.close()
    return data

temp = rpc("Temperature.GetStatus", TEMP_ID)
hum = rpc("Humidity.GetStatus", HUM_ID)

print("Temperatur:", temp.get("tC"), "°C")
print("Luftfeuchte:", hum.get("rh"), "%")

Typische Antworten:

{
  "id": 100,
  "tC": 23.1,
  "tF": 73.6
}

{
  "id": 100,
  "rh": 48.5
}

7. Alle Messwerte über Shelly.GetStatus holen

Das ist für den Unterricht oft die robusteste Variante: Der ESP32 holt einmal den Gesamtstatus und sucht dann die vorhandenen Komponenten.

import urequests

SHELLY_IP = "192.168.178.55"

url = "http://{}/rpc/Shelly.GetStatus".format(SHELLY_IP)
response = urequests.get(url)
status = response.json()
response.close()

for key, value in status.items():
    if key.startswith("temperature:"):
        print(key, "=", value.get("tC"), "°C")

    if key.startswith("humidity:"):
        print(key, "=", value.get("rh"), "%")

    if key.startswith("voltmeter:"):
        print(key, "=", value.get("voltage"), "V")

    if key.startswith("input:"):
        if "percent" in value:
            print(key, "=", value.get("percent"), "%")
        else:
            print(key, "=", value.get("state"))

Vorteil: Man muss die IDs nicht vorher sicher kennen. Der ESP32 zeigt, was wirklich vorhanden ist.

8. Analogwert des Add-on abfragen

Ein analoger Eingang wird über Input.GetStatus abgefragt. Der Messwert erscheint als percent, also 0 bis 100 Prozent.

import urequests

SHELLY_IP = "192.168.178.55"
INPUT_ID = 100

url = "http://{}/rpc/Input.GetStatus?id={}".format(SHELLY_IP, INPUT_ID)
response = urequests.get(url)
data = response.json()
response.close()

print("Antwort:", data)
print("Analogwert:", data.get("percent"), "%")

Typische Antwort:

{
  "id": 100,
  "percent": 37.4
}

9. Spannung über Voltmeter abfragen

Wenn der Eingang als Voltmeter angelegt wurde, wird die Spannung mit Voltmeter.GetStatus abgefragt.

import urequests

SHELLY_IP = "192.168.178.55"
VOLT_ID = 100

url = "http://{}/rpc/Voltmeter.GetStatus?id={}".format(SHELLY_IP, VOLT_ID)
response = urequests.get(url)
data = response.json()
response.close()

print("Spannung:", data.get("voltage"), "V")

Typische Antwort:

{
  "id": 100,
  "voltage": 2.73
}

10. Digitalen Eingang abfragen

Ein Reedkontakt, Schwimmerschalter oder anderer digitaler Kontakt kann als Eingang erscheinen.

import urequests

SHELLY_IP = "192.168.178.55"
INPUT_ID = 100

url = "http://{}/rpc/Input.GetStatus?id={}".format(SHELLY_IP, INPUT_ID)
response = urequests.get(url)
data = response.json()
response.close()

print("Eingangszustand:", data.get("state"))

Typische Antwort:

{
  "id": 100,
  "state": false
}

11. Beispiel: Temperaturgrenze schaltet ESP32-LED

Der ESP32 fragt regelmäßig den Shelly ab. Wenn die Temperatur über 28 °C liegt, wird eine LED eingeschaltet.

import network
import urequests
import time
from machine import Pin

WIFI_SSID = "DEIN_WLAN"
WIFI_PASS = "DEIN_PASSWORT"
SHELLY_IP = "192.168.178.55"
TEMP_ID = 100
GRENZE = 28.0

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)

while True:
    try:
        url = "http://{}/rpc/Temperature.GetStatus?id={}".format(SHELLY_IP, TEMP_ID)
        response = urequests.get(url)
        data = response.json()
        response.close()

        t = data.get("tC")
        print("Temperatur:", t, "°C")

        if t is not None and t > GRENZE:
            led.on()
        else:
            led.off()

    except Exception as e:
        print("Fehler:", e)
        led.off()

    time.sleep(5)

12. Beispiel: Shelly-Relais abhängig vom Add-on-Messwert schalten

Das ist technisch möglich, aber mit Vorsicht zu behandeln: Das Shelly-Relais kann reale 230-V-Verbraucher schalten. Für Experimente zuerst nur ungefährliche Kleinspannung oder eine Testlampe verwenden.

import urequests
import time

SHELLY_IP = "192.168.178.55"
TEMP_ID = 100
EIN_AB = 30.0
AUS_UNTER = 28.0

relais_an = False

while True:
    try:
        url = "http://{}/rpc/Temperature.GetStatus?id={}".format(SHELLY_IP, TEMP_ID)
        response = urequests.get(url)
        data = response.json()
        response.close()

        t = data.get("tC")
        print("Temperatur:", t, "°C")

        if t is not None:
            if not relais_an and t >= EIN_AB:
                url = "http://{}/rpc/Switch.Set?id=0&on=true".format(SHELLY_IP)
                response = urequests.get(url)
                response.close()
                relais_an = True
                print("Relais EIN")

            elif relais_an and t <= AUS_UNTER:
                url = "http://{}/rpc/Switch.Set?id=0&on=false".format(SHELLY_IP)
                response = urequests.get(url)
                response.close()
                relais_an = False
                print("Relais AUS")

    except Exception as e:
        print("Fehler:", e)

    time.sleep(5)

Die zwei Schaltschwellen bilden eine einfache Hysterese. Dadurch klappert das Relais nicht ständig um den Grenzwert herum.

13. Kleine Hilfsfunktion für Unterrichtsprojekte

Diese Funktion macht die Beispiele übersichtlicher.

import urequests

SHELLY_IP = "192.168.178.55"

def shelly_rpc(method, params=""):
    if params:
        url = "http://{}/rpc/{}?{}".format(SHELLY_IP, method, params)
    else:
        url = "http://{}/rpc/{}".format(SHELLY_IP, method)

    response = urequests.get(url)
    data = response.json()
    response.close()
    return data

# Beispiele:
print(shelly_rpc("Shelly.GetStatus"))
print(shelly_rpc("Temperature.GetStatus", "id=100"))
print(shelly_rpc("Humidity.GetStatus", "id=100"))
print(shelly_rpc("Input.GetStatus", "id=100"))
print(shelly_rpc("Voltmeter.GetStatus", "id=100"))

Fehlersuche

Problem Mögliche Ursache Test
404 oder Methode nicht gefunden Falscher RPC-Name oder Add-on nicht aktiviert /rpc/Shelly.GetStatus testen
temperature:100 fehlt Sensor nicht eingerichtet oder Neustart fehlt Webinterface und SensorAddon.GetPeripherals prüfen
tC ist null Sensor kann nicht gelesen werden Verdrahtung, Sensoradresse, Pullup prüfen
ESP32 bekommt keine Antwort Falsche IP, anderes WLAN, Shelly nicht erreichbar Adresse zuerst im Browser testen
Analogwert falsch skaliert Peripheral als Analog Input statt Voltmeter oder falscher Bereich Konfiguration im Shelly-Webinterface prüfen

Merksatz

Der ESP32 fragt nicht den Sensor direkt ab. Er fragt den Shelly Plus 1 ab. Der Shelly Plus 1 stellt die Messwerte des Add-on als RPC-Komponenten bereit.

Quellen

Zurück zur Shelly-Übersicht