Ankündigung

Einklappen
Keine Ankündigung bisher.

eBus->USB->Plugin->KNX

Einklappen
Dieses Thema ist geschlossen.
X
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Ich habs versucht, den Check in ebusd.c wie folgt zu implementieren. Oben das hinzufügen:

    Code:
    #include <fcntl.h>
    #include <sys/ioctl.h>
    Dann in main_loop() ab Zeile 484 das hinzufügen:

    Code:
            /* check if serial device is working and try to reconnect otherwise */
            int serial;
            if (ioctl(serialfd, TIOCMGET, &serial)<0) {    
    
                log_print(L_ALL, "device: %s is not valid any more", device);
    
                /* close serial device */
                if (serialfd > 0) {
                    if (eb_serial_close() == -1)
                        log_print(L_ERR, "can't close device: %s", device);
                    else
                        log_print(L_INF, "%s closed", device);
                }
                sleep (5);
    
                /* open serial device */
                if (eb_serial_open(device, &serialfd) == -1) {
                    log_print(L_ALL, "can't open device: %s, wait 5 secs", device);
                    sleep (5);
                } else {
                    log_print(L_INF, "%s opened", device);
                }
    
            }
    Der Code erkennt, wenn ein Device weg ist und versucht wiederzuverbinden. Letzteres klappt bei mir nicht, da bei mir (noch) das Device umspringt (von ttyUSB0 auf ttyUSB1 und andersrum). Es wäre super, wenn ihr testen könntet.

    Kommentar


      Böse sleep (5);

      Kommentar


        Man kann die beiden Sleeps auch ganz rausnehmen, dann wird nur die Logdatei schnell vollgemacht. Was spricht an der Stelle aber dagegen, sie zu lassen?

        Was noch fehlt ist, dass auf Anfragen der Clients ein Fehler zurückgegeben wird, solange das USB-Device nicht verfügbar ist.

        Kommentar


          Das 2. sleep sollte nicht notwendig sein.

          Das Ganze in die Funktion eb_serial_vaild hinein.

          Für den Daemon eventuell eine Option für den Check.

          Kommentar


            Ich habe an ebusd.c etwas weitergebastelt. Der Code, der die USB-Verbindung prüft, sieht jetzt so aus und er funktioniert bei mir endlich. Muss jedoch im Langzeittest noch validieren.

            Code:
                    /* check if serial device is working and try to reconnect otherwise */
                    int serial;
                    while (serialfd==0 || ioctl(serialfd, TIOCMGET, &serial)<0) {
            
                        /* close serial device */
                        if (serialfd > 0) {
            
                            log_print(L_ERR, "current device: %s is not valid", device);
            
                            if (eb_serial_close() == -1)
                                log_print(L_ERR, "can't close device: %s", device);
                            else
                                log_print(L_INF, "%s closed", device);
                            FD_CLR(serialfd, &listenfds);
                            serialfd=0;
                        }
            
                        sleep (5);
            
                        /* open serial device */
                        if (eb_serial_open(device, &serialfd) == -1) {
                            log_print(L_ALL, "can't open device: %s, errno: %d", device, errno);
                        } else {
                            log_print(L_INF, "%s opened", device);
                            FD_SET(serialfd, &listenfds);
                        }
                    }
            Damit es aber funktioniert waren noch drei kleine Änderungen nötig.

            1. Im Loop "run through connected sockets for new data" soll das am Anfang rein:

            Code:
                         /* skip serial socket */
                        if (readfd==serialfd) continue;
            2. In lib/ebus-bus.c in eb_serial_open() zusätzliche Prüfung, ob ein Device nach dem Öffnen auch wirklich funktioniert:

            Code:
                /* check if the port is working */
                int serial;
                if (ioctl(sfd, TIOCMGET, &serial)<0) 
                {    close(sfd);
                    return -1;
                }
            3. In lib/ebus-bus.c in eb_serial_close() den Fehler beim Reaktivieren alter Einstellungen ignorieren:

            Code:
                ret = tcsetattr(sfd, TCSANOW, &oldtio);
            //    err_ret_if(ret < 0, -1);
            Übrigens die letzte Änderung erlaubt, dass ein abgezogenes USB-Device von ebusd auch wirklich geschlossen werden kann. Ansonsten blieb das Device geöffnet und es wurde beim Wiedereinstecken immer ein neues unter einem anderen Namen geöffnet. Möglicherweise war das eine der Ursachen fürs Hopping.

            Vielleicht kann yuhu die Änderungen bei Interesse einbauen.

            Kommentar


              Ich seh mir das die nächsten Tage etwas genauer an.

              Kommentar


                Ich bin (hoffentlich nah) an der Lösung eines weiteren Stabilitätsproblems. Wenn ein serieller USB-Port geschlossen wird, kommt es bei Linux Kernel 2.6.28 gelegentlich vor, dass das USB-Device bis zum Reboot (sonst hilft wirklich nichts!) blockiert wird. So war das gelegentlich auch bei mir.

                Ein Patch für ftdi_sio.c ist ganz klein und hier beschrieben:

                https://lists.ubuntu.com/archives/ke...ly/006645.html

                Wenn euer Linux zufällig auch Kernel 2.6.28 hat, könnte das helfen. Ich habe das gepatchte Modul am Laufen, mal schauen!

                Kommentar


                  Patch

                  Ich habe ebusd an ein paar Stellen für mehr Stabilität gepatcht.
                  Angehängte Dateien

                  Kommentar


                    Hallo zusammen, und besonders hallo yuhu,
                    mich gibt's auch noch :-)

                    Ihr macht hier einen Superjob, nur um das Offensichtliche nochmal zu wiederholen!

                    Ich spiele jetzt ein wenig mit den Wolf GET/SET-Kommandos rum. Leider darf ich die Codes nicht posten, und leider sind die auch recht kompliziert codiert und besonders CRC-gesichert. Ich werde aber, sobald das Ganze läuft, bei Wolf nochmal mit Nachdruck drum bitten, wenigstens bestimmte Sachen freigeben zu dürfen.

                    Sobald das Ganze läuft.

                    (Ich bitte aber um Verständnis, dass die Entscheidung in dieser Sache nicht in meiner Hand liegt).

                    Um jetzt aber sinnvoll experimentieren zu können, brauche ich die Möglichkeit, dass ebusd mir auch Rohdaten (Hex) de- und encodieren kann. Mit anderen Worten, dass ich Kommandos definieren kann, bei denen ich dem ebusd die Daten einfach als Hex übergebe bzw. Rückdaten als Hex erhalte.

                    Dazu habe ich die Datei ebus-cmd.c minimal gepatcht:

                    Code:
                    --- ebus-cmd.c  2013-05-23 11:44:21.000000000 +0200
                    +++ ebus-cmd.c.NEW      2013-05-23 11:39:57.000000000 +0200
                    @@ -215,6 +215,14 @@
                     
                            if (strncasecmp(com[id].elem[elem].d_type, "asc", 3) == 0) {
                                    sprintf(buf, "%s ", &msg[1]);
                    +       } else if (strncasecmp(com[id].elem[elem].d_type, "hex", 3) == 0) {
                    +               if (p1 > 0 && p2 > p1) {
                    +                 for (i = 0; i <= p2-p1; i++)
                    +                   sprintf((char *) &buf[i * 3], "%02x ", &msg[p1+i]);
                    +                 buf[i*3-1]='\0';
                    +               } else {
                    +                       goto on_error;
                    +               }
                     
                            } else if (strncasecmp(com[id].elem[elem].d_type, "bcd", 3) == 0) {
                                    if (p1 > 0) {
                    @@ -405,7 +413,7 @@
                            char *c1, *c2, *c3;
                            char d_pos[CMD_SIZE_D_POS + 1];
                            unsigned char bcd, d1b, d1c, d2b[2], d2c[2];
                    -       int ret, i, p1, p2, p3;
                    +       int ret, i, j, p1, p2, p3;
                            float f;
                     
                            memset(d_pos, '\0', sizeof(d_pos));
                    @@ -425,7 +433,16 @@
                            if (strncasecmp(com[id].elem[elem].d_type, "asc", 3) == 0) {
                                    for (i = 0; i < strlen(data); i++)
                                            sprintf((char *) &msg[i * 2], "%02x", data[i]);
                    -
                    +       } else if (strncasecmp(com[id].elem[elem].d_type, "hex", 3) == 0) {
                    +         for (i = 0, j = 0; data[i]; i++) {
                    +           if(data[i]>='A' && data[i]<='F') { data[i]+='a'-'A'; } /* lowercase */
                    +           if(data[i]>='0' && data[i]<='9' || data[i]>='a' && data[i]<='f') {
                    +             msg[j]=data[i];
                    +             j++;
                    +           } else if(data[i]!=' ') {
                    +             goto on_error;
                    +           }
                    +         }
                            } else if (strncasecmp(com[id].elem[elem].d_type, "bcd", 3) == 0) {
                                    if (p1 > 0) {
                                            i = (int) (atof(data) / com[id].elem[elem].d_fac);
                    Es kompiliert fehlerfrei durch, ist aber ungetestet. @yuhu: wärst du so nett mal drüberzusehen, ob das für dich ok aussieht?

                    Vielen Dank!
                    Fry

                    Kommentar


                      Zitat von Fry Beitrag anzeigen
                      Ich spiele jetzt ein wenig mit den Wolf GET/SET-Kommandos rum. Leider darf ich die Codes nicht posten, und leider sind die auch recht kompliziert codiert und besonders CRC-gesichert. Ich werde aber, sobald das Ganze läuft, bei Wolf nochmal mit Nachdruck drum bitten, wenigstens bestimmte Sachen freigeben zu dürfen.
                      Hallo Fry,
                      Verstanden, aber falls Du irgendwann die Möglichkeit hast, was zu teilen, bin ich sehr interessiert!

                      Gruß Moritz

                      Kommentar


                        Hallo Fry,

                        danke für die Blumen.

                        Für die Dekodierung gibt es bereits ein hex. Kannst Du deinen Dekodierungstyp statt hex in zb whx umbenennen?

                        in eb_cmd_decode_value
                        Code:
                        [B][COLOR=Red]vorhandener hex Typ[/COLOR][/B]
                            } else if (strncasecmp(com[id].elem[elem].d_type, "[COLOR=Blue][B]hex[/B][/COLOR]", 3) == 0) {
                                for (i = 0; i < msg[0]; i++)
                                    sprintf(&buf[3 * i], "%02x ", msg[i + 1]);
                        
                        [COLOR=Red][B]dein hex Typ[/B][/COLOR]
                            } else if (strncasecmp(com[id].elem[elem].d_type, "[B][COLOR=YellowGreen]whx[/COLOR][/B]", 3) == 0) {
                                if (p1 > 0 && p2 > p1) {
                                    for (i = 0; i <= p2 - p1; i++)
                                        sprintf((char *) &buf[i * 3], "%02x ", &msg[p1 + i]);
                        
                                    buf[i * 3 - 1] = '\0';
                                } else {
                                    goto on_error;
                                }
                        
                            }
                        Für das Encodieren müssten meine Code mit isxdigit und tolower auch genügen.

                        in eb_cmd_encode_value

                        Code:
                            } else if (strncasecmp(com[id].elem[elem].d_type, "[B][COLOR=YellowGreen]whx[/COLOR][/B]", 3) == 0) {
                                for (i = 0, [B][COLOR=Red]j = 0[/COLOR][/B]; data[i]; i++) {
                                    
                                    //~ if (data[i] >= 'A' && data[i] <= 'F')
                                        //~ data[i] += 'a'-'A'; /* lowercase */
                        
                                    //~ if (data[i] >= '0' && data[i] <= '9' ||
                                        //~ data[i] >= 'a' && data[i] <= 'f') {
                        
                                    if (isxdigit(data[i]) {
                                        msg[[B][COLOR=Red]j[/COLOR][/B]] = tolower(data[i]);
                                        [B][COLOR=Red]j++;[/COLOR][/B]
                                    } else if (data[i] != ' ') {
                                        goto on_error;
                                    }
                                }
                                
                            }
                        Ist das wirklich so kodiert, dass die Zählvariable j für msg[j] notwendig ist? Sind da überflüssige Zeichen dazwischen?

                        Kannst Du Strings (codieren/encodieren) zum Testen zur Verfügung stellen?

                        Kommentar


                          Zitat von yuhu Beitrag anzeigen
                          Für die Dekodierung gibt es bereits ein hex. Kannst Du deinen Dekodierungstyp statt hex in zb whx umbenennen?
                          Da brat mir einer einen Storch. Hatte ich komplett übersehen. Nun, dann nehme ich halt deinen hex-Typ und lösche meinen wieder.


                          Für das Encodieren müssten meine Code mit isxdigit und tolower auch genügen.

                          in eb_cmd_encode_value

                          Code:
                              } else if (strncasecmp(com[id].elem[elem].d_type, "[B][COLOR=YellowGreen]whx[/COLOR][/B]", 3) == 0) {
                                  for (i = 0, [B][COLOR=Red]j = 0[/COLOR][/B]; data[i]; i++) {
                                      if (isxdigit(data[i]) {
                                          msg[[B][COLOR=Red]j[/COLOR][/B]] = tolower(data[i]);
                                          [B][COLOR=Red]j++;[/COLOR][/B]
                                      } else if (data[i] != ' ') {
                                          goto on_error;
                                      }
                                  }
                                  
                              }
                          Ich kannte isxdigit und tolower nicht, so ist es natürlich kürzer - oben fehlt allerdings eine Klammer hinter if (isxdigit(data[i])

                          Ist das wirklich so kodiert, dass die Zählvariable j für msg[j] notwendig ist? Sind da überflüssige Zeichen dazwischen?
                          Geht nur um Spaces, die würde ich aus Gründen der Lesbarkeit erlauben.

                          Kannst Du Strings (codieren/encodieren) zum Testen zur Verfügung stellen?
                          Es handelt sich einfach um Rohdaten. Nix besonderes. Bei den Wolf-Telegrammen muss man halt manchmal Bitfelder zusammensetzen und zusätzliche CRCs ausrechnen. Das will ich lieber in Perl realisieren, es wäre für den C-Code zu viel Ballast und bräuchte ganz eigene Config-Files mit wieder anderem Format.

                          Übrigens ist mir gerade aufgefallen, dass im Hexdump (loglevel=EBH) des ebusd bei zu sendenden Master-Slave-Telegrammen das erste Byte (QQ) nicht ausgedruckt wird. Mein Slave antwortet nämlich nicht, und da dachte ich zuerst, QQ würde gar nicht gesendet. Wird es aber, nur nicht aufgezeichnet.

                          Danke! VG, Fry

                          @kleinklausi: Ist klar.

                          Kommentar


                            Das Problem mit der unvollständigen Aufzeichnung im Log (loglevel EBH) habe ich nun durch eine Krücke behoben. Wirklich schön ist es nicht, scheint aber zu funktionieren:

                            Code:
                            --- ebus-bus.c  2013-05-24 06:12:06.000000000 +0200
                            +++ ebus-bus.c.NEW      2013-05-24 06:17:11.000000000 +0200
                            @@ -883,7 +883,6 @@
                                    } else {
                                            /* prepare command - if prepare failed buflen > 0 */
                                            eb_cmd_prepare(id, data, msg, &msglen, buf);
                            -               eb_print_hex(msg, msglen);
                                    }               
                             
                                    if (cycdata == NO && strlen(buf) == 0) {
                            @@ -916,7 +915,14 @@
                                                            memset(msg, '\0', sizeof(msg));
                                                            msglen = sizeof(msg);
                                                            eb_recv_data_get(msg, &msglen);
                            -                               eb_print_hex(msg, msglen);
                            +                               
                            +                               char mymsg[2*SERIAL_BUFSIZE];
                            +                               memcpy(mymsg, &send_data.msg_esc[0], send_data.len_esc);
                            +                               mymsg[send_data.len_esc]='\0'; /* add an ACK */
                            +                               memcpy(&mymsg[send_data.len_esc+1], msg, msglen);
                            +                               mymsg[send_data.len_esc+1+msglen]=eb_calc_crc(&mymsg[send_data.len_esc+1],msglen);
                            +                               mymsg[send_data.len_esc+2+msglen]=0;
                            +                               eb_print_hex(mymsg, send_data.len_esc+3+msglen);                                          
                             
                                                            /* decode */
                                                            if (eb_cmd_check_type(id, "set") == YES) {
                            PS. Hintergrund, warum ich das brauche: ich lese den Log per Perl-Skript mit und möchte, dass dort der gesamte Bustraffic (außer den überflüssigen Syncs) aufgezeichnet wird. Das schließt auch solche Telegramme ein, die vom PC kommen.

                            Kommentar


                              Die beide hex Typen (deine bzw. die bestehende) zum dekodieren sind nicht ident.
                              • Die bestehende Version gibt alle Bytes der Antwort aus.
                              • Deine Version gibt einen Bereich (p1=Anfang; p2=Ende) vor.



                              Wenn wir nur eine Version weiterführen würde ich den Typ (decode/encode) wieder mit hex benennen.

                              ---

                              zum EBH bei aktiv gesendeten Nachrichten:


                              Ausser QQ fehlt noch
                              • CRC vom Master
                              • ACK vom Slave
                              • CRC vom Slave
                              • ACK vom Master

                              Code:
                              2013-05-24 07:57:53.582 [EBH]   08 b5 09 03 0d 80 00
                              2013-05-24 07:57:53.698 [EBH]   02 00 00
                              
                              2013-05-24 07:57:53.582 [EBH]   [COLOR=YellowGreen]QQ[/COLOR] 08 b5 09 03 0d 80 00 [COLOR=Red]CRC[/COLOR]
                              2013-05-24 07:57:53.698 [EBH]   [COLOR=Blue]ACK[/COLOR] 02 00 00 [COLOR=Blue]CRC[/COLOR] [COLOR=Red]ACK[/COLOR]
                              Ich habe das zwecks Übersichtlichkeit rausgenommen. Falls CRC bzw. ACK nicht gültig sind, kommt ja ohnehin ein error zurück.

                              Eventuell wäre es leichter zum Lesen, wenn die komplette Nachricht als ganzes ausgegeben wird. Zyklische werden ebenfalls so ausgegeben.

                              Code:
                              2013-05-24 07:57:53.582 [EBH]   [COLOR=YellowGreen]QQ[/COLOR] 08 b5 09 03 0d 80 00 [COLOR=Red]CRC[/COLOR] [COLOR=Blue]ACK[/COLOR] 02 00 00 [COLOR=Blue]CRC[/COLOR] [COLOR=Red]ACK[/COLOR]

                              Kommentar


                                Hi yuhu,

                                Für meine Zwecke würde der eine hex-Typ reichen. Also kein whx.

                                Der oben gepostete Patch gibt die gesendete Nachricht komplett und in einer Zeile aus. Das vereinfacht und vereinheitlicht die Analyse (GETs vom PC sehen genauso aus wie GETs zwischen den anderen Aggregaten).

                                Mittlerweile antwortet mein Slave übrigens. Das Ganze ist auf einem guten Weg.

                                Ich fände es gut, wenn du die Patches (ggf. besser codiert) in den Hauptentwicklungszweig übernehmen könntest. Höchstwahrscheinlich sind damit die für mich notwendigen Änderungen auch erledigt (ich muss mir allerdings später noch das SET ansehen).

                                Danke dir!
                                Fry

                                Kommentar

                                Lädt...
                                X