Ankündigung

Einklappen
Keine Ankündigung bisher.

Neues Plugin: SMAModbus (zu Auslesen eines SMA-Wechselrichters über speedwire/modbus)

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

    #46
    tut immer noch
    Zapft ihr Narren der König hat Durst

    Kommentar


      #47
      Zitat von klab Beitrag anzeigen
      Habe noch ein paar Kleinigkeiten geändert.
      Ich habe die user_doc.rst noch ein wenig angepasst (Platzhalter gelöscht, etc.) und das Plugin in den develop Branch des Plugin Repos gepusht.
      Viele Grüße
      Martin

      There is no cloud. It's only someone else's computer.

      Kommentar


        #48
        Unabhäning von dem Thread hier habe ich ein eigenes Plugin für die Modbus Schnittstelle von SMA erstellt. Bei dem Plugin im Develop-Branche frage ich mich, wie mit den verschiedenen Datentypen und Längen umgegangen wird. Lt. Spec kennt SMA 7 Datentype und NaN-Werte die auch mit unterschiedlichen längen.
        Meine Lösung war das Item zu parsen:
        <Registeradresse SMA>-<Anzahl zusammenhängender SMA Register>-<Datentyp SMA>


        PV:
        Typenschild:
        Seriennummer:
        name: Seriennummer
        type: num
        smamodbus@pv: 30005-2-U32


        In der Inverter-Klasse (inverter.py) wirds dann entsprechend decoded (decode_16bit_int(), decode_32bit_int(),decode_32bit_uint() usw..).

        Wegen der Dateigrößenbeschränkung habe ich die Specs entfernt. Die Wechselrichter die ich im Einsatz habe ist einmal der Batteriewechselrichter Sunny Island 4.4.M-13 sowie den PV Wechselrichter Sunny Tripower 8.0

        https://files.sma.de/downloads/MODBU...32009R_V10.zip
        https://files.sma.de/downloads/MODBU...3AV-40_V10.zip

        Hab das Plugin ein paar Monate am laufen, les aber derzeit nur den Batteriezustand aus.
        Zuletzt geändert von Gast; 30.04.2021, 11:25.

        Kommentar


          #49
          Servus

          So, nachdem ich endlich wieder zuhause bin, habe ich mal schnell das neue Plugin von Develop geholt und kann bestätigen dass es nun mit meinem SB1.5 läuft.
          Wie erwartet ist das Schwierige, die passenden Register aus der schlechten SMA Dokumentation rauszusuchen und zu testen.
          Die wichtigsten habe ich nach einigen erfolglosen Versuchen gefunden.
          Einige suche ich noch.

          Super Arbeit!

          Gruß, Martin

          Kommentar


            #50
            Guten Morgen

            Nachdem ich nun auch einen simplen Plot der AC-Leistung in der smartVISU gebastelt habe, ist mir vorhin etwas aufgefallen.


            Screenshot 2021-04-28 085900.png

            Mein Wechselrichter macht etwas völlig beknacktes. Bei Sonnenuntergang sieht man noch wie die Leistung runter geht auf 0 und dann auf 2147483648.
            Laut Modbusbeschreibung von SMA ist das ein S32 Wert, also wohl SIGNED 32 Bit. Da gibt es wohl eine Art Überlauf und das wird falsch interpretiert. Die Leistung geht zuerst auf 0 (alle 32 Bits sind 0) und dann springt das MSB (das Vorzeichenbit) plötzlich auf 1 und das wird vom Plugin als 2147483648 gesehen. Ich schätze, der Datentyp im Plugin ist UNSIGNED 32bit anstatt SIGNED 32Bit, dann passiert genau das, wenn das MSB 1 und alle anderen Bits 0 sind. Hier aber Signed zu verwenden würde das Problem nicht lösen, dann wäre der Wert nur -2147483648, was in dem Anwendungsfall auch Quatsch wäre.
            Man müsste im Plugin diesen Wert abfangen und auf 0 setzen. Oder habe ich da nen Denkfehler und das geht einfacher?

            EDIT: Hab gerade gesehen, dass das in diesem Thread schon vor 3 Jahren angemerkt wurde und man das natürlich mit einem EVAL lösen könnte. Fände es aber eleganter, wenn dieser Wert schon im Plugin behandelt werden würde.

            Gruß, Martin
            Zuletzt geändert von Sipple; 28.04.2021, 08:52.

            Kommentar


              #51
              Als Workaround mit eval, ist das so überhaupt korrekt?

              Code:
              SB15:
                  Leistung:
                      AC:
                          type: num
                          smamb_register: 30775
                          eval: 0 if (value == 2147483648) else value
                          eval_trigger: sh.SB15.Leistung.AC
                          Plot:
                              type: num
                              database: yes
                              eval: sh.SB15.Leistung.AC()
                              eval_trigger: E3DC.Zeitgeber
              Bin da nicht ganz sicher ob das im Zusammenhang mit dem Sub-Item klappt, weil ich z.B. nicht weiß, ob der erste eval im Mutterobjekt zuerst behandelt wird, oder es so passieren kann, dass der falsche Wert noch in die DB geschrieben wird, bevor er korrigiert wurde.
              Zuletzt geändert von Sipple; 28.04.2021, 09:12.

              Kommentar


                #52
                Ich habe eben mal in den Plugin Code geschaut. Da wird nur Unsigned-Integer eingelesen:

                Code:
                decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big)
                decoded = {
                    'value': decoder.decode_32bit_uint(),
                }
                valueend = decoded.get("value")
                Ich sehe in den Item Definitionen zumindest keine Definition, wie der Wert zu interpretieren ist.
                Oder sind alle Werte des Wechselrichters SIGNED 32-Bit? Falls es keine UNSIGNED 32-Bit Werte gibt, könnte man das vermutlich leicht anpassen. (Ich kenne mich allerdings mit pymodbus und dem Wechselrichter nicht aus.)
                Viele Grüße
                Martin

                There is no cloud. It's only someone else's computer.

                Kommentar


                  #53
                  Leider gibt es sowohl als auch. Also Unsigned und signed. Beispiel:

                  Screenshot 2021-04-28 101459.png

                  Kommentar


                    #54
                    Könnte so evtl klappen:

                    Code:
                                    decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big)
                                    decoded = {
                                        'value': decoder.decode_32bit_uint(),
                                    }
                                    valueend = decoded.get("value")
                                    if valueend == 2147483648
                                        valueend = 0
                    Allerdings könnte es dann sein, dass wenn irgendwer irgendein anderes Register verwendet, dass den Wert 2147483648 sinnvoll enthalten kann, wäre es da dann falsch.

                    Wasserdicht wäre es wohl nur, wenn man dem Plugin schon bei der Item Definition einen weiteren Parameter zur Datendefinition mitgeben würde, so ähnlich wie beim KNX dpt, und das entsprechend verarbeitet. Ist aber ein größerer Aufwand.

                    Stimmt mein eval Ansatz in Post #51? Dann kann ich damit leben.
                    Zuletzt geändert von Sipple; 28.04.2021, 09:29.

                    Kommentar


                      #55
                      In der Modbus Dokumentation von SMA habe ich auch noch Register mit S16, U64 und STR32 gefunden und evtl. noch etwas übersehen.
                      In der pymodbus Doku hier:

                      https://pymodbus.readthedocs.io/en/l...ode_32bit_uint

                      gibt es aber wohl für all diese Fälle eine decode Variante.

                      Würde man ein Item Attribut, z.B. smamb_dtp einführen (z.B. S16, U32, S32, STR32,....), könnte man den entsprechenden Decoder im Plugin verwenden, simples if-else if-else. Oder was eleganteres, wofür mein Erstklässler-Python-Wissen nicht ausreicht.

                      Kommentar


                        #56
                        Sipple Wenn Du Dich als Tester zur Verfügung stellst, baue ich weitere Datentypen in das Plugin ein. Ich mache das nur im Blindflug, da ich keinen Modbus und keinen Wechselrichter habe.
                        Viele Grüße
                        Martin

                        There is no cloud. It's only someone else's computer.

                        Kommentar


                          #57
                          Aber gerne.

                          Kommentar


                            #58
                            Ich habe eben die v1.5.0 des Plugins gepusht. Die hat ein zusätzliches Item Attribut smamb_datatype. Es werden 10 verschiedene Datentypen unterstützt.

                            Beschrieben ist das in der User Dokumentation des Develop Branches zum Plugin unter

                            https://www.smarthomeng.de/dev/user/.../user_doc.html

                            und der Seite mit der Konfigurationsdokumentation zum Plugin unter

                            https://www.smarthomeng.de/dev/user/...ig/sma_mb.html

                            Damit solltest Du 16, 32 und 64-Bit Werte in Signed und Unsigned, sowie Strings der Längen 8, 12, 16 und 32 auslesen können.


                            Viele Grüße
                            Martin

                            There is no cloud. It's only someone else's computer.

                            Kommentar


                              #59
                              Wahnsinn wie schnell du sowas umsetzt

                              Ich werde das ein zwei Tage testen um zu sehen was in der Nacht dann passiert.

                              Schon mal vielen Dank!

                              Kommentar


                                #60
                                Guten Morgen

                                Zwischenbericht. Die Datentyp-Beachtung funktioniert prinzipiell und sollte so bleiben (Problembeschreibung, siehe unten).

                                1) Wie weiter oben schon vermutet, löst das aber das Problem nicht, dass SMA aus unerklärlichen (sinnlosen?) Gründen in der Nacht alle Bits vieler Register auf '1' setzt anstatt 0. Was das soll weiß nur SMA. Zuerst wollte ich das im Item mit eval abfangen. Hat aber nicht so geklappt, wie ich wollte. Der Effekt war, dass ich nach jedem 2. Abfrageintervall wieder den falschen Wert im Item hatte. Also eine Minute den korrigierten Wert, dann eine Minute den unkorrigierten, dann wieder den korrigierten usw.
                                Letztendlich habe ich im Plugin etwas eingefügt (Zeile 212) und teste das jetzt, scheint aber zu klappen:

                                Code:
                                if valueend in [-2147483648, 4294967295]: valueend = 0
                                # if valueend == -2147483648: #S32 Registers are set to this value (all bits are '1' e.g. at night)
                                # valueend = 0
                                # elif valueend == 4294967295: #U32 Registers are set to this value (all bits are '1' e.g. at night)
                                # valueend = 0
                                Die auskommentierten Zeilen habe ich gestern nach Sonnenuntergang, als das Problem wieder auftrat, eingebaut und das hat bis eben gemacht was es soll. Ich habe es zur Vereinfachung dann in den Einzeiler geändert und beobachte das nun. Diese Variante hat den Vorteil, dass man, falls noch mehr doofe Werte auftauchen, die den Wert 0 haben sollten aber alle Bits auf '1' gesetzt haben (S16, U16, S64, U64), einfach die Liste der abzufangenden Werte erweitern kann. Ich sehe das Setzen aller Bits auf '1' inzwischen grundsätzlich als falsch an, bis jemand einen Fall in der Praxis (ein Register) findet, bei dem das sinnvoll ist. Ich hoffe, das klappt so, weil - ich und meine Python Kentnisse....

                                2) Ein etwas größeres Problem. Wenn ich den Code richtig verstehe, dann passiert die eigentliche Abfrage des Wechselrichters in Zeile 183:

                                Code:
                                result = client.read_holding_registers((int(read_parameter)), 2, unit=3)
                                Der 2er ist das Problem. Wenn ich mich nicht irre, ist das die Anzahl der zusammenhängenden 16bit Register, die gelesen werden sollen. Daher klappt das nur bei 32Bit Werten, also S32 und U32. Das ist in der Praxis natürlich die überwältigende Mehrheit und daher nicht gleich aufgefallen. Vielen wird das völlig egal sein, weil sie nie einen anderen Wert vom Wechselrichter lesen wollen, z.B. U16, U64 oder Strings. Streng genommen müsste man den 2er aber durch eine Variable ersetzen und diese vorher in Abhängigkeit des smamb_datatype Paramteres des Items initialisieren. So wie weiter unten beim Dekodieren der Werte (siehe if self._datatypes[read_parameter] == 'S16': ....). Sehe ich das richtig?

                                Aus diesem Grund werden wohl auch die String Werte nicht funktionieren. Dazu kommt hierbei noch, dass die Registerbeschreibung von SMA meines Wechselrichters (aller Wechselrichter?) fehlerhaft ist. Siehe Bild.

                                Screenshot 2021-04-29 091836.png
                                Das macht keinen Sinn. Die allgemeine Modbus Beschreibung von SMA ist hier auch nicht hilfreich. SMA definiert hier im ganzen Dokument 10 String Werte, alle als STR32, aber mit unterschiedlichen Registerlängen. Die Registerlängen sind wohl korrekt. MacId wäre der einzige, der passt. 16 Register mal 16bit sind 256, dividiert durch 8 Bit (UTF-8) sind 32 Zeichen. DnsSrvIp müsste STR16 sein, Location STR24, was es so in pymodbus gar nicht gibt.
                                Aber ich schließe wie immer nicht aus, dass ich da einen Denkfehler habe.

                                Gruß, Martin
                                Angehängte Dateien

                                Kommentar

                                Lädt...
                                X