Ankündigung

Einklappen
Keine Ankündigung bisher.

- √ - Neues Plugin für Vbus Solarregler Resol

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

    #31
    Hallo Patrick,

    die Kommunikationsverbindung steht nun endlich.
    Über die Resol-Software bekomme ich die Daten-siehe Anhänge.
    Mit HTerm kann ich nichts auslesen, vermute ich muss da zuerst was senden, dass was kommt.
    Wenn Du einen String basteln kannst/willst, kann ich den Testweise an den Solarregler senden, bevor das Plugin geschrieben wird.

    Schätze mal ab, wie kompliziert es nun ist-nur die Werte zu senden und gib mir bescheid.

    Danke und Grüße,
    Lio
    Angehängte Dateien

    Kommentar


      #32
      Hallo Lio

      Ich habe mir nochmal das Protokoll angesehen. Wie gesagt... Das empfangen der Werte sollte nicht so schwierig sein. Das senden hingegen ist mit dem Pluginsystem des Wiregate murks. Da müsste man sich etwas anderes einfallen lassen.

      Was möchtest du den genau realisieren?

      Kommen die Daten nicht Zyklisch? Hat die Schnittstelle eine eigene Adresse als BUS Teilnehmer oder wird damit "heiss" vom BUS gelesen?
      Gruss Patrik alias swiss

      Kommentar


        #33
        Hallo Patrick,
        will eigentlich nur die Parameter Temperatur, Drehzahl, Wärmemenge, etc haben. Nix Steuern, Nix Regeln.

        Also bei Hterm kommt nix automatisch an, so wie ich das von den SML-Zähler z.b. kenne.

        Bei der REsolsoftware dagegen, muss man nichts machen als die Schnittstelle auswählen und verbinden drücken.

        So viel ich weiss, muss man eine Anfrage hin senden und bekommt eine Antwort-aber das schau ich mir noch mal an.

        Eine Adresse? ode Heiss? Was meinst Du damit?

        Grüße,
        Lio

        Kommentar


          #34
          Hallo Lio

          Eine Adresse? ode Heiss? Was meinst Du damit?
          Ich meine damit folgendes...

          Die Geräte kommunizieren über RS485 miteinander. Also ist das Protokoll sehr viel komplexer als bei RS232.

          RS485 ist im Prinzip ein BUS dessen Kommunikation auch (wie beim KNX) über Adressen erfolgt. Jeder Teilnemer an diesem BUS hat eine eindeutige Adresse damit die BUS-Teilnemer wissen für wen die Daten bestimmt sind. Auch die PC Schnittstelle hat AFAIK eine Adresse.

          Die Frage ist nun, ob die Schnittstelle nur Daten ausgibt die entweder an sie Adressiert sind oder als Broadcast gesendet wurden, oder ob die Schnittstelle ALLE Daten ausgibt. Also auch die Kommunikation zwischen z.B. Regler und Therme?

          Wie gesagt. Sobald man etwas senden muss, ist das mit dem Pluginsystem des WG's praktisch nicht mehr zu machen. Da wird es dann sehr komplex und zeitkritisch. Das wäre eine Aufgabe für einen Daemon oder zumindest ein Standalone Plugin dass durch einen cron getriggert wird.

          Die Frage ist, ob du nicht unter Umständen das existierende Perl Programm verwenden kannst (Standalone) und die Werte in eine Datei schreiben lässt. Die kannst du dann bequem zyklisch wieder in einem WG-Plugin einlesen und die Werte auf den BUS senden.

          Ich würde ungern das Rad neu erfinden. Es kommt ja auch niemand auf die Fixe Idee das KNX Protokoll in einem Plugin nachzubilden und direkt Physisch auf den BUS zu schreiben. Zumal hier warscheinlich der Bedarf relativ gering ist. Anders als beim ComfoAir Plugin haben an diesem, weit aus komplexeren Projekt, viel wehniger Leute Interesse bekundet. Da ist der Aufwand alles neu zu erfinden fraglich. Vieleicht gäbe es für die 2-3 Interessenten auch eine andere Lösung die dann hald eventuell etwas Handarbeit von denjenigen erfordert, die es wollen.
          Gruss Patrik alias swiss

          Kommentar


            #35
            Zitat von swiss Beitrag anzeigen
            Die Geräte kommunizieren über RS485 miteinander. Also ist das Protokoll sehr viel komplexer als bei RS232.
            Laut den beiden Links im ersten Posting ist VBus kein RS485.
            Direktlinks zu den entsprechenden Stellen:
            Suche Beschreibung vom VBUS (VegaBus) - Mikrocontroller.net
            VBus-Decoder

            Zitat von swiss Beitrag anzeigen
            RS485 ist im Prinzip ein BUS dessen Kommunikation auch (wie beim KNX) über Adressen erfolgt. Jeder Teilnemer an diesem BUS hat eine eindeutige Adresse damit die BUS-Teilnemer wissen für wen die Daten bestimmt sind. Auch die PC Schnittstelle hat AFAIK eine Adresse.
            Die Frage ist nun, ob die Schnittstelle nur Daten ausgibt die entweder an sie Adressiert sind oder als Broadcast gesendet wurden, oder ob die Schnittstelle ALLE Daten ausgibt. Also auch die Kommunikation zwischen z.B. Regler und Therme?
            Aus dem zweiten Link im ersten Posting:
            Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der Datenfernanzeige.

            An diese sendet der Regler alle von ihm gemessenen Werte.
            Ich interpretiere das so, daß der Solarregeler der Master ist und auch ohne Anforderung (sprich schreibenden Zugriff auf den Bus), immer wieder die interessanten Daten auf den Bus schickt. Man muß "nur" auf die Zieladresse 0x0010 warten und bekommt alle Daten.

            Zitat von swiss Beitrag anzeigen
            Zumal hier warscheinlich der Bedarf relativ gering ist. Anders als beim ComfoAir Plugin haben an diesem, weit aus komplexeren Projekt, viel wehniger Leute Interesse bekundet. Da ist der Aufwand alles neu zu erfinden fraglich. Vieleicht gäbe es für die 2-3 Interessenten auch eine andere Lösung die dann hald eventuell etwas Handarbeit von denjenigen erfordert, die es wollen.
            Mir steckt das Wiregate auch sehr in der Nase (vor allem auch wegen Deinem Comfoair-Plugin, welches ich auch einsetzen will, wenn ich mal ein Wiregate habe. Vielen Dank für die Arbeit) und so habe ich das Wiregate-Forum durchstöbert und bin so auf diesen Thread gestoßen. Da ich mich vorher schonmal mit dem Thema auseinandergesetzt hatte, sprangen mir die Wörter "VBus" und "Resol" im Threadtitel sofort ins Auge. Ich hätte auch Interesse an einem Plugin.
            Mir fallen zwei Gründe ein, warum sich weniger Leute gemeldet haben. Erstens ist dieser Thread im Wiregate-Forum eröffnet worden, welches vielleicht nicht so viele Leute abonniert und es deswegen nicht mitbekommen haben und zweitens ist der Hardwareaufwand etwas höher, da man selber basteln muß.
            Ersteres ließe sich ändern, wenn Du zB durch Links zu Deinen Plugins in der Signatur Werbung machen würdest :-)
            Für zweiteres habe ich keine Lösung.
            Gruß, Carsten

            Kommentar


              #36
              Hallo Carsten,

              um die Linksammlung zu ergänzen:
              V-bus Interface

              Damit hatte ich erfolg.

              Mit Patrick alias swiss, bin ich so verblieben, dass wir das Thema erstmal ruhen lassen, da es aus jetziger Sicht nicht als Plugin laufen kann.

              Grüße,
              Lio

              Kommentar


                #37
                Hallo Lio,

                vielen Dank für den Link. Der Schaltplan ist im Gegensatz zu dem auf Hobbyelektronik.org vollständig und damit für mich auf Lochraster nachbaubar.
                Das da ein Reichelt-Warenkorb dranhängt, ist das Tüpfelchen auf dem i :-)
                Gruß, Carsten

                Kommentar


                  #38
                  Hallo Carsten

                  Ja dass gröste Problem ist, dass das Pluginsystem nicht dafür geeignet ist zeitkritische Funktionen zu übernemen.

                  Wenn der Regler von sich aus einfach drauflos plappert -> Super und lässt sich relativ einfach als Plugin lösen.

                  Wenn aber eine Abfrage gestartet werden muss, dann sehe ich die Grenzen des Pluginsystem erreicht.

                  Auch sobald Befehle an den V_Bus gesendet werden sollen ist da leider Ende im Gelände

                  Kurz: Lesen -> vieleicht, Schreiben -> nein

                  Da müsste man warscheinlich einen anderen Weg gehen aber wie schon gesagt... Dass ist dann nicht mehr nur copy&paste sondern erforgert eingriffe in das Wiregate durch den Nutzer. Ist also nicht für jeden geeignet.

                  Zu RS232 vs. RS485...

                  Beides beschreibt einen Standard zum Datenaustausch, der einerseit's durch die elektrischen Spezifikationen wie auch gewisse Kommunikationsverfahren beschreibt.

                  Die V-Bus Schnittstelle ist Elektrischgesehen keines von beiden ( schon wegen den Spannungspegeln). Aber die Kommunikationsart entspricht in weiten Teilen einem RS485 Standart. Dabei geht es darumm wie die Kommunikation grundsätzlich geregelt ist. RS232 ist für die direkte Kommunikation zwischen zwei Geräten entwickelt worden. RS485 ist ein BUS Protokoll dass sehr viel komplexer ist als dassvon RS232.

                  Desshalb habe schrieb ich auch, dass V_Bus dem RS485 Standart entspricht. Und davon bin ich nach wie vor überzeugt
                  Gruss Patrik alias swiss

                  Kommentar


                    #39
                    Zitat von swiss Beitrag anzeigen
                    Ja dass gröste Problem ist, dass das Pluginsystem nicht dafür geeignet ist zeitkritische Funktionen zu übernemen.
                    Ja, das ist so (ausser mit wirklich extrem viel "feingefühl", Zeit und musse)
                    Soll sich irgendwann ändern, mal sehen, ob das 2013 oder 2033 wird steht aber in den Sternen..

                    Eine andere Option, die ich noch nicht so oft genannt hatte: einfach ein zweites das nur das tut? dann werden die Plugins auch Timing-mässig recht akkurat; Da ist ja nichts falsch sondern nur spagat schwierig, es allen gleichzeitig recht zu machen..
                    Ehrlich, was solls, wenn das Interface (sofern es überhaupt eines gibt) vom Heizi das 2-3x kostet..
                    (Ich hatte die Frage die Tage schonmal, Multi-Mio-Hütte in der das ein oder andere zimperliche Teil abzufragen ist [was ich mit dem HS - der SI dort kennt den sehr viel besser als Perl - für sehr sportlich hielt] für wo dann bitte ein zweites auch drin ist, kostet 1/5 HS

                    Variante 3 ist dann einfach einen eigenen Daemon dafür zu schreiben, package ich gerne und funktioniert auch problemlos (knxdmxd, russconnectd, vzlogger, ...) solange es dafür kein Ruby, Java 18.7, PHP 5.55 oder Python 2.7 braucht

                    Makki
                    EIB/KNX & WireGate & HS3, Russound,mpd,vdr,DM8000, DALI, DMX
                    -> Bitte KEINE PNs!

                    Kommentar


                      #40
                      Da Mittwoch mein Perl-Buch ankam, konnte ich mich endlich mal ein bischen einlesen (ja, ich weiß, daß es auch genug Tutorials im Internet gibt, aber ich bin da ein bischen "Old School": schön mit dem Buch auf der Couch liegen und lesen :-) ).
                      Ich habe mich gestern und heute an das Plugin gesetzt. Es ist also mein erstes Perl-Skript. Bitte nicht wundern, wenn einiges nicht so elegant gelöst sein sollte.
                      Code:
                      use strict;
                      use Device::SerialPort;
                      use Time::HiRes qw( usleep gettimeofday  tv_interval );
                      my $crc;
                      my $d;
                      my $framecount;
                      my $framecrc;
                      my $i;
                      my $packetsize;
                      my $usedbytes;
                      my $value;
                      my $valuedata;
                      my $valuedataf;
                      my $valuedatastr;
                      my $debug = 2;
                      
                      my $connectiontype;
                      my $dfa;
                      my $format;
                      my $lang;
                      my $plugname;
                      my $serial;
                      my $serialcount;
                      my $serialdata;
                      my $serialdev;
                      my $solar;
                      my $timeout;
                      my %msgs;
                      my @serialunpack;
                      my @values;
                      my $cycle;
                      readConf();
                      $plugin_info{$plugname.'_cycle'}  = $cycle; 
                      
                      if ($connectiontype eq "serial"){
                          $serial = Device::SerialPort->new($serialdev) || die "Can't open $serialdev ($!)\n";
                          $serial->baudrate(9600);
                          $serial->parity("none");
                          $serial->databits(8);
                          $serial->stopbits(1);
                          $serial->handshake("none");
                          $serial->write_settings;
                          $serial->lookclear;
                          if($debug>=1){plugin_log($plugname,sprintf($msgs{"log_serial_device_open_$lang"}))}  ;
                      } else {
                          die "Not supported connectiontype '$connectiontype'";
                      }
                      my @packet = ();        # will hold a complete received packet 
                      my @buffer = ();
                      my $loop = 0;
                      my $syncfound = 0;        # will be set to 1 if 0xAA is received
                      my $t0 = [gettimeofday];# now
                      my $res = 0;
                      while ((tv_interval $t0, [gettimeofday]) < $timeout && $res == 0) {        # while timeout is not reached and no valid packet was analyzed
                          ($serialcount, $serialdata) = $serial->read(255);
                          if($serialcount > 0){
                              @serialunpack = unpack "C*", $serialdata;                        # convert received chars to bytes
                              if ($debug>2) {plugin_log($plugname,sprintf($msgs{"log_serial_data_$lang"}, sprintf((" %02X" x ($#serialunpack+1), @serialunpack))))};
                              foreach (@serialunpack) {
                                  if ($_ == 0xAA) {            # sync byte found
                                      if ($syncfound == 0) {    # '0' means found first sync byte
                                          @buffer = (0xAA);
                                          $syncfound = 1;
                                      } else {                # found a second sync byte -> we received a full packet
                                          @packet = @buffer;    # @packet will be analyzed
                                          if ($debug>2) {plugin_log($plugname,sprintf($msgs{"log_data_to_analyze_$lang"}, sprintf((" %02X" x ($#packet+1) ), @serialunpack)))};
                                          $res = analyze_packet(); # result will be '0' if an error occurs and '1' if analysis was successful
                                          @buffer = (0xAA);    # clear buffer and set first byte to the sync byte
                                      }
                                  } else {
                                      if ($_ > 0x7F) {        # bytes greater than 0x7F (127) are not allowed (except for the sync byte 0xAA (170)
                                          @buffer = ();        # clear buffer 
                                          $syncfound = 0;        # reset to skip all bytes until the next sync byte
                                          if ($debug>2) {plugin_log($plugname,sprintf($msgs{"err_byte_gt_0x7f_$lang"}, $_))};
                                      }
                                      if ($syncfound == 1) {
                                          push(@buffer, $_);    # add byte to buffer
                                      }
                                  }
                              }
                          }
                          usleep 50000;                        # sleep for 50,000µs 
                          $loop++;                            # count iterations of the while-loop
                      }
                      
                      my $t1 = [gettimeofday];                # now 2
                      my $t0_t1 = tv_interval $t0, $t1;        # get timespan between start & end 
                      
                      print "\n\nTime needed: $t0_t1 \n";
                      
                      sub analyze_packet {
                          my $source        = $packet[4] * 0x100 + $packet[3];        # source ID of this packet
                          my $target        = $packet[2] * 0x100 + $packet[1];        # target ID of this packet
                          my $protocol    = $packet[5];                            # protocol ID. Must be 0x10
                          my $command        = $packet[7] * 0x100 + $packet[6];        # command. Must be 0x0100 = paket contains data for slave
                          my $offset = 1;                                            # offset and length of header. Values directly used to check CRC of header
                          my $length = 8;
                          my @data;                                                # array for the data bytes as the data offset does not include septet and CRC
                          if ($source   != $solar) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_source_$lang"}, $source)) } ; return 0};
                          if ($target   != $dfa  ) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_target_$lang"}, $target)) } ; return 0};
                          if ($protocol != 0x10  ) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_protocol_$lang"}, $protocol)) } ; return 0};
                          if ($command  != 0x0100) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_command_$lang"}, $command)) } ; return 0};
                          if ($debug >=1) {plugin_log($plugname, sprintf($msgs{"progress_crc_header_$lang"}))};
                          $crc = vbus_crc($offset,$length);     # get CRC of header
                          if ($crc != $packet[9]) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_crc_header_$lang"}, $packet[9] , $crc)) } ; return 0};
                          $framecount = $packet[8];        # number of data frames
                          $packetsize = $#packet + 1;
                          # every dataframe has six bytes
                          if (($packetsize != (10 + $framecount * 6))) { if ($debug >=2) {plugin_log($plugname,sprintf($msgs{"err_packetsize_$lang"}, $packetsize, (10 + $framecount * 6) , $framecount))} ; return 0};
                          # check crc of data frames
                          if ($debug >=1) {plugin_log($plugname, sprintf($msgs{"progress_crc_frame_$lang"}))};
                          $length = 5; # crc includes septet byte
                          for ($i = 0; $i < $framecount; $i++) {
                              $offset = 10 + $i * 6;
                              $framecrc = $packet[10 + $i * 6 + 5];
                              $crc = vbus_crc($offset,$length);
                              if ($crc != $framecrc) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_crc_frame_$lang"} , $i , $framecrc , $crc)) } ; return 0};
                          }
                          # Insert septets and add data bytes to @data
                          if ($debug >=1) {plugin_log($plugname, sprintf($msgs{"progress_insert_septet_$lang"}))};
                          $length = 4;
                          for ($i = 0; $i < $framecount; $i++) {
                              $offset = 10 + $i * 6;
                              &vbus_injectSeptet($offset,$length);
                              push(@data, @packet[$offset..($offset + $length -1)]);
                          }
                          if ($debug >= 2) {plugin_log($plugname, sprintf($msgs{"log_packetdata_$lang"} . (" %02X" x ($#data+1)), @data)) };
                          if ($debug >=1) {plugin_log($plugname, sprintf($msgs{"progress_parse_data_$lang"}))};
                          foreach $value (@values) {
                              if ($debug >= 2) {plugin_log($plugname, sprintf($msgs{"log_valuename_$lang"}, $value->{"Name_$lang"}))};
                              $usedbytes = ($value->{bitsize} +7) / 8;
                              $valuedatastr = "";
                              $offset = $value->{Offset};
                              foreach $d (@data[$offset..($offset+$usedbytes-1)]) {
                                  $valuedatastr = sprintf("%02X", $d) . $valuedatastr;
                              }
                              if ($debug >= 2) {plugin_log($plugname, sprintf($msgs{"log_valuedatahex_$lang"}, $valuedatastr))};
                              $valuedata = hex($valuedatastr) & ((2** $value->{bitsize})-1);
                              if ($debug >= 2) {plugin_log($plugname, sprintf($msgs{"log_valuedatadec_$lang"}, $valuedata))};
                              if ($value->{Factor}) {
                                      $valuedataf = $valuedata * $value->{Factor};
                                      if ($debug >= 2) {plugin_log($plugname, sprintf($msgs{"log_valuedatadec_w_factor_$lang"}, $valuedata, $value->{Factor}, $valuedataf))};
                                      $valuedata = $valuedataf;
                              }
                              if ($value->{bitsize} == 1) {
                                  if ($valuedata > 0) {
                                      $valuedata = 1;
                                      print "bit 1\n";
                                  } else {
                                      $valuedata = 0;
                                  }
                              }
                              if ($value->{GA} ne '') {
                                  knx_write($value->{GA}, $valuedata , $value->{DPT});
                              }
                              if ($debug >= 1) {plugin_log($plugname, sprintf($msgs{"log_value_information_$lang"}, $value->{"Name_$lang"}, $valuedata, $value->{"Unit"})) ; print "-------\n"};
                              
                          }
                          return 1;
                      }
                      
                      ############### END #################
                      sub vbus_crc {
                          my ($offset, $length) = @_;
                          my ($i);
                          my ($crc) = 0x7f;
                          for ($i = 0; $i < $length; $i++) {
                              $crc = ($crc - $packet[$offset + $i]) & 0x7f;
                          }
                          return $crc
                      }
                      
                      sub vbus_injectSeptet {
                          my ($offset, $length) = @_;
                          my ($i, $septet);
                          $septet = $packet[$offset + $length];
                          for ($i = 0; $i < $length; $i++) {
                              if ($septet & (2 ** $i)) {
                                  $packet[$offset + $i] |= 0x80;
                              }
                          }
                      }
                      # sub plugin_log {
                          # my ($plugname, $text) = @_;
                          # print $text . "\n";
                      # }
                      
                      sub readConf
                      {
                          my $confFile = '/etc/wiregate/plugin/generic/conf.d/Resol.conf';
                          #my $confFile = '/etc/wiregate/plugin/generic/conf.d/'.basename($plugname,'.pl').'.conf';
                          if (! -f $confFile)
                          {
                              plugin_log($plugname, " no conf file [$confFile] found!"); 
                          }
                          else
                          {
                              if($debug>=1){plugin_log($plugname, " reading conf file [$confFile].");}
                              open(CONF, $confFile);
                              my @lines = <CONF>;
                              close($confFile);
                              my $result = eval("@lines");
                              ($result) and plugin_log($plugname, "conf file [$confFile] returned result[$result]");
                              if ($@) 
                              {
                                  if($debug>=1){plugin_log($plugname, " conf file [$confFile] returned:");}
                                  my @parts = split(/\n/, $@);
                                  if($debug>=2){plugin_log($plugname, " --> $_") foreach (@parts);}
                              }
                          }
                      } # readConf
                      und die benötigte Conf

                      Code:
                      $debug = 1; 
                      $cycle = 60;
                      $connectiontype = "serial";
                      $serialdev = "/dev/usbserial-1-4.3";
                      $timeout = 3;                                # maximum time in seconds to listen for a valid packet 
                      $solar = 0x427b;                            # ID of your own solar device
                      $dfa   = 0x0010;                            # ID of "DFA". In german "Daten Fernanzeige". englisch ~ "remote data display"
                                                                  # solar device broadcasts his state to this address
                      $lang = "en";
                      %msgs = (
                          # english / englisch
                              err_source_en                => "ERROR: Wrong source ID: 0x%04X",
                              err_target_en                => "ERROR: Wrong target ID: 0x%04X",
                              err_protocol_en              => "ERROR: Wrong protocol version: 0x%02X",
                              err_command_en               => "ERROR: Wrong command 0x%04X",
                              err_crc_header_en            => "ERROR: CRC of header is wrong. In packet: 0x%02X. Calculated: 0x%02X",
                              err_packetsize_en            => "ERROR: Packetsize (%d) != calculated size (%d). Framecount = %d",
                              err_crc_frame_en             => "ERROR: CRC of frame %d is wrong. In frame: 0x%02X. Calculated: 0x%02X",
                              err_byte_gt_0x7f_en          => "ERROR: Byte greater than 0x7F received: 0x%02X",
                              log_packetdata_en            => "Data bytes:",
                              log_valuename_en             => "Value name: %s",
                              log_valuedatahex_en          => "Value data hex: %s",
                              log_valuedatadec_en          => "Value data dec: %d",
                              log_valuedatadec_w_factor_en => "Value has factor: %d * %.2f = %.2f",
                              log_value_information_en     => "Decoded data: %s: %.2f %s",
                              log_serial_data_en           => "Received serial data: %s",
                              log_packet_found_en          => "Packet found: %s",
                              progress_crc_header_en       => "Calc CRC header...",
                              progress_crc_frame_en        => "Calc CRC frame...",
                              progress_insert_septet_en    => "Insert septet...",
                              progress_parse_data_en       => "Parse data...",
                          # german / deutsch    
                              err_source_de                => "ERROR: Falsche Quellen-ID: 0x%04X",
                              err_target_de                => "ERROR: Falsche Ziel-ID: 0x%04X",
                              err_protocol_de              => "ERROR: Falsche Protokollversion: 0x%02X",
                              err_command_de               => "ERROR: Falsches Kommando 0x%04X",
                              err_crc_header_de            => "ERROR: Pruefsumme des Headers falsch. Im Paket: 0x%02X. Berechnet: 0x%02X",
                              err_packetsize_de            => "ERROR: Paketgroesse (%d) enstpricht nicht der berechneten (%d). Frameanzahl = %d",
                              err_crc_frame_de             => "ERROR: Pruefsumme von Frame %d ist falsch. Im Frame: 0x%02X. Berechnet: 0x%02X",
                              err_byte_gt_0x7f_de          => "ERROR: Byte groesser als 0x7F empfangen: 0x%02X",
                              log_packetdata_de            => "Daten Bytes:",
                              log_valuename_de             => "Wertname: %s",
                              log_valuedatahex_de          => "Wert hex: %s",
                              log_valuedatadec_de          => "Wert dec: %d",
                              log_valuedatadec_w_factor_de => "Wert hat einen Faktor: %d * %.2f = %.2f",
                              log_value_information_de     => "Decodierte Daten: %s: %.2f %s",
                              log_serial_data_de           => "Empfangene serielle Daten: %s",
                              log_packet_found_de          => "Packet gefunden: %s",
                              progress_crc_header_de       => "Berechne Pruefsumme Header...",
                              progress_crc_frame_de        => "Berechne Pruefsumme Frame...",
                              progress_insert_septet_de    => "Fuege Septett hinzu...",
                              progress_parse_data_de       => "Parse Daten...",
                      );                                        
                      @values = (
                              { Name_en=>'Temperature sensor 1'    , Name_de=>'Temperatur Sensor 1'     , Offset=> 0, bitsize=>15, bitpos=>undef, Factor=>0.1  , Unit=>'°C', RRD_Name=>'Solar_Temperatur_Sensor_1'     , GA=>'9/5/0' , DPT=>'9.001' },
                              { Name_en=>'Temperature sensor 2'    , Name_de=>'Temperatur Sensor 2'     , Offset=> 2, bitsize=>15, bitpos=>undef, Factor=>0.1  , Unit=>'°C', RRD_Name=>'Solar_Temperatur_Sensor_2'     , GA=>'9/5/1' , DPT=>'9.001' },
                              { Name_en=>'Temperature sensor 3'    , Name_de=>'Temperatur Sensor 3'     , Offset=> 4, bitsize=>15, bitpos=>undef, Factor=>0.1  , Unit=>'°C', RRD_Name=>''                              , GA=>'9/5/2' , DPT=>'9.001' },
                              { Name_en=>'Temperature sensor 4'    , Name_de=>'Temperatur Sensor 4'     , Offset=> 6, bitsize=>15, bitpos=>undef, Factor=>0.1  , Unit=>'°C', RRD_Name=>''                              , GA=>'9/5/3' , DPT=>'9.001' },
                              { Name_en=>'Pump speed 1'            , Name_de=>'Drehzahl Relais 1'       , Offset=> 8, bitsize=> 8, bitpos=>undef, Factor=>1    , Unit=>'%' , RRD_Name=>'Solar_Drehzahl_Relais_1'       , GA=>'9/5/4' , DPT=>'5'     },
                              { Name_en=>'Pump speed 2'            , Name_de=>'Drehzahl Relais 2'       , Offset=>12, bitsize=> 8, bitpos=>undef, Factor=>1    , Unit=>'%' , RRD_Name=>''                              , GA=>'9/5/5' , DPT=>'5'     },
                              { Name_en=>'Operating hours relais 1', Name_de=>'Betriebsstunden Relais 1', Offset=>10, bitsize=>16, bitpos=>undef, Factor=>1    , Unit=>'h' , RRD_Name=>'Solar_Betriebsstunden_Relais_1', GA=>'9/5/6' , DPT=>'7.001' },
                              { Name_en=>'Operating hours relais 2', Name_de=>'Betriebsstunden Relais 2', Offset=>14, bitsize=>16, bitpos=>undef, Factor=>1    , Unit=>'h' , RRD_Name=>''                              , GA=>''      , DPT=>'7.001' },
                              { Name_en=>'UnitType'                , Name_de=>'UnitType'                , Offset=>16, bitsize=> 8, bitpos=>undef, Factor=>undef, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              { Name_en=>'System'                  , Name_de=>'System'                  , Offset=>17, bitsize=> 8, bitpos=>undef, Factor=>undef, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              { Name_en=>'ErrorMask'               , Name_de=>'ErrorMask'               , Offset=>20, bitsize=>16, bitpos=>undef, Factor=>undef, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              { Name_en=>'Systemzeit'              , Name_de=>'Systemzeit'              , Offset=>22, bitsize=>15, bitpos=>undef, Factor=>undef, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              { Name_en=>'Sensor 1 failure'        , Name_de=>'Sensor 1 defekt'         , Offset=>20, bitsize=> 1, bitpos=>0    , Factor=>undef, Unit=>''  , RRD_Name=>'Solar_Sensor_1_defekt'         , GA=>'9/5/12', DPT=>'1.001' },
                              { Name_en=>'Sensor 2 failure'        , Name_de=>'Sensor 2 defekt'         , Offset=>20, bitsize=> 1, bitpos=>1    , Factor=>undef, Unit=>''  , RRD_Name=>'Solar_Sensor_2_defekt'         , GA=>'9/5/13', DPT=>'1.001' },
                              { Name_en=>'Sensor 3 failure'        , Name_de=>'Sensor 3 defekt'         , Offset=>20, bitsize=> 1, bitpos=>2    , Factor=>undef, Unit=>''  , RRD_Name=>'Solar_Sensor_3_defekt'         , GA=>'9/5/14', DPT=>'1.001' },
                              { Name_en=>'Sensor 4 failure'        , Name_de=>'Sensor 4 defekt'         , Offset=>20, bitsize=> 1, bitpos=>3    , Factor=>undef, Unit=>''  , RRD_Name=>'Solar_Sensor_4_defekt'         , GA=>'9/5/15', DPT=>'1.001' },
                              { Name_en=>'Statusmask'              , Name_de=>'Statusmask'              , Offset=>24, bitsize=>32, bitpos=>undef, Factor=>undef, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              { Name_en=>'Heat amount'             , Name_de=>'Wärmemenge'              , Offset=>28, bitsize=>32, bitpos=>undef, Factor=>1    , Unit=>'Wh', RRD_Name=>'Solar_Waermemenge'             , GA=>'9/5/17', DPT=>'12.001'},
                              { Name_en=>'SV Version'              , Name_de=>'SV Version'              , Offset=>32, bitsize=>16, bitpos=>undef, Factor=>0.01 , Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              { Name_en=>'Variante'                , Name_de=>'Variante'                , Offset=>34, bitsize=>16, bitpos=>undef, Factor=>undef, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                      );
                      ########## conf #############
                      • Das Plugin nutzt bis jetzt nur die serielle Schnittstelle. Ich habe mir einige Skripte mit Socat/Socket angeguckt, bin da aber nicht wirklich schlau draus geworden... Eine Erweiterung um Sockets dürfte aber kein Problem sein.
                      • über die Variable $lang kann man bis jetzt zwischen Deutsch und Englisch wählen. Das Hinzufügen weiterer Sprachen ist einfach über die Conf möglich.
                      • Das größte Problem ist das Protokoll, da die gesendeten Daten keinerlei Hinweise auf ihre Bedeutung enthalten. Wenn man sich das Resol Servicecenter installiert (oder es mit 7-zip entpackt) findet man unter .\eclipse\plugins diverse XML-Dateien. In diesen sind die einzelnen Geräte aufgeführt und darunter die verfügbaren Werte mit Namen, Offset, Bitsize, Faktor, usw...
                        Es sind tatsächlich einzelne Dateien pro Gerät. Wenn man den Namen seines Gerätes nicht kennt (auf meinem steht Stiebel drauf und dafür gibt es keine Datei), kommt man über die Adresse weiter. Am einfachsten erfährt man die über das Resol Servicecenter. Über den angezeigten Namen kann man dann die XML-Datei suchen. Wenn das nicht hilft, sucht man in den Dateien nach der angezeigten Adresse (bei mir "0x427B"). Im XML sucht man sich den Abschnitt mit destination = 0x0010. 0x0010 ist die Adresse der "Daten FernAnzeige" (siehe in der weiter oben verlinkten Protokolbeschreibung). Das "command" sollte "0x0100" sein (= Paket enthält Daten für Slave).
                        Um @values in der Conf einfacher füllen zu können, habe ich eine Tabelle in LibreOffice Calc gebaut. In diese überträgt man die Daten aus dem XML und in Spalte L werden automatisch die Zeilen für @value erstellt.
                        Wenn in der Spalte "RRD?" etwas steht (z.B. "x", "j", "Ich will ein RRD"), wird auch ein entsprechender RRD-Name erzeugt (übernimmt die deutsche Bezeichnung und ersetzt Leerzeichen mit einem Unterstrichen). ABER: es gibt noch keine Unterstützung für RRD. Das muß ich mir erst nochmal angucken.
                        Den Inhalt der Spalte L kopiert man und fügt ihn in der Conf unter @values ein.
                        Im Anhang ist meine Tabelle für "Stiebel Eltron SOKI 6 plus" bzw "DeltaSol BS 2009". Sie sollte sich auch mit Excel öffnen lassen. Im Zweifelsfall gibt es LibreOffice hier als Portable App, die sich nur in ein Verzeichnis entpackt und auch von dort restlos wieder entfernen läßt.
                      • Mein Solarregler plappert von sich aus so regelmäßig, daß die Abfrage der seriellen Schnittstelle mit einem Timeout von 3 sec versehen ist. Sprich das Skript läuft auch höchstens diese drei Sekunden. Durch ein 50msec Sleep zwischen den Abfragen, ist die Prozessorlast sehr niedrig. Meine ersten Läufe waren direkt in der Shell und der Perl-Prozess war nur beim Start On Top in top :-). Bei einem 20sec Timeout ohne Abbruch bei vollständigem Paket, lag socat mit 3% an der Spitze. Sobald ein vollständiges Datenpaket erfolgreich geparst werden konnte, wird die While-Schleife verlassen. Laut Pluginlog liegt die Laufzeit bei 1,2-2,1 sec.
                      • In der Conf muß die Variable "$solar" auf die ID des eigenen Solarreglers geändert werden, damit Pakete anderer Busteilnehmer nicht ausgewertet werden (wird bei kaum jemandem der Fall sein, daß mehr als ein Gerät am Bus hängt, aber man weiß ja nie...)
                      • Bei mir läuft das Skript sauber durch. Wer Probleme hat, darf sich gerne melden.
                      • Das Skript meldet sich an keiner GA an. Ist meiner Meinung nach nicht nötig, da es keinerlei steuernde Aufgaben übernehmen kann, sondern nur zur Abfrage der Werte dient.



                      Wenn jemand das Skript ins SVN hochladen kann und will, so mag er dieses gerne tun :-)

                      PS: zum Anschließen des Busses habe ich mich an den Schaltplan hier gehalten und auf einer Lochrasterplatine aufgebaut: V-bus Interface
                      Ich habe den Teil mit dem RS232-Wandler weggelassen und stattdessen sowas zum Anschließen genutzt: DELOCK 83116 - USBSeriell -TTL 6 offene Kabelenden 1,8m 5V bei reichelt elektronik
                      Der Vorteil an dem Kabel ist, daß es auch 5V zur Spannungsversorgung der Schaltung zur Verfügung stellt.
                      Da ist ein FTDI-Chip drin, der vom WG sofort unterstützt wird.
                      Angehängte Dateien
                      Gruß, Carsten

                      Kommentar


                        #41
                        na hola!
                        Werd' das mal ausprobieren!

                        Danke und Grüße,
                        Lio

                        Kommentar


                          #42
                          So, respekt mal wieder hier, Northman!

                          Also erstmal kurze zeit benötigt um Deine Logik zu verstehen, aber danach flutschte das Teil auf anhieb!

                          Patrick, es ist vollbracht!

                          Herzlichen Dank!

                          Aber kannst mir noch verraten, an welcher stelle Du TTL-USB-Wandler angelötet hast?
                          Hab' nämlich bis jetzt den Wandler von meiner KWL zum testen benutzt und aber extra für Solar einen China TTL-USB-Wandler rumliegen-der sollte nun eingesetzt werden.

                          Danke und Grüße,
                          Lio

                          Kommentar


                            #43
                            Cool Respekt! Und wieder hat es ein Gerätan den BUS geschafft. Ein echter Mehrwert für KNX und ein wichtiger Schritt richtung "voll vernetztem" Haus

                            Eigentlich sollte man versuchen jedes Gerät an den BUS anzubinden (KWL, Heizung, Zähler, Multimedia, Zutrittskontrolle, Wasseraufbereitung, Pooltechnik, Lift, Garagentor, Haushaltsgeräte, (ja auch Sauna). Nicht jedes Gerät muss oder soll gesteuert werden. Aber zu mindest das zentrale Sammeln und visualisieren von Betriebszuständen und Fehler sollte für jedes Gerät möglich sein... Nur die Hersteller wollen nicht immer mitspielen
                            Gruss Patrik alias swiss

                            Kommentar


                              #44
                              Zitat von lio123 Beitrag anzeigen
                              So, respekt mal wieder hier, Northman!

                              Also erstmal kurze zeit benötigt um Deine Logik zu verstehen, aber danach flutschte das Teil auf anhieb!
                              Danke für die Blumen :-)

                              Anscheinend war es bei Dir noch nicht unter 0°C kalt, denn sonst wäre Dir ein Fehler aufgefallen :-)
                              Ich wunderte mich am WE, daß der Kollektor über 3000°C warm sein soll. Kurz mal in das Log geguckt und als der gelesene Wert sowas wie FFDB war, wurde mir klar, daß ich negative Zahlen gar nicht berücksichtigt hatte...
                              Unten ist die neue Version, welche auch eine Änderung an der Conf nötigt macht.
                              Ein zusätzlicher Bug war, daß der Plugin-Name nicht im Log auftauchte. Das lag an der Zeile "my Plugname;", welche jetzt gelöscht wurde.
                              Zitat von lio123 Beitrag anzeigen
                              Aber kannst mir noch verraten, an welcher stelle Du TTL-USB-Wandler angelötet hast?
                              Hab' nämlich bis jetzt den Wandler von meiner KWL zum testen benutzt und aber extra für Solar einen China TTL-USB-Wandler rumliegen-der sollte nun eingesetzt werden.
                              Ich habe die Schaltung aus Deinem Link nachgebaut und den unteren Teil mit dem MAX232 komplett weggelassen. RXD in der Schaltung kommt auch an RXD des TTL-Wandlers und TXD an TXD. Wichtig ist auch, daß der Wandler 5V liefert. Deswegen habe ich die China-Wandler nicht genommen, da viele nur GND, RXD & TXD hatten (von der langen Lieferzeit mal abgesehen... Wollte doch so schnell wie möglich loslegen ;-) )
                              Oder meinst Du was anderes?

                              Das neue Skript:
                              Code:
                              #use strict;
                              use Device::SerialPort;
                              use Time::HiRes qw( usleep gettimeofday  tv_interval );
                              my $crc;
                              my $d;
                              my $framecount;
                              my $framecrc;
                              my $i;
                              my $packetsize;
                              my $usedbytes;
                              my $value;
                              my $valuedata;
                              my $valuedataf;
                              my $valuedatastr;
                              my $debug = 2;
                              
                              my $connectiontype;
                              my $dfa;
                              my $format;
                              my $lang;
                              my $serial;
                              my $serialcount;
                              my $serialdata;
                              my $serialdev;
                              my $solar;
                              my $timeout;
                              my %msgs;
                              my @serialunpack;
                              my @values;
                              my $cycle;
                              readConf();
                              $plugin_info{$plugname.'_cycle'}  = $cycle; 
                              
                              if ($connectiontype eq "serial"){
                              	$serial = Device::SerialPort->new($serialdev) || die "Can't open $serialdev ($!)\n";
                              	$serial->baudrate(9600);
                              	$serial->parity("none");
                              	$serial->databits(8);
                              	$serial->stopbits(1);
                              	$serial->handshake("none");
                              	$serial->write_settings;
                              	$serial->lookclear;
                              	if($debug>=1){plugin_log($plugname,sprintf($msgs{"log_serial_device_open_$lang"}))}  ;
                              } else {
                              	die "Not supported connectiontype '$connectiontype'";
                              }
                              my @packet = ();		# will hold a complete received packet 
                              my @buffer = ();
                              my $loop = 0;
                              my $syncfound = 0;		# will be set to 1 if 0xAA is received
                              my $t0 = [gettimeofday];# now
                              my $res = 0;
                              while ((tv_interval $t0, [gettimeofday]) < $timeout && $res == 0) {		# while timeout is not reached and no valid packet was analyzed
                              	($serialcount, $serialdata) = $serial->read(255);
                              	if($serialcount > 0){
                              		@serialunpack = unpack "C*", $serialdata;						# convert received chars to bytes
                              		if ($debug>2) {plugin_log($plugname,sprintf($msgs{"log_serial_data_$lang"}, sprintf((" %02X" x ($#serialunpack+1), @serialunpack))))};
                              		foreach (@serialunpack) {
                              			if ($_ == 0xAA) {			# sync byte found
                              				if ($syncfound == 0) {	# '0' means found first sync byte
                              					@buffer = (0xAA);
                              					$syncfound = 1;
                              				} else {				# found a second sync byte -> we received a full packet
                              					@packet = @buffer;	# @packet will be analyzed
                              					if ($debug>2) {plugin_log($plugname,sprintf($msgs{"log_data_to_analyze_$lang"}, sprintf((" %02X" x ($#packet+1) ), @serialunpack)))};
                              					$res = analyze_packet(); # result will be '0' if an error occurs and '1' if analysis was successful
                              					@buffer = (0xAA);	# clear buffer and set first byte to the sync byte
                              				}
                              			} else {
                              				if ($_ > 0x7F) {		# bytes greater than 0x7F (127) are not allowed (except for the sync byte 0xAA (170)
                              					@buffer = ();		# clear buffer 
                              					$syncfound = 0;		# reset to skip all bytes until the next sync byte
                              					if ($debug>2) {plugin_log($plugname,sprintf($msgs{"err_byte_gt_0x7f_$lang"}, $_))};
                              				}
                              				if ($syncfound == 1) {
                              					push(@buffer, $_);	# add byte to buffer
                              				}
                              			}
                              		}
                              	}
                              	usleep 50000;						# sleep for 50,000µs 
                              	$loop++;							# count iterations of the while-loop
                              }
                              
                              my $t1 = [gettimeofday];				# now 2
                              my $t0_t1 = tv_interval $t0, $t1;		# get timespan between start & end 
                              
                              print "\n\nTime needed: $t0_t1 \n";
                              
                              sub analyze_packet {
                              	my $source		= $packet[4] * 0x100 + $packet[3];		# source ID of this packet
                              	my $target		= $packet[2] * 0x100 + $packet[1];		# target ID of this packet
                              	my $protocol	= $packet[5];							# protocol ID. Must be 0x10
                              	my $command		= $packet[7] * 0x100 + $packet[6];		# command. Must be 0x0100 = paket contains data for slave
                              	my $offset = 1;											# offset and length of header. Values directly used to check CRC of header
                              	my $length = 8;
                              	my @data;												# array for the data bytes as the data offset does not include septet and CRC
                              	if ($source   != $solar) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_source_$lang"}, $source)) } ; return 0};
                              	if ($target   != $dfa  ) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_target_$lang"}, $target)) } ; return 0};
                              	if ($protocol != 0x10  ) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_protocol_$lang"}, $protocol)) } ; return 0};
                              	if ($command  != 0x0100) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_command_$lang"}, $command)) } ; return 0};
                              	if ($debug >=1) {plugin_log($plugname, sprintf($msgs{"progress_crc_header_$lang"}))};
                              	$crc = vbus_crc($offset,$length); 	# get CRC of header
                              	if ($crc != $packet[9]) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_crc_header_$lang"}, $packet[9] , $crc)) } ; return 0};
                              	$framecount = $packet[8];		# number of data frames
                              	$packetsize = $#packet + 1;
                              	# every dataframe has six bytes
                              	if (($packetsize != (10 + $framecount * 6))) { if ($debug >=2) {plugin_log($plugname,sprintf($msgs{"err_packetsize_$lang"}, $packetsize, (10 + $framecount * 6) , $framecount))} ; return 0};
                              	# check crc of data frames
                              	if ($debug >=1) {plugin_log($plugname, sprintf($msgs{"progress_crc_frame_$lang"}))};
                              	$length = 5; # crc includes septet byte
                              	for ($i = 0; $i < $framecount; $i++) {
                              		$offset = 10 + $i * 6;
                              		$framecrc = $packet[10 + $i * 6 + 5];
                              		$crc = vbus_crc($offset,$length);
                              		if ($crc != $framecrc) {if ($debug >=2) {plugin_log($plugname, sprintf($msgs{"err_crc_frame_$lang"} , $i , $framecrc , $crc)) } ; return 0};
                              	}
                              	# Insert septets and add data bytes to @data
                              	if ($debug >=1) {plugin_log($plugname, sprintf($msgs{"progress_insert_septet_$lang"}))};
                              	$length = 4;
                              	for ($i = 0; $i < $framecount; $i++) {
                              		$offset = 10 + $i * 6;
                              		&vbus_injectSeptet($offset,$length);
                              		push(@data, @packet[$offset..($offset + $length -1)]);
                              	}
                              	if ($debug >= 2) {plugin_log($plugname, sprintf($msgs{"log_packetdata_$lang"} . (" %02X" x ($#data+1)), @data)) };
                              	if ($debug >=1) {plugin_log($plugname, sprintf($msgs{"progress_parse_data_$lang"}))};
                              	foreach $value (@values) {
                              		if ($debug >= 2) {plugin_log($plugname, sprintf($msgs{"log_valuename_$lang"}, $value->{"Name_$lang"}))};
                              		$usedbytes = int(($value->{bitsize} +7) / 8);
                              		$valuedatastr = "";
                              		$offset = $value->{Offset};
                              		foreach $d (@data[$offset..($offset+$usedbytes-1)]) {
                              			$valuedatastr = sprintf("%02X", $d) . $valuedatastr;
                              		}
                              		if ($debug >= 2) {plugin_log($plugname, sprintf($msgs{"log_valuedatahex_$lang"}, $valuedatastr))};
                              		$valuedata = hex($valuedatastr) & ((2** $value->{bitsize})-1);
                              		if ($value->{signed} == 1) {
                              			if ((hex($valuedatastr) & (2**($usedbytes*8-1))) > 0) {
                              				$valuedata = -(2**($usedbytes*8) - hex($valuedatastr));
                              			}
                              		}
                              		if ($debug >= 2) {plugin_log($plugname, sprintf($msgs{"log_valuedatadec_$lang"}, $valuedata))};
                              		if ($value->{Factor}) {
                              				$valuedataf = $valuedata * $value->{Factor};
                              				if ($debug >= 2) {plugin_log($plugname, sprintf($msgs{"log_valuedatadec_w_factor_$lang"}, $valuedata, $value->{Factor}, $valuedataf))};
                              				$valuedata = $valuedataf;
                              		}
                              		if ($value->{bitsize} == 1) {
                              			if ($valuedata > 0) {
                              				$valuedata = 1;
                              				print "bit 1\n";
                              			} else {
                              				$valuedata = 0;
                              			}
                              		}
                              		if ($value->{GA} ne '') {
                              			knx_write($value->{GA}, $valuedata , $value->{DPT});
                              		}
                              		if ($debug >= 1) {plugin_log($plugname, sprintf($msgs{"log_value_information_$lang"}, $value->{"Name_$lang"}, $valuedata, $value->{"Unit"})) ; print "-------\n"};
                              		
                              	}
                              	return 1;
                              }
                              
                              ############### END #################
                              sub vbus_crc {
                              	my ($offset, $length) = @_;
                              	my ($i);
                              	my ($crc) = 0x7f;
                              	for ($i = 0; $i < $length; $i++) {
                              		$crc = ($crc - $packet[$offset + $i]) & 0x7f;
                              	}
                              	return $crc
                              }
                              
                              sub vbus_injectSeptet {
                              	my ($offset, $length) = @_;
                              	my ($i, $septet);
                              	$septet = $packet[$offset + $length];
                              	for ($i = 0; $i < $length; $i++) {
                              		if ($septet & (2 ** $i)) {
                              			$packet[$offset + $i] |= 0x80;
                              		}
                              	}
                              }
                              # sub plugin_log {
                              	# my ($plugname, $text) = @_;
                              	# print $text . "\n";
                              # }
                              
                              sub readConf
                              {
                                  my $confFile = '/etc/wiregate/plugin/generic/conf.d/Resol.conf';
                                  #my $confFile = '/etc/wiregate/plugin/generic/conf.d/'.basename($plugname,'.pl').'.conf';
                                  if (! -f $confFile)
                                  {
                                      plugin_log($plugname, " no conf file [$confFile] found!"); 
                                  }
                                  else
                                  {
                                      if($debug>=1){plugin_log($plugname, " reading conf file [$confFile].");}
                                      open(CONF, $confFile);
                                      my @lines = <CONF>;
                                      close($confFile);
                                      my $result = eval("@lines");
                                      ($result) and plugin_log($plugname, "conf file [$confFile] returned result[$result]");
                                      if ($@) 
                                      {
                                          if($debug>=1){plugin_log($plugname, " conf file [$confFile] returned:");}
                                          my @parts = split(/\n/, $@);
                                          if($debug>=2){plugin_log($plugname, " --> $_") foreach (@parts);}
                                      }
                                  }
                              } # readConf
                              In der CONF bekommt jeder Wert, der negativ sein kann, noch zusätzlich ein "signed=>1" und alle anderen ein "signed=>0".
                              Code:
                              $debug = 1; 
                              $cycle = 60;
                              $connectiontype = "serial";
                              $serialdev = "/dev/usbserial-1-4.3";
                              $timeout = 3;								# maximum time in seconds to listen for a valid packet 
                              $solar = 0x427b;							# ID of your own solar device
                              $dfa   = 0x0010;							# ID of "DFA". In german "Daten Fernanzeige". englisch ~ "remote data display"
                              											# solar device broadcasts his state to this address
                              $lang = "en";
                              %msgs = (
                              	# english / englisch
                              		err_source_en                => "ERROR: Wrong source ID: 0x%04X",
                              		err_target_en                => "ERROR: Wrong target ID: 0x%04X",
                              		err_protocol_en              => "ERROR: Wrong protocol version: 0x%02X",
                              		err_command_en               => "ERROR: Wrong command 0x%04X",
                              		err_crc_header_en            => "ERROR: CRC of header is wrong. In packet: 0x%02X. Calculated: 0x%02X",
                              		err_packetsize_en            => "ERROR: Packetsize (%d) != calculated size (%d). Framecount = %d",
                              		err_crc_frame_en             => "ERROR: CRC of frame %d is wrong. In frame: 0x%02X. Calculated: 0x%02X",
                              		err_byte_gt_0x7f_en          => "ERROR: Byte greater than 0x7F received: 0x%02X",
                              		log_packetdata_en            => "Data bytes:",
                              		log_valuename_en             => "Value name: %s",
                              		log_valuedatahex_en          => "Value data hex: %s",
                              		log_valuedatadec_en          => "Value data dec: %d",
                              		log_valuedatadec_w_factor_en => "Value has factor: %d * %.2f = %.2f",
                              		log_value_information_en     => "Decoded data: %s: %.2f %s",
                              		log_serial_data_en           => "Received serial data: %s",
                              		log_packet_found_en          => "Packet found: %s",
                              		progress_crc_header_en       => "Calc CRC header...",
                              		progress_crc_frame_en        => "Calc CRC frame...",
                              		progress_insert_septet_en    => "Insert septet...",
                              		progress_parse_data_en       => "Parse data...",
                              	# german / deutsch	
                              		err_source_de                => "ERROR: Falsche Quellen-ID: 0x%04X",
                              		err_target_de                => "ERROR: Falsche Ziel-ID: 0x%04X",
                              		err_protocol_de              => "ERROR: Falsche Protokollversion: 0x%02X",
                              		err_command_de               => "ERROR: Falsches Kommando 0x%04X",
                              		err_crc_header_de            => "ERROR: Pruefsumme des Headers falsch. Im Paket: 0x%02X. Berechnet: 0x%02X",
                              		err_packetsize_de            => "ERROR: Paketgroesse (%d) enstpricht nicht der berechneten (%d). Frameanzahl = %d",
                              		err_crc_frame_de             => "ERROR: Pruefsumme von Frame %d ist falsch. Im Frame: 0x%02X. Berechnet: 0x%02X",
                              		err_byte_gt_0x7f_de          => "ERROR: Byte groesser als 0x7F empfangen: 0x%02X",
                              		log_packetdata_de            => "Daten Bytes:",
                              		log_valuename_de             => "Wertname: %s",
                              		log_valuedatahex_de          => "Wert hex: %s",
                              		log_valuedatadec_de          => "Wert dec: %d",
                              		log_valuedatadec_w_factor_de => "Wert hat einen Faktor: %d * %.2f = %.2f",
                              		log_value_information_de     => "Decodierte Daten: %s: %.2f %s",
                              		log_serial_data_de           => "Empfangene serielle Daten: %s",
                              		log_packet_found_de          => "Packet gefunden: %s",
                              		progress_crc_header_de       => "Berechne Pruefsumme Header...",
                              		progress_crc_frame_de        => "Berechne Pruefsumme Frame...",
                              		progress_insert_septet_de    => "Fuege Septett hinzu...",
                              		progress_parse_data_de       => "Parse Daten...",
                              );										
                              @values = (
                              		{ Name_en=>'Temperature sensor 1'    , Name_de=>'Temperatur Sensor 1'     , Offset=> 0, bitsize=>15, bitpos=>undef, Factor=>0.1  , signed=>1, Unit=>'°C', RRD_Name=>'Solar_Temperatur_Sensor_1'     , GA=>'9/5/0' , DPT=>'9.001' },
                              		{ Name_en=>'Temperature sensor 2'    , Name_de=>'Temperatur Sensor 2'     , Offset=> 2, bitsize=>15, bitpos=>undef, Factor=>0.1  , signed=>1, Unit=>'°C', RRD_Name=>'Solar_Temperatur_Sensor_2'     , GA=>'9/5/1' , DPT=>'9.001' },
                              		{ Name_en=>'Temperature sensor 3'    , Name_de=>'Temperatur Sensor 3'     , Offset=> 4, bitsize=>15, bitpos=>undef, Factor=>0.1  , signed=>1, Unit=>'°C', RRD_Name=>''                              , GA=>''      , DPT=>'' },
                              		{ Name_en=>'Temperature sensor 4'    , Name_de=>'Temperatur Sensor 4'     , Offset=> 6, bitsize=>15, bitpos=>undef, Factor=>0.1  , signed=>1, Unit=>'°C', RRD_Name=>''                              , GA=>''      , DPT=>'' },
                              		{ Name_en=>'Pump speed 1'            , Name_de=>'Drehzahl Relais 1'       , Offset=> 8, bitsize=> 8, bitpos=>undef, Factor=>1    , signed=>0, Unit=>'%' , RRD_Name=>'Solar_Drehzahl_Relais_1'       , GA=>'9/5/4' , DPT=>'5'     },
                              		{ Name_en=>'Pump speed 2'            , Name_de=>'Drehzahl Relais 2'       , Offset=>12, bitsize=> 8, bitpos=>undef, Factor=>1    , signed=>0, Unit=>'%' , RRD_Name=>''                              , GA=>''      , DPT=>''     },
                              		{ Name_en=>'Operating hours relais 1', Name_de=>'Betriebsstunden Relais 1', Offset=>10, bitsize=>16, bitpos=>undef, Factor=>1    , signed=>0, Unit=>'h' , RRD_Name=>'Solar_Betriebsstunden_Relais_1', GA=>'9/5/6' , DPT=>'7.001' },
                              		{ Name_en=>'Operating hours relais 2', Name_de=>'Betriebsstunden Relais 2', Offset=>14, bitsize=>16, bitpos=>undef, Factor=>1    , signed=>0, Unit=>'h' , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              		{ Name_en=>'UnitType'                , Name_de=>'UnitType'                , Offset=>16, bitsize=> 8, bitpos=>undef, Factor=>undef, signed=>0, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              		{ Name_en=>'System'                  , Name_de=>'System'                  , Offset=>17, bitsize=> 8, bitpos=>undef, Factor=>undef, signed=>0, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              		{ Name_en=>'ErrorMask'               , Name_de=>'ErrorMask'               , Offset=>20, bitsize=>16, bitpos=>undef, Factor=>undef, signed=>0, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              		{ Name_en=>'Systemzeit'              , Name_de=>'Systemzeit'              , Offset=>22, bitsize=>15, bitpos=>undef, Factor=>undef, signed=>0, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              		{ Name_en=>'Sensor 1 failure'        , Name_de=>'Sensor 1 defekt'         , Offset=>20, bitsize=> 1, bitpos=>0    , Factor=>undef, signed=>0, Unit=>''  , RRD_Name=>'Solar_Sensor_1_defekt'         , GA=>'9/5/12', DPT=>'1.001' },
                              		{ Name_en=>'Sensor 2 failure'        , Name_de=>'Sensor 2 defekt'         , Offset=>20, bitsize=> 1, bitpos=>1    , Factor=>undef, signed=>0, Unit=>''  , RRD_Name=>'Solar_Sensor_2_defekt'         , GA=>'9/5/13', DPT=>'1.001' },
                              		{ Name_en=>'Sensor 3 failure'        , Name_de=>'Sensor 3 defekt'         , Offset=>20, bitsize=> 1, bitpos=>2    , Factor=>undef, signed=>0, Unit=>''  , RRD_Name=>'Solar_Sensor_3_defekt'         , GA=>'9/5/14', DPT=>'1.001' },
                              		{ Name_en=>'Sensor 4 failure'        , Name_de=>'Sensor 4 defekt'         , Offset=>20, bitsize=> 1, bitpos=>3    , Factor=>undef, signed=>0, Unit=>''  , RRD_Name=>'Solar_Sensor_4_defekt'         , GA=>'9/5/15', DPT=>'1.001' },
                              		{ Name_en=>'Statusmask'              , Name_de=>'Statusmask'              , Offset=>24, bitsize=>32, bitpos=>undef, Factor=>undef, signed=>0, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              		{ Name_en=>'Heat amount'             , Name_de=>'Wärmemenge'              , Offset=>28, bitsize=>32, bitpos=>undef, Factor=>1    , signed=>0, Unit=>'Wh', RRD_Name=>'Solar_Waermemenge'             , GA=>'9/5/17', DPT=>'12.001'},
                              		{ Name_en=>'SV Version'              , Name_de=>'SV Version'              , Offset=>32, bitsize=>16, bitpos=>undef, Factor=>0.01 , signed=>0, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              		{ Name_en=>'Variante'                , Name_de=>'Variante'                , Offset=>34, bitsize=>16, bitpos=>undef, Factor=>undef, signed=>0, Unit=>''  , RRD_Name=>''                              , GA=>''      , DPT=>''      },
                              );
                              ########## conf #############
                              Gruß, Carsten

                              Kommentar


                                #45
                                Zitat von swiss Beitrag anzeigen
                                Eigentlich sollte man versuchen jedes Gerät an den BUS anzubinden (KWL, Heizung, Zähler, Multimedia, Zutrittskontrolle, Wasseraufbereitung, Pooltechnik, Lift, Garagentor, Haushaltsgeräte, (ja auch Sauna). Nicht jedes Gerät muss oder soll gesteuert werden. Aber zu mindest das zentrale Sammeln und visualisieren von Betriebszuständen und Fehler sollte für jedes Gerät möglich sein... Nur die Hersteller wollen nicht immer mitspielen
                                versuche festzustellen, wie die wärmepumpe mit solar harmoniert.
                                Mein gefühl sagt-disharmonie

                                @northman
                                Kannst mir trotzdem quick'n'dirty die Anschlusspunkte in den schaltplan einzeichnen (ggf. Koordinaten?)

                                Ne 0° hatten wir gestern nicht

                                Den Link auf die Conf im Plugin war irgendwie blöd.
                                Dadurch war kein CopyPaste möglich und die Dateinamen mussten angepasst werden.

                                Probiers den nächsten Tagen aus.

                                Grüße,
                                Lio

                                Kommentar

                                Lädt...
                                X