Ankündigung

Einklappen
Keine Ankündigung bisher.

ESP8266 Werte an OpenHab Rest API übergeben

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    ESP8266 Werte an OpenHab Rest API übergeben

    Hallo,

    ich möchte über meinen Wemos D1 mini (EPS8266) die Daten meines Windmessers (Technoline TX20) auslesen. Der Löwenanteil dabei hat mir http://blog.bubux.de/windsensor-tx20-mit-esp8266/ geholfen bzw. bunnyhu https://github.com/bunnyhu/ESP8266_TX20_wind_sensor/ .

    Jetzt ist mein Problem das ich die Daten (Windgeschwindigkeit + Windrichtung) gerne per curl an die Openhab Rest API senden würde.

    Ich habe im prinzip den Curl Befehl (von einer Raspi-Integration die ich schon die Rest läuft)

    Code:
    curl -u Benutzername:Passwort -s -X PUT -H "Content-Type: text/plain" -d $value "http://192.168.0.5:8080/rest/items/"$item"/state"
    weiß nur nicht wie ich den in den Code integriere...

    Kann mir da wer helfen?
    Mein kompletter Sketch ist bisher:

    Code:
    #include <ESP8266WiFi.h>
    #include <WiFiManager.h>
    
    // WLAN Zugangsdaten
    const char* ssid      = "TX20Test";
    const char* password  = "12345678";
    // Host wo Daten hingesendet werden soll
    const char* datahost  = "192.168.0.5";
    
    unsigned long previousMillis = 0;
    const long interval = 300000;      // 300000ms = 5 Minuten Intervall
    
    WiFiServer server(80);
    ADC_MODE(ADC_VCC);
    
    const byte DATAPIN=D2;
    volatile boolean TX20IncomingData = false;
    
    unsigned char chk;
    unsigned char sa,sb,sd,se;
    unsigned int sc,sf, pin;
    
    String tx20RawDataS = "";
    
    void isTX20Rising() {
      if (!TX20IncomingData) {
        TX20IncomingData = true;
      }  
    }
    
    /*
     * SETUP
     */
    void setup() {
      pinMode(DATAPIN, INPUT);
      attachInterrupt(digitalPinToInterrupt(DATAPIN), isTX20Rising, RISING);
      Serial.begin(115200);
      delay(10);
    
      Serial.println();
      Serial.println();
    
      WiFiManager wifiManager;
    
      // AP deaktivieren
      WiFi.softAPdisconnect();
      WiFi.disconnect();
      WiFi.mode(WIFI_STA);
      delay(100);
    
      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");
      server.begin();
      Serial.println("Server started");
      Serial.println(WiFi.localIP());
    }
    
    boolean readTX20() {
        int bitcount=0;
    
        sa=sb=sd=se=0;
        sc=0;sf=0;
        tx20RawDataS = "";
    
        for (bitcount=41; bitcount>0; bitcount--) {
          pin = (digitalRead(DATAPIN));
          if (!pin) {
            tx20RawDataS += "1";      
          } else {
            tx20RawDataS += "0";      
          }
          if ((bitcount==41-4) || (bitcount==41-8) || (bitcount==41-20)  || (bitcount==41-24)  || (bitcount==41-28)) {
            tx20RawDataS += " ";
          }      
          if (bitcount > 41-5){
            // start, inverted
            sa = (sa<<1)|(pin^1);
          } else
          if (bitcount > 41-5-4){
            // wind dir, inverted
            sb = sb>>1 | ((pin^1)<<3);
          } else
          if (bitcount > 41-5-4-12){
            // windspeed, inverted
            sc = sc>>1 | ((pin^1)<<11);
          } else
          if (bitcount > 41-5-4-12-4){
            // checksum, inverted
            sd = sd>>1 | ((pin^1)<<3);
          } else 
          if (bitcount > 41-5-4-12-4-4){
            // wind dir
            se = se>>1 | (pin<<3);
          } else {
            // windspeed
            sf = sf>>1 | (pin<<11);
          } 
    
          delayMicroseconds(1220);    
        }
        chk= ( sb + (sc&0xf) + ((sc>>4)&0xf) + ((sc>>8)&0xf) );chk&=0xf;
        delayMicroseconds(2000);  // just in case
        TX20IncomingData = false;  
    
        if (sa==4 && sb==se && sc==sf && sd==chk){      
          return true;
        } else {
          return false;      
        }
    }
    
    /*
     * LOOP
     */
    void loop() {
      if (TX20IncomingData) {
        char a[90];
        boolean validData = readTX20();
        Serial.println(tx20RawDataS);
        sprintf(a, "ID: %d\t%d\n", sa, B00100);
        Serial.write (a);
        sprintf(a, "Wind direction: %d\t%d\n", sb, se);
        Serial.write (a);
        sprintf(a, "Wind speed: %d\t%d\n", sc, sf);
        Serial.write (a);
        sprintf(a, "Checksum: %d\t%d\n", sd, chk);
        Serial.write (a);
        if (validData){      
          Serial.println(" :) OK :) OK :) OK :) OK");
        } else {
          Serial.println(" !!! ERROR !!! ERROR !!!");
        }
        Serial.println("");
      }
      Serial.println("");
    
        // Pruefen ob sich ein Client verbunden hat
        WiFiClient client = server.available();
        if (!client) {
          return;
        }
    
        // Warten bis der Client Daten sendet
        Serial.println("neuer Client");
        while(!client.available()){
          delay(1);
        }
    
        // Lese die erste Zeile der Anfrage
        String req = client.readStringUntil('\r');
        Serial.println(req);
        client.flush();
    
        // WIFI Signalstaerke auslesen
        long rssi = WiFi.RSSI();
        Serial.print("RSSI:");
        Serial.println(rssi);
    
        // Batteriespannung auslesen
        float vcc = ESP.getVcc() / 1000.0;
    
        /* "externe" Webseite aufrufen um Sensordaten zu übergeben
        unsigned long currentMillis = millis();  
        if(currentMillis - previousMillis >= interval) 
        {
          previousMillis = currentMillis;
          sendData();
        }
        */
        // Anfrage an ESP-Webserver beantworten
        int val;
        String content;
        if (req.indexOf("/json") != -1) {
          // Sensordaten als JSON zurueck liefern
          // http://<url_zum_esp>/json
          Serial.println("JSON");
          content = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
          //content += "{"Windgeschwindigkeit":";
          content += sc;
          //content += ","Windrichtung":";
          content += sb;
          content += "}\n";
        } else {
          // Sensordaten als Webseite anzeigen
          Serial.println("HTML");
          content = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html><head><title>Windsensor</title></head><body>\r\n";
          //style="font-family:verdana;";
          content += "<p style='font-size:18px;font-weight:bold;'>Windsensor</p><br>";
          content += "<table>";
          content += "<tr><td>Windgeschwindigkeit</td><td>";
          content += sc;
          content += "</td></tr><tr><td>Windrichtung</td><td>";
          content += sb;
          content += "</td></tr>";
          content += "<tr><td><br></td><td></td></tr>";
          content += "<tr><td>WIFI-Signal</td><td>";
          content += rssi;
          content += " dBm</td>";
          content += "<tr><td>Signal Qualit&auml;t</td><td>";
          content += 2 * (rssi + 100);
          content += "%</td></tr>";
          content += "<tr><td>Batteriespannung</td><td>";
          content += vcc;
          content += " V</td></tr>";
          content += "</table>";
          content += "</body></html>\n";
        }
    
        // Senden der Antwort zum Webserver
        client.print(content);
        delay(1);
        Serial.println("Client Verbindung beendet");
    
      }
    
    
    // Verbindung zu Server herstellen und Sensordaten übermitteln (aktiv)
    void sendData() 
    {
      Serial.println("");
      Serial.print(F("Verbinde zu '"));
      Serial.print(datahost);
      Serial.print("'");
    
      WiFiClient client;
      const int httpPort = 80;
      if (!client.connect(datahost, httpPort)) {
        Serial.println(F(" Fehler beim verbinden zum Host"));
        return;
      }
    
      String url = "/umwelt/windsensor.php";
      url += "?windgeschwindigkeit=";
      url += sc;
      url += "&windrichtung=";
      url += sb;
    
      Serial.print("URL-Anfrage: ");
      Serial.println(url);
    
      client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                   "Host: " + datahost + "\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;
        }
      }
    
      while(client.available()){
        String line = client.readStringUntil('\r');
        Serial.print(line);
      }
      Serial.println("");
      Serial.print(F("Verbindung zu '"));
      Serial.print(datahost);
      Serial.println(F("' beendet."));
    }
    in dem Sketch gibt es schon 3 Varianten des Abrufens:
    1) Website die man aufrufen kann, Daten werden angezeigt
    2) Daten per JSON abrufen (an der Website-URL angehangen)
    3) Daten vom ESP senden an eine Website

    Nun wäre das 3. im Prinzip das senden, aber ich steige beim Code nicht durch. Wie kriege ich meine Rest-API angesprochen?

    Diese ist erreichbar unter: "http://192.168.0.5:8080/rest/items/"$item"/state"

    Danke!
    Gruß

    #2
    PHP-Code:
       const int httpPort 8080;

        
    String url "/rest/items/";
        
    url += <itemname>;
        
    url += "/state";
        
    String StateOfItem "TestWert";
        
    client.print("POST ");
        
    client.print(url);
        
    client.println(" HTTP/1.1");
        
    client.print("Host: ");
        
    client.println(datahost);
        
    client.println("Content-Type: text/plain");
        
    client.print("Content-Length: ");
        
    client.println(StateOfItem.length());
        
    client.println();
        
    client.println(StateOfItem);
        
    client.println("Connection: close\r\n"); 
    Code ungeprüft!
    Zuletzt geändert von FlyingEaglE; 27.10.2017, 08:26.

    Kommentar


      #3
      Hallo,

      danke FlyingEaglE für deinen Code.

      ich habe deinen Code "const int httpPort = 8080;" oben bei der Variablen Definition gepackt und in den void loop() per {} als einzelnen code hinzugefügt und angepasst.

      Kriege nur einen Fehler der mir schon was sagt, aber (auch durch googlen) finde ich keine Lösung.

      Sketch_oct27a:129: error: 'client' was not declared in this scope

      client.print("POST ");
      Mein Sketch ist nun: (ich habe den Sketch gekürzt auf das nötigste (ohne den "an Rest-API senden" funktioniert es auch per Seriellen Monitor)

      Code:
      #include <ESP8266WiFi.h>
      #include <WiFiManager.h>
      
      // WLAN Zugangsdaten
      const char* ssid      = "WLAN-ID";
      const char* password  = "Passwort";
      const char* datahost  = "192.168.0.5";
      const int httpPort = 8080;
      
      const byte DATAPIN=D2;
      volatile boolean TX20IncomingData = false;
      
      unsigned char chk;
      unsigned char sa,sb,sd,se;
      unsigned int sc,sf, pin;
      
      String tx20RawDataS = "";
      
      
      void isTX20Rising() {
        if (!TX20IncomingData) {
          TX20IncomingData = true;
        }  
      }
      
      /*
       * SETUP
       */
      void setup() {
        pinMode(DATAPIN, INPUT);
        attachInterrupt(digitalPinToInterrupt(DATAPIN), isTX20Rising, RISING);
        Serial.begin(115200);
      
          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(WiFi.localIP());
      }
      
      boolean readTX20() {
          int bitcount=0;
      
          sa=sb=sd=se=0;
          sc=0;sf=0;
          tx20RawDataS = "";
      
          for (bitcount=41; bitcount>0; bitcount--) {
            pin = (digitalRead(DATAPIN));
            if (!pin) {
              tx20RawDataS += "1";      
            } else {
              tx20RawDataS += "0";      
            }
            if ((bitcount==41-4) || (bitcount==41-8) || (bitcount==41-20)  || (bitcount==41-24)  || (bitcount==41-28)) {
              tx20RawDataS += " ";
            }      
            if (bitcount > 41-5){
              // start, inverted
              sa = (sa<<1)|(pin^1);
            } else
            if (bitcount > 41-5-4){
              // wind dir, inverted
              sb = sb>>1 | ((pin^1)<<3);
            } else
            if (bitcount > 41-5-4-12){
              // windspeed, inverted
              sc = sc>>1 | ((pin^1)<<11);
            } else
            if (bitcount > 41-5-4-12-4){
              // checksum, inverted
              sd = sd>>1 | ((pin^1)<<3);
            } else
            if (bitcount > 41-5-4-12-4-4){
              // wind dir
              se = se>>1 | (pin<<3);
            } else {
              // windspeed
              sf = sf>>1 | (pin<<11);
            }
      
            delayMicroseconds(1220);    
          }
          chk= ( sb + (sc&0xf) + ((sc>>4)&0xf) + ((sc>>8)&0xf) );chk&=0xf;
          delayMicroseconds(2000);  // just in case
          TX20IncomingData = false;  
      
          if (sa==4 && sb==se && sc==sf && sd==chk){      
            return true;
          } else {
            return false;      
          }
      }
      
      /*
       * LOOP
       */
      void loop() {
        if (TX20IncomingData) {
          char a[90];
          boolean validData = readTX20();
          Serial.println(tx20RawDataS);
          sprintf(a, "ID: %d\t%d\n", sa, B00100);
          Serial.write (a);
          sprintf(a, "Wind direction: %d\t%d\n", sb, se);
          Serial.write (a);
          sprintf(a, "Wind speed: %d\t%d\n", sc, sf);
          Serial.write (a);
          sprintf(a, "Checksum: %d\t%d\n", sd, chk);
          Serial.write (a);
          if (validData){      
            Serial.println(" :) OK :) OK :) OK :) OK");
          } else {
            Serial.println(" !!! ERROR !!! ERROR !!!");
          }
          Serial.println("");
        }
      
      
      String url = "/rest/items/";
      url += "Windgeschwindigkeit";
      url += "/state";
      String StateOfItem = "sc";
      client.print("POST ");
      client.print(url);
      client.println(" HTTP/1.1");
      client.print("Host: ");
      client.println(datahost);
      client.println("Content-Type: text/plain");
      client.print("Content-Length: ");
      client.println(StateOfItem.length());
      client.println();
      client.println(StateOfItem);
      client.println("Connection: close\r\n");  
      
      }
      kannst du mir nochmal helfen wie ich client deklariert bekomme?
      DANKE! (oder muss ich eine zusätzliche Library deklarieren?
      Zuletzt geändert von desidia; 27.10.2017, 21:34.

      Kommentar


        #4
        Zitat von desidia Beitrag anzeigen
        WiFiClient client;
        Diese Zeile fehlt im neuen Sketch.

        Kommentar


          #5
          oh man, ich Idiot... :-\
          das war natürlich im alten Code mit drin, aber im zusammengesetzten nicht mehr.. DANKE!

          jetzt ging alles zu kompilieren, aber es kommen keine Daten an... :-\
          Das Script läuft sauber dauerhaft durch und zeigt im Seriellen Monitor alles fein an, aber in der Rest-API kommt nichts an.

          Ich habe es aber richtig verstanden mit meinen Anpassungen an deinem Script?


          Code:
          WiFiClient client;
          String url = "/rest/items/";
          url += [COLOR=#FF0000]"Windgeschwindigkeit"[/COLOR];
          url += "/state";
          String StateOfItem = [COLOR=#FF0000]"sc"[/COLOR];
          client.print("POST ");
          client.print(url);
          client.println(" HTTP/1.1");
          client.print("Host: ");
          client.println(datahost);
          client.println("Content-Type: text/plain");
          client.print("Content-Length: ");
          client.println(StateOfItem.length());
          client.println();
          client.println(StateOfItem);
          client.println("Connection: close\r\n");

          Kommentar


            #6
            ach, ich kann mir vorstellen wodran es liegt.
            Ich habe ja auch noch eine Authorisierung drin, welche im Script ja nicht vorhanden ist.
            Wie funktioniert diese? (Benutzername + Passwort)

            Kommentar


              #7
              Probier es mal hiermit:

              PHP-Code:
              WiFiClient client;

              String url "/rest/items/";
              url += "Windgeschwindigkeit";
              url += "/state";
              String StateOfItem "sc";
              client.print("POST ");
              client.print(url);
              client.println(" HTTP/1.1");
              client.print("Host: ");
              client.println(datahost);
              client.println("Content-Type: text/plain");
              client.println("Authorization""Basic <benutzername:passwort--verschlüsselt-base64-encoded_GibtsOnlineGeneratorenFür>");
              // Als Beispiel: YmVudXR6ZXJuYW1lOnBhc3N3b3J0 Das steht für "benutzername:passwort" client.print("Content-Length: ");
              client.println(StateOfItem.length());
              client.println();
              client.println(StateOfItem);
              client.println("Connection: close\r\n"); 
              Probiert habe ich das aber selber bisher nicht, eine entsprechende Rückmeldung wäre sehr schön. Ggfs. mal das Authorisierungsgedöns ausmachen, damit man sieht ob überhaupt was "richtiges" passiert.
              Zuletzt geändert von FlyingEaglE; 01.11.2017, 22:47.

              Kommentar


                #8
                Zitat von FlyingEaglE Beitrag anzeigen
                Probier es mal hiermit:

                Probiert habe ich das aber selber bisher nicht, eine entsprechende Rückmeldung wäre sehr schön. Ggfs. mal das Authorisierungsgedöns ausmachen, damit man sieht ob überhaupt was "richtiges" passiert.

                ich verstehe den Teil:

                Code:
                client.println("Authorization", "Basic <passwort-verschlüsselt-base64-encoded_GibtsOnlineGeneratorenFür>");
                // Als Beispiel: dXNlcm5hbWU6cGFzc3dvcmQ= Das steht für "password" client.print("Content-Length: ");
                nicht.
                (die base64 Codierung schon) aber wie bekomme ich Benutzernamen und Passwort zusammen?

                ich komme nicht klar :-\

                bzw. den Login kann ich nur sehr erschwert deaktivieren, da das mein Livesystem ist und viele andere Inputs ankommen mit Autorisierung....


                Kommentar


                  #9
                  base64:
                  Code:
                  benutzername:passwort
                  Habe den Beitrag oben ergänzt.
                  Zuletzt geändert von FlyingEaglE; 01.11.2017, 22:48.

                  Kommentar


                    #10
                    Zitat von FlyingEaglE Beitrag anzeigen
                    base64:
                    Code:
                    benutzername:passwort
                    Habe den Beitrag oben ergänzt.
                    musste den Code abändern weil er es nicht kompiliert hat

                    Code:
                    client.print("Authorization: ");
                    client.println("Basic TkFNRTpQQVNT");
                    aber funktioniert noch immer nicht.
                    Kann man ein "Verbindung erfolgreich aufgebaut einbauen oder eine Fehlerdiagnose?
                    So komplett ohne anhaltspunkt ist ja wirklich blöd :-\

                    edit: kann es sein das im Code auch ganz und gar der Port fehlt? Ich habe Ihn ja oben mit 8080 definiert, aber im script fehlt der doch komplett oder?
                    Zuletzt geändert von desidia; 02.11.2017, 21:01.

                    Kommentar


                      #11
                      Code:
                      if (!client.connect(datahost, httpPort)) {
                           Serial.println(F(" Fehler beim verbinden zum Host"));     return;   }
                      Das muss schon auch drin sein. Poste mal deinen kompletten Code, ist dein benutzername : passwort wirklich so kurz?

                      Ich kann dir leider nicht mehr helfen als mit Hinweisen, in der Hoffnung das es richtig ist. Habe aktuell keine Hardware mit der ich das testen kann und leider auch keine Zeit. Ich wage gerade den Umstieg von 1.8.3 auf 2 - Junge junge wasn Krampf.

                      Kommentar


                        #12
                        Zitat von FlyingEaglE Beitrag anzeigen
                        Ich wage gerade den Umstieg von 1.8.3 auf 2 - Junge junge wasn Krampf.
                        Ja. Für Neueinsteiger ist es vielleicht einfacher (wobei es mich dann auch eher verwirren würde, warum ich einen Teil grafisch und einen Teil textuell konfigurieren soll), für alte Hasen ist es eher ein Abtörner obwohl das Thing-Modell durchaus zur Entflechtung beitragen kann. Mittelfristig werden hoffentlich nach und nach alle alten Bindings nach 2.0 protiert, so dass sich die Situation vielleicht auch bessert...

                        Kommentar


                          #13
                          Hallo desidia,

                          vielleicht wäre es einfacher, eine REST-Bibliothek einzubinden. Vielleicht https://github.com/DaKaZ/esp8266-restclient o.ä.

                          Was mir auffällt, ohne dass ich richtige Ahnung habe: du definierst zwar die Variablen datahost und port, aber ich sehe nur die Verwendung von datahost....
                          Im ursprünglichen "curl"-Aufruf arbeitest du mit PUT, in deinem ESP8266 Code nimmst Du dann POST...

                          Ich selbst würde auf eine Bibliothek zurückgreifen, da sich dort kompetente Leute schon viel Gedanken dazu gemacht haben. Schließlich möchte man das Rad ja nicht jedes Mal neu erfinden, sondern sich um die wichtigen Dinge kümmern...

                          Andreas

                          edit:
                          Habe gerade noch etwas gefunden, vielleicht ist das einfach zu verwenden: https://github.com/Br3nda/openhab-rest-esp8266
                          Zuletzt geändert von imhofa; 03.11.2017, 08:08. Grund: Ergänzung

                          Kommentar


                            #14
                            imhofa : das ist ja das was ich meine, es fehlt code.

                            ich habe es so verstanden, dass er genau bei den rest-api-zeugs ein pw vorgeschaltet hat.
                            aber soweit ich weiß müssen diese daten auch per post übersandt werden.

                            muss mir mal in ruhe den link ansehen.
                            Zuletzt geändert von FlyingEaglE; 03.11.2017, 14:55.

                            Kommentar


                              #15
                              Zitat von udo1toni Beitrag anzeigen

                              Ja. Für Neueinsteiger ist es vielleicht einfacher (wobei es mich dann auch eher verwirren würde, warum ich einen Teil grafisch und einen Teil textuell konfigurieren soll), für alte Hasen ist es eher ein Abtörner obwohl das Thing-Modell durchaus zur Entflechtung beitragen kann. Mittelfristig werden hoffentlich nach und nach alle alten Bindings nach 2.0 protiert, so dass sich die Situation vielleicht auch bessert...
                              ja, bis jetzt geht genau null, evtl. mache ich dazu mal noch nen eigenen fred auf.
                              Zuletzt geändert von FlyingEaglE; 03.11.2017, 15:03.

                              Kommentar

                              Lädt...
                              X