# Slider und Switch Zustand auf Website in JSON Datei schreiben/lesen



## tiluhe (19. Okt 2020)

Hallo,

als blutiger Neuling möchte ich gerne ein kleines Projekt umsetzen. Zum Verständnis beschreib ich das mal:
Ich habe einen ESP32 Mikrocontroller so programmiert, dass er per Relais die Stromzufuhr zur Kaffeemaschine an- und abschalten kann und dass er auf Knopfdruck das Mahlwerk einer Espressomühle für eine festgelegte Zeitdauer einschaltet. Über WLAN kann ich auf den ESP32 zugreifen und den Zustand des Relais bzw. die Mahlzeit verändern. Im Heimnetz funktioniert das gut, nur leider da der Internetzugang bei uns im Haus nicht über DSL geht habe ich Internet über einen LTE Surfstick in der Fritzbox. Leider ist es Mobilfunkbetreiberseitig nicht möglich über das Internet auf das Heimnetz zuzugreifen (auch nicht mit Dyndns). Deswegen wollte ich nun einen Umweg gehen und habe den ESP32 nicht mehr als Webserver in Betrieb, sondern als HTTP Client. Er fragt jede Minute den Zustand von zwei Variablen (boolean: "machineOn" und int "grindTime") ab, die ich in einer .json-Datei auf einem Webserver gespeichert habe. Das funktioniert.

Was noch fehlt: die dazu passende sehr einfache Seite, die ich dann mit meinem Handy aufrufe und über die ich von überall via Internet die Kaffemaschine einschalten kann, damit sie vorgeheizt ist, wenn ich zuhause ankomme  Das ganze ist ein Lernprojekt bei dem es mir mehr ums Verstehen und in die Materie eintauchen geht, als dass es mir wirklich unsterblich wichtig ist von überall die Kaffemaschine anschalten zu können... aber jetzt hab ich schonmal angefangen und würde es auch gerne zu ende bringen 

Das Frontend der Seite hab ich erstellt, nur bin ich damit überfordert den Zustand bzw. Wert des Switches und des Sliders bei Veränderung auszulesen und in die JSON zu schreiben. Ich habe versucht das zu googeln, aber bin damit nicht weitergekommen, weil das irgendwie immer zu anderen Zwecken genutzt wird 

Ich glaube für jemand, der sich mit HTML und Java auskennt ist das vermutlich ein Klacks, ich bin leider hoffnungslos überfordert!
Vielleicht gibt es auch eine einfachere Möglichkeit als JSON zum Datenaustausch zwischen ESP32 und der Website, auch dafür bin ich ganz offen!

Link zum Frontend: www.coffee.djanetskis.de


[CODE lang="html" title="HTML der Website"]<!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Coffee</title>
            <link href="styles/style.css" rel="stylesheet">
            <link href="https://fonts.googleapis.com/css2?family=Amatic+SC:wght@700&display=swap" rel="stylesheet">
        </head>
        <body>
            <h1>Cappucino Zentrale</h1>
            <img src="images/cappucino.jpg" alt="cappucino">
            <h2>Stromzufuhr Kaffemaschine:</h2>
            <!-- Rounded switch -->
            <label class="switch">
              <input type="checkbox" id="machineOnSwitch">
              <span class="slider round"></span>
            </label>
            <h2>Mahlzeit Kaffemühle:</h2>
          <div class="slidecontainer">
            <input type="range" min="16000" max="18000" value="17000" class="slider" id="grindTimeSlider" oninput="this.nextElementSibling.value = this.value">
             <output>16000</output> ms
          </div>
        <script src="scripts/main.js"></script>

        </body>
    </html>[/CODE]


ich würde mich sehr über Hilfe freuen!
Danke schonmal und liebe Grüße,
Tim


----------



## httpdigest (19. Okt 2020)

Andere Idee: da du ja jetzt einen Surfstick mit SIM Karte verwendest, könntest du eigentlich einfach eine SMS an die Rufnummer der SIM schicken und per Http Schnittstelle des Surfsticks diese vom ESP auslesen lassen. Zumindest die Huawei sticks haben ne Http Rest Schnittstelle.


----------



## tiluhe (19. Okt 2020)

Vielen Dank für die Antwort, soweit ich weiß ist das bei meinem Stick nicht möglich (ZTE). Ich werde das aber nochmal nachschauen...

Außerdem bin ich jetzt mit allem anderen schon quasi fertig, es fehlt nur das kleine Verbindungsstück =) und dann ist das am Ende quasi wie mittels App vom Handy aus möglich...


----------



## mihe7 (20. Okt 2020)

Mit Kaffee kennen wir uns aus  



tiluhe hat gesagt.:


> Vielleicht gibt es auch eine einfachere Möglichkeit als JSON zum Datenaustausch zwischen ESP32 und der Website, auch dafür bin ich ganz offen!


JSON ist nicht schwer: so sind `0` oder `1` oder `"An"` oder `true` bzw. `false` alles gültige JSON-Dokumente  

Die "Schwierigkeit" besteht eher darin, dass Du bei HTTP serverseitig etwas brauchst, das sich den Zustand merkt. Das kannst Du mit einem kleinen PHP-Skript lösen, das den Zustand in eine Datei schreibt, während Dein ESP eben diese Datei abruft.

Zum Beispiel könnte folgendes Skript bei einem PUT-Request die Kaffeemaschine einschalten und beim DELETE ausschalten. Setzt natürlich voraus, dass das Verzeichnis, in dem sich das PHP-Skript befindet, beschreibbar ist:

```
<?php
$method = $_SERVER['REQUEST_METHOD'];
$filename = "status.json";
switch($method) {
    case "GET":
        echo (file_get_contents($filename));
        break;
    case "PUT":
        file_put_contents($dateiname, "1");
        break;
    case "DELETE":
        file_put_contents($dateiname, "0");
        break;
}
?>
```
Sagen wir mal, Du legst das Skript unter http://www.coffee.djanetskis.de/coffee.php ab. Dann musst Du in Deiner HTML-Seite lediglich dafür sorgen, dass der betreffende Request abgesetzt wird, z. B. 

```
function switchMachine(onOff) {
    const reqMethod = onOff ? "PUT" : "DELETE";
    fetch("http://www.coffee.djanetskis.de/coffee.php", {method: reqMethod})
        .then(r => {
            if (!r.ok) window.alert("Fehler " + r.statusText);
        });
}
```

Dein ESP braucht jetzt nur entweder http://www.coffee.djanetskis.de/coffee.php oder http://www.coffee.djanetskis.de/status.json per GET abzurufen. Inhalt ist entweder "0" oder "1" (ohne Anführungszeichen) 

Achtung: das Zeug kann Fehler enthalten.


----------



## tiluhe (20. Okt 2020)

mit php hat es jetzt geklappt. Wenn ich den slider bewege oder den switch umschalte ändert sich die JSON und der ESP32 schaltet das Relais, sehr cool!

Das einzige was mir jetzt noch fehlt, ist dass beim Aufrufen der Seite der Slider und der Switch den "Ist-Wert" aus der json als Startwert übernehmen. Also wenn grindTimer in der json den Wert 17846 hat, soll auch der slider diesen Wert annehmen. Ansonsten wird bei Betätigung des Switches der Wert in der json überschrieben und es steht dort 17000. 

Die Werte aus der json auslesen sollte doch relativ einfach mittels js und fetch() gehen, aber ich schaff es nicht einen funktionierenden Code zu schreiben, der die Werte dann in Variablen einträgt und den Status von Switch und Slider anpasst.


----------



## mihe7 (20. Okt 2020)

Wenn ich Deine main.js anschaue, speicherst Du jetzt ein JSON-Objekt.


```
fetch("http://www.coffee.djanetskis.de/coffee.php")
    .then(r => r.json())
    .then(data => machWasMit(data.machineOn, data.grindTime));
```


----------



## tiluhe (20. Okt 2020)

genau, ich speichere jedes mal wenn sich ein Wert des Slider oder Switches ändert, den neuen Zustand in einer JSON-Datei.

kannst du mir vielleicht noch erklären, was genau in diesen 3 Zeilen passiert? Ich steh da irgendwie noch auf dem Schlauch!

mit: fetch("coffee.json")
kann ich die coffee.json Datei, die sich im selben Verzeichnis befindet quasi einlesen, oder wie?

was macht: .then(r => r.json())

und: .then(data => machWasMit(data.machineOn, data.grindTime))

kann mir das jemand Anfängerfreundlich erklären?
ich stell mir das so vor, dass bei Aufrufen der Seite so etwas passiert wie:

[CODE lang="javascript" title="Werte aus JSON in value und checked Eigenschaften von Slider und Switch schreiben"]document.GetElementById('grindTimeSlider').value = data.grindTime
document.GetElementById('machineOnSwitch').checked = data.machineOn[/CODE]

wobei in data vorher die Werte aus der JSON gespeichert wurden. Aber das klappt so nicht! Was mache ich falsch, bzw. wie kann ich es richtig machen?


----------



## mihe7 (20. Okt 2020)

tiluhe hat gesagt.:


> kannst du mir vielleicht noch erklären, was genau in diesen 3 Zeilen passiert? Ich steh da irgendwie noch auf dem Schlauch!


fetch dient dazu, einen Request abzusetzen, dabei liefert fetch nicht das Ergebnis direkt, sondern ein "Promise". Die then()-Methode von Promise liefert wieder ein Promise, so dass sich die Aufrufe miteinander verketten lassen.

D. h. das Promise von fetch gibt das Ergebnis (die Response) als Parameter an then() weiter. Den Parameter habe ich hier einfach r genannt, dabei ist `r => r.json()` die Kurzschreibweise für

```
function(r) {
    return r.json();
}
```
Du könntest also auch

```
fetch("....").then(function(r) {
    return r.json();
});
```
schreiben. Beim dem übergebenen Parameter handelt es sich um ein Response-Objekt. Die json-Methode des Response-Objekts parst den empfangenen Text und wandelt es in ein JavaScript-Objekt um. Das nächste then() bekommt nun also ein JavaScript-Objekt übergeben und dort rufe ich einfach eine Funktion machWasMit auf, wobei die zwei Parameter dem übergebenen Javascript-Objekt entnommen werden.

Vereinfacht: fetch holt den Text aus der angegebenen Datei, z. B.

```
{
    "machineOn": true,
    "grindTime": 17200
}
```
then(r=>r.json()) wandelt den Text in ein JS-Objekt um:

```
{machineOn:true,grindTime:17200}
```
then(data=>machWasMit(data.machineOn, data.grindTime)) liest die Werte aus dem JS-Objekt aus und übergibt sie an eine Funktion machWasMit


----------

