Ankündigung

Einklappen
Keine Ankündigung bisher.

Plugin für Stiebel Eltron LWZ 304/404 (CAN Bus)

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

    #61
    Die WPF 7E ist aus dem Jahr 2012, ich meine das ich keine Definition angepasst habe, ist schon so lange her. Ich habe aber die warnings ausgeblendet, weil meine Wiregate immer nach einiger Zeit kein Speicherplatz mehr frei hatte, durch die riesigen Log-Dateien...

    Ich habe mal meine Konfiguration angehängt, die läuft so bei mir.

    WPF 7E.zip

    Kommentar


      #62
      Da ist noch kein WPM3 drin oder?

      Kommentar


        #63
        Die WPM3 kam erst später, habe noch den WPM2...

        Kommentar


          #64
          Hallo,

          ich habe das Plugin jetzt mit einem WPM3 am Laufen, einige Werte stimmen mit denen des Plugins überein, andere nicht. Wie bereits geschrieben wurde, werden wohl ein paar definitions angepasst werden müssen. Hat hier jemand Erkenntnisse bzgl. WPM3?

          VG Thomas

          Kommentar


            #65
            Ich bin gerade auf der Suche nach einem Logger für die Can-Telegramme. Kann das Wiregate sowas zufällig auch?

            Kommentar


              #66
              Hallo zusammen,

              habe das Plugin an einer THZ504 am laufen. Das Auslesen der Außentemperatur/Status Lüftungsstufe klappt wunderbar : (s. log unten)
              meine Test-config:
              push @mapped, { name => 'Außentemperatur', knxStatusGA => '11/4/0', knxWriteGA => undef, cycle => 1 };
              push @mapped, { name => 'Lüftung_Stufe_Nacht', knxStatusGA => '11/5/2', knxWriteGA => '11/5/1', cycle => 1 };

              Leider funktioniert das Einstellen der Lüftungsstufen. z.B.: "Lüftung_Stufe_Nacht" nicht.

              Hier der Log dazu:
              2017-02-28 22:45:15.495,StiebelEltron-LWZ-x04,Bearbeite: Außentemperatur 2017-02-28 22:45:15.497,StiebelEltron-LWZ-x04,Bearbeite: Lüftung_Stufe_Nacht 2017-02-28 22:45:15.673,StiebelEltron-LWZ-x04,Außentemperatur: 5.2 2017-02-28 22:45:15.997,StiebelEltron-LWZ-x04,Lüftung_Stufe_Nacht: 1

              Auf dem CAN:
              slcan1 6A0 [7] 31 00 FA 00 0C 00 00 Anfrage Außentemperatur
              slcan1 6A0 [7] 31 00 FA 05 6D 00 00 Anfrage Lüfterstufe Nacht
              slcan1 180 [7] D2 20 FA 00 0C 00 32 Antwort WP Außentemperatur
              slcan1 180 [7] D2 20 FA 05 6D 00 01 Antwort Lüfterstufe Nacht


              Hat das jemand von euch ans Laufen bekommen?
              Wie bekomme ich auf dem CAN statt der 31(WP request) in Byte 0 eine 30 (WP write) ?
              Auf dem CAN passiert doch bzgl Lüftung nur was wegen knxStatusGA => '11/5/2', was muss an knxWriteGA => '11/5/1' noch ergänzt werden? GA im Wiregate ist bekannt. DPT 7.001.

              Vielen Dank im vorraus.

              Grüße
              Joachim

              Kommentar


                #67
                Moin,
                welchen WPM hast du denn?
                vg

                Kommentar


                  #68
                  Guten Morgen,

                  ich habe die TECALOR THZ 504 im Einsatz.

                  Ich habe jetzt doch ein Schreibbefehl auf dem CAN gesehen.
                  Kann es sein dass das Schreiben fehlschlägt wenn die Registrierung an der WP nicht korrekt abläuft? (die Registrierung habe ich bisher noch gar nicht gesehen)

                  Grüßle
                  Joachim

                  Kommentar


                    #69
                    Moin,
                    Ich meinte die Version des Wärmepumpenmanagers?
                    lg

                    Kommentar


                      #70
                      Hi,

                      ich habe gar keinen WPM. Ich habe nur die Bedieneinheit direkt an der WP und das Plugin am WG in Betrieb.

                      Bin nun etwas weiter. Habe nun das Display als my $displaynum = 0; konfiguriert. Jetzt funktioniert die Kommunikation über CAN ID 0x69E. Auch schreiben ist möglich.
                      Allerdings sind auf dem CAN die letzten beiden Bytes der Lüfterstufe Tag vertauscht:
                      Ich schicke eine GA DPT 7: 00 01

                      Auf dem CAN sehe ich dann:

                      slcan1 69E [7] 30 00 FA 05 6C 01 00

                      Wenn ich die aktuelle Stufe auslese kommt:
                      slcan1 69E [7] 31 00 FA 05 6C 00 00
                      slcan1 180 [7] D2 1E FA 05 6C 00 01

                      Das habe ich nun im Plugin so gelöst:
                      in
                      sub send_lwz_write
                      ...
                      can_send($sock, $c, $id, [($definition->{writeTarget}<<4) | TYPE_WRITE, $entry->{target}, 0xFA, $definition->{valueId}, $definition->{valueSubId}, $value2, $value1]);

                      $value1 und $value 2 vertauscht.

                      Jemand ne bessere Idee / Lösung?

                      Vor allem sollte das auch für alle lwz_write Zugriffe passen...

                      Grüße

                      Joachim

                      Kommentar


                        #71
                        Hi,
                        Frage bekommt man denn als CAN Wert VL und RL und die aktuelle Wassermenge der Heizung raus? Im Display kann man die ja sehen.
                        VG
                        Jürgen

                        Kommentar


                          #72
                          Stehe gerade nicht vor der WP. In welchen Menüs tauchen die Werte auf? Wassermenge erinnere ich so nicht...

                          Kommentar


                            #73
                            weil in einem anderen Thread die Frage nach den Definitions für den WPM3 aufkam, poste ich hier mal das angepasste Plugin. Die Anpassung ist schon eine Weile her. Ich meine mich zu erinnern, dass ich mit der Umstellung von Heizkreis1 und Heizkreis2 Probleme hatte. Evtl. hat hier ja jemand eine Lösung. Die Definitions müssten aber passen.

                            Code:
                            ######################################################################################
                            # Plugin StiebelEltron-LWZ-x04
                            # V0.3 2016-12-27
                            # Lizenz: GPLv2
                            # Autor Plugin: krumboeck (http://knx-user-forum.de/members/krumboeck.html)
                            # Autor Definitions_WPC: (https://knx-user-forum.de/member/6803-sirtom)
                            #
                            # Benötigt:
                            # * CAN Bus Adapter
                            # * Kernel Update für CAN Bus
                            # * iproute2 für CAN Bus Konfiguration
                            #
                            # ACHTUNG: Es handelt sich hier um ein experimentelles Plugin!!
                            # Es wird keine Haftung für Beschädigungen aller Art übernommen!
                            #
                            # Die verwendeten Variablen basieren auf Reverse Engineering und
                            # sind weder geprüft noch ausreichend getestet.
                            #
                            # TIPP: Bevor Sie eine Variable beschreiben, lesen sie diese bitte
                            # ein und überprüfen sie die Korrektheit des Wertes.
                            #
                            # Changelog:
                            # 2014-09-13  0.1  Initiale Version veröffentlicht
                            # 2015-01-11  0.2  Unterstützung von negativen Temperatur Werten
                            #                  Unterstützung von Gruppierten Werten
                            # 2016-12-27  0.3  Anpassung auf WPC-Cool Serie mit WPM3i
                            #                  (Format ist für Druck- und Zeitangaben nicht angepasst)
                            #
                            ######################################################################################
                            
                            
                            use warnings;
                            use strict;
                            use Socket qw(SOCK_RAW);
                            use Convert::Binary::C;
                            
                            ######################
                            # Startevent ermitteln
                            ######################
                            my $event=undef;
                            if (!$plugin_initflag) {
                                $event = 'restart';
                            } elsif ($plugin_info{$plugname.'_lastsaved'} > $plugin_info{$plugname.'_last'}) {
                                $event = 'modified'; # Plugin modifiziert
                            } elsif (%msg) {
                                $event = 'knx'; # KNX/EIB Bustraffic
                            } elsif ($fh) {
                                $event = 'socket'; # Netzwerktraffic
                            } else {
                                $event = 'cycle'; # Zyklus
                            }
                            
                            #########################
                            ### BEGINN DEFINITION ###
                            #########################
                            
                            my $socknum = 500; # Eindeutige Nummer des Sockets
                            
                            use constant {
                                    PF_CAN                  => 29,
                                    AF_CAN                  => 29,
                                    CAN_RAW                 => 1,
                                    SOL_CAN_BASE            => 100,
                                    SOL_CAN_RAW             => 101,
                                    CAN_RAW_FILTER          => 1,
                                    CAN_RAW_ERR_FILTER      => 2,
                                    CAN_RAW_LOOPBACK        => 3,
                                    CAN_RAW_RECV_OWN_MSGS   => 4,
                                    # special address description flags for the CAN_ID
                                    CAN_EFF_FLAG            => 0x80000000, # EFF/SFF is set in the MSB
                                    CAN_RTR_FLAG            => 0x40000000, # remote transmission request
                                    CAN_ERR_FLAG            => 0x20000000, # error frame
                                    # valid bits in CAN ID for frame formats
                                    CAN_SFF_MASK            => 0x000007FF, # standard frame format (SFF)
                                    CAN_EFF_MASK            => 0x1FFFFFFF, # extended frame format (EFF)
                                    CAN_ERR_MASK            => 0x1FFFFFFF, # omit EFF, RTR, ERR flags
                                    # bits/ioctls.h
                                    SIOCGIFINDEX            => 0x8933,
                                    # LWZ protocol
                                    TARGET_SYSTEM            => 0x03,
                                    TARGET_HEIZKREIS        => 0x0C,
                                    TARGET_SENSOR            => 0x08,
                                    TARGET_DISPLAY            => 0x0D,
                                    SOURCE_SYSTEM            => 0x01,
                                    SOURCE_HEIZKREIS        => 0x06,
                                    SOURCE_SENSOR            => 0x04,
                                    SOURCE_DISPLAY            => 0x06,
                                    HEIZKREIS_1                => 0x01,
                                    HEIZKREIS_2                => 0x02,
                                    TYPE_WRITE                => 0x00,
                                    TYPE_REQUEST            => 0x01,
                                    TYPE_RESPONSE            => 0x02,
                                    TYPE_REGISTER            => 0x06,
                            
                            };
                            
                            my $cstruct = "
                            typedef unsigned long canid_t;
                            
                            #define ifr_name       ifr_ifrn.ifrn_name      /* interface name  */
                            #define ifr_ifindex    ifr_ifru.ifru_ivalue    /* interface index */
                            struct ifreq {
                                    union {
                                            char ifrn_name[16];
                                    } ifr_ifrn;
                                    union {
                                            int ifru_ivalue;
                                    } ifr_ifru;
                            };
                            
                            struct can_frame {
                                    canid_t can_id;
                                    unsigned char can_dlc;
                                    unsigned char align[3];
                                    unsigned char data[8];
                            };
                            
                            struct sockaddr_can {
                                    int can_family;
                                    int can_ifindex;
                                    union {
                                            struct { canid_t rx_id, tx_id; } tp;
                                    } can_addr;
                            };
                            
                            struct can_filter {
                                    canid_t can_id;
                                    canid_t can_mask;
                            };
                            
                            ";
                            
                            my @definitions;
                            push @definitions, { name => 'Warmwasser_Solltemperatur_eco', valueId => 0x0A, valueSubId => 0x06,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Warmwasser_Solltemperatur', valueId => 00, valueSubId => 0x13,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Warmwasser_Temperatur', valueId => 0x00, valueSubId => 0x0E,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Raumtemperatur_komfort', valueId => 0x00, valueSubId => 0x05,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Raumtemperatur_eco', valueId => 0x00, valueSubId => 0x08,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Raumsolltemperatur_FEK', valueId => 0x4E, valueSubId => 0x66,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Raumtemperatur_FEK', valueId => 0x4E, valueSubId => 0x64,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Taupunkttemperatur_FEK', valueId => 0x02, valueSubId => 0x64,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Außentemperatur', valueId => 0x00, valueSubId => 0x0C,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };            
                            push @definitions, { name => 'Heizkreis1_Temperatur', valueId => 0x02, valueSubId => 0xCA,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };    
                            push @definitions, { name => 'Heizkreis1_Solltemperatur', valueId => 0x00, valueSubId => 0x04,
                                        writeTarget => undef, requestTarget => 0x06, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Heizkreis2_Temperatur', valueId => 0x00, valueSubId => 0x0F,
                                        writeTarget => undef, requestTarget => 0x0C, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };    
                            push @definitions, { name => 'Heizkreis2_Solltemperatur', valueId => 0x00, valueSubId => 0x04,
                                        writeTarget => undef, requestTarget => 0x0C, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Vorlaufisttemperatur_WP', valueId => 0x06, valueSubId => 0xA1,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };            
                            push @definitions, { name => 'Vorlaufisttemperatur_NHZ', valueId => 0x06, valueSubId => 0xA0,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Rücklaufisttemperatur', valueId => 0x00, valueSubId => 0x16,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Pufferisttemperatur', valueId => 0x00, valueSubId => 0x78,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };                    
                            push @definitions, { name => 'Puffersolltemperatur', valueId => 0x01, valueSubId => 0xD5,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };    
                            push @definitions, { name => 'Heizungsdruck', valueId => 0x06, valueSubId => 0x74,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 100, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Volumenstrom', valueId => 0x06, valueSubId => 0x73,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 100, format => 'tenthDegree', knxTyp => '9.001' };            
                            push @definitions, { name => 'Anlagenfrost', valueId => 0x0A, valueSubId => 0x00,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Quellentemperatur', valueId => 0x01, valueSubId => 0xD4,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Quellendruck', valueId => 0x06, valueSubId => 0x75,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 100, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Laufzeit_VD_Heizen', valueId => 0x07, valueSubId => 0xFC,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Laufzeit_VD_Warmwasser', valueId => 0x08, valueSubId => 0x02,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Laufzeit_VD_Kühlen', valueId => 0x07, valueSubId => 0xFF,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Laufzeit_NHZ1', valueId => 0x02, valueSubId => 0x59,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Laufzeit_NHZ2', valueId => 0x02, valueSubId => 0x5A,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Laufzeit_NHZ1/2', valueId => 0x08, valueSubId => 0x05,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Leistungsaufnahme_VD_Heizen_Tag_Wh', valueId => 0x09, valueSubId => 0x1E,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'wattHour', knxTyp => '13.010' };
                            push @definitions, { name => 'Leistungsaufnahme_VD_Heizen_Tag_KWh', valueId => 0x09, valueSubId => 0x1F,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'kiloWattHour', knxTyp => '13.013' };    
                            push @definitions, { name => 'Leistungsaufnahme_VD_Heizen_Summe_KWh', valueId => 0x09, valueSubId => 0x20,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'kiloWattHour', knxTyp => '13.013' };
                            push @definitions, { name => 'Leistungsaufnahme_VD_Heizen_Summe_MWh', valueId => 0x09, valueSubId => 0x21,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 0.001, format => 'megaWattHour', knxTyp => '13.013' };            
                            push @definitions, { name => 'Leistungsaufnahme_VD_Warmwasser_Tag_Wh', valueId => 0x09, valueSubId => 0x1A,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'wattHour', knxTyp => '13.010' };
                            push @definitions, { name => 'Leistungsaufnahme_VD_Warmwasser_Tag_KWh', valueId => 0x09, valueSubId => 0x1B,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'kiloWattHour', knxTyp => '13.013' };    
                            push @definitions, { name => 'Leistungsaufnahme_VD_Warmwasser_Summe_KWh', valueId => 0x09, valueSubId => 0x1C,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'kiloWattHour', knxTyp => '13.013' };
                            push @definitions, { name => 'Leistungsaufnahme_VD_Warmwasser_Summe_MWh', valueId => 0x09, valueSubId => 0x1D,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 0.001, format => 'megaWattHour', knxTyp => '13.013' };    
                            push @definitions, { name => 'Wärmemenge_VD_Heizen_Tag_Wh', valueId => 0x09, valueSubId => 0x2E,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'wattHour', knxTyp => '13.010' };
                            push @definitions, { name => 'Wärmemenge_VD_Heizen_Tag_KWh', valueId => 0x09, valueSubId => 0x2F,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'kiloWattHour', knxTyp => '13.013' };        
                            push @definitions, { name => 'Wärmemenge_VD_Heizen_Summe_KWh', valueId => 0x09, valueSubId => 0x30,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'kiloWattHour', knxTyp => '13.013' };
                            push @definitions, { name => 'Wärmemenge_VD_Heizen_Summe_MWh', valueId => 0x09, valueSubId => 0x31,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 0.001, format => 'megaWattHour', knxTyp => '13.013' };            
                            push @definitions, { name => 'Wärmemenge_VD_Warmwasser_Tag_Wh', valueId => 0x09, valueSubId => 0x2A,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'wattHour', knxTyp => '13.010' };
                            push @definitions, { name => 'Wärmemenge_VD_Warmwasser_Tag_KWh', valueId => 0x09, valueSubId => 0x2B,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'kiloWattHour', knxTyp => '13.013' };    
                            push @definitions, { name => 'Wärmemenge_VD_Warmwasser_Summe_KWh', valueId => 0x09, valueSubId => 0x2C,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'kiloWattHour', knxTyp => '13.013' };
                            push @definitions, { name => 'Wärmemenge_VD_Warmwasser_Summe_MWh', valueId => 0x09, valueSubId => 0x2D,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 0.001, format => 'megaWattHour', knxTyp => '13.013' };    
                            push @definitions, { name => 'Wärmemenge_NHZ_Heizen_Summe_KWh', valueId => 0x09, valueSubId => 0x28,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'kiloWattHour', knxTyp => '13.013' };
                            push @definitions, { name => 'Wärmemenge_NHZ_Heizen_Summe_MWh', valueId => 0x09, valueSubId => 0x29,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 0.001, format => 'megaWattHour', knxTyp => '13.013' };            
                            push @definitions, { name => 'Wärmemenge_NHZ_Warmwasser_Summe_KWh', valueId => 0x09, valueSubId => 0x23,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'kiloWattHour', knxTyp => '13.013' };
                            push @definitions, { name => 'Wärmemenge_NHZ_Warmwasser_Summe_MWh', valueId => 0x09, valueSubId => 0x24,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 0.001, format => 'megaWattHour', knxTyp => '13.013' };    
                            push @definitions, { name => 'Heissgastemperatur', valueId => 02, valueSubId => 0x65,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 10, format => 'tenthDegree', knxTyp => '9.001' };
                            push @definitions, { name => 'Hochdruck', valueId => 0x02, valueSubId => 0x68,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 100, format => 'tenthDegree', knxTyp => '9.001' };    
                            push @definitions, { name => 'Niederdruck', valueId => 0x07, valueSubId => 0xA5,
                                        writeTarget => undef, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 100, format => 'tenthDegree', knxTyp => '9.001' };                
                            push @definitions, { name => 'Betriebsart', valueId => 0x01, valueSubId => 0x12,
                                        writeTarget => 0x03, requestTarget => 0x03, responseTarget => 0x0D,
                                        decimalFactor => 1, format => 'none', knxTyp => '16.001' };
                            
                            
                            my @combinations;
                            push @combinations, { name => 'Leistungsaufnahme_VD_Heizen_Summe', def1 => 'Leistungsaufnahme_VD_Heizen_Summe_MWh', def2 => 'Leistungsaufnahme_VD_Heizen_Summe_KWh', knxTyp => '13.013' };
                            push @combinations, { name => 'Leistungsaufnahme_VD_Warmwasser_Summe', def1 => 'Leistungsaufnahme_VD_Warmwasser_Summe_MWh', def2 => 'Leistungsaufnahme_VD_Warmwasser_Summe_KWh', knxTyp => '13.013' };
                            push @combinations, { name => 'Wärmemenge_VD_Heizen_Summe', def1 => 'Wärmemenge_VD_Heizen_Summe_MWh', def2 => 'Wärmemenge_VD_Heizen_Summe_KWh', knxTyp => '13.013' };
                            push @combinations, { name => 'Wärmemenge_VD_Warmwasser_Summe', def1 => 'Wärmemenge_VD_Warmwasser_Summe_MWh', def2 => 'Wärmemenge_VD_Warmwasser_Summe_KWh', knxTyp => '13.013' };
                            push @combinations, { name => 'Wärmemenge_NHZ_Heizen_Summe', def1 => 'Wärmemenge_NHZ_Heizen_Summe_MWh', def2 => 'Wärmemenge_NHZ_Heizen_Summe_KWh', knxTyp => '13.013' };
                            push @combinations, { name => 'Wärmemenge_NHZ_Warmwasser_Summe', def1 => 'Wärmemenge_NHZ_Warmwasser_Summe_MWh', def2 => 'Wärmemenge_NHZ_Warmwasser_Summe_KWh', knxTyp => '13.013' };
                            
                            push @combinations, { name => 'Leistungsaufnahme_VD_Heizen_Tag', def1 => 'Leistungsaufnahme_VD_Heizen_Tag_Wh', def2 => 'Leistungsaufnahme_VD_Heizen_Tag_KWh', knxTyp => '13.013' };
                            push @combinations, { name => 'Leistungsaufnahme_VD_Warmwasser_Tag', def1 => 'Leistungsaufnahme_VD_Warmwasser_Tag_Wh', def2 => 'Leistungsaufnahme_VD_Warmwasser_Tag_KWh', knxTyp => '13.013' };
                            push @combinations, { name => 'Wärmemenge_VD_Heizen_Tag', def1 => 'Wärmemenge_VD_Heizen_Tag_Wh', def2 => 'Wärmemenge_VD_Heizen_Tag_KWh', knxTyp => '13.013' };
                            push @combinations, { name => 'Wärmemenge_VD_Warmwasser_Tag', def1 => 'Wärmemenge_VD_Warmwasser_Tag_Wh', def2 => 'Wärmemenge_VD_Warmwasser_Tag_KWh', knxTyp => '13.013' };
                            
                            
                            
                            my @mapped;
                            my $interface = 'can0';
                            my @display = (0x1E, 0x1F, 0x20, 0x21, 0x22);
                            my $displaynum = 2;
                            
                            ###############################
                            # Lesen der Konfigurationsdatei
                            ###############################
                            
                            # Read config file in conf.d
                            my $confFile = '/etc/wiregate/plugin/generic/conf.d/'.basename($plugname,'.pl').'.conf';
                            if (! -f $confFile) {
                                plugin_log($plugname, " no conf file [$confFile] found.");
                                return "no conf file [$confFile] found.";
                            } else {
                                open(CONF, $confFile);
                                my @lines = <CONF>;
                                close($confFile);
                                my $result = eval("@lines");
                                if ($@) {
                                    plugin_log($plugname, "conf file [$confFile] returned:");
                                    my @parts = split(/\n/, $@);
                                    plugin_log($plugname, "--> $_") foreach (@parts);
                                }
                            }
                            
                            # Festlegen, dass das Plugin alle 5 Minuten laufen soll
                            #$plugin_info{$plugname.'_cycle'} = 300;
                            $plugin_info{$plugname.'_cycle'} = 60;
                            
                            my $debug = 0;
                            
                            ############
                            ### MAIN ###
                            ############
                            
                            my $displayId = $display[$displaynum];
                            my $canId = 0x0680 + $displayId;
                            my $sc;
                            
                            my $c = Convert::Binary::C->new();
                            $c->parse($cstruct);
                            
                            if (!$socket[$socknum]) {
                                socket($sc, PF_CAN, SOCK_RAW, CAN_RAW)
                                             or die "Can't open socket $!\n";
                                my $if_idx = can_if_idx($sc, $c, $interface);
                                bind($sc, $c->pack('sockaddr_can', {can_family => AF_CAN, can_ifindex => $if_idx}))
                                             or die "Can't bind to can $!\n";
                            
                                $socket[$socknum] = $sc;
                                $socksel->add($socket[$socknum]); # add socket to select
                                $plugin_socket_subscribe{$socket[$socknum]} = $plugname;
                                plugin_log($plugname, 'Socket verbunden. Socketnummer: ' . $socknum);
                            
                                return "opened socket $socknum";
                            }
                            
                            $sc = $socket[$socknum];
                            
                            if ($event =~ /socket/) {
                                my $frame_len = $c->sizeof('can_frame');
                                recv($sc, my $frame, $frame_len, 0) or die "Recv failed $!\n";
                                my $f = $c->unpack('can_frame', $frame);
                                @{$f->{data}}[$f->{can_dlc} .. $#{$f->{data}}] = (0,0,0,0,0,0,0,0);
                            
                                handle_response($displayId, $f->{can_id}, $f->{can_dlc}, $f->{data});
                            } elsif ($event =~ /knx/) {
                                if ($msg{apci} eq "A_GroupValue_Write") {
                                    my $ga = $msg{dst};
                                    my ($entry, $definition) = find_mapping_ga($ga);
                                    if (!defined $entry) {
                                        delete $plugin_subscribe{$ga}{$plugname};
                                        plugin_log($plugname, 'Unbekannte Gruppenadresse: ' . $ga . ' -> abgemeldet');
                                        return;
                                    }
                                    my $value = undef;
                                    if (defined $msg{value}) {
                                        $value = $msg{value};
                                    } else {
                                        my @typArray = split(/\./, $definition->{knxTyp});
                                        my $majorTyp = $typArray[0];
                                        if ($majorTyp eq "9") {
                                            $value = decode_dpt9($msg{data});
                                        } else {
                                            plugin_log($plugname, 'Kann KNX Wert für ' . $entry->{name} . ' nicht lesen: ' . $definition->{knxTyp});
                                        }
                                    }
                                    if (defined $value) {
                                        plugin_log($plugname, 'Empfange KNX Wert für ' . $entry->{name} . ': ' . $value);
                                        send_lwz_write($sc, $c, $canId, $entry, $definition, $value);
                                    }
                                }
                            } elsif ($event =~ /cycle/) {
                                foreach my $entry (@mapped) {
                                    if ($entry->{cycle}) {
                                        send_lwz_request($sc, $c, $canId, $entry->{name}, $entry->{target});
                                    }
                                }
                            } elsif ($event =~ /restart|modified/) {
                                plugin_log($plugname, 'Registriere Display: ' . $displaynum);
                                register_display($sc, $c, $canId, $displayId);
                                foreach my $entry (@mapped) {
                                    if (defined $entry->{knxWriteGA}) {
                                        my $ga = $entry->{knxWriteGA};
                                        $plugin_subscribe{$ga}{$plugname} = 1;
                                        plugin_log($plugname, 'Registriere Gruppenadresse: ' . $ga);
                                    }
                                }
                            }
                            
                            return;
                            
                            sub register_display {
                                my ($sock, $c, $id, $displayId) = @_;
                                can_send($sock, $c, $id, [TARGET_DISPLAY, $displayId, 0xFD, 0x01, 0x00, 0x00, 0x00]);
                            }
                            
                            sub can_send {
                                my ($sock, $c, $id, $data) = @_;
                                my $frame = $c->pack('can_frame', {
                                        can_id => $id,
                                        can_dlc => scalar @$data,
                                        data => $data
                                });
                                syswrite($sock, $frame) or die "Send failed $!\n";
                            }
                            
                            sub can_if_idx {
                                my ($sock, $c, $if_name) = @_;
                                my @if = map { ord($_) } split(//, $if_name);
                                my $ifreq = $c->pack('ifreq', {ifr_ifrn => {ifrn_name => \@if}});
                                ioctl($sock, SIOCGIFINDEX, $ifreq) or die "Ioctl call failed $!\n";
                                my $res = $c->unpack('ifreq', $ifreq);
                                return $res->{ifr_ifru}{ifru_ivalue};
                            }
                            
                            sub send_lwz_request {
                                my ($sock, $c, $id, $name, $target) = @_;
                                my $definition = get_definition($name);
                            
                                if (! defined $definition) {
                                    my $combination = get_combination_definition($name);
                                    if (defined $combination) {
                                        send_lwz_request($sock, $c, $id, $combination->{def1}, $target);
                                        send_lwz_request($sock, $c, $id, $combination->{def2}, $target);
                                        return;
                                    }
                                    plugin_log($plugname, 'Kann Definition nicht finden: ' . $name);
                                    return;
                                }
                            
                                plugin_log($plugname, 'Bearbeite: ' . $definition->{name});
                                if ($definition->{requestTarget} == TARGET_SYSTEM) {
                                    can_send($sock, $c, $id, [(TARGET_SYSTEM<<4) | TYPE_REQUEST, 0x00, 0xFA, $definition->{valueId}, $definition->{valueSubId}, 0x00, 0x00]);
                                } elsif ($definition->{requestTarget} == TARGET_HEIZKREIS) {
                                    if (defined $target) {
                                        if ($target == HEIZKREIS_1 || $target == HEIZKREIS_2) {
                                            can_send($sock, $c, $id, [(TARGET_HEIZKREIS<<4) | TYPE_REQUEST, $target, 0xFA, $definition->{valueId}, $definition->{valueSubId}, 0x00, 0x00]);
                                        } else {
                                            plugin_log($plugname, $name . ': Attribut "target" enthält einen ungültigen Wert');
                                        }
                                    } else {
                                        plugin_log($plugname, $name . ': Attribut "target" wird benötigt');
                                    }
                                } else {
                                    plugin_log($plugname, $name . ': Request type noch nicht implementiert');
                                }
                            }
                            
                            sub send_lwz_write {
                                my ($sock, $c, $id, $entry, $definition, $value) = @_;
                                if (defined $definition->{writeTarget}) {
                                    my ($value1, $value2) = convert_to_lwz_value($definition, $value);
                                    if (defined $value1) {
                                        can_send($sock, $c, $id, [($definition->{writeTarget}<<4) | TYPE_WRITE, $entry->{target}, 0xFA, $definition->{valueId}, $definition->{valueSubId}, $value1, $value2]);
                                    }
                                } else {
                                    plugin_log($plugname, $entry->{name} . ': Readonly-Wert kann nicht geschrieben werden');
                                }
                            }
                            
                            sub handle_response {
                                my ($displayId, $id, $dlc, $dataRef) = @_;
                                my @data = @{$dataRef};
                                if ($dlc == 7) {
                                    my $target = ($data[0] & 0xF0) >> 4;
                                    my $type = $data[0] & 0x0F;
                                    my $subTarget = $data[1];
                                    if ($type == TYPE_RESPONSE || $type == TYPE_WRITE) {
                                        if ($target == TARGET_DISPLAY && ($subTarget == $displayId || $subTarget == 0x3C)) {
                                            my $source = ($id & 0xFF00) >> 8;
                                            my $subSource = $id & 0x00FF;
                                            my $fix = $data[2];
                                            my $valueId = $data[3];
                                            my $valueSubId = $data[4];
                                            if (($source == SOURCE_SYSTEM || $source == SOURCE_HEIZKREIS) && $fix == 0xFA) {
                                                my ($entry, $combination, $definition) = find_combination_mapping($source, $subSource, $valueId, $valueSubId);
                                                if (! defined $entry) {
                                                    ($entry, $definition) = find_mapping($source, $subSource, $valueId, $valueSubId);
                                                }
                                                if (defined $entry) {
                                                    my $value = ($data[5] << 8) | $data[6];
                                                    my $convertedValue = convert_response_value($definition, $value);
                                                    if (defined $convertedValue) {
                                                        plugin_log($plugname, $entry->{name} . ': ' . $convertedValue);
                                                        if (defined $combination) {
                                                            my $currentTime = time();
                                                            saveCombinationValue($definition->{name}, $convertedValue, $currentTime);
                                                            my ($def1, $def2, $value1, $value2);
                                                            if ($combination->{def1} eq $definition->{name}) {
                                                                $def1 = $definition;
                                                                $value1 = $convertedValue;
                                                                $def2 = get_definition($combination->{def2});
                                                                $value2 = loadCombinationValue($combination->{def2}, $currentTime - 10);
                                                            } else {
                                                                $def2 = $definition;
                                                                $value2 = $convertedValue;
                                                                $def1 = get_definition($combination->{def1});
                                                                $value1 = loadCombinationValue($combination->{def1}, $currentTime - 10);
                                                            }
                                                            if (!defined $def1 || !defined $def2 || !defined $value1 || !defined $value2) {
                                                                return;
                                                            }
                                                            $value1 = convertValueToTargetTyp($value1, $def1->{knxTyp}, $combination->{knxTyp});
                                                            $value2 = convertValueToTargetTyp($value2, $def2->{knxTyp}, $combination->{knxTyp});
                                                            if (!defined $value1 || !defined $value2) {
                                                                dump_can_message('Kombinationswert konnte nicht in das richtige Format umgewandelt werden', $id, $dlc, \@data);
                                                                return;
                                                            }
                                                            $convertedValue = $value1 + $value2;
                                                            knx_write($entry->{knxStatusGA}, $convertedValue, $combination->{knxTyp});
                                                        } else {
                                                            knx_write($entry->{knxStatusGA}, $convertedValue, $definition->{knxTyp});
                                                        }        
                                                    } else {
                                                        dump_can_message('Wert konnte nicht verarbeitet werden', $id, $dlc, \@data);
                                                    }
                                                } elsif ($target != TARGET_DISPLAY || $subTarget != 0x3C) {
                                                    dump_can_message('Nicht erwarteter Transfer', $id, $dlc, \@data);
                                                }
                                            } else {
                                                dump_can_message('Unbekannter Transfer', $id, $dlc, \@data);
                                            }
                                        }
                                    }
                                } else {
                                    dump_can_message('Fehlerhafte Transferlänge', $id, $dlc, \@data);
                                }
                            }
                            
                            sub find_mapping {
                                my ($source, $subSource, $valueId, $valueSubId) = @_;
                                foreach my $entry (@mapped) {
                                    my $definition = get_definition($entry->{name});
                                    if ($valueId == $definition->{valueId} && $valueSubId == $definition->{valueSubId}) {
                                        if ($source == SOURCE_SYSTEM) {
                                            if ($subSource == 0x80) {
                                                return ($entry, $definition);
                                            }
                                        } else {
                                            if ($subSource == $entry->{target}) {
                                                return ($entry, $definition);
                                            }
                                        }
                                    }
                                }
                                return (undef, undef);
                            }
                            
                            sub find_combination_mapping {
                                my ($source, $subSource, $valueId, $valueSubId) = @_;
                                foreach my $entry (@mapped) {
                                    my $combination = get_combination_definition($entry->{name});
                            
                                    my $definition = get_definition($combination->{def1});
                                    if ($valueId == $definition->{valueId} && $valueSubId == $definition->{valueSubId}) {
                                        if ($source == SOURCE_SYSTEM) {
                                            if ($subSource == 0x80) {
                                                return ($entry, $combination, $definition);
                                            }
                                        } else {
                                            if ($subSource == $entry->{target}) {
                                                return ($entry, $combination, $definition);
                                            }
                                        }
                                    }
                            
                                    $definition = get_definition($combination->{def2});
                                    if ($valueId == $definition->{valueId} && $valueSubId == $definition->{valueSubId}) {
                                        if ($source == SOURCE_SYSTEM) {
                                            if ($subSource == 0x80) {
                                                return ($entry, $combination, $definition);
                                            }
                                        } else {
                                            if ($subSource == $entry->{target}) {
                                                return ($entry, $combination, $definition);
                                            }
                                        }
                                    }
                            
                                }
                                return (undef, undef, undef);
                            }
                            
                            sub convert_response_value {
                                my ($definition, $value) = @_;
                                if ($definition->{format} eq 'tenthDegree') {
                                    $value -= 0x10000 if $value >= 0x8000;
                                }
                                if (defined $definition->{decimalFactor}) {
                                    return $value / $definition->{decimalFactor};
                                } else {
                                    return $value;
                                }
                            }
                            
                            sub convert_to_lwz_value {
                                my ($definition, $value) = @_;
                                if ($definition->{format} eq 'tenthDegree') {
                                    $value += 0x10000 if $value < 0;
                                }
                                if (defined $definition->{decimalFactor}) {
                                    return $value * $definition->{decimalFactor};
                                    my $value1 = (($value * $definition->{decimalFactor}) >> 8) & 0x00FF;
                                    my $value2 = ($value * $definition->{decimalFactor}) & 0x00FF;
                                    return $value1, $value2;
                                } else {
                                    my $value1 = ($value >> 8) & 0x00FF;
                                    my $value2 = $value & 0x00FF;
                                    return $value1, $value2;
                                }
                            }
                            
                            sub dump_can_message {
                                my ($msg, $id, $dlc, $dataRef) = @_;
                                my @data = @{$dataRef};
                                my $dump = sprintf("%4X [%d] %02X %02X %02X %02X %02X %02X %02X %02X", $id, $dlc, @data);
                                plugin_log($plugname, $msg . ': ' . $dump);
                            }
                            
                            sub find_mapping_ga {
                                my ($ga) = @_;
                                foreach my $entry (@mapped) {
                                    if (defined $entry->{knxWriteGA}) {
                                        if ($ga eq $entry->{knxWriteGA}) {
                                            my $definition = get_definition($entry->{name});
                                            return ($entry, $definition);
                                        }
                                    }
                                }
                                return (undef, undef);
                            }
                            
                            sub get_definition {
                                my ($name) = @_;
                                foreach my $definition (@definitions) {
                                    if ($name eq $definition->{name}) {
                                        return $definition;
                                    }
                                }
                                return undef;
                            }
                            
                            sub get_combination_definition {
                                my ($name) = @_;
                                foreach my $combination (@combinations) {
                                    if ($name eq $combination->{name}) {
                                        return $combination;
                                    }
                                }
                                return undef;
                            }
                            
                            #####################################
                            # Wert für Wertekombination speichern
                            #####################################
                            sub saveCombinationValue {
                                my ($name, $value, $time) = @_;
                                $plugin_info{$plugname . '_Combination_' . $name} = $time . ':' . $value;
                            }
                            
                            
                            #################################
                            # Wert für Wertekombination laden
                            #################################
                            sub loadCombinationValue {
                                my ($name, $time) = @_;
                                my $loaded = $plugin_info{$plugname . '_Combination_' . $name};
                                my ($valueTime, $value) = split(':', $loaded, 2);
                                if ($valueTime >= $time) {
                                    return $value;
                                } else {
                                    return undef;
                                }
                            }
                            
                            sub convertValueToTargetTyp {
                                my ($value, $typ, $targetTyp) = @_;
                                if ($typ eq $targetTyp) {
                                    return $value;
                                } elsif ($typ eq '13.010' && $targetTyp eq '13.013') {
                                    return $value / 1000;
                                } elsif ($typ eq '13.013' && $targetTyp eq '13.010') {
                                    return $value * 1000;
                                } else {
                                    return undef;
                                }
                            }
                            Zuletzt geändert von SirTom; 11.03.2018, 11:24.

                            Kommentar

                            Lädt...
                            X