Ankündigung

Einklappen
Keine Ankündigung bisher.

BWT Aqua Perla auslesen, jedoch fehlt mir der aktuelle Durchfluss

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

    BWT Aqua Perla auslesen, jedoch fehlt mir der aktuelle Durchfluss

    Hallo ihr,

    wollt mal einen tollen Link einstellen, welcher mir gut weiter geholfen hat.

    BWT Aqa Perla goes IP-Symcon

    Hab mir ein kleines C++ Tool geschrieben, welches mir ein paar Werte über http an OpenHab schickt.

    Was mir jedoch noch fehlt ist der aktuelle Durchfluss. Weiß zufällig jemand wie ich diese Abfragen kann?

    Gruß, Seb

    #2
    Hallo

    Ich hab mir eine kleine Python-Lib zusammengebastelt, die die Werte von der USB-Schnittstelle abfragen kann (und das mittels Webservice zur Verfügung stellt). Den aktuellen Durchfluss bekomm ich aber nicht raus.
    Mein OpenHAB fragt alle 15 Minuten den Gesamtverbrauch ab und so kann ich auch schöne Verbrauchswerte zusammenstellen und Diagramme zeichnen lassen.

    Ich hatte die Sache jetzt 5 Tage lang am Laufen und alles funktionierte problemlos. Seit heute bekomme ich aber keine Werte mehr von der Anlage. Egal was ich über die USB-Schnittstelle sende, die BWT liefert nichts zurück.

    Kommentar


      #3
      Hallo wqrt,
      konntest du das Problem lösen?
      Hatte auch nach einigen Wochen den Effekt, dass ich nicht mehr Abfragen konnte. Aber ein Reconnect der COM Schnittstelle hat geholfen. Hab das dann in mein C++ Programm integriert, dass es neu Verbindet, wenn ein Fehler aufgetreten ist...
      Gruß, Seb

      Kommentar


        #4
        Hallo wqrt,
        würdest Du ggf. Dein Python Script teilen? Ich bin sehr daran interessiert, meine AqaPerla auch an mein OpenHAB anzubinden.
        Beste Grüße,
        Marcel

        Kommentar


          #5
          Hi Marcel,

          entschuldige, hab deine Frage erst jetzt gelesen.
          Ich selbst habe das Projekt in C++ verfasst. Meine Referenz war das PHP Script von https://www.symcon.de/forum/threads/...goes-IP-Symcon
          Als Python Script habe ich es selber nicht. Sorry.

          Gruß, Seb

          Kommentar


            #6
            Hallo Seb,
            habe es zwischenzeitlich auch in Orientierung an den PHP Scripten der oben genannten Quelle in Python implementiert. Läuft gut.
            Beste Grüße,
            Marcel

            Kommentar


              #7
              Im Anhang mein c++ code

              Gerne auch Verbesserungen einbauen. Die Durchflussberechnung ist noch nicht so wie es gerne hätte, kam aber noch nicht dazu mehr daraus zu machen
              Angehängte Dateien

              Kommentar


                #8
                Hallo Seb,
                ich habe heute eine Aqa Perla 3 bekommen und würde gern die Daten auslesen.
                leide kann ich deine Datei nicht öffnen
                Grüsse aus Berlin
                Jan

                Kommentar


                  #9
                  Hallo Jan,
                  hab's nochmal angehängt.Hoffe es klappt jetzt und hilft dir weiter.
                  Gruß, Seb
                  Angehängte Dateien

                  Kommentar


                    #10
                    aqaperla.h
                    Code:
                    #ifndef AQUA_PERLA_HEADER
                    #define AQUA_PERLA_HEADER
                    #define DEBUG 3
                    
                    #define START_BYTE        0x0D
                    #define STOP_BYTE        0x0A
                    
                    #define CMD_Anzahl        256        // Anzahl Kommandos (Zeilen)
                    #define CMD_VERBRAUCH_SEIT_IBN                0x10
                    #define CMD_SAEULE1_RESTKAPAZITAET            0x02    // Sollkapazität Säule 1
                    #define CMD_SAEULE2_RESTKAPAZITAET            0x03    // Sollkapazität Säule 2
                    #define CMD_MAX_DURCHFLUSS_HEUTE_LITER        0x05    // Spitzendurchfluss heute
                    #define CMD_MAX_DURCHFLUSS_GESTERN_LITER    0x06    // Spitzendurchfluss gestern
                    #define CMD_MAX_DURCHFLUSS_SEIT_IBN_LITER    0x07    // Spitzendurchfluss seit IBN
                    #define CMD_REGENERATIONEN_SEIT_IBN            0x11    // Regenerationen seit IBN
                    #define CMD_SALZVERBRAUCH_GRAMM_SEIT_IBN    0x13    // Salztverbrauch seit IBN
                    #define CMD_ALARM                            0x20    // Alarm
                    
                    #define SEND_COMMANDS    {    0x10, /*Verbrauchdaten seit IBN Verbrauch*/\
                                                0x02, 0x03, 0x08, 0x11, 0x13, 0x25, 0x26}
                    
                    /*
                    Typ
                    0D,01,00,0E,0A,
                    0D 01 01 0C 1B 0A
                    0D 01 01 0C 1B 0A
                    
                    Sollkapazität Säule 1
                    0D,25,00,32,0A,
                    0D 25 02 D8 01 0D 0A
                    0D 25 02 LSB HSB CRC STOP
                    
                    Sollkapazität Säule 2
                    0D,26,00,33,0A,
                    0D 26 02 D8 01 0E 0A
                    0D 26 02 LSB HSB CRC STOP
                    
                    Restkapazität Säule 1
                    0D,02,00,0F,0A,
                    0D 02 02 5B 01 6D 0A
                    0D 02 02 LSB HSB CRC STOP
                    
                    Restkapazität Säule 2
                    0D,03,00,10,0A,
                    0D 03 02 3B 01 4E 0A
                    0D 03 02 LSB HSB CRC STOP
                    
                    Regenerationsschritt
                    0D,04,00,11,0A,
                    0D 04 01 00 12 0A
                    0D 04 01 Reg-Schritt CRC STOP
                    
                    Softwareversion
                    0D,19,00,26,0A,
                    0D 19 11 56 65 72 73 69 6F 6E 3A 20 33 2E 39 34 23 31 35 35 03 0A
                    <CR><EM><DC1>Version:<Space>3.94#155<ETX><LF>
                    
                    Verbrauchdaten Allgemein Spitzendurchfluss
                    0D,05,00,12,0A,
                    0D 05 02 00 00 14 0A
                    0D 05 02 LSB HSB CRC STOP
                    
                    Verbrauchdaten Allgemein Spitzendurchfluss 24h
                    0D,06,00,13,0A,
                    0D 06 02 70 03 88 0A
                    0D 06 02 LSB HSB CRC STOP
                    
                    Verbrauchdaten Allgemein Verbrauch 24h
                    0D,08,00,15,0A,
                    0D 08 02 00 00 17 0A
                    0D 08 02 90 00 A7 0A!!!!!
                    
                    Verbrauchdaten seit IBN Spitzendurchfluss
                    0D,07,00,14,0A,
                    0D 07 02 39 04 53 0A
                    0D 07 02 LSB HSB CRC STOP
                    
                    Verbrauchdaten seit IBN Verbrauch 24h
                    0D,09,00,16,0A,
                    0D 09 02 A7 00 BF 0A
                    0D 09 02 LSB HSB CRC STOP
                    
                    Verbrauchdaten seit IBN Salzverbrauch
                    0D,13,00,20,0A,
                    0D 13 04 FA 00 00 00 1E 0A
                    0D 13 04 LSB HSB 00 00 CRC STOP
                    
                    Verbrauchdaten seit IBN Reg-Mitteleinsparung
                    0D,14,00,21,0A,
                    0D 14 02 00 00 23 0A
                    0D 14 02 LSB HSB CRC STOP
                    
                    Verbrauchdaten seit IBN Verbrauch
                    0D,10,00,1D,0A,
                    0D 10 04 08 02 00 00 2B 0A
                    0D 10 04 LSB .SB .SB HSB CRC STOP
                    
                    Regenerationen seit IBN
                    0D,11,00,1E,0A,
                    0D 11 02 01 00 21 0A
                    0D 11 02 LSB HSB CRC STOP
                    
                    Regenerationen seit letztem Service
                    0D,12,00,1F,0A,
                    0D 12 02 01 00 22 0A
                    0D 12 02 LSB HSB CRC STOP
                    
                    Abfrage KW (38d 26h, 14d 0Eh)
                    0D,24,02,26,0E,67,0A,
                    0D 24 1C 32 32 2D 30 39 2D 31 34 23 20 20 31 30 38 31 23 20 20 20 31 32 31 23 20 20 20 20 32 F2 0A
                    HEADER Reportdatum Trennzeichen LEER LEER max. Durchfluss (l/h) Trennzeichen LEER LEER LEER Wochenverbrauch (l) Trennzeichen LEER LEER LEER LEER Regenerationen Appendix
                    
                    Abfrage Log
                    0D,21,02,00,09,39,0A, Monat Prüfsumme
                    0D 21 25 32 31 2D 30 39 2D 31 34 2D 2D 2D 31 36 3A 32 36 3A 30 38 2D 3E 3E 74 79 70 65 20 63 68 61 6E 67 65 3A 20 31 32 BE 0A
                    <CR>!%21-09-14---16:26:08->>type<Space>change:<Space>12<(BE)><LF>
                    
                    Abfrage Alarm
                    0D,20,01,00,2E,0A, Zähler Prüfsumme
                    0D 20 1F 41 6C 61 72 6D 3A 20 32 34 20 3A 20 32 31 2D 30 39 2D 31 34 20 2D 20 31 36 3A 34 35 3A 34 35 18 0A
                    <CR><Space><US>Alarm:<Space>24<Space>:<Space>21-09-14<Space>-<Space>16:45:45<CAN><LF>
                    
                    0D,20,01,01,2F,0A, Zähler Prüfsumme *
                    */
                    #else
                    #endif
                    http.h
                    Code:
                    #ifndef HTTP_HEADER
                    #define HTTP_HEADER
                    
                    #define HTTP_HEAD                        "curl --header \"Content-Type: text/plain\" --request POST --data \""
                    #define HTTP_TARGET                        "\" http://192.168.123.123:8080/rest/items/"
                    #define ITEM_WASSER_GESAMTVERBRAUCH_LITER                    "UG_TECHNIK_Wasser_Gesamtverbrauch_Liter"
                    #define ITEM_WASSER_SAEULE1_RESTKAPZIAET                    "UG_TECHNIK_Wasser_Saeule1_Restkapazitaet_Liter"
                    #define ITEM_WASSER_SAEULE2_RESTKAPZIAET                    "UG_TECHNIK_Wasser_Saeule2_Restkapazitaet_Liter"
                    #define ITEM_WASSER_MAX_DURCHFLUSS_HEUTE_LITER                "UG_TECHNIK_Wasser_MaxDurchlfuss_Heute_Liter"
                    #define ITEM_WASSER_MAX_DURCHFLUSS_GESTERN_LITER            "UG_TECHNIK_Wasser_MaxDurchlfuss_Gestern_Liter"
                    #define ITEM_WASSER_MAX_DURCHFLUSS_SEIT_IBN_LITER            "UG_TECHNIK_Wasser_MaxDurchlfuss_Seit_IBN_Liter"
                    #define ITEM_WASSER_AKTUELLER_DURCHFLUSS_LITER_PRO_STUNDE    "UG_TECHNIK_Wasser_AktuellerDurchfluss_LiterProStunde"
                    #define ITEM_REGENERATIONEN_SEIT_IBN                        "UG_TECHNIK_Wasser_Regenerationen_Seit_IBN"
                    #define ITEM_WASSER_SALZVERBRAUCH_KG_SEIT_IBN                "UG_TECHNIK_Wasser_Salzverbrauch_Seit_IBN_kg"
                    
                    
                    int http(char *httpString);
                    
                    #else
                    #endif
                    serial.h
                    Code:
                    #ifndef SERIAL_HEADER
                    #define SERIAL_HEADER
                    
                    #define MIN_LOOP_TIME_MS                    200.0    // alle 200ms (abfrage Durchfluss)
                    #define LOOP_TIME_ALLGEMEINE_COMMANDOS_MS    5000.0    // alle 5s (generelle Abfrage aller Befehle)
                    
                    int openConnection(int *USBCon);
                    int closeConnection(int *USBCon);
                    char serialRead(int *USBCon, float *ptrfWirkarbeitBezugTotal_kWh, float *ptrfLeistung_W, float *ptrfLeistungMin_W, float *ptrfLeistungMax_W);
                    int checkInputBuf(char *inBuf, int length);
                    int frameAnalyse(char *frame, int size, float *ptrfWirkarbeitBezugTotal_kWh, float *ptrfLeistung_W, float *ptrfLeistungMin_W, float *ptrfLeistungMax_W);
                    
                    #else
                    #endif
                    wasser.cpp
                    Code:
                    #include <iostream>
                    #include <stdio.h>      // standard input / output functions
                    #include <stdlib.h>
                    #include <string.h>     // string function definitions
                    #include <unistd.h>     // UNIX standard function definitions
                    #include <fcntl.h>      // File control definitions
                    #include <errno.h>      // Error number definitions
                    #include <termios.h>    // POSIX terminal control definitions
                    #include <iomanip>        // cout hex into string
                    
                    #include <getopt.h>
                    #include <sys/types.h>
                    #include <sys/stat.h>
                    
                    #include "../header/serial.h"
                    #include "../header/http.h"
                    
                    using namespace std;
                    using std::string;
                    
                    extern bool tryReconnect;
                    /*
                        Hauptfunktion
                    */
                    int main()
                    {
                        int USBCon = -1;
                        float fWirkarbeitBezugTotal_kWh = -1.0;
                        float fLeistung_W = -1.0;
                        float fLeistungMin_W = 9999.0;
                        float fLeistungMax_W = 0.0;
                    
                        cout << "*** Starte Wasserablesung ***\n\n";
                        
                        // Probiere USB/Seriell Verbindung zu öffnen
                        printf("Open Connection...\n");
                        openConnection(&USBCon);
                            
                        while(true)
                        {
                            //printf("Serial Read...\n");
                            serialRead(&USBCon, &fWirkarbeitBezugTotal_kWh, &fLeistung_W, &fLeistungMin_W, &fLeistungMax_W);
                            // wurden plausible Werte geschrieben?
                            //if ( (fWirkarbeitBezugTotal_kWh != -1.0) && (fLeistung_W != -1.0) )
                            //    http(&fWirkarbeitBezugTotal_kWh, &fLeistung_W);
                    
                            if(tryReconnect)
                            {
                                tryReconnect=false;
                                // Ein Fehler ist aufgetreten (Timeout während Selection)
                                // Neu Verbindung durchführen
                                closeConnection(&USBCon);
                                // Probiere USB/Seriell Verbindung zu öffnen
                                printf("Open Connection...\n");
                                openConnection(&USBCon);
                    
                            }
                                
                            usleep(MIN_LOOP_TIME_MS);    // damit die CPU etwas entlasstet ist
                        }
                        
                        closeConnection(&USBCon);
                        
                    }
                    serial.cpp
                    Code:
                    #include <iostream>
                    #include <stdio.h>      // standard input / output functions
                    #include <stdlib.h>
                    #include <string.h>     // string function definitions
                    #include <unistd.h>     // UNIX standard function definitions
                    #include <fcntl.h>      // File control definitions
                    #include <errno.h>      // Error number definitions
                    #include <termios.h>    // POSIX terminal control definitions
                    #include <iomanip>        // cout hex into string
                    
                    #include <sys/time.h>        // time
                    #include <sys/select.h>
                    
                    #include "../header/serial.h"        // eigener Header
                    #include "../header/aqaperla.h"    // Zähler Eigenschaften
                    #include "../header/http.h"
                    
                    using namespace std;
                    using std::string;
                    using std::ostringstream;
                    //using std::stringstream
                    
                    //struct termios tty;
                    //struct termios tty_old;
                    //memset (&tty, 0, sizeof tty);
                    
                    fd_set readFds, writeFds, exceptFds;
                    struct timeval timeout;
                    bool tryReconnect=false;
                    int cntConnections=0;
                    
                    /*
                            Öffne  Serielle USB Verbindung
                    */
                    int openConnection(int *USBCon)
                    {
                        struct termios tty;
                        string serialPort = "/dev/ttyACM0";
                        
                        *USBCon = open("/dev/ttyACM0", O_RDWR| O_NONBLOCK | O_NDELAY );
                        if (*USBCon == -1)
                        {
                            perror("Fehler: Serieller Port </dev/ttyACM0>konnte nicht geöffnet werden\n");
                            exit(EXIT_FAILURE);
                        }
                        cntConnections++;
                        fcntl(*USBCon, F_SETFL, 0);
                        
                        FD_ZERO(&readFds); /* clear the set */
                        FD_ZERO(&writeFds); /* clear the set */
                        FD_ZERO(&exceptFds); /* clear the set */
                        FD_SET(*USBCon, &readFds); /* add our file descriptor to the set */
                        
                        timeout.tv_sec = 3;            // 3s
                        timeout.tv_usec = 0;    
                        
                        cout << "Serieller Port <" << serialPort << "> wurde erfolgreich geöffnet. File description ist <" << *USBCon << ">" << endl << endl;
                        
                        /* Set Baud Rate */
                        cfsetospeed (&tty, (speed_t)B19200);
                        cfsetispeed (&tty, (speed_t)B19200);
                    
                        /* Setting other Port Stuff */
                        tty.c_cflag     &=  ~PARENB;        // Parity none
                        tty.c_cflag     &=  ~CSTOPB;        // one StopBit
                        tty.c_cflag     &=  ~CSIZE;            // clear out the current word size
                        tty.c_cflag     |=  CS8;            // 8Bits (plus 1 Parity Bit)
                    
                        tty.c_cflag     &=  ~CRTSCTS;        // no flow control
                        //tty.c_cflag     |=  CRTSCTS;        // flow control
                        tty.c_cc[VMIN]    =   0;//1;            // read doesn't block
                        tty.c_cc[VTIME]    =   5;                // Timeout (Einheit: 100ms)
                        tty.c_cflag     |=  CREAD | CLOCAL;    // turn on READ & ignore ctrl lines
                    
                        /* Make raw */
                        cfmakeraw(&tty);
                        
                        /* Flush Port, then applies attributes */
                        printf("Flush Port...\n");
                        tcflush( *USBCon, TCIFLUSH );
                        if ( tcsetattr ( *USBCon, TCSANOW, &tty ) != 0)
                        {
                            cout << "Error " << errno << " from tcsetattr" << endl;
                        }
                        
                        /* Flush Port, then applies attributes */
                        tcflush( *USBCon, TCIFLUSH );
                    
                    }
                    
                    double  curTimeMs = 0.0;
                    double  lastTimeMs_LoopDurchfluss = 0.0;
                    double  difTimeMs_LoopDurchfluss = 0.0;
                    double  timeMs_LoopDurchfluss = MIN_LOOP_TIME_MS;
                    uint durchflussLiterProStunde = 0;
                    
                    double  lastTimeMs_LoopAllgemein = 0.0;
                    double  difTimeMs_LoopAllgemein = 0.0;
                    double  timeMs_LoopAllgemein = LOOP_TIME_ALLGEMEINE_COMMANDOS_MS;
                    
                    uint curLiter = 0;
                    uint lastLiter = 0;
                    double timeMs_LastLiter = 0.0;
                    
                    bool nurDurchfluss = false;
                    
                    char serialRead(int *USBCon, float *ptrfWirkarbeitBezugTotal_kWh, float *ptrfLeistung_W, float *ptrfLeistungMin_W, float *ptrfLeistungMax_W)
                    {
                        // erst senden dann empfangen
                        //char sendCmds[] = SEND_COMMANDS;
                        char outBuf[16];
                        char inBuf[256];
                        int result = -1;
                    
                        // generell normale Abfrage
                        nurDurchfluss = false;
                    
                        char cmd[CMD_Anzahl];//[CMD_Length];
                        int cmdPos = 0;
                        // get current time
                        timeval tv;
                        gettimeofday(&tv, NULL);
                        curTimeMs = (double)(tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0);
                    
                        difTimeMs_LoopDurchfluss = curTimeMs - lastTimeMs_LoopDurchfluss;
                        difTimeMs_LoopAllgemein = curTimeMs - lastTimeMs_LoopAllgemein;
                        //printf("dif %f - cur %f - last %f\n", difTimeMs_LoopDurchfluss, curTimeMs_LoopDurchfluss, lastTimeMs_LoopDurchfluss);
                        if (difTimeMs_LoopDurchfluss < 0.0)
                        {
                            // bei Zählerüberlauf einfach neu Setzen;
                            printf("Zählerüberlauf (Loop Durchlauf) ... dif %f cur %f last %f\n", difTimeMs_LoopDurchfluss, curTimeMs, lastTimeMs_LoopDurchfluss);
                            lastTimeMs_LoopDurchfluss = curTimeMs;
                        }
                        if (difTimeMs_LoopAllgemein < 0.0)
                        {
                            // bei Zählerüberlauf einfach neu Setzen;
                            printf("Zählerüberlauf (Loop Allgemein) ... dif %f cur %f last %f\n", difTimeMs_LoopAllgemein, curTimeMs, lastTimeMs_LoopAllgemein);
                            lastTimeMs_LoopAllgemein = curTimeMs;
                        }
                    
                        if (difTimeMs_LoopDurchfluss >= timeMs_LoopDurchfluss)
                        {
                            // nur abfragen, wenn LoopTime abgelaufen ist
                            cmd[cmdPos++] = CMD_VERBRAUCH_SEIT_IBN;
                            //printf("Dif %d Cur %d last %d\n", (int)difTimeMs_LoopDurchfluss, (int)curTimeMs, (int) lastTimeMs_LoopDurchfluss);
                            lastTimeMs_LoopDurchfluss = curTimeMs;
                            nurDurchfluss = true;
                        }
                        
                        if (difTimeMs_LoopAllgemein >= timeMs_LoopAllgemein)
                        {
                            if (!nurDurchfluss) // falls in diesem Zyklus auch LoopDurchfluss zutrifft, dann wurde diese Abfrage bereits angefügt
                                cmd[cmdPos++] = CMD_VERBRAUCH_SEIT_IBN;
                            cmd[cmdPos++] = CMD_SAEULE1_RESTKAPAZITAET;
                            cmd[cmdPos++] = CMD_SAEULE2_RESTKAPAZITAET;
                            cmd[cmdPos++] = CMD_MAX_DURCHFLUSS_HEUTE_LITER;
                            cmd[cmdPos++] = CMD_MAX_DURCHFLUSS_GESTERN_LITER;
                            cmd[cmdPos++] = CMD_MAX_DURCHFLUSS_SEIT_IBN_LITER;
                            cmd[cmdPos++] = CMD_REGENERATIONEN_SEIT_IBN;
                            cmd[cmdPos++] = CMD_SALZVERBRAUCH_GRAMM_SEIT_IBN;
                            
                            /* Alarmabfrage kann zum Absturz der AquaPerla führen
                               Strom und USB ziehe
                               Strom anschließen
                               anschließend auch wieder USB*/
                            //cmd[cmdPos++] = CMD_ALARM;
                        
                            //printf("Dif %d Cur %d last %d\n", (int)difTimeMs_LoopAllgemein, (int)curTimeMs, (int)lastTimeMs_LoopAllgemein);
                            lastTimeMs_LoopAllgemein = curTimeMs;
                            nurDurchfluss = false;
                        }
                        //cmd[0][1] = CMD_VERBRAUCH_SEIT_IBN_LENGTH;
                    
                    
                        for (int i = 0; i < cmdPos; i++)
                        {
                            int pos = 0;
                            int crc = 0;
                            outBuf[pos++] = START_BYTE;                    // START
                            crc = outBuf[pos - 1];
                            outBuf[pos++] = cmd[i];                        // COMMANDO
                            crc += outBuf[pos - 1];
                            if (cmd[i] == CMD_ALARM)
                                outBuf[pos++] = 1;                        // ANZAHL PARAMETER
                            else
                                outBuf[pos++] = 0;                        // ANZAHL PARAMETER
                            crc += outBuf[pos - 1];
                            if (cmd[i] == CMD_ALARM)
                            {
                                outBuf[pos++] = 1;                        // Zähler
                                crc += outBuf[pos - 1];
                            }
                            outBuf[pos++] = crc;                        // CRC
                            outBuf[pos++] = STOP_BYTE;                    // STOP
                            
                            // senden...
                            //printf("Write... (%d)\n", *USBCon);
                            result = write(*USBCon, outBuf, pos);
                            
                            if (0)
                            {
                                printf("Gesendet: %dBytes - Buffer: ", result);
                                for (int j = 0; j < result; j++)
                                {
                                    printf("%02x", 0xFF & outBuf[j]);
                                }
                                cout << endl << endl;
                            }
                            
                            // Antwort empfangen...
                            //printf("Select...\n");
                            result = select(*USBCon + 1, &readFds, &writeFds, &exceptFds, &timeout);
                            if(result == -1)
                            {
                                printf("Fehler: Select-Funktion (Kommando 0x%02X)\n", cmd[i]);
                            }
                            else if(result == 0)
                            {
                                printf("Warnung: Timeout Select-Funktion (Kommando 0x%02X)\n", cmd[i]);
                                tryReconnect=true;
                            }
                            else
                            {
                                result = read(*USBCon, inBuf, sizeof(inBuf));//cmd[i][1]);
                                //printf("Read...(Erg = %d)\n", result);
                                if (0)
                                {
                                    printf("Gelesen: %dBytes - Buffer: ", result);
                                    for (int j = 0; j < result; j++)
                                    {
                                        printf("%02x", 0xFF & inBuf[j]);
                                    }
                                    printf("\n");
                                }
                                result = checkInputBuf(inBuf, result);
                                //printf("Check...(Erg = %d)\n", result);
                                
                                if (result == 0)
                                {
                                    char strhttp[200];
                                    uint uErg = 0;
                                    // Im Falle folgender Abfragen benötigt es keiner integer Berechnung
                                    // ...CMD_ALARM
                                    if ((inBuf[1] & 0xFF) != CMD_ALARM)
                                    {
                                        for (int j = 0; j < inBuf[2]; j++)
                                            uErg += (inBuf[3 + j] & 0xFF) << (8 * j);
                                    }
                                    
                                    //printf("Switch...(Erg = 0x%X)\n", inBuf[1] & 0xFF);
                                    switch (inBuf[1] & 0xFF)
                                    {
                                    case CMD_VERBRAUCH_SEIT_IBN:
                                        //printf("CMD_VERBRAUCH_SEIT_IBN\n");
                                        if (1) // Durchfluss bei jeder Möglichkeit überprüfen
                                        {
                                            // aktueller Verbrauch (Liter)
                                            curLiter = uErg;
                                            //printf("Liter %d\n", curLiter);
                                            bool sendDurchfluss = false;
                    
                                            if (((curLiter > lastLiter) && (lastLiter > 0)) || (durchflussLiterProStunde > 0))
                                            {
                                                // Durchfluss berechnen
                                                if ((curLiter > lastLiter) && (lastLiter > 0))
                                                {
                                                    durchflussLiterProStunde = (uint)((double)(curLiter - lastLiter) / (curTimeMs - timeMs_LastLiter)* 1000.0 * 60.0 * 60.0);
                                                    sendDurchfluss = true;
                                                }
                                                else
                                                {
                                                    // Kurve abfallen lassen
                                                    // Annahme 100ml wurde Verbraucht
                                                    uint neuDurchflussLiterProStunde = (uint)(0.1 / (curTimeMs - timeMs_LastLiter)* 1000.0 * 60.0 * 60.0);
                                                    if (neuDurchflussLiterProStunde < durchflussLiterProStunde)
                                                    {
                                                        durchflussLiterProStunde = neuDurchflussLiterProStunde;
                                                        sendDurchfluss = true;
                                                    }
                                                }
                    
                                                // nur wenn min. 1Liter verbraucht wurde
                                                // neuer letzter Verbrauch (Liter) und Zeitstempel
                                                // ...dadurch wird eine Abfallende Flanke bis auf 0 Liter/Stunde erzeugt
                                                if ((curLiter > lastLiter) && (lastLiter > 0))
                                                {
                                                    lastLiter = curLiter;
                                                    timeMs_LastLiter = curTimeMs;
                                                }
                                            }
                    
                                            // für den initalen Fall
                                            if (lastLiter == 0)
                                            {
                                                // einmaliges initales setzen
                                                // letzter Verbrauch (Liter) und Zeitstempel
                                                lastLiter = curLiter;
                                                timeMs_LastLiter = curTimeMs;
                                                durchflussLiterProStunde = 0;
                                                sendDurchfluss = true;
                                            }
                    
                                            // über http verschicken...
                                            if (sendDurchfluss)
                                            {
                                                printf("Durchfluss %d l/h\n", durchflussLiterProStunde);
                                                sprintf(strhttp, "%d" HTTP_TARGET ITEM_WASSER_AKTUELLER_DURCHFLUSS_LITER_PRO_STUNDE, durchflussLiterProStunde);
                                                http(strhttp);
                                            }
                                        }
                                        // wird nicht benötigt, da nur Durchfluss berechnet werden soll
                                        if (!nurDurchfluss)
                                        {
                                            printf("Wasserverbrauch: %u Liter\n", uErg);
                                            // über http verschicken...
                                            sprintf(strhttp, "%d" HTTP_TARGET ITEM_WASSER_GESAMTVERBRAUCH_LITER, uErg);
                                            http(strhttp);
                                        }
                                    break;
                                    case CMD_SAEULE1_RESTKAPAZITAET:
                                        printf("Säule1 Restkapiztät: %u Liter\n", uErg);
                                        // über http verschicken...
                                        sprintf(strhttp, "%d" HTTP_TARGET ITEM_WASSER_SAEULE1_RESTKAPZIAET, uErg);
                                        http(strhttp);
                                        break;
                                    case CMD_SAEULE2_RESTKAPAZITAET:
                                        printf("Säule2 Restkapiztät: %u Liter\n", uErg);
                                        // über http verschicken...
                                        sprintf(strhttp, "%d" HTTP_TARGET ITEM_WASSER_SAEULE2_RESTKAPZIAET, uErg);
                                        http(strhttp);
                                        break;
                                    case CMD_MAX_DURCHFLUSS_HEUTE_LITER:
                                        printf("Max. Druchfluss heute: %u Liter\n", uErg);
                                        // über http verschicken...
                                        sprintf(strhttp, "%d" HTTP_TARGET ITEM_WASSER_MAX_DURCHFLUSS_HEUTE_LITER, uErg);
                                        http(strhttp);
                                        break;
                                    case CMD_MAX_DURCHFLUSS_GESTERN_LITER:
                                        printf("Max. Durchfluss gestern: %u Liter\n", uErg);
                                        // über http verschicken...
                                        sprintf(strhttp, "%d" HTTP_TARGET ITEM_WASSER_MAX_DURCHFLUSS_GESTERN_LITER, uErg);
                                        http(strhttp);
                                        break;
                                    case CMD_MAX_DURCHFLUSS_SEIT_IBN_LITER:
                                        printf("Max. Durchfluss seit IBN: %u Liter\n", uErg);
                                        // über http verschicken...
                                        sprintf(strhttp, "%d" HTTP_TARGET ITEM_WASSER_MAX_DURCHFLUSS_SEIT_IBN_LITER, uErg);
                                        http(strhttp);
                                        break;
                                    case CMD_REGENERATIONEN_SEIT_IBN:
                                        printf("Regenerationen seit IBN %u\n", uErg);
                                        sprintf(strhttp, "%d" HTTP_TARGET ITEM_REGENERATIONEN_SEIT_IBN, uErg);
                                        http(strhttp);
                                        break;
                                    case CMD_SALZVERBRAUCH_GRAMM_SEIT_IBN:
                                    {
                                        float salzKg = (float)uErg / 1000.0;
                                        printf("Salzverbrauch seit IBN %.3f kg\n", salzKg);
                                        printf("Anzahl der USB-Verbindungsaubauten %d\n",cntConnections);
                                        // über http verschicken...
                                        sprintf(strhttp, "%.3f" HTTP_TARGET ITEM_WASSER_SALZVERBRAUCH_KG_SEIT_IBN, salzKg);
                                        http(strhttp);
                                    }
                                        break;
                                    case CMD_ALARM:
                                        printf("Alarm ...\n  ");
                                        for (int j = 0; j < inBuf[2]; j++)
                                        {
                                            // gehe alle Zeichen durch
                                            printf("%c", inBuf[3 + j] & 0xFF);
                                        }
                                        printf("\n");
                                        sleep(1); // sicherheitshalber drin, damit sich die AquaPerla nicht verhändert und abstürtzt
                                        break;
                                    default:
                                        printf("Fehler: Unbekanntes Kommando");
                                        break;
                                    }
                    
                                    //usleep(10);    // 10us sleep - Sicherheitshalber wegen Instabilität von AquaPerla
                                    //printf("sleep 100ms\n");
                                    usleep(100*1000);    // 100ms
                                }
                            }
                            
                        }
                            
                        return 0;
                    }
                    
                    int checkInputBuf(char *inBuf, int length)
                    {
                        int res = 0;
                        // prüfe Start und Stop Byte
                        if ((inBuf[0] != START_BYTE) && (inBuf[length] != STOP_BYTE))
                        {
                            printf("Fehler: Start oder Stop Byte nicht vorhanden\n");
                            res--;
                        }
                    
                        // prüfe CRC
                        int crc = 0;
                        // CRC errechnen (ohne letztes zwei Bytes)
                        for (int i = 0; i < (length - 2); i++)
                        {
                            crc += inBuf[i];
                        }
                        // Vergleichen
                        if ((crc & 0xFF) != (inBuf[length - 2] & 0xFF))
                        {
                            printf("Fehler CRC: Erhalten 0x%x - Errechnet 0x%x\n", (inBuf[length - 2] & 0xFF), (crc & 0xFF));
                            res--;
                        }
                    
                        if (res != 0)
                        {
                            printf("Fehlerhafter Eingangsbuffer: %dBytes - Buffer: ", length);
                            for (int j = 0; j < length; j++)
                            {
                                printf("%02x", 0xFF & inBuf[j]);
                            }
                            printf("\n");
                        }
                    
                        return res;
                    }
                    
                    int frameAnalyse(char *frame, int size, float *ptrfWirkarbeitBezugTotal_kWh, float *ptrfLeistung_W, float *ptrfLeistungMin_W, float *ptrfLeistungMax_W)
                    {
                        return -1;
                    }
                    
                    int closeConnection(int * USBCon)
                    {
                        close(*USBCon);
                        return 0;
                    }
                    http.cpp
                    Code:
                    #include <iostream>        // Standard-Ein-/Ausgabe
                    #include <stdio.h>      // standard input / output functions
                    #include <string.h>     // string function definitions
                    #include <stdlib.h>
                    
                    #include "../header/http.h"
                    
                    using namespace std;
                    using std::string;
                    
                    int http(char *httpString)
                    {
                        char strToSend[256];
                        printf("     Try to send via http...");
                        sprintf(strToSend, HTTP_HEAD "%s\n", httpString);
                        system(strToSend);
                        printf("done\n");
                        
                        return 0;
                    }

                    Kommentar


                      #11
                      Schon ein alter Thread, aber vielleicht kann mir einer helfen. Ich habe meine Perla AQA nun per USB an einen Rasberry PI4 angeschlossen, USB wird auch erkannt als "Bus 001 Device 004: ID 04d8:0009 Microchip Technology, Inc.", aber ich sehe kein device /dev/ttyACM0, gibt es auf dem PI einfach nicht. Sehe /dev/ttyAMA0, aber das ist wohl ein anderes Device. Habt ihr eine Idee?

                      openhabian@openhab:~/bwt$ ls /dev/tty*
                      /dev/tty /dev/tty12 /dev/tty17 /dev/tty21 /dev/tty26 /dev/tty30 /dev/tty35 /dev/tty4 /dev/tty44 /dev/tty49 /dev/tty53 /dev/tty58 /dev/tty62 /dev/ttyAMA0
                      /dev/tty0 /dev/tty13 /dev/tty18 /dev/tty22 /dev/tty27 /dev/tty31 /dev/tty36 /dev/tty40 /dev/tty45 /dev/tty5 /dev/tty54 /dev/tty59 /dev/tty63 /dev/ttyprintk
                      /dev/tty1 /dev/tty14 /dev/tty19 /dev/tty23 /dev/tty28 /dev/tty32 /dev/tty37 /dev/tty41 /dev/tty46 /dev/tty50 /dev/tty55 /dev/tty6 /dev/tty7
                      /dev/tty10 /dev/tty15 /dev/tty2 /dev/tty24 /dev/tty29 /dev/tty33 /dev/tty38 /dev/tty42 /dev/tty47 /dev/tty51 /dev/tty56 /dev/tty60 /dev/tty8
                      /dev/tty11 /dev/tty16 /dev/tty20 /dev/tty25 /dev/tty3 /dev/tty34 /dev/tty39 /dev/tty43 /dev/tty48 /dev/tty52 /dev/tty57 /dev/tty61 /dev/tty9
                      Zuletzt geändert von fritzrichter; 01.06.2020, 23:35.

                      Kommentar


                        #12
                        Kann es sich bei dem USB-Device vielleicht um eine Serielle Schnittstelle handeln?

                        Mal "ls -l /dev/serial/by-id" probiert?

                        Tom

                        Kommentar


                          #13
                          Naja alle Implementierungen oben (Python, PHP, C++) gehen alle von "/dev/ttyACM0" aus. Denke mal das die Schnittstelle daher bei BWT immer die gleiche ist. Bekomme folgende Informationen:

                          Code:
                          ls -l /dev/serial/by-id
                          ls: /dev/serial/by-id: No such file or directory

                          Kommentar


                            #14
                            Die Bezeichnung der Schnittstelle in GNU/Linux ist abhängig von der verwendeten Hardware, nicht vom angeschlossenen Gerät.

                            Wie der Anschluss heißt, kannst Du am leichtesten ermitteln, indem Du den Raspberry ohne angesteckte Hardware startest und Dir einmal die Devices ausgeben lässt. Dann schließt Du die Hardware an und wiederholst die Eingabe.

                            Kommentar


                              #15
                              Danke für den Tipp, macht Sinn. Anscheinend wird mein BWT Gerät als USB Disk erkannt, hier der diff zwischen den beiden ls Aufrufen (sprich die Unterschiede im /dev Verzeichnis vor und nach dem Anschluss):
                              Code:
                              66,67d64
                              < brw-rw---- 1 root disk 8, 0 Jun 3 22:52 sda
                              < brw-rw---- 1 root disk 8, 1 Jun 3 22:52 sda1
                              < crw-rw---- 1 root disk 21, 0 Jun 3 22:52 sg0
                              Habe mal das /dev/sda1 gemountet und kann tatsächlich Dateien sehen, also irgendwie scheint mir das seltsam mit meiner Anlage. Dachte der USB Port ist zur seriellen Kommunikation gedacht und nicht als "Laufwerk". Finde dort Bilder (BMP) und die Menü-Texte.

                              tail -f /var/log/messages (beim einstecken)
                              Code:
                              Jun 3 23:21:13 openHABianPi kernel: [123837.263178] usb 1-1.5: new full-speed USB device number 10 using dwc_otg
                              Jun 3 23:21:13 openHABianPi kernel: [123837.403177] usb 1-1.5: New USB device found, idVendor=04d8, idProduct=0009, bcdDevice= 0.01
                              Jun 3 23:21:13 openHABianPi kernel: [123837.403196] usb 1-1.5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
                              Jun 3 23:21:13 openHABianPi kernel: [123837.403205] usb 1-1.5: Product: Microchip Mass Storage Drive
                              Jun 3 23:21:13 openHABianPi kernel: [123837.403213] usb 1-1.5: Manufacturer: Microchip Technology Inc.
                              Jun 3 23:21:13 openHABianPi kernel: [123837.403221] usb 1-1.5: SerialNumber: 123456789099
                              Jun 3 23:21:13 openHABianPi kernel: [123837.409641] usb-storage 1-1.5:1.0: USB Mass Storage device detected
                              Jun 3 23:21:13 openHABianPi kernel: [123837.430672] scsi host0: usb-storage 1-1.5:1.0
                              Jun 3 23:21:13 openHABianPi mtp-probe: checking bus 1, device 10: "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5"
                              Jun 3 23:21:13 openHABianPi mtp-probe: bus: 1, device: 10 was not an MTP device
                              Jun 3 23:21:14 openHABianPi kernel: [123838.445131] scsi 0:0:0:0: Direct-Access Microchp Mass Storage 0001 PQ: 0 ANSI: 4
                              Jun 3 23:21:14 openHABianPi kernel: [123838.447991] sd 0:0:0:0: [sda] 964608 512-byte logical blocks: (494 MB/471 MiB)
                              Jun 3 23:21:14 openHABianPi kernel: [123838.454640] sd 0:0:0:0: [sda] Write Protect is off
                              Jun 3 23:21:14 openHABianPi kernel: [123838.459620] sd 0:0:0:0: Attached scsi generic sg0 type 0
                              Jun 3 23:21:14 openHABianPi kernel: [123838.489115] sda: sda1
                              Jun 3 23:21:14 openHABianPi kernel: [123838.494630] sd 0:0:0:0: [sda] Attached SCSI removable disk
                              Zuletzt geändert von fritzrichter; 03.06.2020, 22:23.

                              Kommentar

                              Lädt...
                              X