🏠 FabLab Startseite | Nutzungsbedingungen | Impressum | Wiki

ESP8266 MySQL Daten Senden und Empfangen

Hallo zusammen,

ich möchte für diverse Projekte einen “Standardaufbau” schaffen, den ich immer wieder nutzen kann.
Ein ESP8266-NodeMCU (genutzt mit Arduino IDE) soll von diversen Sensoren (RFID, Temperatur und Luftfeuchte (DHT22) etc.) Daten an einen MySQL-Server senden.

Das Senden der Daten an den Server funktioniert bereits tadellos durch Nutzung eines PHP-Scripts auf einem RaspberryPi. Die gemessenen Daten werden vie URL an das PHP-Script übergeben.
(Beispiel: 192.168.178.55/myphp.php/?temp=24.5)

Jetzt möchte ich aber auch Daten vom Server an den ESP8266 senden um beispielsweise die Durchschnitttemperatur der letzten Stunde abzubilden oder den Nutzer-Namen zu einem RFID-Tag im Display anzuzeigen.

Die Durchschnittstemperaturen kann ich ja einfach durch einen SQL-SELECT in der PHP ermitteln.
Das gleiche funktioniert auch zur Ermittlung des Namens zu einem RFID-Tag. (RFID-Nummern und dazugehörige Namen sind in einer MySQL Tabelle abgelegt.)
Ich habe aber noch keinen Weg gefunden, um diese Daten an den ESP8266 zu übergeben.

Am liebsten wäre mir eine Methode, bei der ein vom Server übermittelter Wert (String oder Integer oder Float oder whatever) vom ESP8266 in einer Variable abgelegt wird um damit innerhalb des Arduino-Codes weiterzuarbeiten.

Vielleicht hat hier jemand schon Erfahrung mit einem ähnlichen Projekt und kann mit weiterhelfen.

Grüße
Jonas

Hallo Jonas, muss diese Kommunikation denn wirklich vom Server ausgehen? Erfahrungsgemäß ist es meist einfacher, vom Client (z. B. per GET Request) auf die Daten zuzugreifen sobald sie gebraucht werden (sonst brauchst du auf dem Server auch cronjobs o. ä.). Wie sich das konkret auf dem ESP schreiben lässt kann ich dir auf die schnelle nicht sagen, das kann ich machen wenn ich wieder daheim bin

Viele Grüße,
Ian

Hallo Ian,

schonmal vielen Dank für deine Antwort.
Nein, die Kommunikation muss nicht vom Server ausgehen. Kann gerne auch vom Client angefordert werden.

Hatte nur ein eine Aktion vom Server in Betracht gezogen, um auch per Weboberfläche Befehle an den ESP schicken zu können.

Grüße
Jonas

Ok, um Daten vom Server an den Client zu schicken gibt es unterschiedliche Möglichkeiten.

Die eine ist, auf dem Client einen Webserver laufen zu lassen. Dieser Webserver wird dann vom PHP-Skript (oder auch direkt von dir im Browser) angesprochen um deine Aktion auszuführen. Mithilfe von Anfrageparametern kannst du dieser Anfrage dann zusätzliche Daten mitgeben auf die der ESP reagiert. Eine Anleitung für einen Webserver mit ESP8266 findest du hier:


Um das ganze dann in einem PHP-Skript ansprechen zu können solltest du dir das Programm cUrl anschauen, dafür gibt es auch eine PHP-Erweiterung.

Alternativ kann auch eine einfache TCP-Verbindung genutzt werden um Daten direkt zu übertragen. Der Vorteil hierbei ist, dass es weniger Overhead auf dem MC erzeugt (weil nur das gesendet wird was gebraucht wird). Ein Beispiel kannst du dir hier anschauen:
https://www.esp8266.com/viewtopic.php?f=32&t=7005

Alternativ kann natürlich auch der Client Anfragen senden und die Antwort verarbeiten. Dafür würde ich am ehesten eine Library verwenden um das Parsen nicht selbst übernehmen zu müssen. Hierfür eignet sich zum Beispiel diese:


Da du vermutlich relativ bald an den Punkt kommen wirst, an dem einfache Zahlenreihen oder Texte nicht mehr ausreichen, solltest du dir zusätzlich das JSON-Format anschauen. In PHP kann ein Array einfach zu einem JSON-Text formatiert werden, der Arduino kann diesen z.B. mit dieser Library verarbeiten:

Falls du dazu Fragen hast oder Hilfe brauchst kannst du auch gerne Freitags von 18 - 22 Uhr bei uns am OpenLab vorbei kommen, diese Woche bin ich zwar nicht da aber es findet sich bestimmt jemand der dir hilft. Ab nächster Woche bin ich dann auch wieder anzutreffen :wink:

Viele Grüße,
Ian

1 „Gefällt mir“

Wow!
Hab bisher zwar nur bisschen rumprobiert, aber JSON scheint genau das zu sein, wonach ich gesucht habe.
Danke!

Kein Problem

Wenn du eine laufende Version hast poste sie gerne hier, dann können andere das als Referenz nutzen

Hallo Jonas,

bei meinem Temperatursensor setze ich für die Kommunikation MQTT ein. Auf dem Raspberry läuft der MQTT Server mosquitto. Jeder Client, der dort den Topic mit der Temperatur abonniert hat, empfängt die Daten und kann sie weiterverarbeiten (Anzeigen, in eine Datenbank schreiben, verändert wieder beim Server publizieren). So kannst du dann auch auf dem ESP8266 einen Client laufen lassen, der einem Topic auf dem Server lauscht und bei Veränderung eine Aktion ausführt (-> Befehle an den ESP8266 senden). Für die Arduino IDE gibt es die Bibliothek PubSubClient. Die kenne ich aber nicht, da ich Lua bzw. microPython nutze.

Zum Abbonieren und Publizieren auf dem Rechner kann ich mqtt-spy und als Dashboards für Android MQTT Dash oder Linear MQTT Dashboard empfehlen.

Viele Grüße
Tronje

Also: Mit JSON und nem PHP-Script läuft es nun genau so wie ich es mir vorgestellt habe.

Zunächst ein Blick in die MySQL-Tabelle der bekannten Nutzer mit RFID-Tags. Aktuell sind zwei Nutzer angelegt.

grafik

Der Arduino empfängt per 433 MHz (der Aufbau stand bei mir noch so rum, deshalb) das RFID-Tag.

grafik

Das Arduino-Script sendet eine Anfrage an den Server. In der URL wird die RFID übermittelt.
Das PHP-Script startet eine SQL-Abfrage und gibt den zur RFID gehörigen Nutzer per JSON zurück.

Die Verarbeitung und Ausgabe kann dann beliebig erfolgen. Zur Demonstration ist die Ausgabe im seriellen Monitor abgebildet.

grafik

Arduino Code

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
#include <RCSwitch.h>           //433 MHz
RCSwitch mySwitch = RCSwitch(); //433 MHz

// WiFi Parameters
const char* ssid = "SSID eintragen";
const char* password = "Passwort eintragen";


void setup() {
Serial.begin(115200);

// WiFi-Initialisierung##############################
                                                
WiFi.begin(ssid, password); 
while (WiFi.status() != WL_CONNECTED){ 
    delay(1000);
    Serial.println("Connecting to WiFi...");} 
 
if (WiFi.status() == WL_CONNECTED){ 
    Serial.println("WiFi Connected"); 
    Serial.println();}          


  
//433 MHz Receiver PIN Belegung##########
mySwitch.enableReceive(D4);  // Empfänger ist an Interrupt-Pin "0" - Das ist am UNO der Pin2
//##########################
  
} //void Setup end


void loop() {
  // Check WiFi Status
  if (WiFi.status() == WL_CONNECTED) {
    
    HTTPClient http;  //Object of class HTTPClient


if (mySwitch.available()) // Wenn ein Code Empfangen wird...
  {
     Serial.println("RFID-Tag empfangen");
    int value = mySwitch.getReceivedValue(); // Empfangene Daten werden unter der Variable "value" gespeichert.
  
    if (value == 0) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      Serial.println("Unbekannter Code");
    } 
    
    else // Wenn der Empfangene Code brauchbar ist, wird er hier an den Serial Monitor gesendet.
    {
      Serial.print("Via 433 MHz Empfangener RFID-Tag: ");
      Serial.println( mySwitch.getReceivedValue() );
      Serial.println();
    }
       
    

int inrfid = mySwitch.getReceivedValue(); //Variable inrfid wird beschrieben

mySwitch.resetAvailable(); // Hier wird der 433 MHz-Empfänger "resettet"

String url =  "http://192.168.178.46/jsonRFIDcheck.php?RFID=";
             url += inrfid;

    Serial.println("Serverabfrage....");


    http.begin(url);
    int httpCode = http.GET();
    //Check the returning code                                                                  
    if (httpCode > 0) {
      // Parsing
      const size_t bufferSize = JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(8) + 370;
      DynamicJsonBuffer jsonBuffer(bufferSize);
      JsonObject& root = jsonBuffer.parseObject(http.getString());
      // Parameters
      int id = root["id"]; // 1
      const char* name = root["NAME"];
      const char* rfid = root["RFID"];

      // Output to serial monitor
      Serial.print("RFID: ");
      Serial.println(rfid);
      Serial.print("Name: ");
      Serial.println(name);
      Serial.println();

    }
    http.end();   //Close connection
  }
  }
  // Delay
  delay(1000);
}

PHP-Script

<?php
$host="192.168.178.46";
$username="arduino";
$password="codearduino";
$db_name="db_arduino";
$tbl_name="tbl_user";


//Get Values from URL
$RFID = $_GET['RFID'];




    //open connection to mysql db
    $connection = mysqli_connect("$host","$username","$password","$db_name") or die("Error " . mysqli_error($conne$

    //fetch table rows from mysql db
    //SQL Select wird nach input RFID gefiltert
    $sql = "select * from $tbl_name WHERE RFID=$RFID";
    $result = mysqli_query($connection, $sql) or die("Error in Selecting " . mysqli_error($connection));

    //create an array
    $emparray = array();
    while($row =mysqli_fetch_assoc($result))
    {
       // $emparray[] = $row;
        $emparray = $row;
    }
    echo json_encode($emparray);

    //close the db connection
    mysqli_close($connection);
?>
1 „Gefällt mir“

Das mit dem Quelcode ist ja Mist. Gibts dafür ne elegante Darstellung im Forum?

Du kannst Code mit

```php
.```

einbinden. (Den Punkt vor den schließenden Anführungszeichen musst du entfernen, den musste ich da schreiben damit die Anzeige passt).
Die Sprache gibt das Syntax-Highlighting vor. Dein PHP-Code enthält komischer weise keine Zeilenumbrüche, da musst du nochmal schauen woran das liegt

1 „Gefällt mir“

Wunderbar, habs verbessert.

Sehr gut.
Zu deinem PHP-Code:
Für Datenbankanfragen verwendet man üblicherweise Prepared-Statements, wenn Nutzerdaten in eine Abfrage eingebaut werden sollen. Die haben den Vorteil dass Angriffe wie SQL-Injection nicht möglich sind. In deinem Fall ist das vermutlich nicht notwendig, weil es bei dir im Netzwerk passiert, aber falls es dich interessiert kannst du das hier nachlesen:
http://php.net/manual/de/mysqli.quickstart.prepared-statements.php