ESP8266 Zugriff auf SQL-DB (auf Raspberry Pi)

Hallo miteinander,
ich möchte mittels einem ESP8266 Daten in ne DB eintragen und wieder abrufen können.
Habe bereits mehrere Libs ausprobiert. Es scheitert aber immer am Zugriff.
In PHPmyAdmin habe ich für den Benutzer alle (aus meiner Sicht möglichen) Rechte vergeben.
Ich hab die Lib von Chuck Bell (SQL-Connector) verwendet und auch die Tipps aus diesem Threat hier
Bislang bekomme ich es nur über eine HTTP-Abfrage, also wenn ich die Daten von einem PHP-Script eintragen lasse bzw. dann wieder mittels echo ausgebe und entsprechend einlese.
Das wäre alles ok, wenn die Abfrage nicht jedes mal ca. 2-3 Sekunden dauern würde. Das ist mir eigentlich zu langsam. Vielleicht habe ich ja aber auch nur irgendwo ne Bremse eingebaut…
Ich hab mal meinen Code angehängt.

Kurze Erklärung des Programms:
Es soll ein Kassensystem für unseren Verein werden.
Das Eintragen der Daten in die DB erfolgt an anderer Stelle.
Das Programm hier bedient lediglich den Drucker (Epson Thermo-Bon-Drucker). Dieser holt sich ne ungedruckte Bestellung ab, druckt diese aus und bestätigt anschließend den Druck an die DB.
Zur Sicherheit lasse ich den Bon erst dann abschneiden, wenn die Bestätigung an die DB erfolgt ist. Hier merkt mann ganz deutlich, wie lange es dauert zwischen Druck und Papier abschneiden.

#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>
#include "thermalprinter.h"

// Vorbereitung des Druckers
#define rxPin 13
#define txPin 12
int printStatus = 0;
int paperStatus = 0;
Epson TM88 = Epson(rxPin, txPin);

const char* ssid     = "FreeWiFi";
const char* password = "123456";

const char* host = "xxx";

String produkt[] = {"Bier Halbe", "Bier Mass", "Radler Halbe Suess", "Radler Mass Suess", "Weizen Halbe", "Weizen Mass", "Russen Halbe Suess", "Russen Mass Suess", "Cola", "Spezi"};
int preis[] = {250, 480, 250, 480, 250, 480, 250, 480, 250, 250};
float umsatz[10];
int steuer;
String bedienung[] = {"Michi", "Tanja", "Oliver", "Bianca", "", "", "", "", "", ""};
String puffer[14];
int bestellung[14];
String bestellText[1];
int i;
String n;
String url;


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

    // We start by connecting to a WiFi network

    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());


    Serial.print("connecting to ");
    Serial.println(host);

    // Use WiFiClient class to create TCP connections
    WiFiClient client;
    const int httpPort = 80;
    if (!client.connect(host, httpPort)) {
        Serial.println("connection failed");
        return;
    }

    // We now create a URI for the request
    url = "/bestelldruck.php";
    url += "?status=1";

    Serial.print("Requesting URL: ");
    Serial.println(url);

    // This will send the request to the server
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n\r\n");
    unsigned long timeout = millis();
    while (client.available() == 0) {
        if (millis() - timeout > 5000) {
            Serial.println(">>> Client Timeout !");
            client.stop();
            return;
        }
    }
    String line;
    // Read all the lines of the reply from server and print them to Serial
    while(client.available()) {
        line = client.readStringUntil('\r');
        Serial.print(line);
    }



    //String nach "a<Zahl>;" durchsuchen und somit die Zahlen heraustrennen
    for (i=0; i<15; i++) {
        char startIndex[5];
        sprintf(startIndex, "a%d;", i);
        char stopIndex[5];
        sprintf(stopIndex, "a%d;", i+1);
        byte vonPos;
        byte bisPos;
        if (i<10) {
            vonPos = line.indexOf(startIndex);
            bisPos = line.indexOf(stopIndex);
            puffer[i] = line.substring(vonPos+3, bisPos);
            bestellung[i] = atoi(puffer[i].c_str());
            Serial.print("Puffer ");
            Serial.print(i);
            Serial.print(": ");
            Serial.println(puffer[i]);
        }
        else {
            vonPos = line.indexOf(startIndex);
            bisPos = line.indexOf(stopIndex);
            puffer[i] = line.substring(vonPos+4, bisPos);
            Serial.print("Puffer ");
            Serial.print(i);
            Serial.print(": ");
            Serial.println(puffer[i]);
        }
    }
    if (puffer[0] == "") {
      Serial.println("Kein Datensatz gefunden!");
      delay(5000);
    }
    else {

    
    for (i=0; i<13; i++) {
        bestellung[i] = atoi(puffer[i].c_str());
        Serial.print("Bestellung ");
        Serial.print(i);
        Serial.print(": ");
        Serial.println(bestellung[i]);
    }


// Teil2-Druck des Bons

    printStatus = TM88.getStatus();
    while (printStatus != 22) {
        printStatus = TM88.getStatus();
        delay(1000);
    }
    paperStatus=TM88.getPaper();
    
    if (paperStatus == 30) {
        TM88.doubleSizeOn();
        TM88.println("---------------------");
        TM88.println("Papier geht aus!!");
        TM88.feed(5);
        TM88.println("Bitte Rolle wechseln!");
        TM88.println("---------------------");
        TM88.feed(5);
      }
      while (paperStatus == 126 or paperStatus == 114 or paperStatus == 30) {
        paperStatus = TM88.getPaper();
        if (paperStatus == 18) {
          TM88.doubleSizeOn();
          TM88.println("---------------------");
          TM88.println("Danke fuers Wechseln!");
          TM88.println("weiter gehts!! :-)");
          TM88.println("---------------------");
          TM88.cut();
        }
      }
      if (bestellung[0] > 0) {
        TM88.doubleSizeOn();
        TM88.justifyCenter();
        TM88.println("Starkbierfest 2019");
        TM88.doubleSizeOff();
        TM88.print("Bedienung Nr.:");
        TM88.println(bedienung[bestellung[1]]);
        TM88.justifyLeft();
        TM88.print("Bon-Nr.: ");
        TM88.println(bestellung[0]);
        TM88.println(puffer[13]);
        TM88.println("------------------------------------------");
        for (i=2; i<12; i++) {
            if (bestellung[i] > 0) {
                TM88.print(bestellung[i]);
                TM88.print(" X ");
                TM88.println(produkt[i-2]);
            }
        }
        if (puffer[14] != "") {
          TM88.doubleSizeOn();
          TM88.println("Sonderwunsch:");
          TM88.doubleSizeOff();
          TM88.println(puffer[14]);
        }
        TM88.println("------------------------------------------");
      }




    
// Teil3-Bestätigung des Drucks

       if (!client.connect(host, httpPort)) {
        Serial.println("connection failed");
        return;
    }
        // We now create a URI for the request
    url = "/bestelldruck.php";
    url += "?status=2&index=";
    url += bestellung[0];

    Serial.print("Requesting URL: ");
    Serial.println(url);

    // This will send the request to the server
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n\r\n");
    timeout = millis();
    while (client.available() == 0) {
        if (millis() - timeout > 5000) {
            Serial.println(">>> Client Timeout !");
            client.stop();
            return;
        }
    }

    // Read all the lines of the reply from server and print them to Serial
    while(client.available()) {
        line = client.readStringUntil('\r');
        Serial.print(line);
    }
    n = line.substring(1, 2);
    Serial.println();
    Serial.println(n);
    if (n == "1") {
        TM88.cut();
    }

    Serial.println();
    Serial.println("closing connection");

}

}
void loop()
{
  delay(50);
}

Findet Ihr nen “Bremsklotz”? Oder dauern so HTTP-Anfragen immer so lange?

Grüße
Alex

Edit: Ganz vergessen. Aktuell liegt die DB auf nem Webserver. Die DB, auf welche ich mit dem Connector zugreifen möchte liegt bereits auf nem Rpi. Sonst hätte sich bestimmt jemand über das Thema gewundert :slight_smile:

Hier funktioniert der direkte Zugriff (Posting #6).

Gruß Tommy

Vielleicht braucht die /bestelldruck.php auch einfach 3 Sekunden um die Antwort zu generieren. Hast du dir das schon angeschaut?

    while(client.available()) {
        line = client.readStringUntil('\r');
        Serial.print(line);
    }

Warum eigendlich available() und nicht connected()?

BTW.: HTTP1.1 erlaubt das Transfer-Encoding chunked. Vielleicht besser HTTP1.0 benutzen.

Hallo,

auf die MySQL-Datenbank auf dem RasPi darf von außen auch zugegriffen werden? Portfreigabe, Firewall usw. usw.
In MySQL festgelegt, welches Netz/welcher Rechner zugreifen darf?
Standardinstallationen lassen meines Wissens nach nur den Zugriff von localhist bzw. dem Rechner aus zu, auf dem MySQL läuft.

Der Weg über PHP hat da zumindest den Vorteil, daß der Zugriff local belbt und man sich nicht Sicherheitslücken oder Scheunentore einbaut.

Gruß aus Berlin
Michael

Hey,
danke schonmal für die Antworten:

Tommy56:
Hier funktioniert der direkte Zugriff (Posting #6).

Gruß Tommy

Das Thema hatte ich bereits verlinkt :slight_smile: Klappt aber auch nicht.

Rintin:
Vielleicht braucht die /bestelldruck.php auch einfach 3 Sekunden um die Antwort zu generieren. Hast du dir das schon angeschaut?

So schnell kann ich gar nicht schauen, wie die Seite im Browser geladen ist.

Rintin:
Warum eigendlich available() und nicht connected()?

BTW.: HTTP1.1 erlaubt das Transfer-Encoding chunked. Vielleicht besser HTTP1.0 benutzen.

Ok, hier hab ich keinen Dunst. Hab mir das aus nem Tutorial rausgelesen.
Kann ich stattdessen auch Connected nehmen? Das teste ich mal. Danke. Vielleicht geht es dann schneller. Lieber wäre mir jedoch der direkte Zugriff.

amithlon:
auf die MySQL-Datenbank auf dem RasPi darf von außen auch zugegriffen werden?

Ja (%) - Musste aber bei der Einrichtung mit Fehlermeldungen kämpfen.

amithlon:
Portfreigabe, Firewall usw. usw.
In MySQL festgelegt, welches Netz/welcher Rechner zugreifen darf?

Nein. Da ich mich im lokalen Netz befinde.... Brauch ich das da? Am Router oder der DB?

Auch in PHP kann man Scheunentore öffnen, vielleicht sogar noch leichter.

Danke schonmal an alle für die fleißigen Antworten. Ich teste das mal alles durch.

sprudelkarre:
Ok, hier hab ich keinen Dunst. Hab mir das aus nem Tutorial rausgelesen.
Kann ich stattdessen auch Connected nehmen? Das teste ich mal. Danke. Vielleicht geht es dann schneller.

Ok... ich denke du benutzt besser eine fertige HTTP-Library.
z.B.: diese hier

Lieber wäre mir jedoch der direkte Zugriff.

Ich glaube du holst dir damit unnötig Komplexität auf den ESP. HTTP ist ein einfacheres Protokoll als MySQL.
Auch dürften kurzfristige Änderungen leichter in PHP zu machen sein als auf dem ESP.

Ach nochwas:

String produkt[] = {"Bier Halbe", "Bier Mass", "Radler Halbe Suess", "Radler Mass Suess", "Weizen Halbe", "Weizen Mass", "Russen Halbe Suess", "Russen Mass Suess", "Cola", "Spezi"};
int preis[] = {250, 480, 250, 480, 250, 480, 250, 480, 250, 250};
String bedienung[] = {"Michi", "Tanja", "Oliver", "Bianca", "", "", "", "", "", ""};

Sowas gehört nicht hardcodiert auf den ESP. Am Tag des Events gibts da noch ein paar kleinere Änderungen...
Dennis springt für Tanja ein, Bier wird auf 5€ aufgerundet und Fanta soll auch einzelnd erkauft werden...

sprudelkarre:
Das Thema hatte ich bereits verlinkt :slight_smile: Klappt aber auch nicht.

Da geht aber nichts über PHP, sondern direkt, also ist Dein vorgestellter Aufruf falsch.

Der Fehler muss bei Dir liegen, da es bei mir seit >1 Jahr im Dauerbetrieb problemlos läuft (DB beim Provider).
Auch schon angesprochen wurden die Berechtigungen des DB-Users, besonders Host: any oder IP Deines ESP.

Gruß Tommy

Tommy56:
Da geht aber nichts über PHP, sondern direkt, also ist Dein vorgestellter Aufruf falsch.

Der Fehler muss bei Dir liegen, da es bei mir seit >1 Jahr im Dauerbetrieb problemlos läuft (DB beim Provider).
Auch schon angesprochen wurden die Berechtigungen des DB-Users, besonders Host: any oder IP Deines ESP.

Gruß Tommy

Ok, war blöd von mir geschrieben. Habs erst direkt versucht. Bin genau dem von uns beiden verlinkten Post gefolgt. Als das nicht geklappt hat, hab ich es über http und PHP versucht. Wie erwähnt, dauert die Abfrage halt (relativ) lang. Ich bleib da aber dran! Vielleicht habe ich ja Glück und es reicht, den Raspi nochmal ordentlich aufzuziehen. Mein Webspace (auch mit MariaDB) lässt keinen Zugriff von außen zu. Außerdem hätte ich alles gerne Lokal ohne dass ein Zugriff über Internet möglich ist.

@Rintin:
Die Lib schau ich mir mal an, danke.
Bezüglich den Preisen, Bedienungen & Co.: Die hab ich nur aktuell hart einprogrammiert. Wird später aus der DB gezogen.
Hab mir das so vorgestellt: Es gibt eine kleine Tabelle mit den Speisen, Getränken, jeweiligen Preisen, Bedienungen und sonstigen evtl. Informationen rund ums Fest. Mittels PHP-Script wird dann die "Bestell-Tabelle" erstellt. Jedes Gerät lädt sich erst die Info's über Preise etc. - Später wird nur noch mit der Bestell-Tabelle gearbeitet.

Ob es jetzt ein direkter Zugriff, oder über PHP wird, ist mir eigentlich egal. Nur wäre es cool, wenn der Abruf der Daten schneller geht. Schließlich steht das Programm in der Zeit, kann also keine Angaben von "Außen" (Buttons etc) annehmen.

Grüße Alex

Hast Du die Version 1.1.1 der Lib benutzt?

Hast Du dem DB-User die Rechte SELECT, INSERT, UPDATE, DELETE, FILE und Host = % gegeben?

Mehr kann ich nicht für Dich tun.

Gruß Tommy

Tommy56:
Hast Du die Version 1.1.1 der Lib benutzt?

Hast Du dem DB-User die Rechte SELECT, INSERT, UPDATE, DELETE, FILE und Host = % gegeben?

Mehr kann ich nicht für Dich tun.

Gruß Tommy

Ja, hab ich gemacht. Der Fehler kommt schon beim Verbinden zur DB.
Wie bereits erwähnt. Der Fehler wird an mir liegen...
Trotzdem Danke :slight_smile:

Hey,
hier nochmal ein Update von mir.
Ich bekomme es nachwievor nicht auf die Kette, mittels der Lib auf die DB zuzugreifen.
Aber das Geschwindigkeitsproblem bei der HTTP-Abfrage konnte ich lösen. Somit parse ich den Inhalt des PHP-Scripts und lese das in meine Variablen ein.

Aus:

    while(client.available()) {
        line = client.readStringUntil('\r');
        Serial.print(line);
    }

Wurde:

    while(client.available()) {
        line = client.read();
        Serial.print(line);
    }

Dazu musste ich den Variablentyp von String in Char ändern. Dann hat es geflutscht.

Danke für alle Beiträge!