Ankündigung

Einklappen
Keine Ankündigung bisher.

Pluggit AP190 Lüftungsgerät per Modbus TCP in den Gira Homeserver einbinden

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

    HS/FS Pluggit AP190 Lüftungsgerät per Modbus TCP in den Gira Homeserver einbinden

    Hallo Leute,

    Ich weiß nicht ob jemand von euch mir weiterhelfen kann, ich versuche aktuell ein Pluggit AP190 Lüftungsgerät per Modbus TCP mit dem Gira Homeserver zu verbinden, sodass ich es schaffe einmal den Modus des Lüftungsgerätes umzuschalten und den aktuellen Modsu auch anzuzeigen, die Lüfterstufe dem Lüftungsgerät mitzuteilen sodass im Manuellen Modus das Lüftungsgerät auf diese Stufen reagiert.

    Ich habe das ganze jetzt einmal mit den Modbus TCP Writer 14185 und Modbus TCP Reader 14184 von SvenB versucht und auch mit den originalen Modbus Bausteinenen von Gira versucht.

    Ich komme aber nicht wirklich weiter. Hat jemand von euch Erfahrungen damit? Denn ich denke ohne Lüftungsgerät lässt sich das auch schwierig nachstellen. Im Anhang die beiden PDF Datein mit den Schnittstellenbeschreibungen.

    grafik.png

    Vielen vielen Dank inzwischen für eure Hilfe
    Angehängte Dateien

    #2
    @Harry115: Dann zeig mal her deinen Versuch. (Screenshot vom Logikeditor. Welches Register hast du wie versucht zu lesen?

    Kommentar


      #3
      Zitat von SvenB Beitrag anzeigen
      @Harry115: Dann zeig mal her deinen Versuch. (Screenshot vom Logikeditor. Welches Register hast du wie versucht zu lesen?
      grafik.png
      grafik.png

      Kommentar


        #4
        Naja, uint gibt es nicht. Probiere mal uint32, weil es auf seite 2 so steht. Auch klingt es nach Highbyte-First (E8 auf 1)

        image.png
        Vergiss den typen "uint", gucke auf Min und max, das ist ein 32bit unsignedint: uint32.

        Ich würde auch drauf tippen, dass du E10 auf -1 setzen musst, da die Register alle ungerade sind.
        (Holding Register scheint korrekt zu sein)

        Kommentar


          #5
          Hallo Harry, ich habe eine Pluggit 310 und ein eigenes Logikmodul geschrieben. Bzgl. Veröffentlichung ist es schwierig, da es so viele Zusatzfeaturs gibt, die die Funktionalität ändern (z.B. Servoflow). Wenn Du noch interessiert bist, dann schaue ich mal, was sich machen lässt. Die Doku ist meiner Meinung nach in einigen Punkten falsch bzw. inkonsistent.
          lg,
          Ralf
          Zuletzt geändert von hypnotoad; 25.01.2024, 17:55.

          Kommentar


            #6
            Bzgl. Registern würde ich empfehlen, dies nicht mit dem HS auszuprobieren, sondern mit Python und pymodbus zu skripten, weil man einfach viel schneller voran kommt. Z.B.:
            Code:
            #!/usr/bin/python3
            
            from pymodbus.client import ModbusTcpClient
            import struct
            
            def read_int(r):
                 return r[0] + (2**16)*r[1]
            def read_float(r):
                # word order of registers: little endian (registers[0] is lowest word)
                # big endian = hoechstwertiges word zuerst (an der niedrigsten speicherstelle)
                # swap words
                temp = struct.pack("=HH", r[1], r[0])
                # convert 2 words (little endian) to float
                return struct.unpack("=f", temp)[0]
            
                        
            client = ModbusTcpClient('pluggit.lan')
            client.connect()
            
            # 40003 in docu, but the bytes are in different order
            result = client.read_holding_registers(2, 2)
            t = result.registers[1]>>8 & 255
            z = result.registers[1] & 255
            assert(z == 0)
            c = result.registers[0]>>8 & 255
            d = result.registers[0] & 255
            types={1:"AP190", 2:"AP310", 3:"AP460"}
            print("Type: %s\nInstalled: 0x%x%x" % (types[t], d, c))
            
            # 40029 in docu
            result = client.read_holding_registers(28, 2)
            a = result.registers[1]>>8 & 255
            b = result.registers[1] & 255
            c = result.registers[0]>>8 & 255
            d = result.registers[0] & 255
            print("IP address: %d.%d.%d.%d" % (a, b, c, d))
            
            # 40085/40087 (halleft=B/halright=A) in docu
            result = client.read_holding_registers(86, 2)
            print("Pos A: {}".format(read_int(result.registers)))
            result = client.read_holding_registers(84, 2)
            print("Pos B: {}".format(read_int(result.registers)))
                
            # 40325 in docu
            result = client.read_holding_registers(324, 2)
            print("Speed Level: {}".format(read_int(result.registers)))
            
            # 40613 in docu
            # 0: <33
            # 1: <67
            # 2: <100
            # 3: >100%
            result = client.read_holding_registers(612, 2)
            print("Filter Status: {}".format(read_int(result.registers)))
            
            # 40457/59/61/63 in docu
            result = client.read_holding_registers(456, 2)
            print("Init In: {}".format(read_int(result.registers)))
            result = client.read_holding_registers(458, 2)
            print("Init Out: {}".format(read_int(result.registers)))
            result = client.read_holding_registers(460, 2)
            print("Last In: {}".format(read_int(result.registers)))
            result = client.read_holding_registers(462, 2)
            print("Last Out: {}".format(read_int(result.registers)))
            
            # 40559 in docu
            result = client.read_holding_registers(558, 2)
            print("Filter Reset: {}".format(read_int(result.registers)))
            
            # 40557 in docu
            result = client.read_holding_registers(556, 2)
            print("Filter Lifetime: {}".format(read_int(result.registers)))
            
            # 40457-63 in docu
            ins = client.read_holding_registers(456, 2)
            ine = client.read_holding_registers(458, 2)
            cus = client.read_holding_registers(460, 2)
            cue = client.read_holding_registers(462, 2)
            print("Filter Usage: {} (in), {} (out)".format(
                 (read_int(cus.registers)-read_int(ins.registers))/4,
                 (read_int(cue.registers)-read_int(ine.registers))/4)
                  )
            
            # 40161 in docu
            result = client.read_holding_registers(160, 2)
            preheater_percent = read_int(result.registers)
            print("Preheater: %d %%" % preheater_percent)
            
            # 40625 in docu
            result = client.read_holding_registers(624, 2)
            working_hours = read_int(result.registers)
            print("Working time: {} h = {} y".format(working_hours, working_hours/356/24))
            
            # 40515 in docu
            result = client.read_holding_registers(514, 2)
            print("Error: {}".format(read_int(result.registers)))
            
            # 40101 in docu
            result = client.read_holding_registers(101, 2)
            result2 = client.read_holding_registers(103, 2)
            print("RPM: {} {}".format(read_float(result.registers),
                                      read_float(result2.registers)));
            
            # 40445/40447 in docu
            t_outdoor_bypass_min = read_float(client.read_holding_registers(445, 2).registers);
            t_extract_bypass_max = read_float(client.read_holding_registers(447, 2).registers);
            # 40199 in docu
            bypass_state = client.read_holding_registers(198, 2)
            print("Bypass: {} (open when outdoor > {} && extract > {})".format(read_int(bypass_state.registers), t_outdoor_bypass_min, t_extract_bypass_max))
            
            
            # 40133 in docu
            t_outdoor = read_float(client.read_holding_registers(133, 2).registers);
            t_supply  = read_float(client.read_holding_registers(135, 2).registers);
            t_extract = read_float(client.read_holding_registers(137, 2).registers);
            t_exhaust = read_float(client.read_holding_registers(139, 2).registers);
            print(" {:3.1f} >=\\\\  //=< {:3.1f}".format(t_extract, t_outdoor));
            print("          \\\\           ");
            print(" {:3.1f} <=//  \\\\=> {:3.1f}".format(t_supply, t_exhaust));
            
            
            # 40473 in docu
            result = client.read_holding_registers(472, 2)
            print("Current linear mode: {}".format(read_int(result.registers)))
            # 0 1: manual
            # 0 9: fireplace
            
            # 40169 in docu???
            #start fireplace: put 0x0040 to 40169 (uint 16 bit)
            #stop fireplace: put 0x8040 to 40169 (uint 16 bit)
            # es muessen immer 32 bit gesendet werden
            #handle = client.write_registers(169, [0x0040, 0x0000])
            #handle = client.write_registers(169, [0x8040, 0x0000])#32832
            ###################################### ^^ [0]    [1]
            
            result = client.read_holding_registers(169, 2)
            print("Current combined mode: {}".format(read_int(result.registers)))

            Kommentar


              #7
              Wieso nimmst du pymodbus und machst die Umrechnung der Bytes / Register Manuell?

              Der BinaryPayloadBuilder nimmt die Endianess und hat dann Methoden, um einzelne oder mehrwre Register direkt in das Format umzurechnen.
              Du kannst auch 8 Register gleichzeitig lesen und diese dann iterative mit den Builder auswerten. Sparst dir Lesezugriffe und machen die Kostal Plugins zur Optimierung.

              besserer Tipp ist in meinen Augen ne UI zu nehmen. Verhält sich ähnlich wie der Baustein und intern nimmt der Baustein dann pymodbus.
              Zuletzt geändert von SvenB; 25.01.2024, 21:48.

              Kommentar

              Lädt...
              X